github.com/mitranim/sqlb@v0.7.2/readme.md (about)

     1  ## Overview
     2  
     3  `sqlb`: **SQL** **B**uilder for Go. Features:
     4  
     5  * Supports plain SQL queries with ordinal or named params.
     6    * Supports argument lists.
     7    * Supports argument maps.
     8    * Supports argument structs.
     9  * Supports generating SQL clauses from structs.
    10    * Generate "select" clauses from structs.
    11    * Generate "insert" clauses from structs.
    12    * Generate "update" clauses from structs.
    13    * Generate "delete" clauses from structs.
    14    * Generate "and" and "or" conditional clauses from structs.
    15  * Provides data structures forming an SQL DSL in Go.
    16    * Shortcuts for common queries such as select, insert, update, delete.
    17    * Arbitrarily composable and nestable.
    18    * Uses data literals, not a builder API.
    19  * Supports an optional "JSON Expression Language" (JEL) for expressing SQL expressions with nested Lisp-style calls in JSON.
    20  * Supports safely parsing "order by" clauses from JSON and text, for specific struct types, converting field names from `"json"` field tags to `"db"` field tags.
    21  * Supports "sparse" structs, where not all fields are "present", allowing to implement HTTP PATCH semantics without sacrificing static typing.
    22  * Compatible with standard SQL syntax, biased towards Postgres.
    23  * Decently optimized.
    24  * Small and dependency-free.
    25  
    26  API docs: https://pkg.go.dev/github.com/mitranim/sqlb.
    27  
    28  See the sibling library https://github.com/mitranim/gos for scanning SQL rows into structs.
    29  
    30  ## Examples
    31  
    32  All examples imply the following import:
    33  
    34  ```golang
    35  import s "github.com/mitranim/sqlb"
    36  ```
    37  
    38  ### Query with named parameters and structs
    39  
    40  ```golang
    41  func ExampleStrQ_structs() {
    42    type Output struct {
    43      Col0 string `db:"col0"`
    44      Col1 string `db:"col1"`
    45    }
    46  
    47    type Filter struct {
    48      Col2 int64 `db:"col2"`
    49      Col3 int64 `db:"col3"`
    50    }
    51  
    52    fmt.Println(s.Reify(
    53      s.StrQ{`
    54        select :cols from some_table where :filter
    55      `, s.Dict{
    56        `cols`:   s.Cols{(*Output)(nil)},
    57        `filter`: s.And{Filter{10, 20}},
    58      }},
    59    ))
    60    // Output:
    61    // select "col0", "col1" from some_table where "col2" = $1 and "col3" = $2 [10 20]
    62  }
    63  ```
    64  
    65  ### AST-style query building
    66  
    67  ```golang
    68  func ExampleInsert_nonEmpty() {
    69    type Fields struct {
    70      Col0 int64 `db:"col0"`
    71      Col1 int64 `db:"col1"`
    72    }
    73  
    74    fmt.Println(s.Reify(s.Insert{`some_table`, Fields{10, 20}}))
    75  
    76    // Output:
    77    // insert into "some_table" ("col0", "col1") values ($1, $2) returning * [10 20]
    78  }
    79  ```
    80  
    81  ### Composition
    82  
    83  ```golang
    84  func Example_composition() {
    85    inner := s.StrQ{
    86      `select * from some_table where col0 = :val`,
    87      s.Dict{`val`: 10},
    88    }
    89  
    90    outer := s.StrQ{
    91      `select * from (:inner) as _ where col1 = :val`,
    92      s.Dict{`inner`: inner, `val`: 20},
    93    }
    94  
    95    fmt.Println(s.Reify(outer))
    96    // Output:
    97    // select * from (select * from some_table where col0 = $1) as _ where col1 = $2 [10 20]
    98  }
    99  ```
   100  
   101  ## Changelog
   102  
   103  ### v0.7.2
   104  
   105  Added `ValidateUnusedArguments` that globally disables or enables argument validation.
   106  
   107  Internal improvements in errors.
   108  
   109  ### v0.7.1
   110  
   111  Added `InsertVoid`, `UpdateVoid`, `DeleteVoid`, `UpsertVoid`.
   112  
   113  ### v0.7.0
   114  
   115  Renamed method `.Append` in various types to `.AppendTo` for consistency with other libraries.
   116  
   117  Renamed interface `Appender` to `AppenderTo`.
   118  
   119  ### v0.6.8
   120  
   121  Added `LaxDict`: dictionary of named arguments similar to `Dict`, but without support for validating unused arguments.
   122  
   123  ### v0.6.7
   124  
   125  Fixed an edge case bug in `Upsert`.
   126  
   127  ### v0.6.6
   128  
   129  Fixed support for non-empty sparse structs in `Upsert`.
   130  
   131  ### v0.6.5
   132  
   133  Add `Upsert`.
   134  
   135  ### v0.6.4
   136  
   137  `OrdsParser` support default "dir" and "nulls" in struct tags:
   138  
   139  ```go
   140  type Ordable struct {
   141    Name string `json:"name" db:"name" ord.dir:"desc" ord.nulls:"last"`
   142  }
   143  ```
   144  
   145  ### v0.6.3
   146  
   147  * `Dir` supports text parsing and encoding.
   148  * Minor breaking change: `Bui.Arg` now appends both an argument and a parameter.
   149  
   150  ### v0.6.2
   151  
   152  `CommaAppender` and `ArrayAppender` are now parametrized on the element type.
   153  
   154  ### v0.6.1
   155  
   156  Added `StructsInsert`, `StructsInsertOf`.
   157  
   158  ### v0.6.0
   159  
   160  * Support `role:"ref"` struct field annotation for pointer-like generic types.
   161  
   162  * Require Go 1.18.
   163  
   164  ### v0.5.3
   165  
   166  Added `SliceCommaAppender`.
   167  
   168  ### v0.5.2
   169  
   170  `Update` now defaults to `where null` rather than `where true`. The new behavior is aligned with `Delete`.
   171  
   172  Embedded struct fields tagged with `db:""` or `db:"-"` are now completely ignored. The old behavior treated them as untagged, traversing them. The new behavior allows to completely skip an embedded struct, on an opt-in basis, without having to modify the `db` tags of its inner fields.
   173  
   174  ### v0.5.1
   175  
   176  Added optional support for a hidden `Nullable` interface, shared with the library `github.com/mitranim/gt`.
   177  
   178  ### v0.5.0
   179  
   180  * Revised ords parsing.
   181    * Split `OrdsParser` into two types:
   182      * `ParserOrds` → suitable for inclusion into other types.
   183      * `OrdsParser` → suitable for transient, stackframe-local use.
   184    * Added `(*Ords).OrdsParser` suitable for use by types that embed `Ords` and implement custom parsing methods.
   185    * Support arbitrary filters for struct fields.
   186    * Added `TagFilter` for field filtering.
   187  * Renamed `Sparse.HasField` to `Sparse.AllowField`. `Filter` uses a method with the same signature, and the old name didn't make sense for it.
   188  * Misc:
   189    * Renamed `(*Ords).AppendVals` → `(*Ords).Add`.
   190    * Added `(*Ords).Zero`.
   191    * Replaced `Ords.Grow` with `(*Ords).Grow` that modifies the receiver.
   192  
   193  ### v0.4.3
   194  
   195  Add `SelectCount`.
   196  
   197  ### v0.4.2
   198  
   199  Add `Limit`, `Offset`, `LimitUint`, `OffsetUint`.
   200  
   201  ### v0.4.1
   202  
   203  Exported `ErrEmptyAssign` used by `StructAssign` and `Update` to indicate the inability to generate a valid SQL "update set" clause.
   204  
   205  ### v0.4.0
   206  
   207  Added low-level tools for text encoding and SQL array encoding:
   208  
   209    * `ArrayAppender`
   210    * `CommaAppender`
   211    * `String`
   212    * `TryString`
   213    * `Append`
   214    * `TryAppend`
   215    * `TryAppendWith`
   216    * `AppendWith`
   217    * `AppenderString`
   218  
   219  Breaking changes:
   220  
   221    * Removed useless expression type `Int`.
   222    * Renamed `Bui.TryExprs` to `Bui.CatchExprs`.
   223  
   224  ### v0.3.0
   225  
   226  Revised AST-style expressions:
   227  
   228  * Removed uselessly low-level exprs such as `Space`, `ReturningStar`, and so on.
   229  * Added higher-level shortcuts for extremely common yet simple operations:
   230    * `Select`
   231    * `Insert`
   232    * `Update`
   233    * `Delete`
   234  
   235  ### v0.2.1
   236  
   237  Added `Sparse` and `Partial` to support "sparse" structs, allowing to implement HTTP PATCH semantics more easily, efficiently, and correctly.
   238  
   239  ### v0.2.0
   240  
   241  Full API revision. Added many AST/DSL-like types for common expressions. Optimized parsing and expression building. Use caching and pooling to minimize redundant work. String-based query building now uses partial parsing with caching, and should no longer be a measurable expense. Ported JEL support from `github.com/mitranim/jel`.
   242  
   243  ### v0.1.17
   244  
   245  Added `Ords.OrType`.
   246  
   247  ### v0.1.16
   248  
   249  Added `NamedArg.Norm`. Improved `NamedArg.IsNil` and `NamedArgs.Conditions`. They now use the `driver.Valuer.Value` method, if present, to determine null-ness, which works for non-pointer "nullable" types.
   250  
   251  ### v0.1.15
   252  
   253  `Ords.Or` is now a value method that returns a modified version, rather than a pointer method that mutated the original.
   254  
   255  ### v0.1.14
   256  
   257  `StructMap` and `StructNamedArgs` now tolerate `nil` inputs. Previously, they tolerated non-nil interfaces where the underlying value was a nil struct pointer. Now they also allow nil interfaces.
   258  
   259  ### v0.1.13
   260  
   261  Fixed the bug where the `Ords.Lax` mode was appending malformed ords, instead of skipping them entirely.
   262  
   263  ### v0.1.12
   264  
   265  * `StrQuery` now interpolates directly, without invoking `(*Query).Append` on the provided query. This allows to interpolate `StrQuery` strings that contain parameter placeholders. Use at your own risk.
   266  
   267  * `(*Query).Append` no longer has an argument length limit.
   268  
   269  ### v0.1.11
   270  
   271  Added `Ords.Lax`: a boolean that causes `Ords` to skip unknown fields during parsing.
   272  
   273  ### v0.1.10
   274  
   275  Breaking changes in the name of efficiency:
   276  
   277  * `NamedArgs.Conditions` now uses `=` and `is null`, as appropriate, instead of previous `is not distinct from`. At the time of writing, Postgres (version <= 12) is unable to use indexes for `is not distinct from`, which may result in much slower queries. The new approach avoids this gotcha.
   278  
   279  * In `Ord`, `nulls last` is now opt-in rather than default. In addition, `asc/desc` in input strings is now optional. This more precisely reflects SQL semantics and allows finer-grained control. More importantly, it avoids a potential performance gotcha. At the time of writing, Postgres (version <= 12) is unable to use normal indexes for `nulls last` ordering. Instead it requires specialized indexes where `nulls last` is set explicitly. Making it opt-in reduces the chance of accidental slowness.
   280  
   281    * Added `OrdAscNl` and `OrdDescNl` for convenient construction.
   282  
   283    * Minor breaking change: `Ord.IsDesc` is now `Ord.Desc`.
   284  
   285  * Minor breaking change: removed `Ord.IsValid`.
   286  
   287  Non-breaking additions:
   288  
   289  * `Ords.RowNumber()`: generates a Postgres window function expression `row_number() over (order by ...)`, falling back on a constant value when the ordering is empty.
   290  
   291  * `QueryOrd()`: shortcut for making a `Query` with a single `.Append()` invocation.
   292  
   293  * `QueryNamed()`: shortcut for making a `Query` with a single `.AppendNamed()` invocation.
   294  
   295  ### 0.1.9
   296  
   297  Added `Ords` and `Ord`: structured representation of `order by`, able to decode from external input such as JSON, but also flexible enough to store arbitrary sub-queries. Ported from `github.com/mitranim/jel`, while also adding the ability to store sub-queries rather than only identifiers.
   298  
   299  ### 0.1.8
   300  
   301  Added `StrQuery`.
   302  
   303  ### 0.1.7
   304  
   305  Corrected `CheckUnused` to be `true` by default, which was always intended.
   306  
   307  ### 0.1.6
   308  
   309  Added `CheckUnused` which allows to opt out of unused parameter checks in `Query.Append` and `Query.AppendNamed`. Can be convenient for development.
   310  
   311  ### 0.1.5
   312  
   313  Minor bugfix: `Query.String` is now implemented on the non-pointer type, as intended. Also updated the `sqlp` dependency.
   314  
   315  ### 0.1.4
   316  
   317  Breaking changes in `Query`: simpler interface, better performance.
   318  
   319  Instead of storing and operating on a parsed AST, `Query` now stores the query text as `[]byte`. We use `sqlp.Tokenizer` to parse inputs without generating an AST, transcoding parameters on the fly. `IQuery` now simply appends to an externally-passed `Query`, instead of having to return a parsed AST representation. All together, this significantly simplifies the implementation of `Query` and any external `IQuery` types.
   320  
   321  ### 0.1.3
   322  
   323  Added `Query.Clear()`.
   324  
   325  ### 0.1.2
   326  
   327  Breaking: methods of `NamedArgs` now return queries, suitable for inclusion into other queries. Separate methods for strings and arg slices have been removed.
   328  
   329  ### 0.1.1
   330  
   331  Dependency update.
   332  
   333  ### 0.1.0
   334  
   335  First tagged release.
   336  
   337  ## License
   338  
   339  https://unlicense.org
   340  
   341  ## Misc
   342  
   343  I'm receptive to suggestions. If this library _almost_ satisfies you but needs changes, open an issue or chat me up. Contacts: https://mitranim.com/#contacts