update docs; fix set-options!
This commit is contained in:
parent
d0ae02a6ef
commit
bf96f034c3
8 changed files with 106 additions and 11 deletions
|
|
@ -1,10 +1,12 @@
|
|||
# Changes
|
||||
|
||||
* 2.4.next in progress
|
||||
* Fix `set-options!` (only `:checking` worked in 2.4.947).
|
||||
* Fix `:cast` formatting when quoting is enabled, via PR [#443](https://github.com/seancorfield/honeysql/pull/443) [duddlf23](https://github.com/duddlf23).
|
||||
* Fix [#441](https://github.com/seancorfield/honeysql/issues/441) by adding `:replace-into` to in-flight clause order (as well as registering it for the `:mysql` dialect).
|
||||
* Fix [#434](https://github.com/seancorfield/honeysql/issues/434) by special-casing `:'ARRAY`.
|
||||
* Fix [#433](https://github.com/seancorfield/honeysql/issues/433) by supporting additional `WITH` syntax, via PR [#432](https://github.com/seancorfield/honeysql/issues/432), [@MawiraIke](https://github.com/MawiraIke). _[Technically, this was in 2.4.947, but I kept the issue open while I wordsmithed the documentation]_
|
||||
* Address [#405](https://github.com/seancorfield/honeysql/issues/405) by adding `:numbered` option, which can also be set globally using `set-options!`.
|
||||
|
||||
* 2.4.947 -- 2022-11-05
|
||||
* Fix [#439](https://github.com/seancorfield/honeysql/issues/439) by rewriting how DDL options are processed; also fixes [#386](https://github.com/seancorfield/honeysql/issues/386) and [#437](https://github.com/seancorfield/honeysql/issues/437); **Whilst this is intended to be purely a bug fix, it has the potential to be a breaking change -- hence the version jump to 2.4!**
|
||||
|
|
|
|||
51
README.md
51
README.md
|
|
@ -116,6 +116,13 @@ If you want to format the query as a string with no parameters (e.g. to use the
|
|||
=> ["SELECT a, b, c FROM foo WHERE foo.a = 'baz'"]
|
||||
```
|
||||
|
||||
As seen above, the default parameterization uses positional parameters (`?`) with the order of values in the generated vector matching the order of those placeholders in the SQL. As of 2.4.next, you can specified `:numbered true` as an option to produce numbered parameters (`$1`, `$2`, etc):
|
||||
|
||||
```clojure
|
||||
(sql/format sqlmap {:numbered true})
|
||||
=> ["SELECT a, b, c FROM foo WHERE foo.a = $1" "baz"]
|
||||
```
|
||||
|
||||
Namespace-qualified keywords (and symbols) are generally treated as table-qualified columns: `:foo/bar` becomes `foo.bar`, except in contexts where that would be illegal (such as the list of columns in an `INSERT` statement). This approach is likely to be more compatible with code that uses libraries like [`next.jdbc`](https://github.com/seancorfield/next-jdbc) and [`seql`](https://github.com/exoscale/seql), as well as being more convenient in a world of namespace-qualified keywords, following the example of `clojure.spec` etc.
|
||||
|
||||
```clojure
|
||||
|
|
@ -388,6 +395,19 @@ INSERT INTO comp_table
|
|||
VALUES (?, (?, ?)), (?, (?, ?))
|
||||
"
|
||||
"small" 1 "inch" "large" 10 "feet"]
|
||||
;; with numbered parameters:
|
||||
(-> (insert-into :comp_table)
|
||||
(columns :name :comp_column)
|
||||
(values
|
||||
[["small" (composite 1 "inch")]
|
||||
["large" (composite 10 "feet")]])
|
||||
(sql/format {:pretty true :numbered true}))
|
||||
=> ["
|
||||
INSERT INTO comp_table
|
||||
(name, comp_column)
|
||||
VALUES ($1, ($2, $3)), ($4, ($5, $6))
|
||||
"
|
||||
"small" 1 "inch" "large" 10 "feet"]
|
||||
;; or as pure data DSL:
|
||||
(-> {:insert-into [:comp_table],
|
||||
:columns [:name :comp_column],
|
||||
|
|
@ -608,6 +628,12 @@ Keywords that begin with `?` are interpreted as bindable parameters:
|
|||
(where [:= :a :?baz])
|
||||
(sql/format {:params {:baz "BAZ"}}))
|
||||
=> ["SELECT id FROM foo WHERE a = ?" "BAZ"]
|
||||
;; or with numbered parameters:
|
||||
(-> (select :id)
|
||||
(from :foo)
|
||||
(where [:= :a :?baz])
|
||||
(sql/format {:params {:baz "BAZ"} :numbered true}))
|
||||
=> ["SELECT id FROM foo WHERE a = $1" "BAZ"]
|
||||
;; or as pure data DSL:
|
||||
(-> {:select [:id], :from [:foo], :where [:= :a :?baz]}
|
||||
(sql/format {:params {:baz "BAZ"}}))
|
||||
|
|
@ -832,6 +858,24 @@ LIMIT ?
|
|||
OFFSET ?
|
||||
"
|
||||
"bort" "gabba" 1 2 2 3 1 2 3 10 20 0 50 10]
|
||||
;; with numbered parameters:
|
||||
(sql/format big-complicated-map
|
||||
{:params {:param1 "gabba" :param2 2}
|
||||
:pretty true :numbered true})
|
||||
=> ["
|
||||
SELECT DISTINCT f.*, b.baz, c.quux, b.bla AS \"bla-bla\", NOW(), @x := 10
|
||||
FROM foo AS f, baz AS b
|
||||
INNER JOIN draq ON f.b = draq.x INNER JOIN eldr ON f.e = eldr.t
|
||||
LEFT JOIN clod AS c ON f.a = c.d
|
||||
RIGHT JOIN bock ON bock.z = c.e
|
||||
WHERE ((f.a = $1) AND (b.baz <> $2)) OR (($3 < $4) AND ($5 < $6)) OR (f.e IN ($7, $8, $9)) OR f.e BETWEEN $10 AND $11
|
||||
GROUP BY f.a, c.e
|
||||
HAVING $12 < f.e
|
||||
ORDER BY b.baz DESC, c.quux ASC, f.a NULLS FIRST
|
||||
LIMIT $13
|
||||
OFFSET $14
|
||||
"
|
||||
"bort" "gabba" 1 2 2 3 1 2 3 10 20 0 50 10]
|
||||
```
|
||||
```clojure
|
||||
;; Printable and readable
|
||||
|
|
@ -882,8 +926,13 @@ Or perhaps your database supports syntax like `a BETWIXT b AND c`, in which case
|
|||
;; example usage:
|
||||
(-> (select :a) (where [:betwixt :a 1 10]) sql/format)
|
||||
=> ["SELECT a WHERE a BETWIXT ? AND ?" 1 10]
|
||||
;; with numbered parameters:
|
||||
(-> (select :a) (where [:betwixt :a 1 10]) (sql/format {:numbered true}))
|
||||
=> ["SELECT a WHERE a BETWIXT $1 AND $2" 1 10]
|
||||
```
|
||||
|
||||
> Note: the generation of positional placeholders (`?`) or numbered placeholders (`$1`, `$2`, etc) is handled automatically by `format-expr` so you get this behavior "for free" in your extensions, as long as you use the public API for `honey.sql`. You should avoid writing extensions that generate placeholders directly if you want them to work with numbered parameters.
|
||||
|
||||
You can also register SQL clauses, specifying the keyword, the formatting function, and an existing clause that this new clause should be processed before:
|
||||
|
||||
```clojure
|
||||
|
|
@ -909,6 +958,6 @@ If you find yourself registering an operator, a function (syntax), or a new clau
|
|||
|
||||
## License
|
||||
|
||||
Copyright (c) 2020-2021 Sean Corfield. HoneySQL 1.x was copyright (c) 2012-2020 Justin Kramer and Sean Corfield.
|
||||
Copyright (c) 2020-2022 Sean Corfield. HoneySQL 1.x was copyright (c) 2012-2020 Justin Kramer and Sean Corfield.
|
||||
|
||||
Distributed under the Eclipse Public License, the same as Clojure.
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ You can now select a non-ANSI dialect of SQL using the new `honey.sql/set-dialec
|
|||
|
||||
## Option Changes
|
||||
|
||||
The `:quoting <dialect>` option has superseded by the new dialect machinery and a new `:quoted` option that turns quoting on or off. You either use `:dialect <dialect>` instead or set a default dialect (via `set-dialect!`) and then use `:quoted true` in `format` calls where you want quoting.
|
||||
The `:quoting <dialect>` option has been superseded by the new dialect machinery and a new `:quoted` option that turns quoting on or off. You either use `:dialect <dialect>` instead (which turns on quoting by default) or set a default dialect (via `set-dialect!`) and then use `:quoted true` in `format` calls where you want quoting.
|
||||
|
||||
SQL entity names are automatically quoted if you specify a `:dialect` option to `format`, unless you also specify `:quoted false`.
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ The following options are no longer supported:
|
|||
* `:allow-dashed-names?` -- if you provide dashed-names in 2.x, they will be left as-is if quoting is enabled, else they will be converted to snake_case (so you will either get `"dashed-names"` with quoting or `dashed_names` without). If you want dashed-names to be converted to snake_case when `:quoted true`, you also need to specify `:quoted-snake true`.
|
||||
* `:allow-namespaced-names?` -- this supported `foo/bar` column names in SQL which I'd like to discourage.
|
||||
* `:namespace-as-table?` -- this is the default in 2.x: `:foo/bar` will be treated as `foo.bar` which is more in keeping with `next.jdbc`.
|
||||
* `:parameterizer` -- this would add a lot of complexity to the formatting engine and I do not know how widely it was used (especially in its arbitrarily extensible form).
|
||||
* `:parameterizer` -- this would add a lot of complexity to the formatting engine and I do not know how widely it was used (especially in its arbitrarily extensible form). _[As of 2.4.next, the ability to generated SQL with numbered parameters, i.e., `$1` instead of positional parameters, `?`, has been added via the `:numbered true` option]_
|
||||
* `:return-param-names` -- this was added to 1.x back in 2013 without an associated issue or PR so I've no idea what use case this was intended to support.
|
||||
|
||||
> Note: I expect some push back on those first three options and the associated behavior changes.
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ Some "functions" are considered to be operators. In general,
|
|||
`42` and `"c"` lifted out into the overall vector result
|
||||
(with a SQL string followed by all its parameters).
|
||||
|
||||
> Note: you can use the `:numbered true` option to `format` to produce SQL containing numbered placeholders, like `FOO(a, $1, $2)`, instead of positional placeholders (`?`).
|
||||
|
||||
Operators can be strictly binary or variadic (most are strictly binary).
|
||||
Special syntax can have zero or more arguments and each form is
|
||||
described in the [Special Syntax](special-syntax.md) section.
|
||||
|
|
@ -179,7 +181,7 @@ expression requires an extra level of nesting:
|
|||
|
||||
As indicated in the preceding sections, values found in the DSL data structure
|
||||
that are not keywords or symbols are lifted out as positional parameters.
|
||||
They are replaced by `?` in the generated SQL string and added to the
|
||||
By default, they are replaced by `?` in the generated SQL string and added to the
|
||||
parameter list in order:
|
||||
|
||||
<!-- :test-doc-blocks/skip -->
|
||||
|
|
@ -187,6 +189,14 @@ parameter list in order:
|
|||
[:between :size 10 20] ;=> "size BETWEEN ? AND ?" with parameters 10 and 20
|
||||
```
|
||||
|
||||
If you specify the `:numbered true` option to `format`, numbered placeholders (`$1`, `$2`, etc) will be used instead of positional placeholders (`?`).
|
||||
|
||||
<!-- :test-doc-blocks/skip -->
|
||||
```clojure
|
||||
;; with :numbered true option:
|
||||
[:between :size 10 20] ;=> "size BETWEEN $1 AND $2" with parameters 10 and 20
|
||||
```
|
||||
|
||||
HoneySQL also supports named parameters. There are two ways
|
||||
of identifying a named parameter:
|
||||
* a keyword or symbol that begins with `?`
|
||||
|
|
@ -206,6 +216,18 @@ call as the `:params` key of the options hash map.
|
|||
;;=> ["SELECT * FROM table WHERE a = ?" 42]
|
||||
```
|
||||
|
||||
Or with `:numbered true`:
|
||||
```clojure
|
||||
(sql/format {:select [:*] :from [:table]
|
||||
:where [:= :a :?x]}
|
||||
{:params {:x 42} :numbered true})
|
||||
;;=> ["SELECT * FROM table WHERE a = $1" 42]
|
||||
(sql/format {:select [:*] :from [:table]
|
||||
:where [:= :a [:param :x]]}
|
||||
{:params {:x 42} :numbered true})
|
||||
;;=> ["SELECT * FROM table WHERE a = $1" 42]
|
||||
```
|
||||
|
||||
## Functional Helpers
|
||||
|
||||
In addition to the hash map (and sequences) approach of building
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ All options may be omitted. The default behavior of each option is described in
|
|||
* `:checking` -- `:none` (default), `:basic`, or `:strict` to control the amount of lint-like checking that HoneySQL performs,
|
||||
* `:dialect` -- a keyword that identifies a dialect to be used for this specific call to `format`; the default is to use what was specified in `set-dialect!` or `:ansi` if no other dialect has been set,
|
||||
* `:inline` -- a Boolean indicating whether or not to inline parameter values, rather than use `?` placeholders and a sequence of parameter values; the default is `false` -- values are not inlined,
|
||||
* `:numbered` -- a Boolean indicating whether to generate numbered placeholders in the generated SQL (`$1`, `$2`, etc) or positional placeholders (`?`); the default is `false` (positional placeholders); this option was added in 2.4.next,
|
||||
* `:params` -- a hash map providing values for named parameters, identified by names (keywords or symbols) that start with `?` in the DSL; the default is that any such named parameters will have `nil` values,
|
||||
* `:quoted` -- a Boolean indicating whether or not to quote (strop) SQL entity names (table and column names); the default is `nil` -- alphanumeric SQL entity names are not quoted but (as of 2.3.928) "unusual" SQL entity names are quoted; a `false` value turns off all quoting,
|
||||
* `:quoted-snake` -- a Boolean indicating whether or not quoted and string SQL entity names should have `-` replaced by `_`; the default is `false` -- quoted and string SQL entity names are left exactly as-is,
|
||||
|
|
@ -29,6 +30,7 @@ global defaults of certain options:
|
|||
|
||||
* `:checking` -- can be `:basic` or `:strict`; specify `:none` to reset to the default,
|
||||
* `:inline` -- can be `true` but consider the security issues this causes by not using parameterized SQL statements; specify `false` (or `nil`) to reset to the default,
|
||||
* `:numbered` -- can be `true` or `false`; specify `false` to reset to the default,
|
||||
* `:quoted` -- can be `true` or `false`; specify `nil` to reset to the default; calling `set-dialect!` or providing a `:dialect` option to `format` will override the global default,
|
||||
* `:quoted-snake` -- can be `true`; specify `false` (or `nil`) to reset to the default.
|
||||
|
||||
|
|
@ -96,6 +98,13 @@ was wrapped in `[:inline `..`]`:
|
|||
|
||||
> Note: you can provide additional inline formatting by extending the `InlineValue` protocol from `honey.sql.protocols` to new types.
|
||||
|
||||
## `:numbered`
|
||||
|
||||
By default, HoneySQL generates SQL using positional placeholders (`?`).
|
||||
Specifying `:numbered true` tells HoneySQL to generate SQL using
|
||||
numbered placeholders instead (`$1`, `$2`, etc). This can be set
|
||||
globally using `set-options!`.
|
||||
|
||||
## `:params`
|
||||
|
||||
The `:params` option provides a mapping from named parameters
|
||||
|
|
|
|||
|
|
@ -10,6 +10,12 @@ Everything that the nilenso library provided (in 0.4.112) is implemented
|
|||
directly in HoneySQL 2.x although a few things have a
|
||||
slightly different syntax.
|
||||
|
||||
If you are using HoneySQL with the Node.js PostgreSQL driver, it
|
||||
only accepts numbered placeholders, not positional placeholders,
|
||||
so you will need to specify the `:numbered true` option that was
|
||||
added in 2.4.next. You may find it convenient to set this option
|
||||
globally, via `set-options!`.
|
||||
|
||||
## Code Examples
|
||||
|
||||
The code examples herein assume:
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@
|
|||
(def ^:private default-quoted-snake (atom nil))
|
||||
(def ^:private default-inline (atom nil))
|
||||
(def ^:private default-checking (atom :none))
|
||||
(def ^:private default-numbered (atom false))
|
||||
|
||||
(def ^:private ^:dynamic *dialect* nil)
|
||||
;; nil would be a better default but that makes testing individual
|
||||
|
|
@ -1667,7 +1668,10 @@
|
|||
([data opts]
|
||||
(let [cache (:cache opts)
|
||||
dialect? (contains? opts :dialect)
|
||||
dialect (when dialect? (get @dialects (check-dialect (:dialect opts))))]
|
||||
dialect (when dialect? (get @dialects (check-dialect (:dialect opts))))
|
||||
numbered (if (contains? opts :numbered)
|
||||
(:numbered opts)
|
||||
@default-numbered)]
|
||||
(binding [*dialect* (if dialect? dialect @default-dialect)
|
||||
*caching* cache
|
||||
*checking* (if (contains? opts :checking)
|
||||
|
|
@ -1681,7 +1685,7 @@
|
|||
*inline* (if (contains? opts :inline)
|
||||
(:inline opts)
|
||||
@default-inline)
|
||||
*numbered* (when (:numbered opts)
|
||||
*numbered* (when numbered
|
||||
(atom []))
|
||||
*quoted* (cond (contains? opts :quoted)
|
||||
(:quoted opts)
|
||||
|
|
@ -1722,11 +1726,12 @@
|
|||
"Set default values for any or all of the following options:
|
||||
* :checking
|
||||
* :inline
|
||||
* :numbered
|
||||
* :quoted
|
||||
* :quoted-snake
|
||||
Note that calling `set-dialect!` can override the default for `:quoted`."
|
||||
[opts]
|
||||
(let [unknowns (dissoc opts :checking :inline :quoted :quoted-snake)]
|
||||
(let [unknowns (dissoc opts :checking :inline :numbered :quoted :quoted-snake)]
|
||||
(when (seq unknowns)
|
||||
(throw (ex-info (str (str/join ", " (keys unknowns))
|
||||
" are not options that can be set globally.")
|
||||
|
|
@ -1734,11 +1739,13 @@
|
|||
(when (contains? opts :checking)
|
||||
(reset! default-checking (:checking opts)))
|
||||
(when (contains? opts :inline)
|
||||
(reset! default-checking (:inline opts)))
|
||||
(reset! default-inline (:inline opts)))
|
||||
(when (contains? opts :numbered)
|
||||
(reset! default-numbered (:numbered opts)))
|
||||
(when (contains? opts :quoted)
|
||||
(reset! default-checking (:quoted opts)))
|
||||
(reset! default-quoted (:quoted opts)))
|
||||
(when (contains? opts :quoted-snake)
|
||||
(reset! default-checking (:quoted-snake opts)))))
|
||||
(reset! default-quoted-snake (:quoted-snake opts)))))
|
||||
|
||||
(defn clause-order
|
||||
"Return the current order that known clauses will be applied when
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; copyright (c) 2020-2021 sean corfield, all rights reserved
|
||||
;; copyright (c) 2020-2022 sean corfield, all rights reserved
|
||||
|
||||
(ns honey.sql.helpers-test
|
||||
(:refer-clojure :exclude [filter for group-by partition-by set update])
|
||||
|
|
|
|||
Loading…
Reference in a new issue