Address #266 by adding :pretty? true option

Adds newline before, after, and between each SQL clause.
This commit is contained in:
Sean Corfield 2020-09-25 23:58:51 -07:00
parent 4d3b317520
commit 6aced04179
2 changed files with 72 additions and 66 deletions

127
README.md
View file

@ -20,8 +20,6 @@ All sample code in this README is automatically run as a unit test using
Note that while some of these samples show pretty-printed SQL, this is just for Note that while some of these samples show pretty-printed SQL, this is just for
README readability; honeysql does not generate pretty-printed SQL. README readability; honeysql does not generate pretty-printed SQL.
_The `#sql/regularize` directive tells the test-runner to ignore the extraneous whitespace._ [TODO: replace with pretty print option!]
## Usage ## Usage
```clojure ```clojure
@ -147,11 +145,12 @@ then provide a collection of rows, each a collection of column values:
[["Jon" "Smith" 34] [["Jon" "Smith" 34]
["Andrew" "Cooper" 12] ["Andrew" "Cooper" 12]
["Jane" "Daniels" 56]]) ["Jane" "Daniels" 56]])
sql/format) (sql/format {:pretty? true}))
=> [#sql/regularize => ["
"INSERT INTO properties (name, surname, age) INSERT INTO properties (name, surname, age)
VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?)" VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?)
"Jon" "Smith" 34 "Andrew" "Cooper" 12 "Jane" "Daniels" 56] "
"Jon" "Smith" 34 "Andrew" "Cooper" 12 "Jane" "Daniels" 56]
``` ```
@ -163,13 +162,14 @@ and the remaining maps *must* have the same set of keys and values:
(values [{:name "John" :surname "Smith" :age 34} (values [{:name "John" :surname "Smith" :age 34}
{:name "Andrew" :surname "Cooper" :age 12} {:name "Andrew" :surname "Cooper" :age 12}
{:name "Jane" :surname "Daniels" :age 56}]) {:name "Jane" :surname "Daniels" :age 56}])
sql/format) (sql/format {:pretty? true}))
=> [#sql/regularize => ["
"INSERT INTO properties (name, surname, age) INSERT INTO properties (name, surname, age)
VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?)" VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?)
"John" "Smith" 34 "
"Andrew" "Cooper" 12 "John" "Smith" 34
"Jane" "Daniels" 56] "Andrew" "Cooper" 12
"Jane" "Daniels" 56]
``` ```
### Nested subqueries ### Nested subqueries
@ -184,13 +184,14 @@ The column values do not have to be literals, they can be nested queries:
:role_id (-> (select :id) :role_id (-> (select :id)
(from :role) (from :role)
(where [:= :name role-name]))}]) (where [:= :name role-name]))}])
sql/format)) (sql/format {:pretty? true})))
=> [#sql/regularize => ["
"INSERT INTO user_profile_to_role (user_profile_id, role_id) INSERT INTO user_profile_to_role (user_profile_id, role_id)
VALUES (?, (SELECT id FROM role WHERE name = ?))" VALUES (?, (SELECT id FROM role WHERE name = ?))
12345 "
"user"] 12345
"user"]
``` ```
```clojure ```clojure
@ -211,11 +212,12 @@ Composite types are supported:
(values (values
[["small" (composite 1 "inch")] [["small" (composite 1 "inch")]
["large" (composite 10 "feet")]]) ["large" (composite 10 "feet")]])
sql/format) (sql/format {:pretty? true}))
=> [#sql/regularize => ["
"INSERT INTO comp_table (name, comp_column) INSERT INTO comp_table (name, comp_column)
VALUES (?, (?, ?)), (?, (?, ?))" VALUES (?, (?, ?)), (?, (?, ?))
"small" 1 "inch" "large" 10 "feet"] "
"small" 1 "inch" "large" 10 "feet"]
``` ```
### Updates ### Updates
@ -228,13 +230,14 @@ with `clojure.core/set`):
(sset {:kind "dramatic" (sset {:kind "dramatic"
:watched (sql/call :+ :watched 1)}) :watched (sql/call :+ :watched 1)})
(where [:= :kind "drama"]) (where [:= :kind "drama"])
sql/format) (sql/format {:pretty? true}))
=> [#sql/regularize => ["
"UPDATE films SET kind = ?, watched = (watched + ?) UPDATE films SET kind = ?, watched = (watched + ?)
WHERE kind = ?" WHERE kind = ?
"dramatic" "
1 "dramatic"
"drama"] 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`),
@ -251,7 +254,7 @@ Deletes look as you would expect:
```clojure ```clojure
(-> (delete-from :films) (-> (delete-from :films)
(where [:<> :kind "musical"]) (where [:<> :kind "musical"])
sql/format) (sql/format))
=> ["DELETE FROM films WHERE kind <> ?" "musical"] => ["DELETE FROM films WHERE kind <> ?" "musical"]
``` ```
@ -262,20 +265,21 @@ If your database supports it, you can also delete from multiple tables:
(from :films) (from :films)
(join :directors [:= :films.director_id :directors.id]) (join :directors [:= :films.director_id :directors.id])
(where [:<> :kind "musical"]) (where [:<> :kind "musical"])
sql/format) (sql/format {:pretty? true}))
=> [#sql/regularize => ["
"DELETE films, directors DELETE films, directors
FROM films FROM films
INNER JOIN directors ON films.director_id = directors.id INNER JOIN directors ON films.director_id = directors.id
WHERE kind <> ?" WHERE kind <> ?
"musical"] "
"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`:
```clojure ```clojure
(-> (truncate :films) (-> (truncate :films)
sql/format) (sql/format))
=> ["TRUNCATE films"] => ["TRUNCATE films"]
``` ```
@ -348,11 +352,12 @@ have a lot of function calls needed in code:
(values [{:location [:ST_SetSRID (values [{:location [:ST_SetSRID
[:ST_MakePoint 0.291 32.621] [:ST_MakePoint 0.291 32.621]
[:cast 4325 :integer]]}]) [:cast 4325 :integer]]}])
(sql/format)) (sql/format {:pretty? true}))
=> [#sql/regularize => ["
"INSERT INTO sample (location) INSERT INTO sample (location)
VALUES (ST_SetSRID(ST_MakePoint(?, ?), CAST(? AS integer)))" VALUES (ST_SetSRID(ST_MakePoint(?, ?), CAST(? AS integer)))
0.291 32.621 4326] "
0.291 32.621 4326]
``` ```
#### Raw SQL fragments #### Raw SQL fragments
@ -477,22 +482,20 @@ big-complicated-map
``` ```
```clojure ```clojure
(sql/format big-complicated-map {:param1 "gabba" :param2 2}) (sql/format big-complicated-map {:param1 "gabba" :param2 2})
=> [#sql/regularize => ["
"SELECT DISTINCT f.*, b.baz, c.quux, b.bla AS bla_bla, now(), @x := 10 SELECT DISTINCT f.*, b.baz, c.quux, b.bla AS bla_bla, now(), @x := 10
FROM foo f, baz b FROM foo f, baz b
INNER JOIN draq ON f.b = draq.x INNER JOIN draq ON f.b = draq.x
LEFT JOIN clod c ON f.a = c.d LEFT JOIN clod c ON f.a = c.d
RIGHT JOIN bock ON bock.z = c.e RIGHT JOIN bock ON bock.z = c.e
WHERE ((f.a = ? AND b.baz <> ?) WHERE ((f.a = ? AND b.baz <> ?) OR (? < ? AND ? < ?) OR (f.e in (?, ?, ?)) OR f.e BETWEEN ? AND ?)
OR (? < ? AND ? < ?) GROUP BY f.a, c.e
OR (f.e in (?, ?, ?)) HAVING ? < f.e
OR f.e BETWEEN ? AND ?) ORDER BY b.baz DESC, c.quux, f.a NULLS FIRST
GROUP BY f.a, c.e LIMIT ?
HAVING ? < f.e OFFSET ?
ORDER BY b.baz DESC, c.quux, f.a NULLS FIRST "
LIMIT ? "bort" "gabba" 1 2 2 3 1 2 3 10 20 0 50 10]
OFFSET ? "
"bort" "gabba" 1 2 2 3 1 2 3 10 20 0 50 10]
``` ```
```clojure ```clojure
;; Printable and readable ;; Printable and readable

View file

@ -374,7 +374,7 @@
;:values 220 ;:values 220
:query-values 230}) :query-values 230})
(defn- format-dsl [x & [{:keys [aliased? nested?]}]] (defn- format-dsl [x & [{:keys [aliased? nested? pretty?]}]]
(let [[sqls params leftover] (let [[sqls params leftover]
(reduce (fn [[sql params leftover] k] (reduce (fn [[sql params leftover] k]
(if-let [xs (k x)] (if-let [xs (k x)]
@ -395,7 +395,9 @@
(str/join ", " (keys leftover))) (str/join ", " (keys leftover)))
leftover)) leftover))
[(str "<unknown" (str/join (keys leftover)) ">")]) [(str "<unknown" (str/join (keys leftover)) ">")])
(into [(cond-> (str/join " " sqls) (into [(cond-> (str/join (if pretty? "\n" " ") sqls)
pretty?
(as-> s (str "\n" s "\n"))
(and nested? (not aliased?)) (and nested? (not aliased?))
(as-> s (str "(" s ")")))] params)))) (as-> s (str "(" s ")")))] params))))
@ -551,7 +553,7 @@
*quoted* (if (contains? opts :quoted) *quoted* (if (contains? opts :quoted)
(:quoted opts) (:quoted opts)
dialect?)] dialect?)]
(mapv #(unwrap % opts) (format-dsl data)))))) (mapv #(unwrap % opts) (format-dsl data opts))))))
(defn set-dialect! (defn set-dialect!
"Set the default dialect for formatting. "Set the default dialect for formatting.
@ -603,9 +605,10 @@
(format {:select [:*] :from [:table] :group-by [[:date :bar]]} {}) (format {:select [:*] :from [:table] :group-by [[:date :bar]]} {})
(format {:select [:*] :from [:table] :order-by [[:foo :desc] :bar]} {}) (format {:select [:*] :from [:table] :order-by [[:foo :desc] :bar]} {})
(format {:select [:*] :from [:table] :order-by [[[:date :expiry] :desc] :bar]} {}) (format {:select [:*] :from [:table] :order-by [[[:date :expiry] :desc] :bar]} {})
(println (format {:select [:*] :from [:table] :order-by [[[:date :expiry] :desc] :bar]} {:pretty? true}))
(format {:select [:*] :from [:table] :where [:< [:date_add :expiry [:interval 30 :days]] [:now]]} {}) (format {:select [:*] :from [:table] :where [:< [:date_add :expiry [:interval 30 :days]] [:now]]} {})
(format-expr [:interval 30 :days]) (format-expr [:interval 30 :days])
(format {:select [:*] :from [:table] :where [:= :id (int 1)]} {:dialect :mysql}) (format {:select [:*] :from [:table] :where [:= :id (int 1)]} {:dialect :mysql})
(map fn? (format {:select [:*] :from [:table] :where [:= :id (with-meta (constantly 42) {:foo true})]} {:dialect :mysql})) (map fn? (format {:select [:*] :from [:table] :where [:= :id (with-meta (constantly 42) {:foo true})]} {:dialect :mysql}))
(format {:select [:*] :from [:table] :where [:in :id [1 2 3 4]]} {}) (println (format {:select [:*] :from [:table] :where [:in :id [1 2 3 4]]} {:pretty? true}))
,) ,)