Skip to content

Commit

Permalink
fixes #551 by supporting multiple window clauses
Browse files Browse the repository at this point in the history
Signed-off-by: Sean Corfield <[email protected]>
  • Loading branch information
seancorfield committed Nov 18, 2024
1 parent 6fa606f commit 21ce3a2
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changes

* 2.6.next in progress
* Fix [#551](https://github.com/seancorfield/honeysql/issues/551) by supporting multiple `WINDOW` clauses.
* Fix [#549](https://github.com/seancorfield/honeysql/issues/549) by using `:bb` conditionals to support Babashka (and still support Clojure 1.9.0), and add testing against Babashka so it is fully-supported as a target via PR [#550](https://github.com/seancorfield/honeysql/pull/550) [@borkdude](https://github.com/borkdude)
* Address [#532](https://github.com/seancorfield/honeysql/issues/532) by adding support for `EXCLUDE` and `RENAME` and starting to write tests for XTDB compatibility.

Expand Down
33 changes: 32 additions & 1 deletion doc/clause-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ but is rendered into the SQL later in precedence order.

## window, partition-by (and over)

`:window` accepts a pair of SQL entity (the window name)
`:window` accept alternating pairs of SQL entity (the window name)
and the window "function" as a SQL clause (a hash map).

`:partition-by` accepts the same arguments as `:select` above
Expand All @@ -1116,6 +1116,25 @@ SELECT id, AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) A
FROM employee
WINDOW w AS (PARTITION BY department)
"]
;; multiple windows:
user=> (sql/format {:select [:id
[[:over
[[:avg :salary]
{:partition-by [:department]
:order-by [:designation]}
:Average]
[[:max :salary]
:w
:MaxSalary]]]]
:from [:employee]
:window [:w {:partition-by [:department]}
:x {:partition-by [:salary]}]}
{:pretty true})
["
SELECT id, AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) AS Average, MAX(salary) OVER w AS MaxSalary
FROM employee
WINDOW w AS (PARTITION BY department), x AS (PARTITION BY salary)
"]
;; easier to write with helpers (and easier to read!):
user=> (sql/format (-> (select :id
(over [[:avg :salary] (-> (partition-by :department) (order-by :designation)) :Average]
Expand All @@ -1128,6 +1147,18 @@ SELECT id, AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) A
FROM employee
WINDOW w AS (PARTITION BY department)
"]
;; multiple window clauses:
user=> (sql/format (-> (select :id
(over [[:avg :salary] (-> (partition-by :department) (order-by :designation)) :Average]
[[:max :salary] :w :MaxSalary]))
(from :employee)
(window :w (partition-by :department))
(window :x (partition-by :salary))) {:pretty true})
["
SELECT id, AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) AS Average, MAX(salary) OVER w AS MaxSalary
FROM employee
WINDOW w AS (PARTITION BY department), x AS (PARTITION BY salary)
"]
```

The window function in the `:over` expression may be `{}` or `nil`:
Expand Down
5 changes: 4 additions & 1 deletion src/honey/sql.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,9 @@
(defn- format-selector [k xs]
(format-selects k [xs]))

(defn- format-window [k xs]
(format-selects k (into [] (partition-all 2 xs))))

(declare columns-from-values)

(defn- format-insert [k table]
Expand Down Expand Up @@ -1643,7 +1646,7 @@
:where #'format-on-expr
:group-by #'format-group-by
:having #'format-on-expr
:window #'format-selector
:window #'format-window
:partition-by #'format-selects
:order-by #'format-order-by
:limit #'format-on-expr
Expand Down
27 changes: 27 additions & 0 deletions test/honey/sql/helpers_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,33 @@
" MAX(salary) OVER w AS MaxSalary"
" FROM employee"
" WINDOW w AS (PARTITION BY department)")]))
;; multiple window tests
(is (= (-> (select :id
(over [[:avg :salary] (-> (partition-by :department) (order-by :designation)) :Average]
[[:max :salary] :w :MaxSalary]))
(from :employee)
(window :w (partition-by :department))
(window :x (partition-by :salary))
sql/format)
[(str "SELECT id,"
" AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) AS Average,"
" MAX(salary) OVER w AS MaxSalary"
" FROM employee"
" WINDOW w AS (PARTITION BY department)"
", x AS (PARTITION BY salary)")]))
(is (= (-> (select :id
(over [[:avg :salary] (-> (partition-by :department) (order-by :designation)) :Average]
[[:max :salary] :w :MaxSalary]))
(from :employee)
(window :w (partition-by :department)
:x (partition-by :salary))
sql/format)
[(str "SELECT id,"
" AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) AS Average,"
" MAX(salary) OVER w AS MaxSalary"
" FROM employee"
" WINDOW w AS (PARTITION BY department)"
", x AS (PARTITION BY salary)")]))
;; test nil / empty window function clause:
(is (= (-> (select :id
(over [[:avg :salary] {} :Average]
Expand Down

0 comments on commit 21ce3a2

Please sign in to comment.