2021-02-02 22:50:12 +00:00
|
|
|
# SQL Special Syntax
|
|
|
|
|
|
|
|
|
|
This section lists the function-like expressions that
|
|
|
|
|
HoneySQL supports out of the box which are formatted
|
|
|
|
|
as special syntactic forms.
|
|
|
|
|
|
|
|
|
|
## array
|
2021-02-03 00:43:09 +00:00
|
|
|
|
|
|
|
|
Accepts a single argument, which is expected to evaluate to
|
|
|
|
|
a sequence, and produces `ARRAY[?, ?, ..]` for the elements
|
|
|
|
|
of that sequence (as SQL parameters):
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format-expr [:array (range 5)])
|
|
|
|
|
;;=> ["ARRAY[?, ?, ?, ?, ?]" 0 1 2 3 4]
|
|
|
|
|
```
|
|
|
|
|
|
2021-02-02 22:50:12 +00:00
|
|
|
## between
|
2021-02-03 00:43:09 +00:00
|
|
|
|
|
|
|
|
Accepts three arguments: an expression, a lower bound, and
|
|
|
|
|
an upper bound:
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format-expr [:between :id 1 100])
|
|
|
|
|
;;=> ["id BETWEEN ? AND ?" 1 100]
|
|
|
|
|
```
|
|
|
|
|
|
2021-02-02 22:50:12 +00:00
|
|
|
## case
|
2021-02-03 00:43:09 +00:00
|
|
|
|
|
|
|
|
A SQL CASE expression. Expects an even number of arguments:
|
|
|
|
|
alternating condition and result expressions. A condition
|
|
|
|
|
may be `:else` (or `'else`) to produce `ELSE`, otherwise
|
|
|
|
|
`WHEN <condition> THEN <result>` will be produced:
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format-expr [:case [:< :a 10] "small" [:> :a 100] "big" :else "medium"])
|
|
|
|
|
;;=> ["CASE WHEN a < ? THEN ? WHEN a > ? THEN ? ELSE ? END"
|
|
|
|
|
;; 10 "small" 100 "big" "medium"]
|
|
|
|
|
```
|
|
|
|
|
|
2021-02-02 22:50:12 +00:00
|
|
|
## cast
|
2021-02-03 00:43:09 +00:00
|
|
|
|
|
|
|
|
A SQL CAST expression. Expects an expression and something
|
|
|
|
|
that produces a SQL type:
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format-expr [:cast :a :int])
|
|
|
|
|
;;=> ["CAST(a AS int)"]
|
|
|
|
|
```
|
|
|
|
|
|
2021-02-02 22:50:12 +00:00
|
|
|
## composite
|
2021-02-03 00:43:09 +00:00
|
|
|
|
|
|
|
|
Accepts any number of expressions and produces a composite
|
|
|
|
|
expression (comma-separated, wrapped in parentheses):
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format-expr [:composite :a :b "red" [:+ :x 1]])
|
|
|
|
|
;;=> ["(a, b, ?, x + ?)" "red" 1]
|
|
|
|
|
```
|
|
|
|
|
|
2021-02-02 22:50:12 +00:00
|
|
|
## default
|
2021-02-03 00:43:09 +00:00
|
|
|
|
|
|
|
|
Takes no arguments and produces the SQL keyword `DEFAULT`.
|
|
|
|
|
|
|
|
|
|
_[I expect this to be expanded for PostgreSQL]_
|
|
|
|
|
|
2021-02-02 22:50:12 +00:00
|
|
|
## inline
|
2021-02-03 00:43:09 +00:00
|
|
|
|
|
|
|
|
Accepts a single argument and tries to render it as a
|
|
|
|
|
SQL value directly in the formatted SQL string rather
|
|
|
|
|
than turning it into a positional parameter:
|
|
|
|
|
* `nil` becomes `NULL`
|
|
|
|
|
* keywords and symbols become upper case entities (with `-` replaced by space)
|
|
|
|
|
* strings become inline SQL strings (with single quotes)
|
|
|
|
|
* a sequence has each element formatted inline and then joined with spaces
|
|
|
|
|
* all other values are just rendered via Clojure's `str` function
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format {:where [:= :x [:inline "foo"]]})
|
|
|
|
|
;;=> ["WHERE x = 'foo'"]
|
|
|
|
|
```
|
|
|
|
|
|
2021-02-02 22:50:12 +00:00
|
|
|
## interval
|
2021-02-03 00:43:09 +00:00
|
|
|
|
|
|
|
|
Accepts two arguments: an expression and a keyword (or a symbol)
|
|
|
|
|
that represents a time unit. Produces an `INTERVAL` expression:
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format-expr [:date_add [:now] [:interval 30 :days]])
|
|
|
|
|
;;=> ["DATE_ADD(NOW(), INTERVAL ? DAYS)" 30]
|
|
|
|
|
```
|
|
|
|
|
|
2021-02-02 22:50:12 +00:00
|
|
|
## lift
|
2021-02-03 00:43:09 +00:00
|
|
|
|
|
|
|
|
Used to wrap a Clojure value that should be passed as a
|
|
|
|
|
SQL parameter but would otherwise be treated as a SQL
|
|
|
|
|
expression or statement, i.e., a sequence or hash map.
|
|
|
|
|
This can be useful when dealing with JSON types:
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format {:where [:= :json-col [:lift {:a 1 :b "two"}]]})
|
|
|
|
|
;;=> ["WHERE json_col = ?" {:a 1 :b "two"}]
|
|
|
|
|
```
|
|
|
|
|
|
2021-02-02 22:50:12 +00:00
|
|
|
## nest
|
2021-02-03 00:43:09 +00:00
|
|
|
|
|
|
|
|
Used to wrap an expression when you want an extra
|
|
|
|
|
level of parentheses around it:
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format {:where [:= :x 42]})
|
|
|
|
|
;;=> ["WHERE x = ?" 42]
|
|
|
|
|
(sql/format {:where [:nest [:= :x 42]]})
|
|
|
|
|
;;=> ["WHERE (x = ?)" 42]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`nest` is also supported as a SQL clause for the same reason.
|
|
|
|
|
|
2021-02-02 22:50:12 +00:00
|
|
|
## not
|
2021-02-03 00:43:09 +00:00
|
|
|
|
|
|
|
|
Accepts a single expression and formats it with `NOT`
|
|
|
|
|
in front of it:
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format-expr [:not nil])
|
|
|
|
|
;;=> ["NOT NULL"]
|
|
|
|
|
(sql/format-expr [:not [:= :x 42]])
|
|
|
|
|
;;=> ["NOT x = ?" 42]
|
|
|
|
|
```
|
|
|
|
|
|
2021-02-02 22:50:12 +00:00
|
|
|
## param
|
2021-02-03 00:43:09 +00:00
|
|
|
|
|
|
|
|
Used to identify a named parameter in a SQL expression
|
|
|
|
|
as an alternative to a keyword (or a symbol) that begins
|
|
|
|
|
with `?`:
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format {:where [:= :x :?foo]} {:params {:foo 42}})
|
|
|
|
|
;;=> ["WHERE x = ?" 42]
|
|
|
|
|
(sql/format {:where [:= :x [:param :foo]]} {:params {:foo 42}})
|
|
|
|
|
;;=> ["WHERE x = ?" 42]
|
|
|
|
|
```
|
|
|
|
|
|
2021-02-02 22:50:12 +00:00
|
|
|
## raw
|
2021-02-03 00:43:09 +00:00
|
|
|
|
|
|
|
|
Accepts a single argument and renders it as literal SQL
|
|
|
|
|
in the formatted string:
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format {:select [:a [[:raw "@var := foo"]]]})
|
|
|
|
|
;;=> ["SELECT a, @var := foo"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If the argument is a sequence of expressions, they
|
|
|
|
|
will each be rendered literally and joined together
|
|
|
|
|
(with no spaces):
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format {:select [:a [[:raw ["@var" " := " "foo"]]]]})
|
|
|
|
|
;;=> ["SELECT a, @var := foo"]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
When a sequence of expressions is supplied, any
|
|
|
|
|
subexpressions that are, in turn, sequences will be
|
|
|
|
|
formatted as regular SQL expressions and that SQL
|
|
|
|
|
will be joined into the result, along with any
|
|
|
|
|
parameters from them:
|
|
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
|
(sql/format {:select [:a [[:raw ["@var := " [:inline "foo"]]]]]})
|
|
|
|
|
;;=> ["SELECT a, @var := 'foo'"]
|
|
|
|
|
(sql/format {:select [:a [[:raw ["@var := " ["foo"]]]]]})
|
|
|
|
|
;;=> ["SELECT a, @var := ?" "foo"]
|
|
|
|
|
```
|