diff --git a/CHANGELOG.md b/CHANGELOG.md index 1655b82..650a38a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changes * 2.4.next in progress + * Address [#452](https://github.com/seancorfield/honeysql/pull/452) by adding `:replace-into` to the core SQL supported, instead of just for the MySQL and SQLite dialects (so the latter is not needed yet). * Address [#451](https://github.com/seancorfield/honeysql/issues/451) by adding a test for it, showing how `:nest` produces the desired result. * Address [#447](https://github.com/seancorfield/honeysql/issues/447) by updating GitHub Actions and dependencies. * Address [#445](https://github.com/seancorfield/honeysql/issues/445) and [#453](https://github.com/seancorfield/honeysql/issues/453) by adding key/constraint examples to `CREATE TABLE` docs. diff --git a/doc/clause-reference.md b/doc/clause-reference.md index 76c9ff2..2a9d5e3 100644 --- a/doc/clause-reference.md +++ b/doc/clause-reference.md @@ -556,7 +556,8 @@ or a table/column specifier and a SQL query. For the first and second cases, you'll use the `:values` clause to specify rows of values to insert. -`:replace-into` is part of the `:mysql` dialect that produces a `REPLACE INTO` +`:replace-into` is only supported by MySQL and SQLite but is +part of HoneySQL's "core" dialect anyway. It produces a `REPLACE INTO` statement but otherwise has identical syntax to `:insert-into`. ```clojure diff --git a/src/honey/sql.cljc b/src/honey/sql.cljc index 134ef7e..200aaad 100644 --- a/src/honey/sql.cljc +++ b/src/honey/sql.cljc @@ -55,7 +55,7 @@ :table :select :select-distinct :select-distinct-on :select-top :select-distinct-top :into :bulk-collect-into - :insert-into :update :delete :delete-from :truncate + :insert-into :replace-into :update :delete :delete-from :truncate :columns :set :from :using :join-by :join :left-join :right-join :inner-join :outer-join :full-join @@ -105,13 +105,7 @@ :sqlserver {:quote #(strop \[ % \])} :mysql {:quote #(strop \` % \`) :clause-order-fn - #(do - ;; side-effect: updates global clauses... - (register-clause! :replace-into :insert-into :insert-into) - (-> % - (add-clause-before :set :where) - ;; ...but not in-flight clauses: - (add-clause-before :replace-into :insert-into)))} + #(add-clause-before % :set :where)} :oracle {:quote #(strop \" % \") :as false}}))) ; should become defonce @@ -1171,6 +1165,7 @@ :into #'format-select-into :bulk-collect-into #'format-select-into :insert-into #'format-insert + :replace-into #'format-insert :update (check-where #'format-selector) :delete (check-where #'format-selects) :delete-from (check-where #'format-selector) diff --git a/src/honey/sql/helpers.cljc b/src/honey/sql/helpers.cljc index 52e6daa..d25bd19 100644 --- a/src/honey/sql/helpers.cljc +++ b/src/honey/sql/helpers.cljc @@ -486,6 +486,19 @@ (generic :insert-into [data [table cols] statement]) (generic :insert-into args')))) +(defn replace-into + "Accepts a table name or a table/alias pair. That + can optionally be followed by a collection of + column names. That can optionally be followed by + a (select) statement clause. + + The arguments are identical to insert-into. + The REPLACE INTO statement is only supported by + MySQL and SQLite." + {:arglists '([table] [table cols] [table statement] [table cols statement])} + [& args] + (apply insert-into args)) + (defn update "Accepts either a table name or a table/alias pair. diff --git a/test/honey/sql_test.cljc b/test/honey/sql_test.cljc index 4105806..bd60621 100644 --- a/test/honey/sql_test.cljc +++ b/test/honey/sql_test.cljc @@ -1037,9 +1037,6 @@ ORDER BY id = ? DESC (is (= ["SELECT \"A\"\"B\""] (sut/format {:select (keyword "A\"B")} {:dialect :oracle})))) (deftest issue-421-mysql-replace-into - ;; because the :mysql dialect registers a new clause, and we've probably already run - ;; tests with that dialect, we can't test that :replace-into throws an exception when - ;; no :dialect is specified because the clause might already be in place: (is (= ["INSERT INTO table VALUES (?, ?, ?)" 1 2 3] (sut/format {:insert-into :table :values [[1 2 3]]}))) (is (= ["REPLACE INTO table VALUES (?, ?, ?)" 1 2 3]