first pass of caching formatter
needs more documentation. Initial results suggest a speedup for simple queries of 2-3x. Complex queries can see up to 20x speedup.
This commit is contained in:
parent
91e054c58b
commit
826407e9db
5 changed files with 85 additions and 5 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
* 2.2.next in progress
|
* 2.2.next in progress
|
||||||
* Address #377 by adding `honey.sql/map=` to convert a hash map into an equality condition (for a `WHERE` clause).
|
* Address #377 by adding `honey.sql/map=` to convert a hash map into an equality condition (for a `WHERE` clause).
|
||||||
|
* Address #351 by adding a `:cache` option to `honey.sql/format` (for Clojure only, not ClojureScript).
|
||||||
* Address #281 by adding support for `SELECT * EXCEPT ..` and `SELECT * REPLACE ..` and `ARRAY<>` and `STRUCT<>` column types -- see [SQL Clause Reference - SELECT](https://cljdoc.org/d/com.github.seancorfield/honeysql/CURRENT/doc/getting-started/sql-clause-reference#select-select-distinct) and [SQL Clause Reference - DDL](https://cljdoc.org/d/com.github.seancorfield/honeysql/CURRENT/doc/getting-started/sql-clause-reference#ddl-clauses) respectively for more details.
|
* Address #281 by adding support for `SELECT * EXCEPT ..` and `SELECT * REPLACE ..` and `ARRAY<>` and `STRUCT<>` column types -- see [SQL Clause Reference - SELECT](https://cljdoc.org/d/com.github.seancorfield/honeysql/CURRENT/doc/getting-started/sql-clause-reference#select-select-distinct) and [SQL Clause Reference - DDL](https://cljdoc.org/d/com.github.seancorfield/honeysql/CURRENT/doc/getting-started/sql-clause-reference#ddl-clauses) respectively for more details.
|
||||||
* Update `build-clj` to v0.6.7.
|
* Update `build-clj` to v0.6.7.
|
||||||
|
|
||||||
|
|
|
||||||
3
deps.edn
3
deps.edn
|
|
@ -16,7 +16,8 @@
|
||||||
:test
|
:test
|
||||||
{:extra-paths ["test"]
|
{:extra-paths ["test"]
|
||||||
:extra-deps {io.github.cognitect-labs/test-runner
|
:extra-deps {io.github.cognitect-labs/test-runner
|
||||||
{:git/tag "v0.5.0" :git/sha "48c3c67"}}
|
{:git/tag "v0.5.0" :git/sha "48c3c67"}
|
||||||
|
org.clojure/core.cache {:mvn/version "RELEASE"}}
|
||||||
:exec-fn cognitect.test-runner.api/test}
|
:exec-fn cognitect.test-runner.api/test}
|
||||||
|
|
||||||
;; various "runners" for tests/CI:
|
;; various "runners" for tests/CI:
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
;; copyright (c) 2020-2021 sean corfield, all rights reserved
|
;; copyright (c) 2020-2022 sean corfield, all rights reserved
|
||||||
|
|
||||||
(ns honey.sql
|
(ns honey.sql
|
||||||
"Primary API for HoneySQL 2.x.
|
"Primary API for HoneySQL 2.x.
|
||||||
|
|
@ -1374,7 +1374,8 @@
|
||||||
as named arguments followed by other options in a hash map."
|
as named arguments followed by other options in a hash map."
|
||||||
([data] (format data {}))
|
([data] (format data {}))
|
||||||
([data opts]
|
([data opts]
|
||||||
(let [dialect? (contains? opts :dialect)
|
(let [cache (:cache opts)
|
||||||
|
dialect? (contains? opts :dialect)
|
||||||
dialect (when dialect? (get dialects (check-dialect (:dialect opts))))]
|
dialect (when dialect? (get dialects (check-dialect (:dialect opts))))]
|
||||||
(binding [*dialect* (if dialect? dialect @default-dialect)
|
(binding [*dialect* (if dialect? dialect @default-dialect)
|
||||||
*checking* (if (contains? opts :checking)
|
*checking* (if (contains? opts :checking)
|
||||||
|
|
@ -1397,7 +1398,16 @@
|
||||||
(:quoted-snake opts))
|
(:quoted-snake opts))
|
||||||
*params* (:params opts)
|
*params* (:params opts)
|
||||||
*values-default-columns* (:values-default-columns opts)]
|
*values-default-columns* (:values-default-columns opts)]
|
||||||
(mapv #(unwrap % opts) (format-dsl data opts)))))
|
(if cache
|
||||||
|
#?(:clj
|
||||||
|
;; prefer requiring-resolve but that's 1.10+ only:
|
||||||
|
(let [_ (require 'clojure.core.cache.wrapped)
|
||||||
|
through (resolve 'clojure.core.cache.wrapped/lookup-or-miss)]
|
||||||
|
(->> (through cache data (fn [_] (format-dsl data (dissoc opts :cache))))
|
||||||
|
(mapv #(unwrap % opts))))
|
||||||
|
:cljs
|
||||||
|
(throw (ex-info "cached queries are not supported in ClojureScript" opts)))
|
||||||
|
(mapv #(unwrap % opts) (format-dsl data opts))))))
|
||||||
([data k v & {:as opts}] (format data (assoc opts k v))))
|
([data k v & {:as opts}] (format data (assoc opts k v))))
|
||||||
|
|
||||||
(defn set-dialect!
|
(defn set-dialect!
|
||||||
|
|
|
||||||
68
test/honey/cache_test.clj
Normal file
68
test/honey/cache_test.clj
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
;; copyright (c) 2022 sean corfield, all rights reserved
|
||||||
|
|
||||||
|
(ns honey.cache-test
|
||||||
|
(:refer-clojure :exclude [format group-by])
|
||||||
|
(:require [clojure.core.cache.wrapped :as cache]
|
||||||
|
[clojure.test :refer [deftest is]]
|
||||||
|
[honey.sql :as sut]
|
||||||
|
[honey.sql.helpers
|
||||||
|
:refer [select-distinct from join left-join right-join where
|
||||||
|
group-by having order-by limit offset]]))
|
||||||
|
|
||||||
|
(def big-complicated-map
|
||||||
|
(-> (select-distinct :f.* :b.baz :c.quux [:b.bla "bla-bla"]
|
||||||
|
[[:now]] [[:raw "@x := 10"]])
|
||||||
|
(from [:foo :f] [:baz :b])
|
||||||
|
(join :draq [:= :f.b :draq.x]
|
||||||
|
:eldr [:= :f.e :eldr.t])
|
||||||
|
(left-join [:clod :c] [:= :f.a :c.d])
|
||||||
|
(right-join :bock [:= :bock.z :c.e])
|
||||||
|
(where [:or
|
||||||
|
[:and [:= :f.a "bort"] [:not= :b.baz [:param :param1]]]
|
||||||
|
[:and [:< 1 2] [:< 2 3]]
|
||||||
|
[:in :f.e [1 [:param :param2] 3]]
|
||||||
|
[:between :f.e 10 20]])
|
||||||
|
(group-by :f.a :c.e)
|
||||||
|
(having [:< 0 :f.e])
|
||||||
|
(order-by [:b.baz :desc] :c.quux [:f.a :nulls-first])
|
||||||
|
(limit 50)
|
||||||
|
(offset 10)))
|
||||||
|
|
||||||
|
(deftest cache-tests
|
||||||
|
(let [cache (cache/basic-cache-factory {})]
|
||||||
|
(is (= ["SELECT * FROM table WHERE id = ?" 1]
|
||||||
|
(sut/format {:select [:*] :from [:table] :where [:= :id 1]}
|
||||||
|
{:cache cache})
|
||||||
|
(sut/format {:select [:*] :from [:table] :where [:= :id 1]}
|
||||||
|
{:cache cache})))
|
||||||
|
(is (= (sut/format {:select [:*] :from [:table] :where [:= :id 1]})
|
||||||
|
(sut/format {:select [:*] :from [:table] :where [:= :id 1]}
|
||||||
|
{:cache cache})))
|
||||||
|
(is (= (sut/format big-complicated-map {:params {:param1 "gabba" :param2 2}})
|
||||||
|
(sut/format big-complicated-map {:cache cache :params {:param1 "gabba" :param2 2}})
|
||||||
|
(sut/format big-complicated-map {:cache cache :params {:param1 "gabba" :param2 2}})))
|
||||||
|
(is (= (sut/format big-complicated-map {:params {:param1 "foo" :param2 42}})
|
||||||
|
(sut/format big-complicated-map {:cache cache :params {:param1 "foo" :param2 42}})
|
||||||
|
(sut/format big-complicated-map {:cache cache :params {:param1 "foo" :param2 42}})))
|
||||||
|
(println "Uncached, simple, embedded")
|
||||||
|
(time (dotimes [_ 100000]
|
||||||
|
(sut/format {:select [:*] :from [:table] :where [:= :id 1]})))
|
||||||
|
(println "Cached, simple, embedded")
|
||||||
|
(time (dotimes [_ 100000]
|
||||||
|
(sut/format {:select [:*] :from [:table] :where [:= :id 1]} {:cache cache})))
|
||||||
|
(println "Uncached, complex, mixed")
|
||||||
|
(time (dotimes [_ 10000]
|
||||||
|
(sut/format big-complicated-map {:params {:param1 "gabba" :param2 2}})))
|
||||||
|
(println "Cached, complex, mixed")
|
||||||
|
(time (dotimes [_ 10000]
|
||||||
|
(sut/format big-complicated-map {:cache cache :params {:param1 "gabba" :param2 2}}))))
|
||||||
|
(let [cache (cache/basic-cache-factory {})]
|
||||||
|
(is (= ["SELECT * FROM table WHERE id = ?" 1]
|
||||||
|
(sut/format {:select [:*] :from [:table] :where [:= :id :?id]}
|
||||||
|
{:cache cache :params {:id 1}})
|
||||||
|
(sut/format {:select [:*] :from [:table] :where [:= :id :?id]}
|
||||||
|
{:cache cache :params {:id 1}})))
|
||||||
|
(is (= (sut/format {:select [:*] :from [:table] :where [:= :id :?id]}
|
||||||
|
{:params {:id 2}})
|
||||||
|
(sut/format {:select [:*] :from [:table] :where [:= :id :?id]}
|
||||||
|
{:cache cache :params {:id 2}})))))
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
;; copyright (c) 2021 sean corfield, all rights reserved
|
;; copyright (c) 2021-2022 sean corfield, all rights reserved
|
||||||
|
|
||||||
(ns honey.sql-test
|
(ns honey.sql-test
|
||||||
(:refer-clojure :exclude [format])
|
(:refer-clojure :exclude [format])
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue