multimethod for extensible sql fn handlers

This commit is contained in:
Justin Kramer 2012-08-16 15:55:50 -04:00
parent 6438c04486
commit c9e3503263

View file

@ -39,19 +39,28 @@
"!=" "<>" "!=" "<>"
"not-in" "not in"}) "not-in" "not in"})
(def fn-handlers (defmulti fn-handler (fn [op & args] op))
{"=" (fn [f1 f2]
(cond (defmethod fn-handler :default [op & args]
(= "NULL" f1) (str f2 " IS NULL") (let [op-upper (string/upper-case op)]
(= "NULL" f2) (str f1 " IS NULL") (if (infix-fns op)
:else (str f1 " = " f2))) (paren-wrap (string/join (str " " op-upper " ") args))
"<>" (fn [f1 f2] (str op-upper (paren-wrap (comma-join args))))))
(cond
(= "NULL" f1) (str f2 " IS NOT NULL") (defmethod fn-handler "=" [_ f1 f2]
(= "NULL" f2) (str f1 " IS NOT NULL") (cond
:else (str f1 " <> " f2))) (= "NULL" f1) (str f2 " IS NULL")
"between" (fn [field upper lower] (= "NULL" f2) (str f1 " IS NULL")
(str field " BETWEEN " upper " AND " lower))}) :else (str f1 " = " f2)))
(defmethod fn-handler "<>" [_ f1 f2]
(cond
(= "NULL" f1) (str f2 " IS NOT NULL")
(= "NULL" f2) (str f1 " IS NOT NULL")
:else (str f1 " <> " f2)))
(defmethod fn-handler "between" [_ field lower upper]
(str field " BETWEEN " lower " AND " upper))
(def clause-order (def clause-order
"Determines the order that clauses will be placed within generated SQL" "Determines the order that clauses will be placed within generated SQL"
@ -99,13 +108,8 @@
(-to-sql [x] (binding [*fn-context?* true] (-to-sql [x] (binding [*fn-context?* true]
(let [fn-name (name (.name x)) (let [fn-name (name (.name x))
fn-name (fn-aliases fn-name fn-name) fn-name (fn-aliases fn-name fn-name)
fn-name-upper (string/upper-case fn-name)
args (map to-sql (.args x))] args (map to-sql (.args x))]
(if-let [handler (fn-handlers fn-name)] (apply fn-handler fn-name args))))
(apply handler args)
(if (infix-fns fn-name)
(paren-wrap (string/join (str " " fn-name-upper " ") args))
(str fn-name-upper (paren-wrap (comma-join args))))))))
SqlRaw SqlRaw
(-to-sql [x] (.s x)) (-to-sql [x] (.s x))
clojure.lang.IPersistentMap clojure.lang.IPersistentMap