From 0052aade7c9ff42dfc741be7e525e325996a2aba Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 25 Sep 2020 16:40:15 -0700 Subject: [PATCH] Implement variadic and/or/+/* --- src/honey/sql.cljc | 58 +++++++++++++++++++++++++++------------- test/honey/sql_test.cljc | 2 ++ 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/honey/sql.cljc b/src/honey/sql.cljc index 0dd9e73..1486441 100644 --- a/src/honey/sql.cljc +++ b/src/honey/sql.cljc @@ -458,27 +458,47 @@ (format-dsl x (assoc opts :nested? true)) (sequential? x) - (let [op (first x)] + (let [op (first x) + op-ignore-nil #{:and :or} + op-variadic #{:and :or :+ :*}] (if (keyword? op) (cond (infix-ops op) - (let [[_ a b] x - [s1 & p1] (format-expr a {:nested? true}) - [s2 & p2] (format-expr b {:nested? true}) - op (get infix-aliases op op)] - (if (and (#{:= :<>} op) (or (nil? a) (nil? b))) - (-> (str (if (nil? a) - (if (nil? b) "NULL" s2) - s1) - (if (= := op) " IS NULL" " IS NOT NULL")) - (cond-> nested? - (as-> s (str "(" s ")"))) - (vector)) - (-> (str s1 " " (sql-kw op) " " s2) - (cond-> nested? - (as-> s (str "(" s ")"))) - (vector) - (into p1) - (into p2)))) + (if (op-variadic op) ; no aliases here, no special semantics + (let [x (if (op-ignore-nil op) (remove nil? x) x) + [sqls params] + (reduce (fn [[sql params] [sql' & params']] + [(conj sql sql') + (if params' (into params params') params)]) + [[] []] + (map #(format-expr % {:nested? true}) + (rest x)))] + (into [(cond-> (str/join (str " " (sql-kw op) " ") sqls) + nested? + (as-> s (str "(" s ")")))] + params)) + (let [[_ a b & y] x + _ (when (seq y) + (throw (ex-info (str "only binary " + op + "is supported") + {:expr x}))) + [s1 & p1] (format-expr a {:nested? true}) + [s2 & p2] (format-expr b {:nested? true}) + op (get infix-aliases op op)] + (if (and (#{:= :<>} op) (or (nil? a) (nil? b))) + (-> (str (if (nil? a) + (if (nil? b) "NULL" s2) + s1) + (if (= := op) " IS NULL" " IS NOT NULL")) + (cond-> nested? + (as-> s (str "(" s ")"))) + (vector)) + (-> (str s1 " " (sql-kw op) " " s2) + (cond-> nested? + (as-> s (str "(" s ")"))) + (vector) + (into p1) + (into p2))))) (special-syntax op) (let [formatter (special-syntax op)] (formatter (rest x))) diff --git a/test/honey/sql_test.cljc b/test/honey/sql_test.cljc index 24e37c1..aa920e9 100644 --- a/test/honey/sql_test.cljc +++ b/test/honey/sql_test.cljc @@ -33,6 +33,8 @@ (sut/format-expr [:+ :id 1]))) (is (= ["? + (? + quux)" 1 1] (sut/format-expr [:+ 1 [:+ 1 :quux]]))) + (is (= ["? + ? + quux" 1 1] + (sut/format-expr [:+ 1 1 :quux]))) (is (= ["FOO(BAR(? + G(abc)), F(?, quux))" 2 1] (sut/format-expr [:foo [:bar [:+ 2 [:g :abc]]] [:f 1 :quux]]))) (is (= ["id"]