Proposed opt quoted-when

Proposing a new option, quoted-when, to allow overriding the default
opinionated quoting when quoting has been disabled.

This can be useful, for example, if a user wants to selectively quote
fields like only quoting reserved words.
This commit is contained in:
Kristofer Ranstrom 2023-11-14 14:31:58 -05:00
parent 18fcddfc34
commit 64e6d338cc
No known key found for this signature in database
GPG key ID: A490C829075F837C
3 changed files with 18 additions and 4 deletions

View file

@ -22,6 +22,7 @@ All options may be omitted. The default behavior of each option is described in
* `: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.962,
* `: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-when` -- a function overriding the default behavior of when to quote entities when `:quoted false` (default). Function should take single argument - the entity/part being quoted - and return a boolean indicator whether to quote it or not.
* `: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,
* `:values-default-columns` -- a sequence of column names that should have `DEFAULT` values instead of `NULL` values if used in a `VALUES` clause with no associated matching value in the hash maps passed in; the default behavior is for such missing columns to be given `NULL` values.

View file

@ -120,6 +120,7 @@
; should become defonce
(def ^:private default-dialect (atom (:ansi @dialects)))
(def ^:private default-quoted (atom nil))
(def ^:private default-quoted-when (atom nil))
(def ^:private default-quoted-snake (atom nil))
(def ^:private default-inline (atom nil))
(def ^:private default-checking (atom :none))
@ -130,6 +131,7 @@
;; functions harder than necessary:
(def ^:private ^:dynamic *clause-order* default-clause-order)
(def ^:private ^:dynamic *quoted* @default-quoted)
(def ^:private ^:dynamic *quoted-when* @default-quoted-when)
(def ^:private ^:dynamic *quoted-snake* @default-quoted-snake)
(def ^:private ^:dynamic *inline* @default-inline)
(def ^:private ^:dynamic *params* nil)
@ -265,9 +267,10 @@
;; characters in entity, then quote it:
(nil? *quoted*)
(fn opt-quote [part]
(if (re-find #"^[A-Za-z0-9_]+$" part)
part
(dialect-q part)))
(let [quote? (or *quoted-when* #(not (re-find #"^[A-Za-z0-9_]+$" %)))]
(if (quote? part)
(dialect-q part)
part)))
:else
identity)
parts-fn (or (:parts-fn *dialect*)
@ -2031,6 +2034,9 @@
true
:else
@default-quoted)
*quoted-when* (if (contains? opts :quoted-when)
(:quoted-when opts)
@default-quoted-when)
*quoted-snake* (if (contains? opts :quoted-snake)
(:quoted-snake opts)
@default-quoted-snake)
@ -2073,10 +2079,11 @@
* :inline
* :numbered
* :quoted
* :quoted-when
* :quoted-snake
Note that calling `set-dialect!` can override the default for `:quoted`."
[opts]
(let [unknowns (dissoc opts :checking :inline :numbered :quoted :quoted-snake)]
(let [unknowns (dissoc opts :checking :inline :numbered :quoted :quoted-when :quoted-snake)]
(when (seq unknowns)
(throw (ex-info (str (str/join ", " (keys unknowns))
" are not options that can be set globally.")
@ -2089,6 +2096,8 @@
(reset! default-numbered (:numbered opts)))
(when (contains? opts :quoted)
(reset! default-quoted (:quoted opts)))
(when (contains? opts :quoted-when)
(reset! default-quoted-when (:quoted-when opts)))
(when (contains? opts :quoted-snake)
(reset! default-quoted-snake (:quoted-snake opts)))))

View file

@ -263,6 +263,10 @@
(sql/format {:select [:foo [[:cast :bar [:char 10]]]]} {:dialect :mysql
:inline true}))))
(deftest test-quoting
(is (= ["SELECT foo, \"bar\""]
(sql/format {:select [:foo :bar]} {:quoted-when #(some #{%} ["bar"])})))) ;; Example showing only quoting reserved words
(deftest test-value
(is (= ["INSERT INTO foo (bar) VALUES (?)" {:baz "my-val"}]
(->