Document special syntax
This commit is contained in:
parent
ea0bfbabc1
commit
1d2b8e8203
3 changed files with 159 additions and 2 deletions
|
|
@ -26,7 +26,7 @@ of two arguments or a previously registered clause (so
|
|||
that you can easily reuse formatters).
|
||||
|
||||
The formatter function will be called with:
|
||||
* The function name (always as a keyword),
|
||||
* The clause name (always as a keyword),
|
||||
* The sequence of arguments provided.
|
||||
|
||||
The third argument to `register-clause!` allows you to
|
||||
|
|
|
|||
|
|
@ -5,15 +5,170 @@ HoneySQL supports out of the box which are formatted
|
|||
as special syntactic forms.
|
||||
|
||||
## array
|
||||
|
||||
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]
|
||||
```
|
||||
|
||||
## between
|
||||
|
||||
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]
|
||||
```
|
||||
|
||||
## case
|
||||
|
||||
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"]
|
||||
```
|
||||
|
||||
## cast
|
||||
|
||||
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)"]
|
||||
```
|
||||
|
||||
## composite
|
||||
|
||||
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]
|
||||
```
|
||||
|
||||
## default
|
||||
|
||||
Takes no arguments and produces the SQL keyword `DEFAULT`.
|
||||
|
||||
_[I expect this to be expanded for PostgreSQL]_
|
||||
|
||||
## inline
|
||||
|
||||
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'"]
|
||||
```
|
||||
|
||||
## interval
|
||||
|
||||
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]
|
||||
```
|
||||
|
||||
## lift
|
||||
|
||||
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"}]
|
||||
```
|
||||
|
||||
## nest
|
||||
|
||||
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.
|
||||
|
||||
## not
|
||||
|
||||
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]
|
||||
```
|
||||
|
||||
## param
|
||||
|
||||
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]
|
||||
```
|
||||
|
||||
## raw
|
||||
|
||||
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"]
|
||||
```
|
||||
|
|
|
|||
|
|
@ -608,7 +608,8 @@
|
|||
(let [[sqlc & paramsc] (when-not (= :else condition)
|
||||
(format-expr condition))
|
||||
[sqlv & paramsv] (format-expr value)]
|
||||
[(if (= :else condition)
|
||||
[(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))]))
|
||||
|
|
@ -892,6 +893,7 @@
|
|||
:pretty true}))
|
||||
;; while working on the docs
|
||||
(require '[honey.sql :as sql])
|
||||
(sql/format-expr [:array (range 5)])
|
||||
(sql/format {:where [:and [:= :id 42] [:= :type "match"]]})
|
||||
(sql/format {:where [:and [:= :type "match"] (when false [:in :status [1 5]])]})
|
||||
(sql/format {:select [:*] :from [:table] :where [:= :id 1]})
|
||||
|
|
|
|||
Loading…
Reference in a new issue