2024-09-22 01:12:10 +00:00
;; copyright (c) 2022-2024 sean corfield, all rights reserved
2022-03-26 04:48:00 +00:00
2022-04-23 22:40:47 +00:00
(ns honey.sql.pg-ops
2022-03-26 04:48:00 +00:00
"Register all the PostgreSQL JSON/JSONB operators
2022-03-26 21:20:58 +00:00
and provide convenient Clojure names for those ops.
2022-04-23 22:40:47 +00:00
In addition, provide names for the PostgreSQL
regex operators as well.
2022-03-26 21:20:58 +00:00
2022-04-23 22:40:47 +00:00
For the eleven that cannot be written directly as
symbols, use mnemonic names: hash for #, at for @,
and tilde for ~.
2022-03-26 21:20:58 +00:00
2022-04-23 22:40:47 +00:00
For the six of those that cannot be written as
2022-03-26 21:20:58 +00:00
keywords, invoke the `keyword` function instead.
2022-04-23 22:40:47 +00:00
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."
2022-03-26 21:20:58 +00:00
(:refer-clojure :exclude [-> ->> -])
2022-03-26 04:48:00 +00:00
(:require [honey.sql :as sql]))
;; see https://www.postgresql.org/docs/current/functions-json.html
2023-02-28 12:58:22 +00:00
(def ->
"The -> operator for accessing nested JSON(B) values as JSON(B).
2024-09-22 01:12:10 +00:00
Ex.:
2023-02-28 12:58:22 +00:00
```clojure
(sql/format {:select [[[:->> [:-> :my_column \"kids\" [:inline 0]] \"name\"]]]})
; => [\"SELECT (my_column -> ? -> 0) ->> ?\" \"kids\" \"name\"]
```
2024-09-22 01:12:10 +00:00
2023-02-28 12:58:22 +00:00
Notice we need to wrap the keys/indices with :inline if we don't want them to become parameters."
:->)
(def ->> "The ->> operator - like -> but returns the value as text instead of a JSON object." :->>)
(def hash> "The #> operator extracts JSON sub-object at the specified path." :#>)
(def hash>> "The #>> operator - like hash> but returns the value as text instead of JSON object." :#>>)
(def at> "The @> operator - does the first JSON value contain the second?" (keyword "@>"))
(def <at "The <@ operator - is the first JSON value contained in the second?" (keyword "<@"))
(def ? "The ? operator - does the text string exist as a top-level key or array element within the JSON value?" :?)
(def ?| "The ?| operator - do any of the strings in the text array exist as top-level keys or array elements?" :?|)
(def ?& "The ?& operator - do all of the strings in the text array exist as top-level keys or array elements?" :?&)
(def || "The || operator - concatenates two jsonb values (arrays or objects; anything else treated as 1-element array)." :||)
(def -
2024-09-22 01:12:10 +00:00
"The - operator:
2023-02-28 12:58:22 +00:00
- text value: deletes a key (and its value) from a JSON object, or matching string value(s) from a JSON array
2024-07-04 15:13:24 +00:00
- text[] array value: as above, but for all the provided keys
2023-02-28 12:58:22 +00:00
- int value: deletes the array element with specified index (negative integers count from the end)"
:-)
(def hash- "The #- operator - deletes the field or array element at the specified path, where path elements can be either field keys or array indexes." :#-)
(def at? "The @? operator - does JSON path return any item for the specified JSON value?" (keyword "@?"))
(def atat
2024-07-14 15:43:28 +00:00
"The @@ operator:
2024-09-22 01:12:10 +00:00
- returns the result of a JSON path predicate check for the specified JSON value. Only the first item of the result is taken into account.
2024-07-14 15:43:28 +00:00
If the result is not Boolean, then NULL is returned.
2024-09-22 01:12:10 +00:00
- checks if a text search vector (or a text value implicitly converted to a text search vector) matches a text search query. Returns a Boolean."
2023-02-28 12:58:22 +00:00
(keyword "@@"))
2022-03-26 04:48:00 +00:00
2022-04-23 22:40:47 +00:00
(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*)
2023-02-11 21:35:55 +00:00
(sql/register-op! :->)
2022-03-26 04:48:00 +00:00
(sql/register-op! :->>)
(sql/register-op! :#>)
(sql/register-op! :#>>)
(sql/register-op! at>)
(sql/register-op! <at)
(sql/register-op! :?)
(sql/register-op! :?|)
(sql/register-op! :?&)
;; these are already known operators:
;(sql/register-op! :||)
;(sql/register-op! :-)
(sql/register-op! :#-)
(sql/register-op! at?)
(sql/register-op! atat)
2022-04-23 22:40:47 +00:00
(sql/register-op! tilde)
(sql/register-op! tilde*)
(sql/register-op! !tilde)
(sql/register-op! !tilde*)