Convert seq param values to literal sql param lists

This allows seqs to be used as param values, e.g. for IN clauses. It
also converts sets to seqs for the same purpose.

It does not expand the parameter name when this occurs, which will lead
to a mismatch between the *param-names* and *params* collections. It is
not clear how *param-names* are intended to be used, so I have no better
fix to suggest other than repeating a seq's param name the corresponding
number of times into that collection.
This commit is contained in:
Donald Ball 2015-04-21 14:28:28 -04:00
parent 2820662f59
commit 4bdaae39af
3 changed files with 44 additions and 3 deletions

View file

@ -1,5 +1,6 @@
## 0.5.3 In development
* Convert seq param values to literal sql param lists (@dball)
* Apply seq to sets when converting to sql (@dball)
* Support locking selects (@dball)
* Add sql array type and reader literal (@loganmhb)

View file

@ -248,10 +248,24 @@
(into [sql-str] @*params*)
[sql-str]))))
(defprotocol Parameterizable
(to-params [value]))
(extend-protocol Parameterizable
clojure.lang.Sequential
(to-params [value]
(paren-wrap (comma-join (mapv to-params value))))
clojure.lang.IPersistentSet
(to-params [value]
(to-params (seq value)))
java.lang.Object
(to-params [value]
(swap! *params* conj value)
(*parameterizer*)))
(defn add-param [pname pval]
(swap! *param-names* conj pname)
(swap! *params* conj pval)
(*parameterizer*))
(to-params pval))
;; Anonymous param name -- :_1, :_2, etc.
(defn add-anon-param [pval]

View file

@ -89,4 +89,30 @@
(is (= ["SELECT * FROM customers WHERE (id in (1))"]
(sql/format {:select [:*]
:from [:customers]
:where [:in :id values]}))))))))
:where [:in :id values]})))
(is (= ["SELECT * FROM customers WHERE (id in (?))" 1]
(sql/format {:select [:*]
:from [:customers]
:where [:in :id :?ids]}
{:ids values}))))))
(testing "with more than one integer"
(let [values [1 2]]
(is (= ["SELECT * FROM customers WHERE (id in (1, 2))"]
(sql/format {:select [:*]
:from [:customers]
:where [:in :id values]})))
(is (= ["SELECT * FROM customers WHERE (id in (?, ?))" 1 2]
(sql/format {:select [:*]
:from [:customers]
:where [:in :id :?ids]}
{:ids values})))))
(testing "with more than one string"
(let [values ["1" "2"]]
(is (= ["SELECT * FROM customers WHERE (id in (?, ?))" "1" "2"]
(sql/format {:select [:*]
:from [:customers]
:where [:in :id values]})
(sql/format {:select [:*]
:from [:customers]
:where [:in :id :?ids]}
{:ids values})))))))