From 2746c6b08b878190ee7c54a7414bf444c660ff1e Mon Sep 17 00:00:00 2001 From: Carlo Zancanaro Date: Mon, 25 Nov 2013 01:13:11 +1100 Subject: Add a 'distinct' operator - still a bug to fix on renaming --- src/clojure_sql/compiler.clj | 4 +++- src/clojure_sql/core.clj | 10 +++++++++- src/clojure_sql/dsl.clj | 11 ++++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/clojure_sql/compiler.clj b/src/clojure_sql/compiler.clj index 50c14af..828da64 100644 --- a/src/clojure_sql/compiler.clj +++ b/src/clojure_sql/compiler.clj @@ -225,7 +225,7 @@ (def ^:private set-operations {:union "UNION", :intersect "INTERSECT"}) (defmulti compile-query (fn [db _] db) :default :postgres) -(defmethod compile-query :postgres [db {:keys [tables fields joins where sort group having take drop set-operation queries]}] +(defmethod compile-query :postgres [db {:keys [tables fields joins where sort group having take drop distinct set-operation queries]}] (or (if set-operation (let [op-str (str ") " (get set-operations set-operation) " (")] (->> queries @@ -234,6 +234,8 @@ ((p-lift string/join op-str)) $add-parentheses))) ($str (return "SELECT ") + (return (if distinct + "DISTINCT ")) (compile-fields db fields) (if tables ($str (return " FROM ") diff --git a/src/clojure_sql/core.clj b/src/clojure_sql/core.clj index 415c7f4..613adf6 100644 --- a/src/clojure_sql/core.clj +++ b/src/clojure_sql/core.clj @@ -17,7 +17,7 @@ (pull clojure-sql.dsl table join - project rename + project rename distinct prefix-names-matching prefix-names as-subobject select group @@ -63,3 +63,11 @@ [query] (assert (:executor query) "Cannot execute a query without a query executor") (q/delete! (:executor query) query)) + +(join (-> (table :x) + (project [:a :b])) + (-> (table :x) + (project [:a :b]) + distinct)) + + diff --git a/src/clojure_sql/dsl.clj b/src/clojure_sql/dsl.clj index 2a22eea..5c804d2 100644 --- a/src/clojure_sql/dsl.clj +++ b/src/clojure_sql/dsl.clj @@ -69,7 +69,6 @@ (throw (ex-info "Cannot union queries with different fields" {:queries queries}))) - (defn ^:private rename-table [query from to] (q/map->Query (walk/prewalk-replace {from to} (into {} query)))) @@ -201,6 +200,7 @@ (nil? (:having query)) (nil? (:take query)) (nil? (:drop query)) + (nil? (:distinct query)) (nil? (:set-operation query)))) (defn ^:private convert-to-subquery [query] @@ -214,6 +214,7 @@ (cond (joinable? query) query (:take query) (convert-to-subquery query) (:drop query) (convert-to-subquery query) + (:distinct query) (convert-to-subquery query) :else (convert-to-subquery (remove-sort query)))) (defn ^:private rename-all-tables [query] @@ -393,6 +394,14 @@ (assoc query :drop (+ old-drop n)) (assoc query :drop n)))) +(defn distinct + "Return only unique rows from this query." + [query] + (assoc (if (or (:take query) (:drop query)) + (convert-to-subquery query) + query) + :distinct true)) + (defn ^:private union-compatible? [& queries] (and (every? (comp seq keys :fields) queries) (apply = (map (comp set keys :fields) queries)) -- cgit v1.2.3