Skip to content

Commit 13794b4

Browse files
committed
1 parent 0b4fd6e commit 13794b4

File tree

3 files changed

+102
-1
lines changed

3 files changed

+102
-1
lines changed

src/honeysql_postgres/format.cljc

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131

3232
(def ^:private postgres-clause-priorities
3333
"Determines the order that clauses will be placed within generated SQL"
34-
(merge {:with 30
34+
(merge {:explain 20
35+
:with 30
3536
:with-recursive 40
3637
:except 45
3738
:except-all 45
@@ -297,3 +298,35 @@
297298
(-> extension-name
298299
util/get-first
299300
sqlf/to-sql)))
301+
302+
(defmethod format-clause :explain [[_ [params]] _]
303+
(if (empty? params)
304+
"EXPLAIN"
305+
(let [params-string-map
306+
{:costs "COSTS"
307+
:settings "SETTINGS"
308+
:buffers "BUFFERS"
309+
:wal "WAL"
310+
:timing "TIMING"
311+
:summary "SUMMARY"}
312+
313+
format-string-map
314+
{:text "TEXT"
315+
:xml "XML"
316+
:json "JSON"
317+
:yaml "YAML"}
318+
319+
->param-string
320+
(fn [[k v]]
321+
(when-let [param-name (params-string-map k)]
322+
(sqlf/paren-wrap
323+
(sqlf/space-join [param-name (if (true? v) "TRUE" "FALSE")]))))]
324+
325+
(sqlf/space-join
326+
(remove nil?
327+
(concat ["EXPLAIN"
328+
(when (:analyze params) "ANALYZE")
329+
(when (:verbose params) "VERBOSE")
330+
(when-let [format-type (:format params)]
331+
(sqlf/paren-wrap (str "FORMAT" " " (format-string-map format-type))))]
332+
(map ->param-string params)))))))

src/honeysql_postgres/helpers.cljc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,6 @@
8383

8484
(defhelper drop-extension [m extension-name]
8585
(assoc m :drop-extension (sqlh/collify extension-name)))
86+
87+
(defhelper explain [m args]
88+
(assoc m :explain args))

test/honeysql_postgres/postgres_test.cljc

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
drop-column
1919
drop-extension
2020
drop-table
21+
explain
2122
filter
2223
insert-into-as
2324
on-conflict
@@ -354,6 +355,7 @@
354355
(within-group [(sql/call :percentile_disc (hsql-types/array [0.25 0.5 0.75])) (order-by :s.i) :alias])
355356
(from (sql/raw "generate_series(1,10) AS s(i)"))
356357
(sql/format)))))
358+
357359
(deftest create-extension-test
358360
(testing "create extension"
359361
(is (= ["CREATE EXTENSION \"uuid-ossp\""]
@@ -372,3 +374,66 @@
372374
(-> (drop-extension :uuid-ossp)
373375
(sql/format :allow-dashed-names? true
374376
:quoting :ansi))))))
377+
378+
(deftest explain-test
379+
(let [query (-> (select :*)
380+
(from :products))]
381+
(testing "EXPLAIN without any arguments"
382+
(is (= ["EXPLAIN SELECT * FROM products"]
383+
(-> query (explain) (sql/format)))))
384+
385+
(testing "Explain with analyze"
386+
(is (= ["EXPLAIN ANALYZE SELECT * FROM products"]
387+
(-> query (explain {:analyze true}) (sql/format)))))
388+
389+
(testing "Explain with analyze verbose"
390+
(is (= ["EXPLAIN ANALYZE VERBOSE SELECT * FROM products"]
391+
(-> query (explain {:analyze true :verbose true}) (sql/format))))
392+
(is (= ["EXPLAIN ANALYZE VERBOSE SELECT * FROM products"]
393+
(-> query (explain {:verbose true :analyze true}) (sql/format)))))
394+
395+
(testing "Explain with costs"
396+
(is (= ["EXPLAIN (COSTS TRUE) SELECT * FROM products"]
397+
(-> query (explain {:costs true}) (sql/format))))
398+
(is (= ["EXPLAIN (COSTS FALSE) SELECT * FROM products"]
399+
(-> query (explain {:costs false}) (sql/format)))))
400+
401+
(testing "Explain with settings"
402+
(is (= ["EXPLAIN (SETTINGS TRUE) SELECT * FROM products"]
403+
(-> query (explain {:settings true}) (sql/format))))
404+
(is (= ["EXPLAIN (SETTINGS FALSE) SELECT * FROM products"]
405+
(-> query (explain {:settings false}) (sql/format)))))
406+
407+
(testing "Explain with buffers"
408+
(is (= ["EXPLAIN (BUFFERS TRUE) SELECT * FROM products"]
409+
(-> query (explain {:buffers true}) (sql/format))))
410+
(is (= ["EXPLAIN (BUFFERS FALSE) SELECT * FROM products"]
411+
(-> query (explain {:buffers false}) (sql/format)))))
412+
413+
(testing "Explain with wal"
414+
(is (= ["EXPLAIN (WAL TRUE) SELECT * FROM products"]
415+
(-> query (explain {:wal true}) (sql/format))))
416+
(is (= ["EXPLAIN (WAL FALSE) SELECT * FROM products"]
417+
(-> query (explain {:wal false}) (sql/format)))))
418+
419+
(testing "Explain with timing"
420+
(is (= ["EXPLAIN (TIMING TRUE) SELECT * FROM products"]
421+
(-> query (explain {:timing true}) (sql/format))))
422+
(is (= ["EXPLAIN (TIMING FALSE) SELECT * FROM products"]
423+
(-> query (explain {:timing false}) (sql/format)))))
424+
425+
(testing "Explain with summary"
426+
(is (= ["EXPLAIN (SUMMARY TRUE) SELECT * FROM products"]
427+
(-> query (explain {:summary true}) (sql/format))))
428+
(is (= ["EXPLAIN (SUMMARY FALSE) SELECT * FROM products"]
429+
(-> query (explain {:summary false}) (sql/format)))))
430+
431+
(testing "Explain with format"
432+
(is (= ["EXPLAIN (FORMAT TEXT) SELECT * FROM products"]
433+
(-> query (explain {:format :text}) (sql/format))))
434+
(is (= ["EXPLAIN (FORMAT XML) SELECT * FROM products"]
435+
(-> query (explain {:format :xml}) (sql/format))))
436+
(is (= ["EXPLAIN (FORMAT JSON) SELECT * FROM products"]
437+
(-> query (explain {:format :json}) (sql/format))))
438+
(is (= ["EXPLAIN (FORMAT YAML) SELECT * FROM products"]
439+
(-> query (explain {:format :yaml}) (sql/format)))))))

0 commit comments

Comments
 (0)