Merge pull request #6919 from timur-sh/6906

[#6906] Added support for PostgreSQL ON CONFLICT .. ON CONSTRAINT ..
This commit is contained in:
Lukas Eder 2017-12-18 13:41:54 +01:00 committed by GitHub
commit 1d5c3a3a3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 144 additions and 27 deletions

View File

@ -69,6 +69,24 @@ import java.util.Collection;
*/
public interface InsertOnDuplicateStep<R extends Record> extends InsertReturningStep<R> {
/**
* Add a <code>ON CONFLICT ON CONSTRAINT</code> clause to this query.
*/
@Support({ POSTGRES_9_5 })
InsertOnConflictDoUpdateStep<R> onConflictOnConstraint(Constraint constraint);
/**
* Add a <code>ON CONFLICT ON CONSTRAINT</code> clause to this query.
*/
@Support({ POSTGRES_9_5 })
InsertOnConflictDoUpdateStep<R> onConflictOnConstraint(Name constraint);
/**
* Add a <code>ON CONFLICT ON CONSTRAINT</code> clause to this query.
*/
@Support({ POSTGRES_9_5 })
InsertOnConflictDoUpdateStep<R> onConflictOnConstraint(UniqueKey<R> constraint);
/**
* Add an <code>ON CONFLICT</code> clause to this insert query.
*/

View File

@ -117,6 +117,30 @@ public interface InsertQuery<R extends Record> extends StoreQuery<R>, Insert<R>
@Support({ POSTGRES_9_5 })
void onConflict(Collection<? extends Field<?>> fields);
/**
* Whether use a <code>On CONFLICT</code> or
* <code>ON CONFLICT ON CONSTRAINT</code> clause in this <code>INSERT</code>
* statement.
*/
@Support({ POSTGRES_9_5 })
void onConflictOnConstraint(Constraint constraint);
/**
* Whether use a <code>On CONFLICT</code> or
* <code>ON CONFLICT ON CONSTRAINT</code> clause in this <code>INSERT</code>
* statement.
*/
@Support({ POSTGRES_9_5 })
void onConflictOnConstraint(UniqueKey<R> constraint);
/**
* Whether use a <code>On CONFLICT</code> or
* <code>ON CONFLICT ON CONSTRAINT</code> clause in this <code>INSERT</code>
* statement.
*/
@Support({ POSTGRES_9_5 })
void onConflictOnConstraint(Name constraint);
/**
* Whether a <code>ON DUPLICATE KEY UPDATE</code> clause should be added to
* this <code>INSERT</code> statement.

View File

@ -38,7 +38,9 @@
package org.jooq.impl;
import static org.jooq.impl.DSL.condition;
import static org.jooq.impl.DSL.constraint;
import static org.jooq.impl.DSL.exists;
import static org.jooq.impl.DSL.name;
import static org.jooq.impl.DSL.not;
import static org.jooq.impl.DSL.notExists;
import static org.jooq.impl.Tools.EMPTY_FIELD;
@ -53,6 +55,7 @@ import javax.annotation.Generated;
import org.jooq.Condition;
import org.jooq.Configuration;
import org.jooq.Constraint;
import org.jooq.Field;
import org.jooq.FieldLike;
import org.jooq.InsertOnConflictConditionStep;
@ -85,6 +88,7 @@ import org.jooq.InsertValuesStep7;
import org.jooq.InsertValuesStep8;
import org.jooq.InsertValuesStep9;
import org.jooq.InsertValuesStepN;
import org.jooq.Name;
import org.jooq.Operator;
import org.jooq.QueryPart;
import org.jooq.Record;
@ -93,6 +97,7 @@ import org.jooq.Result;
import org.jooq.SQL;
import org.jooq.Select;
import org.jooq.Table;
import org.jooq.UniqueKey;
/**
* @author Lukas Eder
@ -604,6 +609,27 @@ class InsertImpl<R extends Record, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
return onDuplicateKeyIgnore();
}
@Override
public final InsertImpl onConflictOnConstraint(Constraint constraint) {
getDelegate().onConflictOnConstraint(constraint);
return this;
}
@Override
public final InsertImpl onConflictOnConstraint(Name constraint) {
onConflictOnConstraint(constraint(constraint));
return this;
}
@Override
public final InsertImpl onConflictOnConstraint(UniqueKey<R> constraint) {
if (constraint.getName() == null)
throw new IllegalStateException("UniqueKey's name is not specified");
onConflictOnConstraint(name(constraint.getName()));
return this;
}
@Override
public final InsertImpl onConflict(Field<?>... keys) {
return onConflict(Arrays.asList(keys));

View File

@ -47,7 +47,9 @@ import static org.jooq.Clause.INSERT_SELECT;
import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL;
// ...
import static org.jooq.impl.DSL.constraint;
import static org.jooq.impl.DSL.dual;
import static org.jooq.impl.DSL.name;
import static org.jooq.impl.DSL.select;
import static org.jooq.impl.DSL.selectFrom;
import static org.jooq.impl.DSL.selectOne;
@ -60,6 +62,7 @@ import static org.jooq.impl.Keywords.K_IGNORE;
import static org.jooq.impl.Keywords.K_INSERT;
import static org.jooq.impl.Keywords.K_INTO;
import static org.jooq.impl.Keywords.K_ON_CONFLICT;
import static org.jooq.impl.Keywords.K_ON_CONSTRAINT;
import static org.jooq.impl.Keywords.K_ON_DUPLICATE_KEY_UPDATE;
import static org.jooq.impl.Keywords.K_OR;
import static org.jooq.impl.Keywords.K_SET;
@ -69,6 +72,7 @@ import static org.jooq.impl.Tools.EMPTY_FIELD;
import static org.jooq.impl.Tools.aliasedFields;
import static org.jooq.impl.Tools.fieldNameStrings;
import static org.jooq.impl.Tools.fieldNames;
import static org.jooq.impl.Tools.DataKey.DATA_CONSTRAINT_REFERENCE;
import static org.jooq.impl.Tools.DataKey.DATA_INSERT_SELECT_WITHOUT_INSERT_COLUMN_LIST;
import java.util.Arrays;
@ -79,6 +83,7 @@ import java.util.Map;
import org.jooq.Clause;
import org.jooq.Condition;
import org.jooq.Configuration;
import org.jooq.Constraint;
import org.jooq.Context;
import org.jooq.Field;
import org.jooq.Identity;
@ -93,6 +98,7 @@ import org.jooq.Record;
import org.jooq.SQLDialect;
import org.jooq.Select;
import org.jooq.Table;
import org.jooq.UniqueKey;
import org.jooq.exception.SQLDialectNotSupportedException;
/**
@ -110,6 +116,7 @@ final class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> impl
private boolean defaultValues;
private boolean onDuplicateKeyUpdate;
private boolean onDuplicateKeyIgnore;
private Constraint onConstraint;
private QueryPartList<Field<?>> onConflict;
private final ConditionProviderImpl condition;
@ -147,6 +154,24 @@ final class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> impl
this.onConflict = new QueryPartList<Field<?>>(fields);
}
@Override
public final void onConflictOnConstraint(Constraint constraint) {
this.onConstraint = constraint;
}
@Override
public void onConflictOnConstraint(UniqueKey<R> constraint) {
if (constraint.getName() == null)
throw new IllegalStateException("UniqueKey's name is not specified");
onConflictOnConstraint(name(constraint.getName()));
}
@Override
public final void onConflictOnConstraint(Name constraint) {
onConflictOnConstraint(constraint(constraint));
}
@Override
public final void onDuplicateKeyUpdate(boolean flag) {
this.onDuplicateKeyIgnore = false;
@ -248,30 +273,41 @@ final class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> impl
case POSTGRES: {
toSQLInsert(ctx);
ctx.formatSeparator()
.start(INSERT_ON_DUPLICATE_KEY_UPDATE)
.visit(K_ON_CONFLICT)
.sql(" (");
.start(INSERT_ON_DUPLICATE_KEY_UPDATE);
if (onConflict != null && onConflict.size() > 0) {
boolean qualify = ctx.qualify();
if (onConstraint != null) {
ctx.data(DATA_CONSTRAINT_REFERENCE, true);
ctx.visit(K_ON_CONSTRAINT)
.sql(' ')
.visit(onConstraint)
.sql(' ');
ctx.qualify(false)
.visit(onConflict)
.qualify(qualify);
}
else if (table.getPrimaryKey() == null) {
ctx.sql("[unknown primary key]");
ctx.data().remove(DATA_CONSTRAINT_REFERENCE);
}
else {
boolean qualify = ctx.qualify();
ctx.visit(K_ON_CONFLICT)
.sql(" (");
ctx.qualify(false)
.visit(new Fields<Record>(table.getPrimaryKey().getFields()))
.qualify(qualify);
if (onConflict != null && onConflict.size() > 0) {
boolean qualify = ctx.qualify();
ctx.qualify(false)
.visit(onConflict)
.qualify(qualify);
} else if (table.getPrimaryKey() == null) {
ctx.sql("[unknown primary key]");
} else {
boolean qualify = ctx.qualify();
ctx.qualify(false)
.visit(new Fields<Record>(table.getPrimaryKey().getFields()))
.qualify(qualify);
}
ctx.sql(") ");
}
ctx.sql(") ")
.visit(K_DO_UPDATE)
ctx.visit(K_DO_UPDATE)
.formatSeparator()
.visit(K_SET)
.sql(' ')
@ -335,18 +371,30 @@ final class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> impl
case POSTGRES: {
toSQLInsert(ctx);
ctx.formatSeparator()
.start(INSERT_ON_DUPLICATE_KEY_UPDATE)
.visit(K_ON_CONFLICT)
.sql(' ');
.start(INSERT_ON_DUPLICATE_KEY_UPDATE);
if (onConflict != null && onConflict.size() > 0) {
boolean qualify = ctx.qualify();
if (onConstraint != null) {
ctx.data(DATA_CONSTRAINT_REFERENCE, true);
ctx.visit(K_ON_CONSTRAINT)
.sql(' ')
.visit(onConstraint)
.sql(' ');
ctx.sql('(')
.qualify(false)
.visit(onConflict)
.qualify(qualify)
.sql(") ");
ctx.data().remove(DATA_CONSTRAINT_REFERENCE);
}
else {
ctx.visit(K_ON_CONFLICT)
.sql(' ');
if (onConflict != null && onConflict.size() > 0) {
boolean qualify = ctx.qualify();
ctx.sql('(')
.qualify(false)
.visit(onConflict)
.qualify(qualify)
.sql(") ");
}
}
ctx.visit(K_DO_NOTHING)

View File

@ -187,6 +187,7 @@ final class Keywords {
static final Keyword K_ON_COMMIT_DROP = keyword("on commit drop");
static final Keyword K_ON_COMMIT_PRESERVE_ROWS = keyword("on commit preserve rows");
static final Keyword K_ON_CONFLICT = keyword("on conflict");
static final Keyword K_ON_CONSTRAINT = keyword("on constraint");
static final Keyword K_ON_DELETE = keyword("on delete");
static final Keyword K_ON_DUPLICATE_KEY_UPDATE = keyword("on duplicate key update");
static final Keyword K_ON_UPDATE = keyword("on update");