diff --git a/CHANGELOG.md b/CHANGELOG.md index 46d7a83..6931b8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # Changes * 2.0.next in progress - * Address #326 by allowing `ON`/`USING` to be optional and not dropping parameters on the floor. _[still needs tests to be written!]_ - * Fix #325 by making the `%` function call syntax respect `:quoted true` and/or `:dialect` options, and also allowing for qualified column names _[some additional tests needed plus likely documentation updates]_. (PR from @lognush) + * Fix #326 by allowing `ON`/`USING` to be optional and not dropping parameters on the floor. + * Fix #325 by making the `%` function call syntax respect `:quoted true` and/or `:dialect` options, and also allowing for qualified column names. (PR from @lognush) * Add `:quoted-snake true` option to force conversion from kebab-case to snake_case when `:quoted true` or a `:dialect` is specified to `format`. * Update `test-runner`. diff --git a/doc/getting-started.md b/doc/getting-started.md index e7e3615..f4e63b3 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -136,6 +136,13 @@ are split at `.` and turned into function calls: %f.a.b ;=> F(a,b) ``` +If you need to reference a table or alias for a column, you can use +qualified names in a function invocation: + +```clojure +%max.foo/bar ;=> MAX(foo.bar) +``` + ## SQL Parameters As indicated in the preceding sections, values found in the DSL data structure diff --git a/test/honey/sql_test.cljc b/test/honey/sql_test.cljc index ff12565..3a500a8 100644 --- a/test/honey/sql_test.cljc +++ b/test/honey/sql_test.cljc @@ -1,4 +1,4 @@ -;; copyright (c) sean corfield, all rights reserved +;; copyright (c) 2021 sean corfield, all rights reserved (ns honey.sql-test (:refer-clojure :exclude [format]) @@ -747,8 +747,39 @@ ORDER BY id = ? DESC (format {:select [[[:greater :foo-foo :bar-bar]]]} :dialect :mysql) (format {:select :%greater.foo-foo.bar-bar} :dialect :mysql))) (is (= ["SELECT MIXED_KEBAB(`yum-yum`)"] - #_(format {:select [[[:mixed-kebab :yum-yum]]]} :dialect :mysql) (format {:select :%mixed-kebab.yum-yum} :dialect :mysql))) + (is (= ["SELECT MIXED_KEBAB(`yum_yum`)"] + (format {:select :%mixed-kebab.yum-yum} :dialect :mysql :quoted-snake true))) + ;; qualifier is always - -> _ converted: + (is (= ["SELECT MIXED_KEBAB(`yum_yum`.`bar-bar`, `a_b`.`c-d`)"] + (format {:select :%mixed-kebab.yum-yum/bar-bar.a-b/c-d} :dialect :mysql))) + ;; name is only - -> _ converted when snake_case requested: + (is (= ["SELECT MIXED_KEBAB(`yum_yum`.`bar_bar`, `a_b`.`c_d`)"] + (format {:select :%mixed-kebab.yum-yum/bar-bar.a-b/c-d} :dialect :mysql :quoted-snake true))) (is (= ["SELECT RANSOM(`NoTe`)"] (format {:select [[[:ransom :NoTe]]]} :dialect :mysql) (format {:select :%ransom.NoTe} :dialect :mysql))))) + +(deftest join-without-on-using + ;; essentially issue 326 + (testing "join does not need on or using" + (is (= ["SELECT foo FROM bar INNER JOIN quux"] + (format {:select :foo + :from :bar + :join [:quux]})))) + (testing "join on select with parameters" + (is (= ["SELECT foo FROM bar INNER JOIN (SELECT a FROM b WHERE id = ?) WHERE id = ?" 123 456] + (format {:select :foo + :from :bar + :join [{:select :a :from :b :where [:= :id 123]}] + :where [:= :id 456]}))) + (is (= ["SELECT foo FROM bar INNER JOIN (SELECT a FROM b WHERE id = ?) AS x WHERE id = ?" 123 456] + (format {:select :foo + :from :bar + :join [[{:select :a :from :b :where [:= :id 123]} :x]] + :where [:= :id 456]}))) + (is (= ["SELECT foo FROM bar INNER JOIN (SELECT a FROM b WHERE id = ?) AS x ON y WHERE id = ?" 123 456] + (format {:select :foo + :from :bar + :join [[{:select :a :from :b :where [:= :id 123]} :x] :y] + :where [:= :id 456]})))))