fixes #571 by supporting empty order by clause

Signed-off-by: Sean Corfield <sean@corfield.org>
This commit is contained in:
Sean Corfield 2025-03-22 10:34:57 -07:00
parent 7611871935
commit 024d17b11e
No known key found for this signature in database
4 changed files with 36 additions and 7 deletions

View file

@ -1,5 +1,8 @@
# Changes # Changes
* 2.7.next in progress
* Fix [#571](https://github.com/seancorfield/honeysql/issues/571) by allowing `:order-by` to take an empty sequence of columns (and be omitted).
* 2.7.1295 -- 2025-03-12 * 2.7.1295 -- 2025-03-12
* Address #570 by adding `:.:.` as special syntax for Snowflake's JSON path syntax, and `:at` as special syntax for general `[`..`]` path syntax. * Address #570 by adding `:.:.` as special syntax for Snowflake's JSON path syntax, and `:at` as special syntax for general `[`..`]` path syntax.
* Drop support for Clojure 1.9 [#561](https://github.com/seancorfield/honeysql/issues/561). * Drop support for Clojure 1.9 [#561](https://github.com/seancorfield/honeysql/issues/561).

View file

@ -1070,6 +1070,9 @@ The `:where` clause can have a single SQL expression, or
a sequence of SQL expressions prefixed by either `:and` a sequence of SQL expressions prefixed by either `:and`
or `:or`. See examples of `:where` in various clauses above. or `:or`. See examples of `:where` in various clauses above.
If `:where` is given an empty sequence, the `WHERE` clause will
be omitted from the generated SQL.
Sometimes it is convenient to construct a `WHERE` clause that Sometimes it is convenient to construct a `WHERE` clause that
tests several columns for equality, and you might have a Clojure tests several columns for equality, and you might have a Clojure
hash map containing those values. `honey.sql/map=` exists to hash map containing those values. `honey.sql/map=` exists to
@ -1210,12 +1213,15 @@ user=> (sql/format {:select [[[:over
## order-by ## order-by
`:order-by` accepts a sequence of one or more ordering `:order-by` accepts a sequence of zero or more ordering
expressions. Each ordering expression is either a simple expressions. Each ordering expression is either a simple
SQL entity or a pair of a SQL expression and a direction SQL entity or a pair of a SQL expression and a direction
(which can be `:asc`, `:desc`, `:nulls-first`, `:desc-null-last`, (which can be `:asc`, `:desc`, `:nulls-first`, `:desc-null-last`,
etc -- or the symbol equivalent). etc -- or the symbol equivalent).
If `:order-by` is given an empty sequence, the `ORDER BY` clause will
be omitted from the generated SQL.
If you want to order by an expression, you should wrap it If you want to order by an expression, you should wrap it
as a pair with a direction: as a pair with a direction:

View file

@ -1119,11 +1119,13 @@
dirs (map #(when (sequential? %) (second %)) xs) dirs (map #(when (sequential? %) (second %)) xs)
[sqls params] [sqls params]
(format-expr-list (map #(if (sequential? %) (first %) %) xs))] (format-expr-list (map #(if (sequential? %) (first %) %) xs))]
(into [(str (sql-kw k) " " (if (seq sqls)
(join ", " (map (fn [sql dir] (into [(str (sql-kw k) " "
(str sql " " (sql-kw (or dir :asc)))) (join ", " (map (fn [sql dir]
sqls (str sql " " (sql-kw (or dir :asc))))
dirs)))] params))) sqls
dirs)))] params)
[])))
(defn- format-lock-strength [k xs] (defn- format-lock-strength [k xs]
(let [[strength tables nowait] (ensure-sequential xs)] (let [[strength tables nowait] (ensure-sequential xs)]
@ -1771,7 +1773,7 @@
(if (seq leftover) (if (seq leftover)
(throw (ex-info (str "These SQL clauses are unknown or have nil values: " (throw (ex-info (str "These SQL clauses are unknown or have nil values: "
(join ", " (keys leftover)) (join ", " (keys leftover))
"(perhaps you need [:lift {" " (perhaps you need [:lift {"
(first (keys leftover)) (first (keys leftover))
" ...}] here?)") " ...}] here?)")
leftover)) leftover))

View file

@ -1486,6 +1486,24 @@ ORDER BY id = ? DESC
(h/select :*) (h/select :*)
(h/from :table))))))) (h/from :table)))))))
(deftest issue-571
(testing "an empty where clause is omitted"
(is (= ["SELECT * FROM foo"]
(sut/format {:select :* :from :foo :where []})))
#?(:clj
(is (thrown? clojure.lang.ExceptionInfo
(sut/format {:select :* :from :foo :where nil}))))
(is (= ["SELECT * FROM foo WHERE 1 = 1"]
(sut/format {:select :* :from :foo :where [:= 1 1]} {:inline true}))))
(testing "an empty order by clause is omitted"
(is (= ["SELECT * FROM foo"]
(sut/format {:select :* :from :foo :order-by []})))
#?(:clj
(is (thrown? clojure.lang.ExceptionInfo
(sut/format {:select :* :from :foo :order-by nil}))))
(is (= ["SELECT * FROM foo ORDER BY bar ASC"]
(sut/format {:select :* :from :foo :order-by [:bar]})))))
(comment (comment
;; partial (incorrect!) workaround for #407: ;; partial (incorrect!) workaround for #407:
(sut/format {:select :f.* :from [[:foo [:f :for :system-time]]] :where [:= :f.id 1]}) (sut/format {:select :f.* :from [[:foo [:f :for :system-time]]] :where [:= :f.id 1]})