From 5441cb548806d4dffd63bd7cc3d488a381c71dd8 Mon Sep 17 00:00:00 2001 From: JC <11434205+dijonkitchen@users.noreply.github.com> Date: Fri, 7 Feb 2020 10:31:57 -0800 Subject: [PATCH 1/2] docs: clarify SQL `AND` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 435aa2e..6a9c2b4 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ To add to clauses instead of replacing them, use `merge-select`, `merge-where`, => ["SELECT a, b, c, d, e FROM foo WHERE (f.a = ? AND b > ?)" "baz" 10] ``` -`where` will combine multiple clauses together using and: +`where` will combine multiple clauses together using SQL's `AND`: ```clojure (-> (select :*) From 3ca332f1117d9576a13c5e57db2880cc7d3b6634 Mon Sep 17 00:00:00 2001 From: JC <11434205+dijonkitchen@users.noreply.github.com> Date: Fri, 7 Feb 2020 13:49:32 -0800 Subject: [PATCH 2/2] docs: section up Readme for permalinkability --- README.md | 56 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6a9c2b4..fcea950 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,8 @@ Everything is built on top of maps representing SQL queries: Column names can be provided as keywords or symbols (but not strings -- HoneySQL treats strings as values that should be lifted out of the SQL as parameters). +### `format` + `format` turns maps into `clojure.java.jdbc`-compatible, parameterized SQL: ```clojure @@ -66,6 +68,8 @@ to jdbc: (jdbc/query conn (sql/format sqlmap)) ``` +### `build` + You can build up SQL maps yourself or use helper functions. `build` is the Swiss Army Knife helper. It lets you leave out brackets here and there: ```clojure @@ -86,6 +90,8 @@ You can provide a "base" map as the first argument to build: :from [:foo]} ``` +### Vanilla SQL clause helpers + There are also functions for each clause type in the `honeysql.helpers` namespace: ```clojure @@ -143,6 +149,8 @@ name and the desired alias: In particular, note that `(select [:a :b])` means `SELECT a AS b` rather than `SELECT a, b` -- `select` is variadic and does not take a collection of column names. +### Inserts + Inserts are supported in two patterns. In the first pattern, you must explicitly specify the columns to insert, then provide a collection of rows, each a collection of column values: @@ -179,6 +187,8 @@ and the remaining maps *must* have the same set of keys and values: "Jane" "Daniels" 56] ``` +### Nested subqueries + The column values do not have to be literals, they can be nested queries: ```clojure @@ -198,6 +208,16 @@ The column values do not have to be literals, they can be nested queries: "user"] ``` +```clojure +(-> (select :*) + (from :foo) + (where [:in :foo.a (-> (select :a) (from :bar))]) + sql/format) +=> ["SELECT * FROM foo WHERE (foo.a in (SELECT a FROM bar))"] +``` + +### Composite types + Composite types are supported: ```clojure @@ -213,6 +233,8 @@ Composite types are supported: "small" 1 "inch" "large" 10 "feet"] ``` +### Updates + Updates are possible too (note the double S in `sset` to avoid clashing with `clojure.core/set`): @@ -238,6 +260,8 @@ There are two variants of `sset` (and the underlying `:set` in the SQL map): * `set0` (and `:set0`) -- this puts the `SET` before `FROM`, * `set1` (and `:set1`) -- a synonym for `sset` (and `:set`) that puts the `SET` after `JOIN`. +### Deletes + Deletes look as you would expect: ```clojure @@ -271,15 +295,7 @@ If you want to delete everything from a table, you can use `truncate`: => ["TRUNCATE films"] ``` -Queries can be nested: - -```clojure -(-> (select :*) - (from :foo) - (where [:in :foo.a (-> (select :a) (from :bar))]) - sql/format) -=> ["SELECT * FROM foo WHERE (foo.a in (SELECT a FROM bar))"] -``` +### Unions Queries may be united within a :union or :union-all keyword: @@ -289,6 +305,8 @@ Queries may be united within a :union or :union-all keyword: => ["SELECT * FROM foo UNION SELECT * FROM bar"] ``` +### Functions + Keywords that begin with `%` are interpreted as SQL function calls: ```clojure @@ -298,6 +316,8 @@ Keywords that begin with `%` are interpreted as SQL function calls: => ["SELECT max(id) FROM foo"] ``` +### Bindable parameters + Keywords that begin with `?` are interpreted as bindable parameters: ```clojure @@ -308,6 +328,8 @@ Keywords that begin with `?` are interpreted as bindable parameters: => ["SELECT id FROM foo WHERE a = ?" "BAZ"] ``` +### Miscellaneous + There are helper functions and data literals for SQL function calls, field qualifiers, raw SQL fragments, inline values, and named input parameters: @@ -326,6 +348,8 @@ call-qualify-map => ["SELECT foo(bar), foo.a, @var := foo.bar FROM foo WHERE (a = ? AND b = 42)" "BAZ"] ``` +#### PostGIS + A common example in the wild is the PostGIS extension to PostgreSQL where you have a lot of function calls needed in code: @@ -341,6 +365,8 @@ have a lot of function calls needed in code: 0.291 32.621 4326] ``` +#### Raw SQL fragments + Raw SQL fragments that are strings are treated exactly as-is when rendered into the formatted SQL string (with no parsing or parameterization). Inline values will not be lifted out as parameters, so they end up in the SQL string as-is. @@ -366,6 +392,8 @@ or the `param` helper. => ["SELECT * FROM foo WHERE expired_at < now() - '? seconds'" 5] ``` +#### Identifiers + To quote identifiers, pass the `:quoting` keyword option to `format`. Valid options are `:ansi` (PostgreSQL), `:mysql`, or `:sqlserver`: ```clojure @@ -376,9 +404,11 @@ To quote identifiers, pass the `:quoting` keyword option to `format`. Valid opti => ["SELECT `foo`.`a` FROM `foo` WHERE `foo`.`a` = ?" "baz"] ``` +#### Locking + To issue a locking select, add a `:lock` to the query or use the lock helper. The lock value must be a map with a `:mode` value. The built-in -modes are the standard :update (FOR UPDATE) or the vendor-specific `:mysql-share` (LOCK IN SHARE MODE) or `:postresql-share` (FOR SHARE). The -lock map may also provide a :wait value, which if false will append the NOWAIT parameter, supported by PostgreSQL. +modes are the standard `:update` (FOR UPDATE) or the vendor-specific `:mysql-share` (LOCK IN SHARE MODE) or `:postresql-share` (FOR SHARE). The +lock map may also provide a `:wait` value, which if false will append the NOWAIT parameter, supported by PostgreSQL. ```clojure (-> (select :foo.a) @@ -402,6 +432,8 @@ To be able to use dashes in quoted names, you can pass ```:allow-dashed-names tr => ["SELECT \"f\".\"foo-id\", \"f\".\"foo-name\" FROM \"foo-bar\" \"f\" WHERE \"f\".\"foo-id\" = ?" 12345] ``` +### Big, complicated example + Here's a big, complicated query. Note that Honey SQL makes no attempt to verify that your queries make any sense. It merely renders surface syntax. ```clojure @@ -538,7 +570,7 @@ To teach `honeysql` how to handle your datatype you need to implement [`honeysql ``` ## TODO -* Create table, etc. +- [ ] Create table, etc. ## Extensions