fix #494 by supporting expressions in on conflict

This commit is contained in:
Sean Corfield 2023-06-20 12:11:00 -07:00
parent 3ec884f881
commit 290537c581
4 changed files with 23 additions and 18 deletions

View file

@ -1,6 +1,7 @@
# Changes
* 2.4.next in progress
* Fix [#494](https://github.com/seancorfield/honeysql/issues/494) by supporting expressions in `:on-conflict` instead of just entities.
* Address [#493](https://github.com/seancorfield/honeysql/issues/493) by clarifying use of `:values` in CTEs (using `:with`).
* Address [#489](https://github.com/seancorfield/honeysql/issues/489) by adding more examples around `:update`.
* Update dev/test dependencies.

View file

@ -1099,10 +1099,11 @@ as if they are separate clauses but they will appear
in pairs: `ON ... DO ...`.
`:on-conflict` accepts a sequence of zero or more
SQL entities (keywords or symbols), optionally
SQL expressions, optionally
followed by a single SQL clause (hash map). It can also
accept either a single SQL entity or a single SQL clause.
The SQL entities are column names and the SQL clause can be an
The SQL expressions can be just column names or function calls etc,
and the SQL clause can be an
`:on-constraint` clause or a`:where` clause.
_[For convenience of use with the `on-conflict` helper, this clause can also accept any of those arguments, wrapped in a sequence; it can also accept an empty sequence, and just produce `ON CONFLICT`, so that it can be combined with other clauses directly]_

View file

@ -881,23 +881,26 @@
(defn- format-on-conflict [k x]
(if (sequential? x)
(let [entities (take-while ident? x)
n (count entities)
(let [exprs (take-while (complement map?) x)
n (count exprs)
[clause & more] (drop n x)
_ (when (or (seq more)
(and clause (not (map? clause))))
_ (when (seq more)
(throw (ex-info "unsupported :on-conflict format"
{:clause x})))
[sql & params] (when clause
(format-dsl clause))]
(into [(str (sql-kw k)
(when (pos? n)
(str " ("
(str/join ", " (map #'format-entity entities))
")"))
(when sql
(str " " sql)))]
params))
[sqls expr-params]
(when (seq exprs)
(format-expr-list exprs))
[sql & clause-params]
(when clause
(format-dsl clause))]
(-> [(str (sql-kw k)
(when (pos? n)
(str " (" (str/join ", " sqls) ")"))
(when sql
(str " " sql)))]
(into expr-params)
(into clause-params)))
(format-on-conflict k [x])))
(defn- format-do-update-set [k x]

View file

@ -772,13 +772,13 @@ DO NOTHING
INSERT INTO customers
(name, email)
VALUES ('Microsoft', 'hotline@microsoft.com')
ON CONFLICT (name, email)
ON CONFLICT (name, TRIM(email))
DO NOTHING
"]
(format {:insert-into :customers
:columns [:name :email]
:values [[[:inline "Microsoft"], [:inline "hotline@microsoft.com"]]]
:on-conflict [:name :email]
:on-conflict [:name [:trim :email]]
:do-nothing true}
{:pretty true})))
(is (= ["