Skip to content

Commit e96970c

Browse files
scimetfookitallis
andauthored
Support FILTER for aggregate expressions (#42)
Also bumps the honeysql version to 1.0.461 Co-authored-by: Akshay Gupta <kitallis@gmail.com>
1 parent b4e31d2 commit e96970c

File tree

6 files changed

+57
-19
lines changed

6 files changed

+57
-19
lines changed

README.md

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ PostgreSQL extensions for the widely used [honeysql](https://github.com/jkk/hone
44

55
This library aims to extend the features of honeysql to support postgres specific SQL clauses and some basic SQL DDL in addition to the ones supported by the parent library. This keeps honeysql clean and single-purpose, any vendor-specific additions can simply be separate libraries that work on top.
66

7+
## Breaking Change
8+
Implementation of `over` has been changed (from 0.2.2) to accept alias as an option and define the aggregator-function within the over clause and not in the select clause, this allows the inclusion of multiple window-function which was not possible in the previous implementation.
9+
10+
The query creation and usage is exactly the same as honeysql.
11+
712
## Index
813

914
- [Usage](#usage)
10-
- [Leiningen](#leiningen)
11-
- [Maven](#maven)
1215
- [REPL](#REPL)
13-
- [Breaking Change](#breaking-change)
1416
- [distinct on](#distinct-on)
1517
- [upsert](#upsert)
1618
- [insert into with alias](#insert-into-with-alias)
@@ -21,6 +23,7 @@ This library aims to extend the features of honeysql to support postgres specifi
2123
- [alter table](#alter-table)
2224
- [pattern matching](#pattern-matching)
2325
- [except](#except)
26+
- [filter](#filter)
2427
- [SQL functions](#sql-functions)
2528
- [License](#license)
2629

@@ -33,14 +36,9 @@ This library aims to extend the features of honeysql to support postgres specifi
3336
'[honeysql-postgres.helpers :as psqlh])
3437
```
3538

36-
### Breaking Change
37-
Implementation of `over` has been changed (from 0.2.2) to accept alias as an option and define the aggregator-function within the over clause and not in the select clause, this allows the inclusion of multiple window-function which was not possible in the previous implementation.
38-
39-
The query creation and usage is exactly the same as honeysql.
40-
4139
### distinct-on
4240
`select` can be written with a `distinct on` clause
43-
``` clj
41+
``` clojure
4442
(-> (select :column-1 :column-2 :column-3)
4543
(from :table-name)
4644
(modifiers :distinct-on :column-1 :column-2)
@@ -180,6 +178,7 @@ The `ilike` and `not-ilike` operators can be used to query data using a pattern
180178
sql/format)
181179
=> ["SELECT name FROM products WHERE name NOT ILIKE ?" "%name%"]
182180
```
181+
183182
### except
184183
```clojure
185184
(sql/format
@@ -190,6 +189,17 @@ The `ilike` and `not-ilike` operators can be used to query data using a pattern
190189
```
191190
`except-all` works the same way as `except`.
192191

192+
### filter
193+
194+
``` clojure
195+
(-> (select (sql/call :count :*))
196+
(filter [(sql/call :count :*) (where [:< :i 5]) :foo]
197+
[(sql/call :count :*) (where [:between :i 3 10]) :bar])
198+
(from (sql/raw "generate_series(1,10) AS s(i)"))
199+
(sql/format))
200+
=> ["SELECT count(*) , count(*) FILTER (WHERE i < ?) AS foo, count(*) FILTER (WHERE i BETWEEN ? AND ?) AS bar FROM generate_series(1,10) AS s(i)" 5 3 10]
201+
```
202+
193203
### SQL functions
194204
The following are the SQL functions added in `honeysql-postgres`
195205
- not
@@ -249,8 +259,9 @@ The following are the SQL functions added in `honeysql-postgres`
249259
(sql/format (sql/call :check [:= :a :b] [:= :c :d]))
250260
["CHECK(a = b AND c = d)"]
251261
```
262+
252263
## License
253264

254-
Copyright © 2020 Nilenso
265+
Copyright © 2021 Nilenso
255266

256267
Distributed under the Eclipse Public License, the same as Clojure.

deps.edn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{:deps {honeysql/honeysql {:mvn/version "0.9.5" :exclusions [org.clojure/clojurescript]}}
1+
{:deps {honeysql/honeysql {:mvn/version "1.0.461" :exclusions [org.clojure/clojurescript]}}
22
:paths ["src"]
33
:aliases {:test {:extra-paths ["test"]}
44
:runner {:extra-deps {com.cognitect/test-runner

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<dependency>
2424
<groupId>honeysql</groupId>
2525
<artifactId>honeysql</artifactId>
26-
<version>0.9.5</version>
26+
<version>1.0.461</version>
2727
<exclusions>
2828
<exclusion>
2929
<groupId>org.clojure</groupId>

src/honeysql_postgres/format.cljc

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
(ns ^{:doc "Extension of the honeysql format functions specifically for postgreSQL"}
22
honeysql-postgres.format
3-
(:require [honeysql.format :as sqlf :refer [fn-handler format-clause format-modifiers]] ;; multi-methods
4-
[honeysql-postgres.util :as util]
5-
[clojure.string :as string]))
3+
(:require [clojure.string :as string]
4+
[honeysql.format :as sqlf :refer [fn-handler format-clause format-modifiers]] ;; multi-methods
5+
[honeysql-postgres.util :as util]))
66

77
(def ^:private custom-additions
88
{:create-table 10
@@ -13,8 +13,9 @@
1313
:add-column 30
1414
:drop-column 40
1515
:create-view 40
16-
:insert-into-as 60
16+
:filter 54
1717
:over 55
18+
:insert-into-as 60
1819
:partition-by 165
1920
:window 195
2021
:upsert 225
@@ -115,6 +116,18 @@
115116
(str "DO UPDATE SET " (sqlf/comma-join (for [[k v] values]
116117
(str (sqlf/to-sql k) " = " (sqlf/to-sql v))))))
117118

119+
(defmethod format-clause :filter [[_ expr] sql-map]
120+
(let [format (fn [expr]
121+
(let [[expression clause alias] (mapv sqlf/to-sql expr)]
122+
(->> alias
123+
(str " AS ")
124+
(when alias)
125+
(str expression " FILTER " clause))))]
126+
(->> expr
127+
(map format)
128+
sqlf/comma-join
129+
(str (when (seq (:select sql-map)) ", ")))))
130+
118131
(defmethod format-clause :do-update-set [[_ values] _]
119132
(let [fields (or (:fields values) values)
120133
where (:where values)]

src/honeysql_postgres/helpers.cljc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
(ns honeysql-postgres.helpers
2-
(:refer-clojure :exclude [partition-by])
2+
(:refer-clojure :exclude [partition-by filter])
33
(:require [honeysql-postgres.format]
44
[honeysql.helpers :as sqlh #?(:clj :refer :cljs :refer-macros) [defhelper]]))
55

@@ -13,6 +13,9 @@
1313
(defhelper do-update-set [m args]
1414
(assoc m :do-update-set (sqlh/collify args)))
1515

16+
(defhelper filter [m args]
17+
(assoc m :filter (sqlh/collify args)))
18+
1619
(defhelper do-update-set! [m args]
1720
(assoc m :do-update-set! args))
1821

test/honeysql_postgres/postgres_test.cljc

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
(ns honeysql-postgres.postgres-test
2-
(:refer-clojure :exclude [update partition-by])
2+
(:refer-clojure :exclude [update partition-by filter])
33
(:require [honeysql-postgres.helpers :as sqlph :refer [upsert on-conflict do-nothing on-conflict-constraint
44
returning do-update-set do-update-set!
55
alter-table rename-column drop-column
66
add-column partition-by insert-into-as
77
create-table rename-table drop-table
88
window create-view over with-columns
9-
create-extension drop-extension]]
9+
create-extension drop-extension filter]]
1010
[honeysql.helpers :as sqlh :refer [insert-into values where select columns
1111
from order-by update sset query-values
1212
modifiers]]
@@ -66,6 +66,17 @@
6666
:do-update-set {:fields [:phone :name]
6767
:where [:= :user.active false]}}}))))
6868

69+
(deftest filter-test
70+
(is (= ["count(*) FILTER (WHERE NOT i BETWEEN ? AND ?) AS a" 3 5]
71+
(sql/format (filter [(sql/call :count :*) (where [:not [:between :i 3 5]]) :a]))))
72+
73+
(is (= ["SELECT count(*) , count(*) FILTER (WHERE s.i < ?) AS foo, count(*) FILTER (WHERE s.i BETWEEN ? AND ?) AS bar FROM generate_series(1,10) AS s(i)" 5 3 10]
74+
(-> (select (sql/call :count :*))
75+
(filter [(sql/call :count :*) (where [:< :s.i 5]) :foo]
76+
[(sql/call :count :*) (where [:between :s.i 3 10]) :bar])
77+
(from (sql/raw "generate_series(1,10) AS s(i)"))
78+
(sql/format)))))
79+
6980
(deftest returning-test
7081
(testing "returning clause in sql generation for postgresql"
7182
(is (= ["DELETE FROM distributors WHERE did > 10 RETURNING *"]

0 commit comments

Comments
 (0)