Revert "Document with / CTE"

This reverts commit c00fbffe30.
This commit is contained in:
Sean Corfield 2021-02-10 11:50:00 -08:00
parent 8f725abe02
commit e02b5b5c82
4 changed files with 16 additions and 80 deletions

View file

@ -12,54 +12,7 @@ Except as noted, these clauses apply to all the SQL
dialects that HoneySQL supports. dialects that HoneySQL supports.
## nest ## nest
This is pseudo-syntax that lets you wrap a substatement
in an extra level of parentheses. It should rarely be
needed and it is mostly present to provide the same
functionality for clauses that `[:nest ..]` provides
for expressions.
## with, with-recursive ## with, with-recursive
These provide CTE support for SQL Server. The argument to
`:with` (or `:with-recursive`) is a pair of
a result set name (or description) and a basic SQL statement.
The result set can either be a SQL entity (a simple name)
or a pair of a SQL entity and a set of column names.
```clojure
user=> (sql/format '{with (stuff {select (:*) from (foo)})
select (id,name)
from (stuff)
where (= status 0)})
["WITH stuff AS (SELECT * FROM foo) SELECT id, name FROM stuff WHERE status = ?" 0]
```
You can specify a list of columns for the CTE like this:
```clojure
user=> (sql/format {:with [[:stuff {:columns [:id :name]}]
{:select [:*] :from [:foo]}]
:select [:id :name]
:from [:stuff]
:where [:= :status 0]})
["WITH stuff (id, name) AS (SELECT * FROM foo) SELECT id, name FROM stuff WHERE status = ?" 0]
```
You can use a `VALUES` clause in the CTE:
```clojure
user=> (sql/format {:with [[:stuff {:columns [:id :name]}]
{:values [[1 "Sean"] [2 "Jay"]]}]
:select [:id :name]
:from [:stuff]})
["WITH stuff (id, name) AS (VALUES (?, ?), (?, ?)) SELECT id, name FROM stuff" 1 "Sean" 2 "Jay"]
```
`:with-recursive` follows the same rules as `:with` and produces `WITH RECURSIVE` instead of just `WITH`.
> Note: HoneySQL 0.6.2 introduced support for CTEs a long time ago and it expected the pair (of result set and query) to be wrapped in a sequence, even though you can only have a single CTE. For backward compatibility, HoneySQL 2.0 accepts that format but it should be considered deprecated.
## intersect, union, union-all, except, except-all ## intersect, union, union-all, except, except-all
These all expect a sequence of SQL clauses, those clauses These all expect a sequence of SQL clauses, those clauses

View file

@ -47,7 +47,7 @@ values identified in the SQL expressions:
;;=> ["SELECT * FROM table WHERE id = ?" 1] ;;=> ["SELECT * FROM table WHERE id = ?" 1]
``` ```
By default, any values found in the data structure, that are not keywords Any values found in the data structure, that are not keywords
or symbols, are treated as positional parameters and replaced or symbols, are treated as positional parameters and replaced
by `?` in the SQL string and lifted out into the vector that by `?` in the SQL string and lifted out into the vector that
is returned from `format`. is returned from `format`.

View file

@ -278,24 +278,21 @@
[(format-entity x)])) [(format-entity x)]))
(defn- format-with [k xs] (defn- format-with [k xs]
;; 1.x and earlier required a sequence of pairs -- X AS expr -- where ;; TODO: a sequence of pairs -- X AS expr -- where X is either [entity expr]
;; X is either [entity expr] or just entity; but a CTE can only contain ;; or just entity, as far as I can tell...
;; one result set definition so 2.x allows this to be just a pair instead (let [[sqls params]
(let [[result-set query] (reduce (fn [[sql params] [sql' & params']]
(case (count xs) [(conj sql sql') (if params' (into params params') params)])
1 (if (= 2 (count (first xs))) [[] []]
(first xs) (map (fn [[x expr]]
(throw (ex-info (str k " expects a sequence with just a single pair") (let [[sql & params] (format-with-part x)
{:elements (count xs)}))) [sql' & params'] (format-dsl expr)]
2 xs
(throw (ex-info (str k " expects a pair (result set, query)")
{:elements (count xs)})))
[sql & params] (format-with-part result-set)
[sql' & params'] (format-dsl query)]
;; according to docs, CTE should _always_ be wrapped: ;; according to docs, CTE should _always_ be wrapped:
(cond-> [(str (sql-kw k) " " sql " AS " (str "(" sql' ")"))] (cond-> [(str sql " AS " (str "(" sql' ")"))]
params (into params) params (into params)
params' (into params')))) params' (into params'))))
xs))]
(into [(str (sql-kw k) " " (str/join ", " sqls))] params)))
(defn- format-selector [k xs] (defn- format-selector [k xs]
(format-selects k [xs])) (format-selects k [xs]))

View file

@ -97,7 +97,6 @@
(format {:select [:vals.a] (format {:select [:vals.a]
:from [[{:values [[1 2 3]]} [:vals {:columns [:a :b :c]}]]]})))) :from [[{:values [[1 2 3]]} [:vals {:columns [:a :b :c]}]]]}))))
(deftest test-cte (deftest test-cte
;; 1.x and earlier with the extra sequence wrapping:
(is (= (format {:with [[:query {:select [:foo] :from [:bar]}]]}) (is (= (format {:with [[:query {:select [:foo] :from [:bar]}]]})
["WITH query AS (SELECT foo FROM bar)"])) ["WITH query AS (SELECT foo FROM bar)"]))
(is (= (format {:with-recursive [[:query {:select [:foo] :from [:bar]}]]}) (is (= (format {:with-recursive [[:query {:select [:foo] :from [:bar]}]]})
@ -109,19 +108,6 @@
{:values [[1 2] [4 5 6]]}]] {:values [[1 2] [4 5 6]]}]]
:select [:*] :select [:*]
:from [:static]}) :from [:static]})
["WITH static (a, b, c) AS (VALUES (?, ?, NULL), (?, ?, ?)) SELECT * FROM static" 1 2 4 5 6]))
;; 2.x should allow just a pair:
(is (= (format {:with [:query {:select [:foo] :from [:bar]}]})
["WITH query AS (SELECT foo FROM bar)"]))
(is (= (format {:with-recursive [:query {:select [:foo] :from [:bar]}]})
["WITH RECURSIVE query AS (SELECT foo FROM bar)"]))
(is (= (format {:with [[:static {:columns [:a :b :c]}] {:values [[1 2 3] [4 5]]}]})
["WITH static (a, b, c) AS (VALUES (?, ?, ?), (?, ?, NULL))" 1 2 3 4 5]))
(is (= (format
{:with [[:static {:columns [:a :b :c]}]
{:values [[1 2] [4 5 6]]}]
:select [:*]
:from [:static]})
["WITH static (a, b, c) AS (VALUES (?, ?, NULL), (?, ?, ?)) SELECT * FROM static" 1 2 4 5 6]))) ["WITH static (a, b, c) AS (VALUES (?, ?, NULL), (?, ?, ?)) SELECT * FROM static" 1 2 4 5 6])))
(deftest insert-into (deftest insert-into