Fixes #307 by adding data DSL examples
I've added a pure data DSL version of nearly all the helper function examples. I've added a few examples of the data DSL with symbols instead of keywords as well.
This commit is contained in:
parent
d789c00f54
commit
97c9236842
1 changed files with 121 additions and 2 deletions
123
README.md
123
README.md
|
|
@ -53,6 +53,10 @@ Column names can be provided as keywords or symbols (but not strings -- HoneySQL
|
||||||
```clojure
|
```clojure
|
||||||
(sql/format sqlmap)
|
(sql/format sqlmap)
|
||||||
=> ["SELECT a, b, c FROM foo WHERE f.a = ?" "baz"]
|
=> ["SELECT a, b, c FROM foo WHERE f.a = ?" "baz"]
|
||||||
|
;; sqlmap as symbols instead of keywords:
|
||||||
|
(-> '{select (a, b, c) from (foo) where (= f.a "baz")}
|
||||||
|
(sql/format))
|
||||||
|
=> ["SELECT a, b, c FROM foo WHERE f.a = ?" "baz"]
|
||||||
```
|
```
|
||||||
|
|
||||||
HoneySQL is a relatively "pure" library, it does not manage your sql connection
|
HoneySQL is a relatively "pure" library, it does not manage your sql connection
|
||||||
|
|
@ -82,16 +86,25 @@ _[In HoneySQL 1.x, this was the behavior when `:namespace-as-table? true` was sp
|
||||||
:where [:= :foo/a "baz"]})
|
:where [:= :foo/a "baz"]})
|
||||||
(sql/format q-sqlmap)
|
(sql/format q-sqlmap)
|
||||||
=> ["SELECT foo.a, foo.b, foo.c FROM foo WHERE foo.a = ?" "baz"]
|
=> ["SELECT foo.a, foo.b, foo.c FROM foo WHERE foo.a = ?" "baz"]
|
||||||
|
;; this also works with symbols instead of keywords:
|
||||||
|
(-> '{select (foo/a, foo/b, foo/c)
|
||||||
|
from (foo)
|
||||||
|
where (= foo/a "baz")}
|
||||||
|
(sql/format))
|
||||||
|
=> ["SELECT foo.a, foo.b, foo.c FROM foo WHERE foo.a = ?" "baz"]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Vanilla SQL clause helpers
|
### Vanilla SQL clause helpers
|
||||||
|
|
||||||
There are also functions for each clause type in the `honey.sql.helpers` namespace:
|
For every single SQL clause supported by HoneySQL (as keywords or symbols
|
||||||
|
in the data structure that is the DSL), there is also a corresponding
|
||||||
|
function in the `honey.sql.helpers` namespace:
|
||||||
|
|
||||||
```clojure
|
```clojure
|
||||||
(-> (select :a :b :c)
|
(-> (select :a :b :c)
|
||||||
(from :foo)
|
(from :foo)
|
||||||
(where [:= :f.a "baz"]))
|
(where [:= :f.a "baz"]))
|
||||||
|
=> {:select [:a :b :c] :from [:foo] :where [:= :f.a "baz"]}
|
||||||
```
|
```
|
||||||
|
|
||||||
Order doesn't matter (for independent clauses):
|
Order doesn't matter (for independent clauses):
|
||||||
|
|
@ -145,6 +158,11 @@ In particular, note that `(select [:a :b])` means `SELECT a AS b` rather than
|
||||||
`SELECT a, b` -- helpers like `select` are generally variadic and do not take
|
`SELECT a, b` -- helpers like `select` are generally variadic and do not take
|
||||||
a collection of column names.
|
a collection of column names.
|
||||||
|
|
||||||
|
The examples in this README use a mixture of data structures and the helper
|
||||||
|
functions interchangably. For any example using the helpers, you could evaluate
|
||||||
|
it (without the call to `sql/format`) to see what the equivalent data structure
|
||||||
|
would be.
|
||||||
|
|
||||||
### Inserts
|
### Inserts
|
||||||
|
|
||||||
Inserts are supported in two patterns.
|
Inserts are supported in two patterns.
|
||||||
|
|
@ -165,6 +183,19 @@ INSERT INTO properties
|
||||||
VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?)
|
VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?)
|
||||||
"
|
"
|
||||||
"Jon" "Smith" 34 "Andrew" "Cooper" 12 "Jane" "Daniels" 56]
|
"Jon" "Smith" 34 "Andrew" "Cooper" 12 "Jane" "Daniels" 56]
|
||||||
|
;; or as pure data DSL:
|
||||||
|
(-> {:insert-into [:properties]
|
||||||
|
:columns [:name :surname :age]
|
||||||
|
:values [["Jon" "Smith" 34]
|
||||||
|
["Andrew" "Cooper" 12]
|
||||||
|
["Jane" "Daniels" 56]]}
|
||||||
|
(sql/format {:pretty true}))
|
||||||
|
=> ["
|
||||||
|
INSERT INTO properties
|
||||||
|
(name, surname, age)
|
||||||
|
VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?)
|
||||||
|
"
|
||||||
|
"Jon" "Smith" 34 "Andrew" "Cooper" 12 "Jane" "Daniels" 56]
|
||||||
```
|
```
|
||||||
|
|
||||||
If the rows are of unequal lengths, they will be padded with `NULL` values to make them consistent.
|
If the rows are of unequal lengths, they will be padded with `NULL` values to make them consistent.
|
||||||
|
|
@ -184,6 +215,19 @@ INSERT INTO properties
|
||||||
"John" "Smith" 34
|
"John" "Smith" 34
|
||||||
"Andrew" "Cooper" 12
|
"Andrew" "Cooper" 12
|
||||||
"Jane" "Daniels" 56]
|
"Jane" "Daniels" 56]
|
||||||
|
;; or as pure data DSL:
|
||||||
|
(-> {:insert-into [:properties]
|
||||||
|
:values [{:name "John", :surname "Smith", :age 34}
|
||||||
|
{:name "Andrew", :surname "Cooper", :age 12}
|
||||||
|
{:name "Jane", :surname "Daniels", :age 56}]}
|
||||||
|
(sql/format {:pretty true}))
|
||||||
|
=> ["
|
||||||
|
INSERT INTO properties
|
||||||
|
(name, surname, age) VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?)
|
||||||
|
"
|
||||||
|
"John" "Smith" 34
|
||||||
|
"Andrew" "Cooper" 12
|
||||||
|
"Jane" "Daniels" 56]
|
||||||
```
|
```
|
||||||
|
|
||||||
The set of columns used in the insert will be the union of all column names from all
|
The set of columns used in the insert will be the union of all column names from all
|
||||||
|
|
@ -209,13 +253,34 @@ INSERT INTO user_profile_to_role
|
||||||
"
|
"
|
||||||
12345
|
12345
|
||||||
"user"]
|
"user"]
|
||||||
|
;; or as pure data DSL:
|
||||||
|
(let [user-id 12345
|
||||||
|
role-name "user"]
|
||||||
|
(-> {:insert-into [:user_profile_to_role]
|
||||||
|
:values [{:user_profile_id 12345,
|
||||||
|
:role_id {:select [:id],
|
||||||
|
:from [:role],
|
||||||
|
:where [:= :name "user"]}}]}
|
||||||
|
(sql/format {:pretty true})))
|
||||||
|
=> ["
|
||||||
|
INSERT INTO user_profile_to_role
|
||||||
|
(user_profile_id, role_id) VALUES (?, (SELECT id FROM role WHERE name = ?))
|
||||||
|
"
|
||||||
|
12345
|
||||||
|
"user"]
|
||||||
```
|
```
|
||||||
|
|
||||||
```clojure
|
```clojure
|
||||||
(-> (select :*)
|
(-> (select :*)
|
||||||
(from :foo)
|
(from :foo)
|
||||||
(where [:in :foo.a (-> (select :a) (from :bar))])
|
(where [:in :foo.a (-> (select :a) (from :bar))])
|
||||||
sql/format)
|
(sql/format))
|
||||||
|
=> ["SELECT * FROM foo WHERE foo.a IN (SELECT a FROM bar)"]
|
||||||
|
;; or as pure data DSL:
|
||||||
|
(-> {:select [:*],
|
||||||
|
:from [:foo],
|
||||||
|
:where [:in :foo.a {:select [:a], :from [:bar]}]}
|
||||||
|
(sql/format))
|
||||||
=> ["SELECT * FROM foo WHERE foo.a IN (SELECT a FROM bar)"]
|
=> ["SELECT * FROM foo WHERE foo.a IN (SELECT a FROM bar)"]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -236,6 +301,18 @@ INSERT INTO comp_table
|
||||||
VALUES (?, (?, ?)), (?, (?, ?))
|
VALUES (?, (?, ?)), (?, (?, ?))
|
||||||
"
|
"
|
||||||
"small" 1 "inch" "large" 10 "feet"]
|
"small" 1 "inch" "large" 10 "feet"]
|
||||||
|
;; or as pure data DSL:
|
||||||
|
(-> {:insert-into [:comp_table],
|
||||||
|
:columns [:name :comp_column],
|
||||||
|
:values [["small" [:composite 1 "inch"]]
|
||||||
|
["large" [:composite 10 "feet"]]]}
|
||||||
|
(sql/format {:pretty true}))
|
||||||
|
=> ["
|
||||||
|
INSERT INTO comp_table
|
||||||
|
(name, comp_column)
|
||||||
|
VALUES (?, (?, ?)), (?, (?, ?))
|
||||||
|
"
|
||||||
|
"small" 1 "inch" "large" 10 "feet"]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Updates
|
### Updates
|
||||||
|
|
@ -256,6 +333,19 @@ WHERE kind = ?
|
||||||
"dramatic"
|
"dramatic"
|
||||||
1
|
1
|
||||||
"drama"]
|
"drama"]
|
||||||
|
;; or as pure data DSL:
|
||||||
|
(-> {:update :films,
|
||||||
|
:set {:kind "dramatic", :watched [:+ :watched 1]},
|
||||||
|
:where [:= :kind "drama"]}
|
||||||
|
(sql/format {:pretty true}))
|
||||||
|
=> ["
|
||||||
|
UPDATE films
|
||||||
|
SET kind = ?, watched = watched + ?
|
||||||
|
WHERE kind = ?
|
||||||
|
"
|
||||||
|
"dramatic"
|
||||||
|
1
|
||||||
|
"drama"]
|
||||||
```
|
```
|
||||||
|
|
||||||
If you are trying to build a compound update statement (with `from` or `join`),
|
If you are trying to build a compound update statement (with `from` or `join`),
|
||||||
|
|
@ -274,6 +364,11 @@ Deletes look as you would expect:
|
||||||
(where [:<> :kind "musical"])
|
(where [:<> :kind "musical"])
|
||||||
(sql/format))
|
(sql/format))
|
||||||
=> ["DELETE FROM films WHERE kind <> ?" "musical"]
|
=> ["DELETE FROM films WHERE kind <> ?" "musical"]
|
||||||
|
;; or as pure data DSL:
|
||||||
|
(-> {:delete-from [:films],
|
||||||
|
:where [:<> :kind "musical"]}
|
||||||
|
(sql/format))
|
||||||
|
=> ["DELETE FROM films WHERE kind <> ?" "musical"]
|
||||||
```
|
```
|
||||||
|
|
||||||
If your database supports it, you can also delete from multiple tables:
|
If your database supports it, you can also delete from multiple tables:
|
||||||
|
|
@ -291,6 +386,19 @@ INNER JOIN directors ON films.director_id = directors.id
|
||||||
WHERE kind <> ?
|
WHERE kind <> ?
|
||||||
"
|
"
|
||||||
"musical"]
|
"musical"]
|
||||||
|
;; or pure data DSL:
|
||||||
|
(-> {:delete [:films :directors],
|
||||||
|
:from [:films],
|
||||||
|
:join [:directors [:= :films.director_id :directors.id]],
|
||||||
|
:where [:<> :kind "musical"]}
|
||||||
|
(sql/format {:pretty true}))
|
||||||
|
=> ["
|
||||||
|
DELETE films, directors
|
||||||
|
FROM films
|
||||||
|
INNER JOIN directors ON films.director_id = directors.id
|
||||||
|
WHERE kind <> ?
|
||||||
|
"
|
||||||
|
"musical"]
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to delete everything from a table, you can use `truncate`:
|
If you want to delete everything from a table, you can use `truncate`:
|
||||||
|
|
@ -299,6 +407,10 @@ If you want to delete everything from a table, you can use `truncate`:
|
||||||
(-> (truncate :films)
|
(-> (truncate :films)
|
||||||
(sql/format))
|
(sql/format))
|
||||||
=> ["TRUNCATE films"]
|
=> ["TRUNCATE films"]
|
||||||
|
;; or as pure data DSL:
|
||||||
|
(-> {:truncate :films}
|
||||||
|
(sql/format))
|
||||||
|
=> ["TRUNCATE films"]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Set operations
|
### Set operations
|
||||||
|
|
@ -344,6 +456,9 @@ regular function calls in a select:
|
||||||
```clojure
|
```clojure
|
||||||
(-> (select [[:max :id]]) (from :foo) sql/format)
|
(-> (select [[:max :id]]) (from :foo) sql/format)
|
||||||
=> ["SELECT MAX(id) FROM foo"]
|
=> ["SELECT MAX(id) FROM foo"]
|
||||||
|
;; the pure data DSL requires an extra level of brackets:
|
||||||
|
(-> {:select [[[:max :id]]], :from [:foo]} sql/format)
|
||||||
|
=> ["SELECT MAX(id) FROM foo"]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Bindable parameters
|
### Bindable parameters
|
||||||
|
|
@ -356,6 +471,10 @@ Keywords that begin with `?` are interpreted as bindable parameters:
|
||||||
(where [:= :a :?baz])
|
(where [:= :a :?baz])
|
||||||
(sql/format {:params {:baz "BAZ"}}))
|
(sql/format {:params {:baz "BAZ"}}))
|
||||||
=> ["SELECT id FROM foo WHERE a = ?" "BAZ"]
|
=> ["SELECT id FROM foo WHERE a = ?" "BAZ"]
|
||||||
|
;; or as pure data DSL:
|
||||||
|
(-> {:select [:id], :from [:foo], :where [:= :a :?baz]}
|
||||||
|
(sql/format {:params {:baz "BAZ"}}))
|
||||||
|
=> ["SELECT id FROM foo WHERE a = ?" "BAZ"]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Miscellaneous
|
### Miscellaneous
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue