[jOOQ/jOOQ#5214] Updated MySQL emulation of EXCLUDED

For INSERT .. VALUES, we now generate the new syntax starting from MySQL 8.0.20, which is using VALUES (...) AS EXCLUDED. This doesn't work yet for INSERT .. SELECT, which I'll fix right away.
This commit is contained in:
Lukas Eder 2022-05-18 11:01:46 +02:00
parent e62218ac9a
commit 8ad020c55b
2 changed files with 42 additions and 8 deletions

View File

@ -100,12 +100,21 @@ implements
case MARIADB:
case MYSQL: {
case MARIADB: {
ctx.visit(K_VALUES).sql('(').qualify(false, c -> c.visit(field)).sql(')');
break;
}
case MYSQL: {
ctx.visit(N_EXCLUDED).sql('.').qualify(false, c -> c.visit(field));
break;
}
default:
ctx.visit(N_EXCLUDED).sql('.').qualify(false, c -> c.visit(field));
break;

View File

@ -56,6 +56,7 @@ import static org.jooq.SQLDialect.MARIADB;
// ...
import static org.jooq.SQLDialect.MYSQL;
// ...
// ...
import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
@ -68,6 +69,7 @@ import static org.jooq.impl.DSL.select;
import static org.jooq.impl.DSL.selectFrom;
import static org.jooq.impl.DSL.selectOne;
import static org.jooq.impl.FieldMapsForInsert.toSQLInsertSelect;
import static org.jooq.impl.Keywords.K_AS;
import static org.jooq.impl.Keywords.K_DEFAULT;
import static org.jooq.impl.Keywords.K_DEFAULT_VALUES;
import static org.jooq.impl.Keywords.K_DO_NOTHING;
@ -81,6 +83,7 @@ import static org.jooq.impl.Keywords.K_ON_DUPLICATE_KEY_UPDATE;
import static org.jooq.impl.Keywords.K_SET;
import static org.jooq.impl.Keywords.K_VALUES;
import static org.jooq.impl.Keywords.K_WHERE;
import static org.jooq.impl.Names.N_EXCLUDED;
import static org.jooq.impl.QueryPartListView.wrap;
import static org.jooq.impl.Tools.aliasedFields;
import static org.jooq.impl.Tools.anyMatch;
@ -151,6 +154,7 @@ implements
private static final Set<SQLDialect> SUPPORTS_OPTIONAL_DO_UPDATE_CONFLICT_TARGETS = SQLDialect.supportedBy(SQLITE);
private static final Set<SQLDialect> NO_SUPPORT_DERIVED_COLUMN_LIST_IN_MERGE_USING = SQLDialect.supportedBy(DERBY, H2);
private static final Set<SQLDialect> NO_SUPPORT_SUBQUERY_IN_MERGE_USING = SQLDialect.supportedBy(DERBY);
static final Set<SQLDialect> REQUIRE_NEW_MYSQL_EXCLUDED_EMULATION = SQLDialect.supportedBy(MYSQL);
final FieldMapForUpdate updateMap;
final FieldMapsForInsert insertMaps;
@ -443,8 +447,16 @@ implements
// wasn't supported (see https://github.com/h2database/h2database/issues/1027)
boolean oldQualify = ctx.qualify();
boolean newQualify = ctx.family() != H2 && oldQualify;
FieldMapForUpdate um = updateMapComputedOnClientStored(ctx);
Set<Field<?>> keys = toSQLInsert(ctx);
// [#5214] TODO: This is incorrect for INSERT .. SELECT
boolean requireNewMySQLExcludedEmulation = REQUIRE_NEW_MYSQL_EXCLUDED_EMULATION.contains(ctx.dialect()) && anyMatch(um.values(), v -> v instanceof Excluded);
if (requireNewMySQLExcludedEmulation)
ctx.formatSeparator()
.visit(K_AS).sql(' ').visit(N_EXCLUDED);
toSQLInsert(ctx);
ctx.formatSeparator()
.start(INSERT_ON_DUPLICATE_KEY_UPDATE)
.visit(K_ON_DUPLICATE_KEY_UPDATE)
@ -456,7 +468,17 @@ implements
if (condition.hasWhere())
ctx.data(DATA_ON_DUPLICATE_KEY_WHERE, condition.getWhere());
ctx.visit(updateMapComputedOnClientStored(ctx));
if (requireNewMySQLExcludedEmulation) {
um.replaceAll((k, v) -> {
if (v instanceof Excluded) { Excluded<?> e = (Excluded<?>) v;
return keys.contains(e.$field()) ? v : qualify(table(), e.$field());
}
else
return v;
});
}
ctx.visit(um);
if (condition.hasWhere())
ctx.data().remove(DATA_ON_DUPLICATE_KEY_WHERE);
@ -610,7 +632,7 @@ implements
return CLAUSES;
}
private final void toSQLInsert(Context<?> ctx) {
private final Set<Field<?>> toSQLInsert(Context<?> ctx) {
ctx.start(INSERT_INSERT_INTO)
.visit(K_INSERT)
.sql(' ');
@ -714,6 +736,8 @@ implements
else
ctx.visit(insertMaps);
return fields;
}
private final void acceptDefaultValuesEmulation(Context<?> ctx, int length) {
@ -909,6 +933,9 @@ implements
private final FieldMapForUpdate updateMapComputedOnClientStored(Context<?> ctx) {
// [#5214] Always make a copy to benefit other emulations
FieldMapForUpdate um = new FieldMapForUpdate(updateMap.table, SetClause.INSERT, updateMap.assignmentClause);
um.putAll(updateMap);
@ -921,9 +948,7 @@ implements
return updateMap;
return um;
}
/**