fix #486 by support ansi/postgresl interval
This commit is contained in:
parent
2efe05def2
commit
1710e07231
5 changed files with 26 additions and 6 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
* 2.4.next in progress
|
* 2.4.next in progress
|
||||||
|
* Fix [#486](https://github.com/seancorfield/honeysql/issues/486) by supporting ANSI-style `INTERVAL` syntax.
|
||||||
* Fix [#484](https://github.com/seancorfield/honeysql/issues/484) by adding `TABLE` to `TRUNCATE`.
|
* Fix [#484](https://github.com/seancorfield/honeysql/issues/484) by adding `TABLE` to `TRUNCATE`.
|
||||||
* Fix [#483](https://github.com/seancorfield/honeysql/issues/483) by adding a function-like `:join` syntax to produce nested `JOIN` expressions.
|
* Fix [#483](https://github.com/seancorfield/honeysql/issues/483) by adding a function-like `:join` syntax to produce nested `JOIN` expressions.
|
||||||
* 2.4.1011 -- 2023-03-23
|
* 2.4.1011 -- 2023-03-23
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ The following new syntax has been added:
|
||||||
* `:default` -- for `DEFAULT` values (in inserts) and for declaring column defaults in table definitions,
|
* `:default` -- for `DEFAULT` values (in inserts) and for declaring column defaults in table definitions,
|
||||||
* `:escape` -- used to wrap a regular expression so that non-standard escape characters can be provided,
|
* `:escape` -- used to wrap a regular expression so that non-standard escape characters can be provided,
|
||||||
* `:inline` -- used as a function to replace the `sql/inline` / `#sql/inline` machinery,
|
* `:inline` -- used as a function to replace the `sql/inline` / `#sql/inline` machinery,
|
||||||
* `:interval` -- used as a function to support `INTERVAL <n> <units>`, e.g., `[:interval 30 :days]` for databases that support it (e.g., MySQL),
|
* `:interval` -- used as a function to support `INTERVAL <n> <units>`, e.g., `[:interval 30 :days]` for databases that support it (e.g., MySQL) and, as of 2.4.next, for `INTERVAL 'n units'`, e.g., `[:interval "24 hours"]` for ANSI/PostgreSQL.
|
||||||
* `:lateral` -- used to wrap a statement or expression, to provide a `LATERAL` join,
|
* `:lateral` -- used to wrap a statement or expression, to provide a `LATERAL` join,
|
||||||
* `:lift` -- used as a function to prevent interpretation of a Clojure data structure as DSL syntax (e.g., when passing a vector or hash map as a parameter value) -- this should mostly be a replacement for `honeysql.format/value`,
|
* `:lift` -- used as a function to prevent interpretation of a Clojure data structure as DSL syntax (e.g., when passing a vector or hash map as a parameter value) -- this should mostly be a replacement for `honeysql.format/value`,
|
||||||
* `:nest` -- used as a function to add an extra level of nesting (parentheses) around an expression,
|
* `:nest` -- used as a function to add an extra level of nesting (parentheses) around an expression,
|
||||||
|
|
|
||||||
|
|
@ -210,15 +210,18 @@ than turning it into a positional parameter:
|
||||||
|
|
||||||
## interval
|
## interval
|
||||||
|
|
||||||
Accepts two arguments: an expression and a keyword (or a symbol)
|
Accepts one or two arguments: either a string or an expression and
|
||||||
that represents a time unit. Produces an `INTERVAL` expression:
|
a keyword (or a symbol) that represents a time unit.
|
||||||
|
Produces an `INTERVAL` expression:
|
||||||
|
|
||||||
```clojure
|
```clojure
|
||||||
(sql/format-expr [:date_add [:now] [:interval 30 :days]])
|
(sql/format-expr [:date_add [:now] [:interval 30 :days]])
|
||||||
;;=> ["DATE_ADD(NOW(), INTERVAL ? DAYS)" 30]
|
;;=> ["DATE_ADD(NOW(), INTERVAL ? DAYS)" 30]
|
||||||
|
(sql/format-expr [:date_add [:now] [:interval "24 Hours"]])
|
||||||
|
;;=> ["DATE_ADD(NOW(), INTERVAL '24 Hours')"]
|
||||||
```
|
```
|
||||||
|
|
||||||
> Note: PostgreSQL has an `INTERVAL` data type which is unrelated to this syntax. In PostgreSQL, the closet equivalent would be `[:cast "30 days" :interval]` which will lift `"30 days"` out as a parameter. In DDL, for PostgreSQL, you can use `:interval` to produce the `INTERVAL` data type (without wrapping it in a vector).
|
> Note: PostgreSQL also has an `INTERVAL` data type which is unrelated to this syntax. In PostgreSQL, the closet equivalent would be `[:cast "30 days" :interval]` which will lift `"30 days"` out as a parameter. In DDL, for PostgreSQL, you can use `:interval` to produce the `INTERVAL` data type (without wrapping it in a vector).
|
||||||
|
|
||||||
## join
|
## join
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1543,8 +1543,12 @@
|
||||||
(format-expr x)))
|
(format-expr x)))
|
||||||
:interval
|
:interval
|
||||||
(fn [_ [n units]]
|
(fn [_ [n units]]
|
||||||
(let [[sql & params] (format-expr n)]
|
(if units
|
||||||
(into [(str "INTERVAL " sql " " (sql-kw units))] params)))
|
(let [[sql & params] (format-expr n)]
|
||||||
|
(into [(str "INTERVAL " sql " " (sql-kw units))] params))
|
||||||
|
(binding [*inline* true]
|
||||||
|
(let [[sql & params] (format-expr n)]
|
||||||
|
(into [(str "INTERVAL " sql)] params)))))
|
||||||
:join
|
:join
|
||||||
(fn [_ [e & js]]
|
(fn [_ [e & js]]
|
||||||
(let [[sqls params] (reduce-sql (cons (format-expr e)
|
(let [[sqls params] (reduce-sql (cons (format-expr e)
|
||||||
|
|
@ -2010,6 +2014,9 @@
|
||||||
(format {:select [:*] :from [:table]
|
(format {:select [:*] :from [:table]
|
||||||
:where [:< [:date_add :expiry [:interval 30 :days]] [:now]]} {})
|
:where [:< [:date_add :expiry [:interval 30 :days]] [:now]]} {})
|
||||||
(format-expr [:interval 30 :days])
|
(format-expr [:interval 30 :days])
|
||||||
|
(format {:select [:*] :from [:table]
|
||||||
|
:where [:< [:date_add :expiry [:interval "30 Days"]] [:now]]} {})
|
||||||
|
(format-expr [:interval "30 Days"])
|
||||||
(format {:select [:*] :from [:table]
|
(format {:select [:*] :from [:table]
|
||||||
:where [:= :id (int 1)]} {:dialect :mysql})
|
:where [:= :id (int 1)]} {:dialect :mysql})
|
||||||
(map fn? (format {:select [:*] :from [:table]
|
(map fn? (format {:select [:*] :from [:table]
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,10 @@
|
||||||
(is (= ["INTERVAL ? DAYS" 30]
|
(is (= ["INTERVAL ? DAYS" 30]
|
||||||
(sut/format-expr [:interval 30 :days]))))
|
(sut/format-expr [:interval 30 :days]))))
|
||||||
|
|
||||||
|
(deftest issue-486-interval
|
||||||
|
(is (= ["INTERVAL '30 Days'"]
|
||||||
|
(sut/format-expr [:interval "30 Days"]))))
|
||||||
|
|
||||||
(deftest issue-455-null
|
(deftest issue-455-null
|
||||||
(is (= ["WHERE (abc + ?) IS NULL" "abc"]
|
(is (= ["WHERE (abc + ?) IS NULL" "abc"]
|
||||||
(sut/format {:where [:= [:+ :abc "abc"] nil]}))))
|
(sut/format {:where [:= [:+ :abc "abc"] nil]}))))
|
||||||
|
|
@ -97,6 +101,8 @@
|
||||||
(sut/format {:select [:*] :from [:table] :order-by [[[:date :expiry] :desc] :bar]} {:quoted true})))
|
(sut/format {:select [:*] :from [:table] :order-by [[[:date :expiry] :desc] :bar]} {:quoted true})))
|
||||||
(is (= ["SELECT * FROM \"table\" WHERE DATE_ADD(\"expiry\", INTERVAL ? DAYS) < NOW()" 30]
|
(is (= ["SELECT * FROM \"table\" WHERE DATE_ADD(\"expiry\", INTERVAL ? DAYS) < NOW()" 30]
|
||||||
(sut/format {:select [:*] :from [:table] :where [:< [:date_add :expiry [:interval 30 :days]] [:now]]} {:quoted true})))
|
(sut/format {:select [:*] :from [:table] :where [:< [:date_add :expiry [:interval 30 :days]] [:now]]} {:quoted true})))
|
||||||
|
(is (= ["SELECT * FROM \"table\" WHERE DATE_ADD(\"expiry\", INTERVAL '30 Days') < NOW()"]
|
||||||
|
(sut/format {:select [:*] :from [:table] :where [:< [:date_add :expiry [:interval "30 Days"]] [:now]]} {:quoted true})))
|
||||||
(is (= ["SELECT * FROM `table` WHERE `id` = ?" 1]
|
(is (= ["SELECT * FROM `table` WHERE `id` = ?" 1]
|
||||||
(sut/format {:select [:*] :from [:table] :where [:= :id 1]} {:dialect :mysql})))
|
(sut/format {:select [:*] :from [:table] :where [:= :id 1]} {:dialect :mysql})))
|
||||||
(is (= ["SELECT * FROM \"table\" WHERE \"id\" IN (?, ?, ?, ?)" 1 2 3 4]
|
(is (= ["SELECT * FROM \"table\" WHERE \"id\" IN (?, ?, ?, ?)" 1 2 3 4]
|
||||||
|
|
@ -127,6 +133,9 @@
|
||||||
(is (= ["SELECT * FROM \"table\" WHERE DATE_ADD(\"expiry\", INTERVAL $1 DAYS) < NOW()" 30]
|
(is (= ["SELECT * FROM \"table\" WHERE DATE_ADD(\"expiry\", INTERVAL $1 DAYS) < NOW()" 30]
|
||||||
(sut/format {:select [:*] :from [:table] :where [:< [:date_add :expiry [:interval 30 :days]] [:now]]}
|
(sut/format {:select [:*] :from [:table] :where [:< [:date_add :expiry [:interval 30 :days]] [:now]]}
|
||||||
{:quoted true :numbered true})))
|
{:quoted true :numbered true})))
|
||||||
|
(is (= ["SELECT * FROM \"table\" WHERE DATE_ADD(\"expiry\", INTERVAL '30 Days') < NOW()"]
|
||||||
|
(sut/format {:select [:*] :from [:table] :where [:< [:date_add :expiry [:interval "30 Days"]] [:now]]}
|
||||||
|
{:quoted true :numbered true})))
|
||||||
(is (= ["SELECT * FROM `table` WHERE `id` = $1" 1]
|
(is (= ["SELECT * FROM `table` WHERE `id` = $1" 1]
|
||||||
(sut/format {:select [:*] :from [:table] :where [:= :id 1]}
|
(sut/format {:select [:*] :from [:table] :where [:= :id 1]}
|
||||||
{:dialect :mysql :numbered true})))
|
{:dialect :mysql :numbered true})))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue