Add PostgreSQL JSON / regex operators fixes #398

This commit is contained in:
Sean Corfield 2022-04-23 15:40:47 -07:00
parent 124fac6f28
commit e45ea8586e
4 changed files with 48 additions and 18 deletions

View file

@ -1,9 +1,12 @@
# Changes
* 2.2.next in progress
* Address [#404](https://github.com/seancorfield/honeysql/issues/404) by documenting PostgreSQL's `ARRAY` constructor syntax and how to produce it.
* Address parts of [#403](https://github.com/seancorfield/honeysql/issues/403) by improving the documentation for `:array` and also improving the exception that was thrown when it was misused.
* Fix [#402](https://github.com/seancorfield/honeysql/issues/402) by allowing for expressions in `:insert-into` table.
* Address [#400](https://github.com/seancorfield/honeysql/issues/400) by adding `:table` clause.
* Address [#399](https://github.com/seancorfield/honeysql/issues/399) by correcting multi-column `RETURNING` clauses in docs and tests.
* Address [#398](https://github.com/seancorfield/honeysql/issues/398) by adding `honey.sql.pg-json` namespace that registers PostgreSQL JSON operators and provides symbolic names for "unwritable" operators (that contain `@` or `#`).
* Fix [#398](https://github.com/seancorfield/honeysql/issues/398) by adding `honey.sql.pg-ops` namespace that registers PostgreSQL JSON and regex operators and provides symbolic names for "unwritable" operators (that contain `@`, `#`, or `~`).
* Fix [#394](https://github.com/seancorfield/honeysql/issues/394) by restoring HoneySQL 1.x's behavior when quoting.
* Fix [#387](https://github.com/seancorfield/honeysql/issues/387) again.
* Update CI to reflect Clojure 1.11 release (master -> 1.11; new master is 1.12).

View file

@ -53,16 +53,19 @@ user=> (sql/format {:select [[[:array [1 2 3]] :a]]})
["SELECT ARRAY[?, ?, ?] AS a" 1 2 3]
```
## Operators with @
## Operators with @, #, and ~
A number of PostgreSQL operators contain `@` which is not legal in a Clojure keyword or symbol (as literal syntax). The recommendation is to `def` your own name for these
operators, using `at` in place of `@`, with an explicit call to `keyword` (or `symbol`), and then use that `def`'d name when registering new operators and when writing
your DSL expressions:
A number of PostgreSQL operators contain `@`, `#`, or `~` which are not legal in a Clojure keyword or symbol (as literal syntax). The namespace `honey.sql.pg-ops` provides convenient symbolic names for these JSON and regex operators, substituting `at` for `@`, `hash` for `#`, and `tilde` for `~`.
The regex operators also have more memorable aliases: `regex` for `~`, `iregex` for `~*`, `!regex` for `!~`, and `!iregex` for `!~*`.
Requiring the namespace automatically registers these operators for use in expressions:
```clojure
(def <at (keyword "<@"))
;; then register it: (sql/register-op! <at)
;; and use it in expressions: [<at :submitted [:range :begin :end]]
user=> (require '[honey.sql.pg-ops :refer [regex]])
nil
user=> (sql/format {:select [[[regex :straw [:inline "needle"]] :match]] :from :haystack})
["SELECT straw ~ 'needle` AS match FROM haystack"]
```
## JSON/JSONB

View file

@ -1,18 +1,27 @@
;; copyright (c) 2022 sean corfield, all rights reserved
(ns honey.sql.pg-json
(ns honey.sql.pg-ops
"Register all the PostgreSQL JSON/JSONB operators
and provide convenient Clojure names for those ops.
In addition, provide names for the PostgreSQL
regex operators as well.
For the seven that cannot be written directly as
symbols, use mnemonic names: hash for # and at for @.
For the eleven that cannot be written directly as
symbols, use mnemonic names: hash for #, at for @,
and tilde for ~.
For the four of those that cannot be written as
For the six of those that cannot be written as
keywords, invoke the `keyword` function instead.
Those latter four (`at>`, `<at`, `at?`, and `atat`)
are the only ones that should really be needed in the
DSL. The other names are provided for completeness."
Those latter eight (`at>`, `<at`, `at?`, `atat`,
`tilde`, `tilde*`, `!tilde`, and `!tilde*`) are
the only ones that should really be needed in the
DSL. The other names are provided for completeness.
`regex` and `iregex` are provided as aliases for the
regex operators `tilde` and `tilde*` respectively.
`!regex` and `!iregex` are provided as aliases for the
regex operators `!tilde` and `!tilde*` respectively."
(:refer-clojure :exclude [-> ->> -])
(:require [honey.sql :as sql]))
@ -33,6 +42,16 @@
(def at? "The @? operator." (keyword "@?"))
(def atat "The @@ operator." (keyword "@@"))
(def tilde "The case-sensitive regex match operator." (keyword "~"))
(def tilde* "The case-insensitive regex match operator." (keyword "~*"))
(def !tilde "The case-sensitive regex unmatch operator." (keyword "!~"))
(def !tilde* "The case-insensitive regex unmatch operator." (keyword "!~*"))
;; aliases:
(def regex tilde)
(def iregex tilde*)
(def !regex !tilde)
(def !iregex !tilde*)
(sql/register-op! :-> :variadic true)
(sql/register-op! :->>)
(sql/register-op! :#>)
@ -48,3 +67,8 @@
(sql/register-op! :#-)
(sql/register-op! at?)
(sql/register-op! atat)
(sql/register-op! tilde)
(sql/register-op! tilde*)
(sql/register-op! !tilde)
(sql/register-op! !tilde*)

View file

@ -1,9 +1,9 @@
;; copyright (c) 2020-2021 sean corfield, all rights reserved
;; copyright (c) 2022 sean corfield, all rights reserved
(ns honey.sql.pg-json-test
(ns honey.sql.pg-ops-test
(:require [clojure.test :refer [deftest is testing]]
[honey.sql :as sql]
[honey.sql.pg-json :as sut]))
[honey.sql.pg-ops :as sut]))
(deftest pg-op-tests
(testing "built-in ops"