diff --git a/CHANGELOG.md b/CHANGELOG.md index 50abf40..3a8dac1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,9 @@ # Changes * 2.4.next in progress - * Address [#474](https://github.com/seancorfield/honeysql/issues/474) by adding dot-selection special syntax. Documentation TBD! + * Address [#474](https://github.com/seancorfield/honeysql/issues/474) by adding dot-selection special syntax. * Improve docstrings for PostgreSQL operators via PR [#473](https://github.com/seancorfield/honeysql/pull/473) [@holyjak](https://github.com/holyjak). - * Address [#471](https://github.com/seancorfield/honeysql/issues/471) by supported interspersed SQL keywords in function calls. Documentation TBD! + * Address [#471](https://github.com/seancorfield/honeysql/issues/471) by supporting interspersed SQL keywords in function calls. Documentation TBD! * Fix [#467](https://github.com/seancorfield/honeysql/issues/467) by allowing single keywords (symbols) as a short hand for a single-element sequence in more constructs via PR [#470](https://github.com/seancorfield/honeysql/pull/470) [@p-himik](https://github.com/p-himik). * Address [#466](https://github.com/seancorfield/honeysql/issues/466) by treating `[:and]` as `TRUE` and `[:or]` as `FALSE`. * Fix [#465](https://github.com/seancorfield/honeysql/issues/465) to allow multiple columns in `:order-by` special syntax via PR [#468](https://github.com/seancorfield/honeysql/pull/468) [@p-himik](https://github.com/p-himik). diff --git a/doc/differences-from-1-x.md b/doc/differences-from-1-x.md index deab784..dee0832 100644 --- a/doc/differences-from-1-x.md +++ b/doc/differences-from-1-x.md @@ -98,6 +98,8 @@ The primary API is just `honey.sql/format`. The `array`, `call`, `inline`, `para Other `honeysql.core` functions that no longer exist include: `build`, `qualify`, and `quote-identifier`. Many other public functions were essentially undocumented (neither mentioned in the README nor in the tests) and also no longer exist. +> As of 2.4.next, the functionality of `qualify` can be achieved through the `:.` dot-selection special syntax. + You can now select a non-ANSI dialect of SQL using the new `honey.sql/set-dialect!` function (which sets a default dialect for all `format` operations) or by passing the new `:dialect` option to the `format` function. `:ansi` is the default dialect (which will mostly incorporate PostgreSQL usage over time). Other dialects supported are `:mysql` (which has a different quoting strategy and uses a different ranking for the `:set` clause), `:oracle` (which is essentially the `:ansi` dialect but will control other things over time), and `:sqlserver` (which is essentially the `:ansi` dialect but with a different quoting strategy). Other dialects and changes may be added over time. > Note: in general, all clauses are available in all dialects in HoneySQL unless the syntax of the clauses conflict between dialects (currently, no such clauses exist). The `:mysql` dialect is the only one so far that changes the priority ordering of a few clauses. diff --git a/doc/special-syntax.md b/doc/special-syntax.md index 4e0638c..0ace7bf 100644 --- a/doc/special-syntax.md +++ b/doc/special-syntax.md @@ -105,6 +105,22 @@ Accepts a single expression and prefixes it with `DISTINCT `: ;;=> ["SELECT COUNT(DISTINCT status) AS n FROM table"] ``` +## dot . + +Accepts an expression and a field (or column) selection: + +```clojure +(sql/format {:select [ [[:. :t :c]] [[:. :s :t :c]] ]}) +;;=> ["SELECT t.c, s.t.c"] +``` + +Can be used with `:nest` for field selection from composites: + +```clojure +(sql/format {:select [ [[:. [:nest :v] :*]] [[:. [:nest [:myfunc :x]] :y]] ]}) +;;=> ["SELECT (v).*, (MYFUNC(x)).y"] +``` + ## entity Accepts a single keyword or symbol argument and produces a diff --git a/src/honey/sql.cljc b/src/honey/sql.cljc index e21813e..227df62 100644 --- a/src/honey/sql.cljc +++ b/src/honey/sql.cljc @@ -1472,9 +1472,12 @@ :primary-key #'function-0 :references #'function-1 :unique #'function-1-opt - :. (fn [_ [expr col]] + :. (fn [_ [expr col subcol]] (let [[sql & params] (format-expr expr)] - (into [(str sql "." (format-entity col))] params))) + (into [(str sql "." (format-entity col) + (when subcol + (str "." (format-entity subcol))))] + params))) ;; used in DDL to force rendering as a SQL entity instead ;; of a SQL keyword: :entity (fn [_ [e]] [(format-entity e)]) diff --git a/test/honey/sql_test.cljc b/test/honey/sql_test.cljc index 96b7b61..be4d84a 100644 --- a/test/honey/sql_test.cljc +++ b/test/honey/sql_test.cljc @@ -1133,11 +1133,20 @@ ORDER BY id = ? DESC (deftest issue-474-dot-selection (testing "basic dot selection" - (is (= ["SELECT a.b, c.d, e.f"] + (is (= ["SELECT a.b, c.d, a.d.x"] (let [t :a c :d] - (sut/format {:select [[[:. t :b]] [[:. :c c]] [[:. :e :f]]]}))))) + (sut/format {:select [[[:. t :b]] [[:. :c c]] [[:. t c :x]]]})))) + (is (= ["SELECT [a].[b], [c].[d], [a].[d].[x]"] + (let [t :a c :d] + (sut/format {:select [[[:. t :b]] [[:. :c c]] [[:. t c :x]]]} + {:dialect :sqlserver}))))) (testing "basic field selection from composite" (is (= ["SELECT (v).*, (w).x, (Y(z)).*"] (sut/format '{select (((. (nest v) *)) ((. (nest w) x)) - ((. (nest (y z)) *)))}))))) + ((. (nest (y z)) *)))}))) + (is (= ["SELECT (`v`).*, (`w`).`x`, (Y(`z`)).*"] + (sut/format '{select (((. (nest v) *)) + ((. (nest w) x)) + ((. (nest (y z)) *)))} + {:dialect :mysql})))))