Implement variadic and/or/+/*

This commit is contained in:
Sean Corfield 2020-09-25 16:40:15 -07:00
parent 5449c23ede
commit 0052aade7c
2 changed files with 41 additions and 19 deletions

View file

@ -458,27 +458,47 @@
(format-dsl x (assoc opts :nested? true)) (format-dsl x (assoc opts :nested? true))
(sequential? x) (sequential? x)
(let [op (first x)] (let [op (first x)
op-ignore-nil #{:and :or}
op-variadic #{:and :or :+ :*}]
(if (keyword? op) (if (keyword? op)
(cond (infix-ops op) (cond (infix-ops op)
(let [[_ a b] x (if (op-variadic op) ; no aliases here, no special semantics
[s1 & p1] (format-expr a {:nested? true}) (let [x (if (op-ignore-nil op) (remove nil? x) x)
[s2 & p2] (format-expr b {:nested? true}) [sqls params]
op (get infix-aliases op op)] (reduce (fn [[sql params] [sql' & params']]
(if (and (#{:= :<>} op) (or (nil? a) (nil? b))) [(conj sql sql')
(-> (str (if (nil? a) (if params' (into params params') params)])
(if (nil? b) "NULL" s2) [[] []]
s1) (map #(format-expr % {:nested? true})
(if (= := op) " IS NULL" " IS NOT NULL")) (rest x)))]
(cond-> nested? (into [(cond-> (str/join (str " " (sql-kw op) " ") sqls)
(as-> s (str "(" s ")"))) nested?
(vector)) (as-> s (str "(" s ")")))]
(-> (str s1 " " (sql-kw op) " " s2) params))
(cond-> nested? (let [[_ a b & y] x
(as-> s (str "(" s ")"))) _ (when (seq y)
(vector) (throw (ex-info (str "only binary "
(into p1) op
(into p2)))) "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) (special-syntax op)
(let [formatter (special-syntax op)] (let [formatter (special-syntax op)]
(formatter (rest x))) (formatter (rest x)))

View file

@ -33,6 +33,8 @@
(sut/format-expr [:+ :id 1]))) (sut/format-expr [:+ :id 1])))
(is (= ["? + (? + quux)" 1 1] (is (= ["? + (? + quux)" 1 1]
(sut/format-expr [:+ 1 [:+ 1 :quux]]))) (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] (is (= ["FOO(BAR(? + G(abc)), F(?, quux))" 2 1]
(sut/format-expr [:foo [:bar [:+ 2 [:g :abc]]] [:f 1 :quux]]))) (sut/format-expr [:foo [:bar [:+ 2 [:g :abc]]] [:f 1 :quux]])))
(is (= ["id"] (is (= ["id"]