From 4bdaae39afc02e8f92ff0c3e691eb13c81aac36a Mon Sep 17 00:00:00 2001 From: Donald Ball Date: Tue, 21 Apr 2015 14:28:28 -0400 Subject: [PATCH] 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. --- CHANGES.md | 1 + src/honeysql/format.clj | 18 ++++++++++++++++-- test/honeysql/core_test.clj | 28 +++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 08fb39f..f61278e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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) diff --git a/src/honeysql/format.clj b/src/honeysql/format.clj index 4687013..99f5f8b 100644 --- a/src/honeysql/format.clj +++ b/src/honeysql/format.clj @@ -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] diff --git a/test/honeysql/core_test.clj b/test/honeysql/core_test.clj index 235586e..9545bb7 100644 --- a/test/honeysql/core_test.clj +++ b/test/honeysql/core_test.clj @@ -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})))))))