Merge pull request #470 from p-himik/467-allow-scalar-order-by-et-al

Allow single kw in :order-by and other clauses
This commit is contained in:
Sean Corfield 2023-02-27 14:00:44 -08:00 committed by GitHub
commit fc3397650e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 9 deletions

View file

@ -209,6 +209,9 @@
{:symbol x {:symbol x
:failure (str t)}))))) :failure (str t)})))))
(defn- ensure-sequential [xs]
(if (sequential? xs) xs [xs]))
(defn format-entity (defn format-entity
"Given a simple SQL entity (a keyword or symbol -- or string), "Given a simple SQL entity (a keyword or symbol -- or string),
return the equivalent SQL fragment (as a string -- no parameters). return the equivalent SQL fragment (as a string -- no parameters).
@ -549,7 +552,7 @@
(-> [sql'] (into params) (into params')))) (-> [sql'] (into params) (into params'))))
(defn- format-select-into [k xs] (defn- format-select-into [k xs]
(let [[v e] (if (sequential? xs) xs [xs]) (let [[v e] (ensure-sequential xs)
[sql & params] (when e (format-expr e))] [sql & params] (when e (format-expr e))]
(into [(str (sql-kw k) " " (format-entity v) (into [(str (sql-kw k) " " (format-entity v)
(when sql (when sql
@ -708,11 +711,12 @@
[])) []))
(defn- format-group-by [k xs] (defn- format-group-by [k xs]
(let [[sqls params] (format-expr-list xs)] (let [[sqls params] (format-expr-list (ensure-sequential xs))]
(into [(str (sql-kw k) " " (str/join ", " sqls))] params))) (into [(str (sql-kw k) " " (str/join ", " sqls))] params)))
(defn- format-order-by [k xs] (defn- format-order-by [k xs]
(let [dirs (map #(when (sequential? %) (second %)) xs) (let [xs (ensure-sequential 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) " " (into [(str (sql-kw k) " "
@ -722,7 +726,7 @@
dirs)))] params))) dirs)))] params)))
(defn- format-lock-strength [k xs] (defn- format-lock-strength [k xs]
(let [[strength tables nowait] (if (sequential? xs) xs [xs])] (let [[strength tables nowait] (ensure-sequential xs)]
[(str (sql-kw k) " " (sql-kw strength) [(str (sql-kw k) " " (sql-kw strength)
(when tables (when tables
(str (str
@ -946,7 +950,7 @@
(format-ddl-options opts context))))) (format-ddl-options opts context)))))
(defn- format-truncate [k xs] (defn- format-truncate [k xs]
(let [[table & options] (if (sequential? xs) xs [xs]) (let [[table & options] (ensure-sequential xs)
[pre table ine options] (destructure-ddl-item [table options] "truncate")] [pre table ine options] (destructure-ddl-item [table options] "truncate")]
(when (seq pre) (throw (ex-info "TRUNCATE syntax error" {:unexpected pre}))) (when (seq pre) (throw (ex-info "TRUNCATE syntax error" {:unexpected pre})))
(when (seq ine) (throw (ex-info "TRUNCATE syntax error" {:unexpected ine}))) (when (seq ine) (throw (ex-info "TRUNCATE syntax error" {:unexpected ine})))

View file

@ -51,7 +51,11 @@
;; implementation helpers: ;; implementation helpers:
(defn- default-merge [current args] (defn- default-merge [current args]
(c/into (vec current) args)) (let [current (cond
(nil? current) []
(sequential? current) (vec current)
:else [current])]
(c/into current args)))
(defn- sym->kw (defn- sym->kw
"Given a symbol, produce a keyword, retaining the namespace "Given a symbol, produce a keyword, retaining the namespace

View file

@ -144,14 +144,14 @@
(deftest select-top-tests (deftest select-top-tests
(testing "Basic TOP syntax" (testing "Basic TOP syntax"
(is (= ["SELECT TOP(?) foo FROM bar ORDER BY quux ASC" 10] (is (= ["SELECT TOP(?) foo FROM bar ORDER BY quux ASC" 10]
(sql/format {:select-top [10 :foo] :from :bar :order-by [:quux]}))) (sql/format {:select-top [10 :foo] :from :bar :order-by :quux})))
(is (= ["SELECT TOP(?) foo FROM bar ORDER BY quux ASC" 10] (is (= ["SELECT TOP(?) foo FROM bar ORDER BY quux ASC" 10]
(sql/format (-> (select-top 10 :foo) (sql/format (-> (select-top 10 :foo)
(from :bar) (from :bar)
(order-by :quux)))))) (order-by :quux))))))
(testing "Expanded TOP syntax" (testing "Expanded TOP syntax"
(is (= ["SELECT TOP(?) PERCENT WITH TIES foo, baz FROM bar ORDER BY quux ASC" 10] (is (= ["SELECT TOP(?) PERCENT WITH TIES foo, baz FROM bar ORDER BY quux ASC" 10]
(sql/format {:select-top [[10 :percent :with-ties] :foo :baz] :from :bar :order-by [:quux]}))) (sql/format {:select-top [[10 :percent :with-ties] :foo :baz] :from :bar :order-by :quux})))
(is (= ["SELECT TOP(?) PERCENT WITH TIES foo, baz FROM bar ORDER BY quux ASC" 10] (is (= ["SELECT TOP(?) PERCENT WITH TIES foo, baz FROM bar ORDER BY quux ASC" 10]
(sql/format (-> (select-top [10 :percent :with-ties] :foo :baz) (sql/format (-> (select-top [10 :percent :with-ties] :foo :baz)
(from :bar) (from :bar)
@ -865,7 +865,7 @@
[[:filter ; two pairs -- alias is on last pair [[:filter ; two pairs -- alias is on last pair
[:avg :x [:order-by :y [:a :desc]]] {:where [:< :i 10]} [:avg :x [:order-by :y [:a :desc]]] {:where [:< :i 10]}
[:sum :q] {:where [:= :x nil]}] :b] [:sum :q] {:where [:= :x nil]}] :b]
[[:within-group [:foo :y] {:order-by [:x]}]]]}) [[:within-group [:foo :y] {:order-by :x}]]]})
[(str "SELECT COUNT(*) FILTER (WHERE i > ?) AS a," [(str "SELECT COUNT(*) FILTER (WHERE i > ?) AS a,"
" AVG(x, y ORDER BY a DESC) FILTER (WHERE i < ?)," " AVG(x, y ORDER BY a DESC) FILTER (WHERE i < ?),"
" SUM(q) FILTER (WHERE x IS NULL) AS b," " SUM(q) FILTER (WHERE x IS NULL) AS b,"

View file

@ -255,6 +255,12 @@
(sql/format))))) (sql/format)))))
(deftest over-test (deftest over-test
(testing "simple window statement"
(is (= ["SELECT AVG(salary) OVER w FROM employee WINDOW w AS (PARTITION BY department ORDER BY salary ASC)"]
(sql/format {:select [[[:over [[:avg :salary] :w]]]]
:from :employee
:window [:w {:partition-by :department
:order-by :salary}]}))))
(testing "window function over on select statemt" (testing "window function over on select statemt"
(is (= ["SELECT id, AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) AS Average, MAX(salary) OVER w AS MaxSalary FROM employee WINDOW w AS (PARTITION BY department)"] (is (= ["SELECT id, AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) AS Average, MAX(salary) OVER w AS MaxSalary FROM employee WINDOW w AS (PARTITION BY department)"]
;; honeysql treats over as a function: ;; honeysql treats over as a function:

View file

@ -83,10 +83,14 @@
(sut/format {:select [:*] :from [:table] :where (sut/map= {:id 1})} {:quoted true}))) (sut/format {:select [:*] :from [:table] :where (sut/map= {:id 1})} {:quoted true})))
(is (= ["SELECT \"t\".* FROM \"table\" AS \"t\" WHERE \"id\" = ?" 1] (is (= ["SELECT \"t\".* FROM \"table\" AS \"t\" WHERE \"id\" = ?" 1]
(sut/format {:select [:t.*] :from [[:table :t]] :where [:= :id 1]} {:quoted true}))) (sut/format {:select [:t.*] :from [[:table :t]] :where [:= :id 1]} {:quoted true})))
(is (= ["SELECT * FROM \"table\" GROUP BY \"foo\""]
(sut/format {:select [:*] :from [:table] :group-by :foo} {:quoted true})))
(is (= ["SELECT * FROM \"table\" GROUP BY \"foo\", \"bar\""] (is (= ["SELECT * FROM \"table\" GROUP BY \"foo\", \"bar\""]
(sut/format {:select [:*] :from [:table] :group-by [:foo :bar]} {:quoted true}))) (sut/format {:select [:*] :from [:table] :group-by [:foo :bar]} {:quoted true})))
(is (= ["SELECT * FROM \"table\" GROUP BY DATE(\"bar\")"] (is (= ["SELECT * FROM \"table\" GROUP BY DATE(\"bar\")"]
(sut/format {:select [:*] :from [:table] :group-by [[:date :bar]]} {:quoted true}))) (sut/format {:select [:*] :from [:table] :group-by [[:date :bar]]} {:quoted true})))
(is (= ["SELECT * FROM \"table\" ORDER BY \"foo\" ASC"]
(sut/format {:select [:*] :from [:table] :order-by :foo} {:quoted true})))
(is (= ["SELECT * FROM \"table\" ORDER BY \"foo\" DESC, \"bar\" ASC"] (is (= ["SELECT * FROM \"table\" ORDER BY \"foo\" DESC, \"bar\" ASC"]
(sut/format {:select [:*] :from [:table] :order-by [[:foo :desc] :bar]} {:quoted true}))) (sut/format {:select [:*] :from [:table] :order-by [[:foo :desc] :bar]} {:quoted true})))
(is (= ["SELECT * FROM \"table\" ORDER BY DATE(\"expiry\") DESC, \"bar\" ASC"] (is (= ["SELECT * FROM \"table\" ORDER BY DATE(\"expiry\") DESC, \"bar\" ASC"]