Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion src/specql/impl/fetch.clj
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,26 @@
path->array-type))
results)))))

(defn distinct-on [all-cols {distinct-opt :specql.core/distinct}]
(case distinct-opt
(nil false)
""

true
" DISTINCT "

(do
(assert (seqable? distinct-opt))
(let [distinct-set (set distinct-opt)]
(str " DISTINCT ON ("
(str/join ", "
(into []
(comp
(filter (fn [[_ [_ col _]]] (contains? distinct-set (first col))))
(map (comp first second)))
all-cols))
") ")))))

(defn- order-by [table-alias
columns
{order :specql.core/order-by
Expand Down Expand Up @@ -303,7 +323,9 @@
(where/sql-where table-info-registry path->table where)

all-cols (into cols has-many-join-cols)
sql (str "SELECT " (sql-columns-list all-cols)
sql (str "SELECT "
(distinct-on all-cols options)
(sql-columns-list all-cols)
" FROM " (sql-from table-info-registry table-alias)
(when-not (str/blank? where-clause)
(str " WHERE " where-clause))
Expand Down
19 changes: 19 additions & 0 deletions test/database.sql
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,25 @@ CREATE TABLE table_with_composite_key (
name TEXT
);

CREATE TABLE parent_table (
id SERIAL PRIMARY KEY
);

CREATE TABLE with_possible_duplicates (
parent_id INTEGER REFERENCES parent_table (id),
"tag" text
);

INSERT INTO parent_table VALUES (1), (2), (3);

INSERT INTO with_possible_duplicates VALUES
(1, 'foo'),
(1, 'bar'),
(2, 'foo'),
(3, 'bar')
;


-- Some tables for multiple has-many join tests

-- CREATE TABLE customer (
Expand Down
65 changes: 65 additions & 0 deletions test/specql/core_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@

["recipient" :recipient/recipient]
["mailinglist" :mailinglist/mailinglist]

["parent_table" :parent-table/parent-table]
["with_possible_duplicates" :with-possible-duplicates/with-possible-duplicates]
)

(defmacro asserted [msg-regex & body]
Expand Down Expand Up @@ -103,6 +106,68 @@
:employee/employees
#{:employee/foo}
{}))))
(:with-possible-duplicates/with-possible-duplicates @specql.impl.registry/table-info-registry)
(deftest distinct-option
(testing "Table contains expected data"
(is (= (list #:with-possible-duplicates{:parent_id 1 :tag "foo"}
#:with-possible-duplicates{:parent_id 1 :tag "bar"}
#:with-possible-duplicates{:parent_id 2 :tag "foo"}
#:with-possible-duplicates{:parent_id 3 :tag "bar"})

(fetch db
;; table
:with-possible-duplicates/with-possible-duplicates
;; columns
#{:with-possible-duplicates/parent_id
:with-possible-duplicates/tag}
;; where
{}
{::specql/order-by :with-possible-duplicates/parent_id}))))

(testing "Distinct false uses `SELECT ALL`"
(is (= (list #:with-possible-duplicates{:parent_id 1 :tag "foo"}
#:with-possible-duplicates{:parent_id 1 :tag "bar"}
#:with-possible-duplicates{:parent_id 2 :tag "foo"}
#:with-possible-duplicates{:parent_id 3 :tag "bar"})

(fetch db
;; table
:with-possible-duplicates/with-possible-duplicates
;; columns
#{:with-possible-duplicates/parent_id
:with-possible-duplicates/tag}
;; where
{}
{::specql/distinct false}))))


(testing "Distinct true removes duplicates"
(is (= (list #:with-possible-duplicates{:tag "foo"}
#:with-possible-duplicates{:tag "bar"})

(fetch db
;; table
:with-possible-duplicates/with-possible-duplicates
;; columns
#{:with-possible-duplicates/tag}
;; where
{}
{::specql/distinct true}))))

(testing "Distinct with seq of columns removes duplicates across columns"
(is (= (list #:with-possible-duplicates{:parent_id 1 :tag "foo"}
#:with-possible-duplicates{:parent_id 2 :tag "foo"}
#:with-possible-duplicates{:parent_id 3 :tag "bar"})

(fetch db
;; table
:with-possible-duplicates/with-possible-duplicates
;; columns
#{:with-possible-duplicates/parent_id
:with-possible-duplicates/tag}
;; where
{}
{::specql/distinct #{:with-possible-duplicates/parent_id}})))))

(deftest query-with-invalid-parameter
(let [x "foo"]
Expand Down