Add :quoted-snake option

This commit is contained in:
Sean Corfield 2021-05-08 21:01:28 -07:00
parent 11fcfd5257
commit d73560b7e3
4 changed files with 47 additions and 34 deletions

View file

@ -1,5 +1,9 @@
# Changes # Changes
* 2.0.next in progress
* Add `:quoted-snake true` option to force conversion from kebab-case to snake_case when `:quoted true` or a `:dialect` is specified to `format`.
* TBD `%` function syntax may respect `:quoted true` or a `:dialect` is specified to `format` (awaiting PR).
* 2.0.0-rc1 (for testing; 2021-05-06) * 2.0.0-rc1 (for testing; 2021-05-06)
* Fix #324 so that `insert-into` supports merging into another statement in all cases. * Fix #324 so that `insert-into` supports merging into another statement in all cases.
* Fix #323 by supporting more than one SQL entity in `:on-conflict`. * Fix #323 by supporting more than one SQL entity in `:on-conflict`.

View file

@ -85,7 +85,7 @@ The `:quoting <dialect>` option has superseded by the new dialect machinery and
Identifiers are automatically quoted if you specify a `:dialect` option to `format`, unless you also specify `:quoted false`. Identifiers are automatically quoted if you specify a `:dialect` option to `format`, unless you also specify `:quoted false`.
The following options are no longer supported: 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). * `: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`. _[New in 2.0.next]_
* `:allow-namespaced-names?` -- this supported `foo/bar` column names in SQL which I'd like to discourage. * `: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`. * `: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).

View file

@ -100,6 +100,7 @@
;; functions harder than necessary: ;; functions harder than necessary:
(def ^:private ^:dynamic *clause-order* default-clause-order) (def ^:private ^:dynamic *clause-order* default-clause-order)
(def ^:private ^:dynamic *quoted* nil) (def ^:private ^:dynamic *quoted* nil)
(def ^:private ^:dynamic *quoted-snake* nil)
(def ^:private ^:dynamic *inline* nil) (def ^:private ^:dynamic *inline* nil)
(def ^:private ^:dynamic *params* nil) (def ^:private ^:dynamic *params* nil)
;; there is no way, currently, to enable suspicious characters ;; there is no way, currently, to enable suspicious characters
@ -165,21 +166,23 @@
return the equivalent SQL fragment (as a string -- no parameters). return the equivalent SQL fragment (as a string -- no parameters).
Handles quoting, splitting at / or ., replacing - with _ etc." Handles quoting, splitting at / or ., replacing - with _ etc."
[x & [{:keys [aliased drop-ns]}]] [e & [{:keys [aliased drop-ns]}]]
(let [nn (if (or *quoted* (string? x)) name name-_) (let [col-fn (if (or *quoted* (string? e))
q (if (or *quoted* (string? x)) (:quote *dialect*) identity) (if *quoted-snake* name-_ name)
[t c] (if-let [n (when-not (or drop-ns (string? x)) name-_)
(namespace-_ x))] quote-fn (if (or *quoted* (string? e)) (:quote *dialect*) identity)
[n (nn x)] [table col] (if-let [n (when-not (or drop-ns (string? e))
(namespace-_ e))]
[n (col-fn e)]
(if aliased (if aliased
[nil (nn x)] [nil (col-fn e)]
(let [[t c] (str/split (nn x) #"\.")] (let [[t c] (str/split (col-fn e) #"\.")]
(if c [t c] [nil t])))) (if c [t c] [nil t]))))
entity (cond->> c entity (cond->> col
(not= "*" c) (not= "*" col)
(q) (quote-fn)
t table
(str (q t) ".")) (str (quote-fn table) "."))
suspicious #";"] suspicious #";"]
(when-not *allow-suspicious-entities* (when-not *allow-suspicious-entities*
(when (re-find suspicious entity) (when (re-find suspicious entity)
@ -188,11 +191,15 @@
entity)) entity))
(comment (comment
(for [v [:foo-bar 'foo-bar "foo-bar" (for [v [:foo-bar "foo-bar" ; symbol is the same as keyword
:f-o.bar 'f-o.bar "f-o.bar"] :f-o.b-r :f-o/b-r]
a [true false] d [true false] q [true false]] a [true false] d [true false] q [true false]]
(binding [*dialect* (:mysql dialects) *quoted* q] (binding [*dialect* (:mysql dialects) *quoted* q]
(format-entity v :aliased a :drop-ns d))) (if q
[v a d (format-entity v {:aliased a :drop-ns d})
(binding [*quoted-snake* true]
(format-entity v {:aliased a :drop-ns d}))]
[v a d (format-entity v {:aliased a :drop-ns d})])))
.) .)
(defn- param-value [k] (defn- param-value [k]
@ -1253,6 +1260,8 @@
*quoted* (if (contains? opts :quoted) *quoted* (if (contains? opts :quoted)
(:quoted opts) (:quoted opts)
dialect?) dialect?)
*quoted-snake* (when (contains? opts :quoted-snake)
(:quoted-snake opts))
*params* (:params opts)] *params* (:params opts)]
(mapv #(unwrap % opts) (format-dsl data opts))))) (mapv #(unwrap % opts) (format-dsl data opts)))))
([data k v & {:as opts}] (format data (assoc opts k v)))) ([data k v & {:as opts}] (format data (assoc opts k v))))