Make params dynamic/implement in/not-in

This commit is contained in:
Sean Corfield 2021-01-31 05:08:21 -08:00
parent 1f4c4ff7ba
commit c92656389b

View file

@ -65,6 +65,7 @@
(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 *inline* nil) (def ^:private ^:dynamic *inline* nil)
(def ^:private ^:dynamic *params* nil)
;; clause helpers ;; clause helpers
@ -108,12 +109,12 @@
(defn- ->param [k] (defn- ->param [k]
(with-meta (constantly k) (with-meta (constantly k)
{::wrapper {::wrapper
(fn [fk {:keys [params]}] (fn [fk _]
(let [k (fk)] (let [k (fk)]
(if (contains? params k) (if (contains? *params* k)
(get params k) (get *params* k)
(throw (ex-info (str "missing parameter value for " k) (throw (ex-info (str "missing parameter value for " k)
{:params (keys params)})))))})) {:params (keys *params*)})))))}))
(defn- format-var [x & [opts]] (defn- format-var [x & [opts]]
(let [c (name-_ x)] (let [c (name-_ x)]
@ -464,7 +465,7 @@
(def ^:private infix-ops (def ^:private infix-ops
(-> #{"mod" "and" "or" "xor" "<>" "<=" ">=" "||" (-> #{"mod" "and" "or" "xor" "<>" "<=" ">=" "||"
"in" "not-in" "like" "not-like" "regexp" "like" "not-like" "regexp"
"ilike" "not-ilike" "similar-to" "not-similar-to" "ilike" "not-ilike" "similar-to" "not-similar-to"
"is" "is-not" "not=" "!=" "regex"} "is" "is-not" "not=" "!=" "regex"}
(into (map str "+-*%|&^=<>")) (into (map str "+-*%|&^=<>"))
@ -485,6 +486,26 @@
(keyword? x) (sql-kw x) (keyword? x) (sql-kw x)
:else (str x))) :else (str x)))
(defn- unwrap [x opts]
(if-let [m (meta x)]
(if-let [f (::wrapper m)]
(f x opts)
x)
x))
(defn- format-in [in [x y]]
(let [[sql-x & params-x] (format-expr x {:nested? true})
[sql-y & params-y] (format-expr y {:nested? true})
values (unwrap (first params-y) {})]
(if (and (= "?" sql-y) (= 1 (count params-y)) (coll? values))
(let [sql (str "(" (str/join ", " (repeat (count values) "?")) ")")]
(-> [(str sql-x " " (sql-kw in) " " sql)]
(into params-x)
(into values)))
(-> [(str sql-x " " (sql-kw in) " " sql-y)]
(into params-x)
(into params-y)))))
(def ^:private special-syntax (def ^:private special-syntax
(atom (atom
{:array {:array
@ -618,6 +639,9 @@
(vector) (vector)
(into p1) (into p1)
(into p2))))) (into p2)))))
(contains? #{:in :not-in} op)
(let [[sql & params] (format-in op (rest x))]
(into [(if nested? (str "(" sql ")") sql)] params))
(contains? @special-syntax op) (contains? @special-syntax op)
(let [formatter (get @special-syntax op)] (let [formatter (get @special-syntax op)]
(formatter op (rest x))) (formatter op (rest x)))
@ -651,13 +675,6 @@
{:valid-dialects (vec (sort (keys dialects)))}))) {:valid-dialects (vec (sort (keys dialects)))})))
dialect) dialect)
(defn- unwrap [x opts]
(if-let [m (meta x)]
(if-let [f (::wrapper m)]
(f x opts)
x)
x))
(defn format (defn format
"Turn the data DSL into a vector containing a SQL string followed by "Turn the data DSL into a vector containing a SQL string followed by
any parameter values that were encountered in the DSL structure." any parameter values that were encountered in the DSL structure."
@ -675,7 +692,8 @@
(:inline opts)) (:inline opts))
*quoted* (if (contains? opts :quoted) *quoted* (if (contains? opts :quoted)
(:quoted opts) (:quoted opts)
dialect?)] dialect?)
*params* (:params opts)]
(mapv #(unwrap % opts) (format-dsl data opts)))))) (mapv #(unwrap % opts) (format-dsl data opts))))))
(defn set-dialect! (defn set-dialect!