From 2fe083f8e60c3876ba7f103aae5f54e8f262a761 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Fri, 9 Apr 2021 17:04:48 -0700 Subject: [PATCH] Support named arguments in format again With the advent of Clojure 1.11 and the ability to call functions that accept named arguments using a hash map, I have restored the named argument version of `format` (in addition to the hash map version), and if you are using Clojure 1.11 you can mix'n'match styles. --- doc/differences-from-1-x.md | 7 ++++--- src/honey/sql.cljc | 3 ++- test/honey/sql_test.cljc | 27 ++++++++++++++++++++++++++- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/doc/differences-from-1-x.md b/doc/differences-from-1-x.md index 75f7352..1c60189 100644 --- a/doc/differences-from-1-x.md +++ b/doc/differences-from-1-x.md @@ -4,7 +4,10 @@ The goal of HoneySQL 1.x and earlier was to provide a DSL for vendor-neutral SQL The goal of HoneySQL 2.x is to provide an easily-extensible DSL for SQL, supporting vendor-specific differences and extensions, that is as consistent as possible. A secondary goal is to make maintenance much easier by streamlining the machinery and reducing the number of different ways to write and/or extend the DSL. -The DSL itself -- the data structures that both versions convert to SQL and parameters via the `format` function -- is almost exactly the same between the two versions so that migration is relatively painless. The primary API -- the `format` function -- is preserved in 2.x, although the variadic options from 1.x have changed to an options hash map in 2.x as this is generally considered more idiomatic. See the **Option Changes** section below for the differences in the options supported. +The DSL itself -- the data structures that both versions convert to SQL and parameters via the `format` function -- is almost exactly the same between the two versions so that migration is relatively painless. The primary API -- the `format` function -- is preserved in 2.x, although the options have changed between 1.x and 2.x. See the **Option Changes** section below for the differences in the options supported. +`format` can accept its options as a single hash map or as named arguments (v1 only supported the latter). +If you are using Clojure 1.11, you can invoke `format` with a mixture of named arguments and a trailing hash +map of additional options, if you wish. HoneySQL 1.x supported Clojure 1.7 and later. HoneySQL 2.x requires Clojure 1.9 or later. @@ -78,8 +81,6 @@ You can now select a non-ANSI dialect of SQL using the new `honey.sql/set-dialec ## Option Changes -As noted above, the variadic options for `format` have been replaced by a single hash map as the optional second argument to `format`. - The `:quoting ` option has superseded by the new dialect machinery and a new `:quoted` option that turns quoting on or off. You either use `:dialect ` instead or set a default dialect (via `set-dialect!`) and then use `:quoted true` in `format` calls where you want quoting. Identifiers are automatically quoted if you specify a `:dialect` option to `format`, unless you also specify `:quoted false`. diff --git a/src/honey/sql.cljc b/src/honey/sql.cljc index baf0ce3..5be39e2 100644 --- a/src/honey/sql.cljc +++ b/src/honey/sql.cljc @@ -1192,7 +1192,8 @@ (:quoted opts) dialect?) *params* (:params opts)] - (mapv #(unwrap % opts) (format-dsl data opts)))))) + (mapv #(unwrap % opts) (format-dsl data opts))))) + ([data k v & {:as opts}] (format data (assoc opts k v)))) (defn set-dialect! "Set the default dialect for formatting. diff --git a/test/honey/sql_test.cljc b/test/honey/sql_test.cljc index 1ccafa1..6b4d4ff 100644 --- a/test/honey/sql_test.cljc +++ b/test/honey/sql_test.cljc @@ -2,7 +2,8 @@ (ns honey.sql-test (:refer-clojure :exclude [format]) - (:require #?(:clj [clojure.test :refer [deftest is testing]] + (:require [clojure.string :as str] + #?(:clj [clojure.test :refer [deftest is testing]] :cljs [cljs.test :refer-macros [deftest is testing]]) [honey.sql :as sut :refer [format]] [honey.sql.helpers :as h])) @@ -383,6 +384,30 @@ :where [:= :bar.b 42]} (format {:dialect :mysql}))))) +(deftest format-arity-test + (testing "format can be called with no options" + (is (= ["DELETE FROM foo WHERE foo.id = ?" 42] + (-> {:delete-from :foo + :where [:= :foo.id 42]} + (format))))) + (testing "format can be called with an options hash map" + (is (= ["\nDELETE FROM `foo`\nWHERE `foo`.`id` = ?\n" 42] + (-> {:delete-from :foo + :where [:= :foo.id 42]} + (format {:dialect :mysql :pretty true}))))) + (testing "format can be called with named arguments" + (is (= ["\nDELETE FROM `foo`\nWHERE `foo`.`id` = ?\n" 42] + (-> {:delete-from :foo + :where [:= :foo.id 42]} + (format :dialect :mysql :pretty true))))) + (when (str/starts-with? #?(:clj (clojure-version) + :cljs *clojurescript-version*) "1.11") + (testing "format can be called with mixed arguments" + (is (= ["\nDELETE FROM `foo`\nWHERE `foo`.`id` = ?\n" 42] + (-> {:delete-from :foo + :where [:= :foo.id 42]} + (format :dialect :mysql {:pretty true}))))))) + (deftest delete-from-test (is (= ["DELETE FROM `foo` WHERE `foo`.`id` = ?" 42] (-> {:delete-from :foo