Fix #382 by adding :case-expr syntax
This commit is contained in:
parent
139de6f56c
commit
8a2f447676
4 changed files with 48 additions and 19 deletions
|
|
@ -1,7 +1,8 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
* 2.2.next in progress
|
* 2.2.next in progress
|
||||||
* Fix #380 by correcting test for function type in `register-clause!`.
|
* Address [#382](https://github.com/seancorfield/honeysql/issues/382) by adding `:case-expr` for BigQuery support.
|
||||||
|
* Fix [#380](https://github.com/seancorfield/honeysql/issues/380) by correcting test for function type in `register-clause!` and `register-fn!`.
|
||||||
|
|
||||||
* 2.2.858 -- 2022-01-20
|
* 2.2.858 -- 2022-01-20
|
||||||
* Address #377 by adding `honey.sql/map=` to convert a hash map into an equality condition (for a `WHERE` clause).
|
* Address #377 by adding `honey.sql/map=` to convert a hash map into an equality condition (for a `WHERE` clause).
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,15 @@ may be `:else` (or `'else`) to produce `ELSE`, otherwise
|
||||||
;; => ["CASE WHEN a < ? THEN ? WHEN a > ? THEN ? ELSE ? END" 10 "small" 100 "big" "medium"]
|
;; => ["CASE WHEN a < ? THEN ? WHEN a > ? THEN ? ELSE ? END" 10 "small" 100 "big" "medium"]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Google BigQuery supports a variant of `CASE` that takes an expression and then the `WHEN`
|
||||||
|
clauses contain expressions to match against, rather than conditions. HoneySQL supports
|
||||||
|
this using `:case-expr`:
|
||||||
|
|
||||||
|
```clojure
|
||||||
|
(sql/format-expr [:case-expr :a 10 "small" 100 "big" :else "medium"])
|
||||||
|
;; => ["CASE a WHEN ? THEN ? WHEN ? THEN ? ELSE ? END" 10 "small" 100 "big" "medium"]
|
||||||
|
```
|
||||||
|
|
||||||
## cast
|
## cast
|
||||||
|
|
||||||
A SQL CAST expression. Expects an expression and something
|
A SQL CAST expression. Expects an expression and something
|
||||||
|
|
|
||||||
|
|
@ -1124,6 +1124,31 @@
|
||||||
(partition 2 pairs))]
|
(partition 2 pairs))]
|
||||||
(into [(str/join ", " sqls)] params)))
|
(into [(str/join ", " sqls)] params)))
|
||||||
|
|
||||||
|
(defn- case-clauses
|
||||||
|
"For both :case and :case-expr."
|
||||||
|
[k clauses]
|
||||||
|
(let [case-expr? (= :case-expr k)
|
||||||
|
[sqlx & paramsx] (when case-expr? (format-expr (first clauses)))
|
||||||
|
[sqls params]
|
||||||
|
(reduce (fn [[sqls params] [condition value]]
|
||||||
|
(let [[sqlc & paramsc] (when-not (= :else condition)
|
||||||
|
(format-expr condition))
|
||||||
|
[sqlv & paramsv] (format-expr value)]
|
||||||
|
[(if (or (= :else condition)
|
||||||
|
(= 'else condition))
|
||||||
|
(conj sqls (sql-kw :else) sqlv)
|
||||||
|
(conj sqls (sql-kw :when) sqlc (sql-kw :then) sqlv))
|
||||||
|
(-> params (into paramsc) (into paramsv))]))
|
||||||
|
[[] []]
|
||||||
|
(partition 2 (if case-expr? (rest clauses) clauses)))]
|
||||||
|
(-> [(str (sql-kw :case) " "
|
||||||
|
(when case-expr?
|
||||||
|
(str sqlx " "))
|
||||||
|
(str/join " " sqls)
|
||||||
|
" " (sql-kw :end))]
|
||||||
|
(into paramsx)
|
||||||
|
(into params))))
|
||||||
|
|
||||||
(def ^:private special-syntax
|
(def ^:private special-syntax
|
||||||
(atom
|
(atom
|
||||||
{;; these "functions" are mostly used in column
|
{;; these "functions" are mostly used in column
|
||||||
|
|
@ -1168,24 +1193,8 @@
|
||||||
(into params-x)
|
(into params-x)
|
||||||
(into params-a)
|
(into params-a)
|
||||||
(into params-b))))
|
(into params-b))))
|
||||||
:case
|
:case #'case-clauses
|
||||||
(fn [_ clauses]
|
:case-expr #'case-clauses
|
||||||
(let [[sqls params]
|
|
||||||
(reduce (fn [[sqls params] [condition value]]
|
|
||||||
(let [[sqlc & paramsc] (when-not (= :else condition)
|
|
||||||
(format-expr condition))
|
|
||||||
[sqlv & paramsv] (format-expr value)]
|
|
||||||
[(if (or (= :else condition)
|
|
||||||
(= 'else condition))
|
|
||||||
(conj sqls (sql-kw :else) sqlv)
|
|
||||||
(conj sqls (sql-kw :when) sqlc (sql-kw :then) sqlv))
|
|
||||||
(-> params (into paramsc) (into paramsv))]))
|
|
||||||
[[] []]
|
|
||||||
(partition 2 clauses))]
|
|
||||||
(into [(str (sql-kw :case) " "
|
|
||||||
(str/join " " sqls)
|
|
||||||
" " (sql-kw :end))]
|
|
||||||
params)))
|
|
||||||
:cast
|
:cast
|
||||||
(fn [_ [x type]]
|
(fn [_ [x type]]
|
||||||
(let [[sql & params] (format-expr x)
|
(let [[sql & params] (format-expr x)
|
||||||
|
|
|
||||||
|
|
@ -42,3 +42,13 @@
|
||||||
{:add-column [:name :string :if-not-exists]}
|
{:add-column [:name :string :if-not-exists]}
|
||||||
{:add-column [:my_struct [:bigquery/struct [:name :string] [:description :string]] :if-not-exists]}
|
{:add-column [:my_struct [:bigquery/struct [:name :string] [:description :string]] :if-not-exists]}
|
||||||
{:add-column [:my_array [:bigquery/array :string] :if-not-exists]}]}))))
|
{:add-column [:my_array [:bigquery/array :string] :if-not-exists]}]}))))
|
||||||
|
|
||||||
|
(deftest test-case-expr
|
||||||
|
(is (= ["SELECT CASE foo WHEN ? THEN ? WHEN ? THEN foo / ? ELSE ? END FROM bar"
|
||||||
|
1 -1 2 2 0]
|
||||||
|
(sut/format
|
||||||
|
{:select [[[:case-expr :foo
|
||||||
|
1 -1
|
||||||
|
2 [:/ :foo 2]
|
||||||
|
:else 0]]]
|
||||||
|
:from [:bar]}))))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue