From b9a1c6ead0daa7691e063ee6b14a8f58f2aeca6a Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 16 Jun 2020 16:26:01 +0200 Subject: [PATCH] [jOOQ/jOOQ#6736] Add support for PostgreSQL ON CONFLICT .. WHERE --- .../java/org/jooq/InsertOnDuplicateStep.java | 4 +-- jOOQ/src/main/java/org/jooq/InsertQuery.java | 11 ++++++ .../main/java/org/jooq/impl/InsertImpl.java | 34 +++++++++++++++---- .../java/org/jooq/impl/InsertQueryImpl.java | 13 +++++++ 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/InsertOnDuplicateStep.java b/jOOQ/src/main/java/org/jooq/InsertOnDuplicateStep.java index effa3d9f53..b82b15968f 100644 --- a/jOOQ/src/main/java/org/jooq/InsertOnDuplicateStep.java +++ b/jOOQ/src/main/java/org/jooq/InsertOnDuplicateStep.java @@ -122,7 +122,7 @@ public interface InsertOnDuplicateStep extends InsertReturning * MERGE, if table meta data is available. */ @Support - InsertOnConflictDoUpdateStep onConflict(Field... keys); + InsertOnConflictWhereIndexPredicateStep onConflict(Field... keys); /** * Add an ON CONFLICT clause to this INSERT statement. @@ -132,7 +132,7 @@ public interface InsertOnDuplicateStep extends InsertReturning * MERGE, if table meta data is available. */ @Support - InsertOnConflictDoUpdateStep onConflict(Collection> keys); + InsertOnConflictWhereIndexPredicateStep onConflict(Collection> keys); /** * Add an ON CONFLICT DO NOTHING clause to this INSERT statement. diff --git a/jOOQ/src/main/java/org/jooq/InsertQuery.java b/jOOQ/src/main/java/org/jooq/InsertQuery.java index 4d5086b924..0b0221db81 100644 --- a/jOOQ/src/main/java/org/jooq/InsertQuery.java +++ b/jOOQ/src/main/java/org/jooq/InsertQuery.java @@ -251,6 +251,17 @@ public interface InsertQuery extends StoreQuery, Insert, @Support({ CUBRID, DERBY, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE }) void addValuesForUpdate(Map map); + /** + * Adds a new condition the {@link #onConflict(Field...)} clause. + *

+ * This is for use with {@link SQLDialect#POSTGRES}'s + * {@link #onConflict(Field...)} clause. + * + * @param condition The condition + */ + @Support({ POSTGRES, SQLITE }) + void onConflictWhere(Condition condition); + /** * Adds a new condition to the query, connecting it to existing conditions * with {@link Operator#AND}. diff --git a/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java b/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java index fb187c10df..504ba39c0f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java @@ -55,7 +55,7 @@ import org.jooq.Constraint; import org.jooq.Field; import org.jooq.FieldLike; import org.jooq.InsertOnConflictConditionStep; -import org.jooq.InsertOnConflictDoUpdateStep; +import org.jooq.InsertOnConflictWhereIndexPredicateStep; import org.jooq.InsertOnDuplicateSetMoreStep; import org.jooq.InsertQuery; import org.jooq.InsertResultStep; @@ -122,7 +122,7 @@ import org.jooq.UniqueKey; * @author Lukas Eder */ @SuppressWarnings({ "rawtypes", "unchecked" }) -class InsertImpl +final class InsertImpl extends AbstractDelegatingRowCountQuery> implements @@ -153,7 +153,7 @@ class InsertImpl, InsertSetMoreStep, InsertOnDuplicateSetMoreStep, - InsertOnConflictDoUpdateStep, + InsertOnConflictWhereIndexPredicateStep, InsertOnConflictConditionStep, InsertResultStep { @@ -167,6 +167,11 @@ class InsertImplDO UPDATE/code> clause. + */ + private transient boolean doUpdateWhere; + InsertImpl(Configuration configuration, WithImpl with, Table into) { super(new InsertQueryImpl<>(configuration, with, into)); @@ -622,11 +627,13 @@ class InsertImpl conditions) { - getDelegate().addConditions(conditions); + if (doUpdateWhere) + getDelegate().addConditions(conditions); + else + getDelegate().onConflictWhere(DSL.and(conditions)); + return this; } diff --git a/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java index 614eb0f49a..f3a3886082 100644 --- a/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java @@ -134,6 +134,7 @@ final class InsertQueryImpl extends AbstractStoreQuery impl private Constraint onConstraint; private UniqueKey onConstraintUniqueKey; private QueryPartList> onConflict; + private final ConditionProviderImpl onConflictWhere; private final ConditionProviderImpl condition; InsertQueryImpl(Configuration configuration, WithImpl with, Table into) { @@ -141,6 +142,7 @@ final class InsertQueryImpl extends AbstractStoreQuery impl this.updateMap = new FieldMapForUpdate(into, INSERT_ON_DUPLICATE_KEY_UPDATE_ASSIGNMENT); this.insertMaps = new FieldMapsForInsert(into); + this.onConflictWhere = new ConditionProviderImpl(); this.condition = new ConditionProviderImpl(); } @@ -178,6 +180,11 @@ final class InsertQueryImpl extends AbstractStoreQuery impl this.onConflict = new QueryPartList<>(fields); } + @Override + public final void onConflictWhere(Condition conditions) { + onConflictWhere.addConditions(conditions); + } + @Override public final void onConflictOnConstraint(Constraint constraint) { onConflictOnConstraint0(constraint); @@ -392,6 +399,12 @@ final class InsertQueryImpl extends AbstractStoreQuery impl ctx.sql(')'); } + if (onConflictWhere.hasWhere()) + ctx.sql(' ') + .visit(K_WHERE) + .sql(' ') + .visit(onConflictWhere.getWhere()); + ctx.sql(' ') .visit(K_DO_UPDATE) .formatSeparator()