diff --git a/src/honey/sql.cljc b/src/honey/sql.cljc index c783d3f..633cea4 100644 --- a/src/honey/sql.cljc +++ b/src/honey/sql.cljc @@ -64,6 +64,7 @@ ;; functions harder than necessary: (def ^:private ^:dynamic *clause-order* default-clause-order) (def ^:private ^:dynamic *quoted* nil) +(def ^:private ^:dynamic *inline* nil) ;; clause helpers @@ -613,9 +614,9 @@ (str " " (first sqls)) (str "(" (str/join ", " sqls) ")")))] params))) - (into [(str "(" (str/join ", " - (repeat (count x) "?")) ")")] - x))) + (if *inline* + [(str "(" (str/join ", " (map #'sqlize-value x)) ")")] + (into [(str "(" (str/join ", " (repeat (count x) "?")) ")")] x)))) (or (true? x) (false? x)) ; because (boolean? x) requires Clojure 1.9+ [(upper-case (str x))] @@ -624,7 +625,9 @@ ["NULL"] :else - ["?" x])) + (if *inline* + [(sqlize-value x)] + ["?" x]))) (defn- check-dialect [dialect] (when-not (contains? dialects dialect) @@ -652,6 +655,8 @@ (f @base-clause-order) @current-clause-order) @current-clause-order) + *inline* (when (contains? opts :inline) + (:inline opts)) *quoted* (if (contains? opts :quoted) (:quoted opts) dialect?)] @@ -736,11 +741,18 @@ (format {:select [:*] :from [:table] :group-by [:foo :bar]} {}) (format {:select [:*] :from [:table] :group-by [[:date :bar]]} {}) (format {:select [:*] :from [:table] :order-by [[:foo :desc] :bar]} {}) - (format {:select [:*] :from [:table] :order-by [[[:date :expiry] :desc] :bar]} {}) - (println (format {:select [:*] :from [:table] :order-by [[[:date :expiry] :desc] :bar]} {:pretty? true})) - (format {:select [:*] :from [:table] :where [:< [:date_add :expiry [:interval 30 :days]] [:now]]} {}) + (format {:select [:*] :from [:table] + :order-by [[[:date :expiry] :desc] :bar]} {}) + (println (format {:select [:*] :from [:table] + :order-by [[[:date :expiry] :desc] :bar]} {:pretty? true})) + (format {:select [:*] :from [:table] + :where [:< [:date_add :expiry [:interval 30 :days]] [:now]]} {}) (format-expr [:interval 30 :days]) - (format {:select [:*] :from [:table] :where [:= :id (int 1)]} {:dialect :mysql}) - (map fn? (format {:select [:*] :from [:table] :where [:= :id (with-meta (constantly 42) {:foo true})]} {:dialect :mysql})) - (println (format {:select [:*] :from [:table] :where [:in :id [1 2 3 4]]} {:pretty? true})) + (format {:select [:*] :from [:table] + :where [:= :id (int 1)]} {:dialect :mysql}) + (map fn? (format {:select [:*] :from [:table] + :where [:= :id (with-meta (constantly 42) {:foo true})]} + {:dialect :mysql})) + (println (format {:select [:*] :from [:table] + :where [:in :id [1 2 3 4]]} {:pretty? true})) ,) diff --git a/test/honey/sql_test.cljc b/test/honey/sql_test.cljc index 5adf001..431be52 100644 --- a/test/honey/sql_test.cljc +++ b/test/honey/sql_test.cljc @@ -248,11 +248,11 @@ ["WITH bar (spam, eggs) AS (VALUES (?, ?), (?, ?), (?, ?)) (SELECT foo FROM bar1) UNION ALL (SELECT foo FROM bar2)" 1 2 3 4 5 6]))) (deftest parameterizer-none - (testing "array parameter -- fail: parameterizer" + (testing "array parameter" (is (= (format {:insert-into :foo :columns [:baz] :values [[[:array [1 2 3 4]]]]} - {:parameterizer :none}) + {:inline true}) ["INSERT INTO foo (baz) VALUES (ARRAY[1, 2, 3, 4])"]))) (testing "union complex values -- fail: parameterizer" @@ -260,7 +260,7 @@ {:select [:foo] :from [:bar2]}] :with [[[:bar {:columns [:spam :eggs]}] {:values [[1 2] [3 4] [5 6]]}]]} - {:parameterizer :none}) + {:inline true}) ["WITH bar (spam, eggs) AS (VALUES (1, 2), (3, 4), (5, 6)) (SELECT foo FROM bar1) UNION (SELECT foo FROM bar2)"])))) (deftest inline-was-parameterizer-none @@ -280,27 +280,25 @@ [[1 2] [3 4] [5 6]])}]]}) ["WITH bar (spam, eggs) AS (VALUES (1, 2), (3, 4), (5, 6)) (SELECT foo FROM bar1) UNION (SELECT foo FROM bar2)"])))) -#_(defmethod parameterize :single-quote [_ value pname] (str \' value \')) -#_(defmethod parameterize :mysql-fill [_ value pname] "?") - (deftest former-parameterizer-tests-where-and - (testing "should ignore a nil predicate -- fail: postgresql parameterizer" - (is (= (format {:where [:and - [:= :foo "foo"] - [:= :bar "bar"] - nil - [:= :quux "quux"]]} - {:parameterizer :postgresql}) - ["WHERE (foo = ?) AND (bar = $2) AND (quux = $3)" "foo" "bar" "quux"]))) - ;; this is _almost_ what :inline should be doing: - #_(testing "should fill param with single quote" + ;; I have no plans for positional parameters -- I just don't see the point + #_(testing "should ignore a nil predicate -- fail: postgresql parameterizer" (is (= (format {:where [:and [:= :foo "foo"] [:= :bar "bar"] nil [:= :quux "quux"]]} - {:parameterizer :single-quote}) - ["WHERE (foo = 'foo') AND (bar = 'bar') AND (quux = 'quux')" "foo" "bar" "quux"]))) + {:parameterizer :postgresql}) + ["WHERE (foo = ?) AND (bar = $2) AND (quux = $3)" "foo" "bar" "quux"]))) + ;; new :inline option is similar to :parameterizer :none in 1.0 + (testing "should fill param with single quote" + (is (= (format {:where [:and + [:= :foo "foo"] + [:= :bar "bar"] + nil + [:= :quux "quux"]]} + {:inline true}) + ["WHERE (foo = 'foo') AND (bar = 'bar') AND (quux = 'quux')"]))) (testing "should inline params with single quote" (is (= (format {:where [:and [:= :foo [:inline "foo"]]