Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

"insert or replace" sugar for row "onConflict()" upsert?

20 views
Skip to first unread message

Stefan Hoffmeister

unread,
Nov 8, 2024, 8:08:06 AM11/8/24
to jOOQ User Group
Is there functionality around, or some feature on the jooq roadmap which would implement "upsert" semantics for complete rows?

Example: DuckDB offers nice sugar in the form of "INSERT OR REPLACE INTO" (https://duckdb.org/docs/sql/statements/insert#insert-or-replace-into), not requiring the ON CONFLICT clause in the SQL statement.

As far as I can tell, jooq could offer similar functionality in the DSL such that instead of
```
val numRows = dsl.insertInto(Tables.MyTable)
    .set(Tables.MyTable.ID, mini.id)
    .set(Tables.MyTable.someVal, mini.someVal)
    .onConflict(Tables.MyTable.ID)
    .doUpdate()
    //.set(Tables.MyTable.ID, mini.id)
    .set(Tables.MyTable.someVal, mini.someVal)
    .execute()
```
it would be come possible to use
```
val numRows = dsl.insertInto(Tables.MyTable)
    .set(Tables.MyTable.ID, mini.id)
    .set(Tables.MyTable.someVal, mini.someVal)
    .onConflict(Tables.MyTable.ID)
    .doReplace()
    .execute()
```
Semantically only the columns in .set() would be touched, with the exception of the .onConflict() columns?

This could make it easier to write simple row-based UPSERTs in jooq?

Lukas Eder

unread,
Nov 8, 2024, 8:10:29 AM11/8/24
to jooq...@googlegroups.com
There's some syntax sugar around the excluded clause:

You can call setAllToExcluded()

--
You received this message because you are subscribed to the Google Groups "jOOQ User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jooq-user+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/jooq-user/b20fbd53-4dcb-4560-a1a4-b9524c84708bn%40googlegroups.com.

Stefan Hoffmeister

unread,
Nov 11, 2024, 2:44:27 AM11/11/24
to jOOQ User Group
.setAllToExcluded() does not seem to behave the way I expect on DuckDB 1.1.0 with jOOQ 3.19.12.

Given
```
val numRows = dsl.insertInto(Tables.MyTable)
    .set(Tables.MyTable.IDmini.id)
    .set(Tables.MyTable.someVal, mini.someVal)
    .onConflict(Tables.MyTable.ID)
    . setAllToExcluded()
    .execute()
```
I get

org.jooq.exception.DataAccessException: SQL [insert into MyTable ("id", "someVal") values (...) on conflict ("id") do update set "id" = excluded."id", "someVal" = excluded."someVal"]; 

java.sql.SQLException: Binder Error: Can not assign to column 'id' because it has a UNIQUE/PRIMARY KEY constraint or is referenced by an INDEX

From the SQL it is clear why the exception is generated - but I do not understand why jOOQ would generate the 

set "id" = excluded."id"

given that this is the column listed in the onConflict() ?

Lukas Eder

unread,
Nov 11, 2024, 3:10:06 AM11/11/24
to jooq...@googlegroups.com

Lukas Eder

unread,
Nov 13, 2024, 9:07:58 AM11/13/24
to jOOQ User Group
https://github.com/jOOQ/jOOQ/issues/16522 has been implemented. New methods, such as setNonPrimaryKeyToExcluded() are now available. Obviously, you can easily emulate these methods yourself by passing Field/excluded(Field) pairs to the set() clauses.

Best Regards,
Lukas
Reply all
Reply to author
Forward
0 new messages