diff options
Diffstat (limited to 'src/clojure_sql/compiler.clj')
-rw-r--r-- | src/clojure_sql/compiler.clj | 74 |
1 files changed, 53 insertions, 21 deletions
diff --git a/src/clojure_sql/compiler.clj b/src/clojure_sql/compiler.clj index 6f940c0..60a5530 100644 --- a/src/clojure_sql/compiler.clj +++ b/src/clojure_sql/compiler.clj @@ -50,18 +50,27 @@ ;; ============================================================== ;; compile-* multimethods are of the signature: -;; (db, expr) -> (fn [s] [sql]) +;; (db, expr) -> [args] -> [sql & args] (declare compile-query compile-expression) -(defmulti compile-expression-sequential (fn [db ex])) +(defmulti compile-expression-list (fn [db _] db)) +(defmethod compile-expression-list :default [db ex] + (->> (map (partial compile-expression db) ex) + (apply sequence) + ((p-lift string/join ",")) + $add-parentheses)) + +(defmulti compile-expression-sequential (fn [db _] db)) (defmethod compile-expression-sequential :default [db ex] (let [compile-exprs #(map (partial compile-expression db) %) op (name (first ex)) num-args (dec (count ex))] (-> (condp u/funcall (first ex) quote? (do (assert (= num-args 1) "`quote` must only take one argument") - (>> (tell (second ex)) (return "?"))) + (if (sequential? (second ex)) + (compile-expression-list db (second ex)) + (>> (tell (second ex)) (return "?")))) unary? (do (assert (= num-args 1) (str "Unary operator `" op "` must take one argument")) (do-m :let [exprs (compile-exprs ex)] vals <- (apply sequence exprs) @@ -120,28 +129,33 @@ (def ^:private join-type-names {:inner "INNER" - :left "LEFT OUTER" - :right "RIGHT OUTER" - :outer "FULL OUTER" + :outer "LEFT OUTER" + :full-outer "FULL OUTER" :cross "CROSS"}) (defmulti compile-tables (fn [db _ _] db)) -(defmethod compile-tables :default [db join tables-map] - (if (vector? join) +(defmethod compile-tables :default [db join tables-map] + (if (vector? join) (->> (for [table-alias join] (make-table-name db (get tables-map table-alias) table-alias)) (apply sequence) ((p-lift string/join ", "))) (let [{:keys [left right type on]} join] - ($str (return "(") - (compile-tables db left tables-map) - (return (str " " (get join-type-names type (name type)) " JOIN ")) - (compile-tables db right tables-map) - (if on - ($str (return " ON ") - (compile-expression db on)) - (return "")) - (return ")"))))) + (if (= type :cross) + ($str (return "(") + (compile-tables db left tables-map) + (return " CROSS JOIN ") + (compile-tables db right tables-map) + (return ")")) + ($str (return "(") + (compile-tables db left tables-map) + (return (str " " (get join-type-names type (name type)) " JOIN ")) + (compile-tables db right tables-map) + (return " ON ") + (if on + (compile-expression db on) + (return "TRUE")) + (return ")")))))) (defmulti compile-where (fn [db _] db)) (defmethod compile-where :default [db expr] @@ -149,8 +163,8 @@ ($str (return " WHERE ") (compile-expression db expr)) (return nil))) -(defmulti compile-sort-by (fn [db _] db)) -(defmethod compile-sort-by :default [db fields] +(defmulti compile-sort (fn [db _] db)) +(defmethod compile-sort :default [db fields] (if fields (->> (for [[[table field] dir] fields] ($str (make-field-name db [table field]) @@ -160,8 +174,24 @@ ($str (return " ORDER BY "))) (return nil))) +(defmulti compile-group (fn [db _] db)) +(defmethod compile-group :default [db fields] + (if fields + (->> (for [[table field] fields] + (make-field-name db [table field])) + (apply sequence) + ((p-lift string/join ",")) + ($str (return " GROUP BY "))) + (return nil))) + +(defmulti compile-having (fn [db _] db)) +(defmethod compile-having :default [db expr] + (if expr + ($str (return " HAVING ") (compile-expression db expr)) + (return nil))) + (defmulti compile-query (fn [db _] db)) -(defmethod compile-query :default [db {:keys [tables fields joins where sort-by]}] +(defmethod compile-query :default [db {:keys [tables fields joins where sort group having]}] ($str (return "SELECT ") (compile-fields db fields) (if tables @@ -169,7 +199,9 @@ (compile-tables db joins tables)) ($str "")) (compile-where db where) - (compile-sort-by db sort-by))) + (compile-group db group) + (compile-having db having) + (compile-sort db sort))) |