[#8479] Emulate INSERT .. ON DUPLICATE KEY UPDATE .. WHERE on MySQL
MySQL doesn't support the useful WHERE clause on ON DUPLICATE KEY UPDATE like PostgreSQL does on ON CONFLICT. But it can easily be emulated using CASE if users do not rely on the effective update counts.
This commit is contained in:
parent
72eda66bdf
commit
3f84ccf58f
@ -317,7 +317,7 @@ insertStatement =
|
||||
)
|
||||
break
|
||||
[
|
||||
'ON DUPLICATE KEY UPDATE' 'SET' setClauses
|
||||
'ON DUPLICATE KEY UPDATE' 'SET' setClauses [ 'WHERE' condition ]
|
||||
| 'ON DUPLICATE KEY IGNORE'
|
||||
| 'ON CONFLICT' ( 'ON CONSTRAINT' constraintName | '(' fieldNames ')' ) 'DO'
|
||||
(
|
||||
|
||||
@ -43,12 +43,15 @@ import static org.jooq.SQLDialect.POSTGRES;
|
||||
import static org.jooq.SQLDialect.SQLITE;
|
||||
// ...
|
||||
// ...
|
||||
import static org.jooq.impl.DSL.when;
|
||||
import static org.jooq.impl.Tools.flattenEntrySet;
|
||||
import static org.jooq.impl.Tools.DataKey.DATA_ON_DUPLICATE_KEY_WHERE;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jooq.Clause;
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.SQLDialect;
|
||||
@ -74,6 +77,7 @@ final class FieldMapForUpdate extends AbstractQueryPartMap<Field<?>, Field<?>> {
|
||||
this.assignmentClause = assignmentClause;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Override
|
||||
public final void accept(Context<?> ctx) {
|
||||
if (size() > 0) {
|
||||
@ -98,9 +102,16 @@ final class FieldMapForUpdate extends AbstractQueryPartMap<Field<?>, Field<?>> {
|
||||
.qualify(supportsQualify)
|
||||
.visit(entry.getKey())
|
||||
.qualify(restoreQualify)
|
||||
.sql(" = ")
|
||||
.visit(entry.getValue())
|
||||
.end(assignmentClause);
|
||||
.sql(" = ");
|
||||
|
||||
// [#8479] Emulate WHERE clause using CASE
|
||||
Condition condition = (Condition) ctx.data(DATA_ON_DUPLICATE_KEY_WHERE);
|
||||
if (condition != null)
|
||||
ctx.visit(when(condition, (Field) entry.getValue()).else_(entry.getKey()));
|
||||
else
|
||||
ctx.visit(entry.getValue());
|
||||
|
||||
ctx.end(assignmentClause);
|
||||
|
||||
separator = ", ";
|
||||
}
|
||||
|
||||
@ -79,6 +79,7 @@ import static org.jooq.impl.Tools.fieldNameStrings;
|
||||
import static org.jooq.impl.Tools.fieldNames;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_CONSTRAINT_REFERENCE;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_INSERT_SELECT_WITHOUT_INSERT_COLUMN_LIST;
|
||||
import static org.jooq.impl.Tools.DataKey.DATA_ON_DUPLICATE_KEY_WHERE;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -305,9 +306,18 @@ final class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> impl
|
||||
.visit(K_ON_DUPLICATE_KEY_UPDATE)
|
||||
.formatIndentStart()
|
||||
.formatSeparator()
|
||||
.qualify(newQualify)
|
||||
.visit(updateMap)
|
||||
.qualify(oldQualify)
|
||||
.qualify(newQualify);
|
||||
|
||||
// [#8479] Emulate WHERE clause using CASE
|
||||
if (condition.hasWhere())
|
||||
ctx.data(DATA_ON_DUPLICATE_KEY_WHERE, condition.getWhere());
|
||||
|
||||
ctx.visit(updateMap);
|
||||
|
||||
if (condition.hasWhere())
|
||||
ctx.data().remove(DATA_ON_DUPLICATE_KEY_WHERE);
|
||||
|
||||
ctx.qualify(oldQualify)
|
||||
.formatIndentEnd()
|
||||
.end(INSERT_ON_DUPLICATE_KEY_UPDATE);
|
||||
|
||||
|
||||
@ -1700,7 +1700,12 @@ final class ParserImpl implements Parser {
|
||||
|
||||
if (parseKeywordIf(ctx, "ON")) {
|
||||
if (parseKeywordIf(ctx, "DUPLICATE KEY UPDATE SET")) {
|
||||
returning = onDuplicate.onDuplicateKeyUpdate().set(parseSetClauseList(ctx));
|
||||
InsertOnConflictWhereStep<?> where = onDuplicate.onDuplicateKeyUpdate().set(parseSetClauseList(ctx));
|
||||
|
||||
if (parseKeywordIf(ctx, "WHERE"))
|
||||
returning = where.where(parseCondition(ctx));
|
||||
else
|
||||
returning = where;
|
||||
}
|
||||
else if (parseKeywordIf(ctx, "DUPLICATE KEY IGNORE")) {
|
||||
returning = onDuplicate.onDuplicateKeyIgnore();
|
||||
|
||||
@ -549,7 +549,12 @@ final class Tools {
|
||||
/**
|
||||
* [#6583] The target table on which a DML operation operates on.
|
||||
*/
|
||||
DATA_DML_TARGET_TABLE
|
||||
DATA_DML_TARGET_TABLE,
|
||||
|
||||
/**
|
||||
* [#8479] There is a WHERE clause to be emulated for ON DUPLICATE KEY
|
||||
*/
|
||||
DATA_ON_DUPLICATE_KEY_WHERE
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user