From 1d22086fce9552c9f813ba76171312504fd55a5d Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sun, 30 Jan 2022 22:31:37 -0800 Subject: [PATCH] fix #381 by adding generic helpers; prep for 2.2.861 --- CHANGELOG.md | 3 ++- README.md | 2 +- doc/differences-from-1-x.md | 2 +- doc/extending-honeysql.md | 22 ++++++++++++++++++++++ doc/getting-started.md | 4 ++-- src/honey/sql/helpers.cljc | 23 ++++++++++++++++++++++- test/honey/sql/helpers_test.cljc | 12 ++++++++++++ 7 files changed, 62 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76922d8..fafea44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Changes -* 2.2.next in progress +* 2.2.861 -- 2022-01-30 * Address [#382](https://github.com/seancorfield/honeysql/issues/382) by adding `:case-expr` for BigQuery support. + * Address [#381](https://github.com/seancorfield/honeysql/issues/381) by adding `generic-helper-variadic` and `generic-helper-unary` to `honey.sql.helpers`. * Fix [#380](https://github.com/seancorfield/honeysql/issues/380) by correcting test for function type in `register-clause!` and `register-fn!`. * 2.2.858 -- 2022-01-20 diff --git a/README.md b/README.md index ea62435..f31e991 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ SQL as Clojure data structures. Build queries programmatically -- even at runtim ## Build -[![Clojars Project](https://clojars.org/com.github.seancorfield/honeysql/latest-version.svg)](https://clojars.org/com.github.seancorfield/honeysql) [![cljdoc badge](https://cljdoc.org/badge/com.github.seancorfield/honeysql?2.2.858)](https://cljdoc.org/d/com.github.seancorfield/honeysql/CURRENT) +[![Clojars Project](https://clojars.org/com.github.seancorfield/honeysql/latest-version.svg)](https://clojars.org/com.github.seancorfield/honeysql) [![cljdoc badge](https://cljdoc.org/badge/com.github.seancorfield/honeysql?2.2.861)](https://cljdoc.org/d/com.github.seancorfield/honeysql/CURRENT) This project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository. diff --git a/doc/differences-from-1-x.md b/doc/differences-from-1-x.md index 907891a..29b5fed 100644 --- a/doc/differences-from-1-x.md +++ b/doc/differences-from-1-x.md @@ -63,7 +63,7 @@ Supported Clojure versions: 1.7 and later. In `deps.edn`: ```clojure -com.github.seancorfield/honeysql {:mvn/version "2.2.858"} +com.github.seancorfield/honeysql {:mvn/version "2.2.861"} ``` Required as: diff --git a/doc/extending-honeysql.md b/doc/extending-honeysql.md index e28a1d7..38655f8 100644 --- a/doc/extending-honeysql.md +++ b/doc/extending-honeysql.md @@ -38,6 +38,28 @@ current ordering of clauses is. > Note: if you call `register-clause!` more than once for the same clause, the last call "wins". This allows you to correct an incorrect clause order insertion by simply calling `register-clause!` again with a different third argument. +## Defining a Helper Function for a New Clause + +Having registered a new clause, you might also want a helper function +for it, just as the built-in clauses have helpers in `honey.sql.helpers`. +Two functions exist in that namespace to make it easier for you to +define your own helpers: + +* `generic-helper-variadic` -- most clauses accept an arbitrary number of items in a sequence and multiple calls in a DSL expression will merge so this is the helper you will use for most clauses, +* `generic-helper-unary` -- a handful of clauses only accept a single item and cannot be merged (they behave as "last one wins"), so this helper supports that semantic. + +Each of these helper support functions should be called with the keyword that +identifies your new clause and the sequence of arguments passed to it. See +the docstrings for more detail. + +You might have: + + +```clojure +(sql/register-clause! :my-clause my-formatter :where) +(defn my-clause [& args] (h/generic-helper-variadic :my-clause args)) +``` + ## Registering a New Operator `honey.sql/register-op!` accepts a keyword (or a symbol) that diff --git a/doc/getting-started.md b/doc/getting-started.md index 85ab79b..ad86fba 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -10,14 +10,14 @@ For the Clojure CLI, add the following dependency to your `deps.edn` file: ```clojure - com.github.seancorfield/honeysql {:mvn/version "2.2.858"} + com.github.seancorfield/honeysql {:mvn/version "2.2.861"} ``` For Leiningen, add the following dependency to your `project.clj` file: ```clojure - [com.github.seancorfield/honeysql "2.2.858"] + [com.github.seancorfield/honeysql "2.2.861"] ``` HoneySQL produces SQL statements but does not execute them. diff --git a/src/honey/sql/helpers.cljc b/src/honey/sql/helpers.cljc index 1e3a30a..3c6346c 100644 --- a/src/honey/sql/helpers.cljc +++ b/src/honey/sql/helpers.cljc @@ -995,6 +995,26 @@ :where where} do-update-set)))))) +(defn generic-helper-variadic + "Most clauses that accept a sequence of items can be implemented + using this helper, as: + + (defn my-helper [& args] (generic-helper-variadic :my-clause args))" + [k args] + (generic k args)) + +(defn generic-helper-unary + "Clauses that accept only a single item can be implemented + using this helper, as: + + (defn my-helper [& args] (generic-helper-unary :my-clause args)) + + Even though your helper is designed for clauses that accept + only a single item, you should still define it as variadic, + because that is the convention all helpers use here." + [k args] + (generic-1 k args)) + #?(:clj (do ;; ensure #295 stays true (all public functions have docstring): @@ -1002,6 +1022,7 @@ ;; ensure all public functions match clauses: (assert (= (clojure.core/set (conj @@#'honey.sql/base-clause-order :composite :filter :lateral :over :within-group - :upsert)) + :upsert + :generic-helper-variadic :generic-helper-unary)) (clojure.core/set (conj (map keyword (keys (ns-publics *ns*))) :nest :raw)))))) diff --git a/test/honey/sql/helpers_test.cljc b/test/honey/sql/helpers_test.cljc index 76fa2f8..c0d0654 100644 --- a/test/honey/sql/helpers_test.cljc +++ b/test/honey/sql/helpers_test.cljc @@ -369,6 +369,18 @@ (join :x [:using :id] :y [:using :foo :bar]) sql/format))))) +(defn my-update [& args] (h/generic-helper-unary :update args)) +(defn my-set [& args] (h/generic-helper-unary :set args)) +(defn my-where [& args] (h/generic-helper-variadic :where args)) + +(deftest custom-helpers-test + (testing "nil join" + (is (= ["UPDATE foo SET bar = ? WHERE quux = ?" 1 2] + (-> (my-update :foo) + (my-set {:bar 1}) + (my-where (sql/map= {:quux 2})) + sql/format))))) + (deftest inline-test (is (= ["SELECT * FROM foo WHERE id = 5"] (-> (select :*)