diff --git a/README.md b/README.md index 4657971..5a37ea0 100644 --- a/README.md +++ b/README.md @@ -459,9 +459,8 @@ Here's a big, complicated query. Note that Honey SQL makes no attempt to verify ```clojure (def big-complicated-map - (-> (select :f.* :b.baz :c.quux [:b.bla "bla-bla"] - [[:now]] [[:raw "@x := 10"]]) - #_(modifiers :distinct) ; this is not implemented yet + (-> (select-distinct :f.* :b.baz :c.quux [:b.bla "bla-bla"] + [[:now]] [[:raw "@x := 10"]]) (from [:foo :f] [:baz :b]) (join :draq [:= :f.b :draq.x]) (left-join [:clod :c] [:= :f.a :c.d]) @@ -479,9 +478,8 @@ Here's a big, complicated query. Note that Honey SQL makes no attempt to verify ``` ```clojure big-complicated-map -=> {:select [:f.* :b.baz :c.quux [:b.bla "bla-bla"] - [[:now]] [[:raw "@x := 10"]]] - :modifiers [:distinct] +=> {:select-distinct [:f.* :b.baz :c.quux [:b.bla "bla-bla"] + [[:now]] [[:raw "@x := 10"]]] :from [[:foo :f] [:baz :b]] :join [:draq [:= :f.b :draq.x]] :left-join [[:clod :c] [:= :f.a :c.d]] diff --git a/src/honey/sql.cljc b/src/honey/sql.cljc index 1d3511f..06f06a7 100644 --- a/src/honey/sql.cljc +++ b/src/honey/sql.cljc @@ -17,7 +17,7 @@ (def ^:private default-clause-order "The (default) order for known clauses. Can have items added and removed." [:nest :with :with-recursive :intersect :union :union-all :except :except-all - :select :insert-into :update :delete :delete-from :truncate + :select :select-distinct :insert-into :update :delete :delete-from :truncate :columns :composite :set :from :join :left-join :right-join :inner-join :outer-join :full-join :cross-join @@ -362,44 +362,45 @@ (def ^:private clause-format "The (default) behavior for each known clause. Can also have items added and removed." - (atom {:nest (fn [_ x] (format-expr x)) - :with #'format-with - :with-recursive #'format-with - :intersect #'format-on-set-op - :union #'format-on-set-op - :union-all #'format-on-set-op - :except #'format-on-set-op - :except-all #'format-on-set-op - :select #'format-selects - :insert-into #'format-insert - :update #'format-selector - :delete #'format-selects - :delete-from #'format-selector - :truncate #'format-selector - :columns #'format-columns - :composite #'format-columns - :set #'format-set-exprs - :from #'format-selects - :join #'format-join - :left-join #'format-join - :right-join #'format-join - :inner-join #'format-join - :outer-join #'format-join - :full-join #'format-join - :cross-join #'format-selects - :where #'format-on-expr - :group-by #'format-group-by - :having #'format-on-expr - :order-by #'format-order-by - :limit #'format-on-expr - :offset #'format-on-expr - :for #'format-lock-strength - :values #'format-values - :on-conflict #'format-on-conflict - :on-constraint #'format-selector - :do-nothing (fn [k _] (vector (sql-kw k))) - :do-update-set #'format-do-update-set - :returning #'format-selects})) + (atom {:nest (fn [_ x] (format-expr x)) + :with #'format-with + :with-recursive #'format-with + :intersect #'format-on-set-op + :union #'format-on-set-op + :union-all #'format-on-set-op + :except #'format-on-set-op + :except-all #'format-on-set-op + :select #'format-selects + :select-distinct #'format-selects + :insert-into #'format-insert + :update #'format-selector + :delete #'format-selects + :delete-from #'format-selector + :truncate #'format-selector + :columns #'format-columns + :composite #'format-columns + :set #'format-set-exprs + :from #'format-selects + :join #'format-join + :left-join #'format-join + :right-join #'format-join + :inner-join #'format-join + :outer-join #'format-join + :full-join #'format-join + :cross-join #'format-selects + :where #'format-on-expr + :group-by #'format-group-by + :having #'format-on-expr + :order-by #'format-order-by + :limit #'format-on-expr + :offset #'format-on-expr + :for #'format-lock-strength + :values #'format-values + :on-conflict #'format-on-conflict + :on-constraint #'format-selector + :do-nothing (fn [k _] (vector (sql-kw k))) + :do-update-set #'format-do-update-set + :returning #'format-selects})) (assert (= (set @base-clause-order) (set @current-clause-order) diff --git a/src/honey/sql/helpers.cljc b/src/honey/sql/helpers.cljc index 8986639..21641bf 100644 --- a/src/honey/sql/helpers.cljc +++ b/src/honey/sql/helpers.cljc @@ -8,13 +8,19 @@ (defn- default-merge [current args] (into (vec current) args)) +(defn- and-merge + [current args] + (let [merged (default-merge current args)] + (cond (= 1 (count merged)) + (vec (first merged)) + (= :and (first merged)) + merged + :else + (into [:and] merged)))) + (def ^:private special-merges - {:where (fn [current args] - (if (= :and (first (first args))) - (default-merge current args) - (-> [:and] - (into current) - (into args))))}) + {:where #'and-merge + :having #'and-merge}) (defn- helper-merge [data k args] (let [merge-fn (special-merges k default-merge)] @@ -26,6 +32,11 @@ (helper-merge data k args)) (helper-merge {} k args))) +(defn- generic-1 [k [data arg]] + (if (map? data) + (assoc data k arg) + (assoc {} k data))) + (defn nest [& args] (generic :nest args)) (defn with [& args] (generic :with args)) (defn with-recursive [& args] (generic :with-recursive args)) @@ -35,6 +46,7 @@ (defn except [& args] (generic :except args)) (defn except-all [& args] (generic :except-all args)) (defn select [& args] (generic :select args)) +(defn select-distinct [& args] (generic :select-distinct args)) (defn insert-into [& args] (generic :insert-into args)) (defn update [& args] (generic :update args)) (defn delete [& args] (generic :delete args)) @@ -55,8 +67,8 @@ (defn group-by [& args] (generic :group-by args)) (defn having [& args] (generic :having args)) (defn order-by [& args] (generic :order-by args)) -(defn limit [& args] (generic :limit args)) -(defn offset [& args] (generic :offset args)) +(defn limit [& args] (generic-1 :limit args)) +(defn offset [& args] (generic-1 :offset args)) (defn for [& args] (generic :for args)) (defn values [& args] (generic :values args)) (defn on-conflict [& args] (generic :on-conflict args))