address #415 by supporting multiple drop columns

This commit is contained in:
Sean Corfield 2022-09-12 13:51:54 -07:00
parent fb601c90d9
commit 5d7a3faea5
5 changed files with 44 additions and 8 deletions

View file

@ -3,6 +3,7 @@
* 2.3.next in progress
* Address [#430](https://github.com/seancorfield/honeysql/issues/430) by treating `:'` as introducing a name that should be treating literally and not formatted as a SQL entity (which respects quoting, dot-splitting, etc); this effectively expands the "escape hatch" introduced via [#352](https://github.com/seancorfield/honeysql/issues/352) in 2.2.868. _Note that the function context behavior formats as a SQL entity, rather than the usual SQL "keyword", whereas this new context is a literal transcription rather than as a SQL entity!_
* Address [#427](https://github.com/seancorfield/honeysql/issues/427) by adding `set-options!`.
* Address [#415](https://github.com/seancorfield/honeysql/issues/415) by supporting multiple column names in `DROP COLUMN`.
* 2.3.928 -- 2022-09-04
* Address [#425](https://github.com/seancorfield/honeysql/issues/425) by clarifying that `INTERVAL` as special syntax may be MySQL-specific and PostgreSQL uses difference syntax (because `INTERVAL` is a data type there).

View file

@ -85,7 +85,8 @@ user=> (sql/format {:alter-table [:fruit
As can be seen above, `:add-column` and `:alter-column`
both accept a column description (as a sequence of simple
expressions); `:drop-column` accepts a single column name,
expressions); `:drop-column` accepts one or more column names
optionally prefixed by `:if-exists`,
and `:rename-column` accepts a sequence with two column
names: the "from" and the "to" names.

View file

@ -981,6 +981,32 @@
(into [(str/join sqls)] params))
[s]))
(defn- destructure-drop-columns [tables]
(let [params
(if (sequential? tables)
tables
[tables])
_ (when-not (every? ident? params)
(throw (ex-info "DROP COLUMNS expects just column names"
{:tables tables})))]
(loop [if-exists false coll params sqls []]
(if (seq coll)
(if (#{:if-exists 'if-exists} (first coll))
(recur true (rest coll) sqls)
(recur false (rest coll)
(conj sqls (cond->> (format-entity (first coll))
if-exists
(str (sql-kw :if-exists) " ")))))
(if if-exists
(throw (ex-info (str "DROP COLUMNS: missing column name after IF EXISTS")
{:tables tables}))
sqls)))))
(defn- format-drop-columns
[k params]
(let [tables (destructure-drop-columns params)]
[(str/join ", " (mapv #(str (sql-kw k) " " %) tables))]))
(defn- check-where
"Given a formatter function, performs a pre-flight check that there is
a non-empty where clause if at least basic checking is enabled."
@ -1009,7 +1035,7 @@
and removed."
(atom {:alter-table #'format-alter-table
:add-column #'format-add-item
:drop-column #'format-drop-items
:drop-column #'format-drop-columns
:alter-column (fn [k spec]
(format-add-item
(if (mysql?) :modify-column k)

View file

@ -172,12 +172,15 @@
(generic :add-column col-elems))
(defn drop-column
"Takes a single column name (use with `alter-table`).
"Takes one or more column names (use with `alter-table`).
(alter-table :foo (drop-column :bar))"
Accepts an `IF EXISTS` flag (keyword or symbol) before
any column names.
(alter-table :foo (drop-column :bar :if-exists :quux))"
{:arglists '([col])}
[& args]
(generic-1 :drop-column args))
[& col-elems]
(generic :drop-column col-elems))
(defn alter-column
"Like add-column, accepts any number of SQL elements

View file

@ -633,8 +633,13 @@
["ALTER TABLE fruit ADD COLUMN id INT NOT NULL"]))
(is (= (sql/format (alter-table :fruit
(add-column :id :int [:not nil])
(drop-column :ident)))
["ALTER TABLE fruit ADD COLUMN id INT NOT NULL, DROP COLUMN ident"])))
(drop-column :ident)
(drop-column :if-exists :another)))
["ALTER TABLE fruit ADD COLUMN id INT NOT NULL, DROP COLUMN ident, DROP COLUMN IF EXISTS another"]))
(is (= (sql/format (alter-table :fruit
(drop-column :a :b :if-exists :c :d)
(drop-column :if-exists :e)))
["ALTER TABLE fruit DROP COLUMN a, DROP COLUMN b, DROP COLUMN IF EXISTS c, DROP COLUMN d, DROP COLUMN IF EXISTS e"])))
(deftest issue-293-insert-into-data
;; insert into as (and other tests) based on :insert-into