[jOOQ/jOOQ#14742] Fix regressions. These still don't work in MariaDB:
- INSERT INTO t VALUES ((SELECT .. FROM t)) - DELETE FROM t USING t AS u WHERE u.x = (SELECT .. FROM t)
This commit is contained in:
parent
57204a93cc
commit
2b5cc36086
@ -103,6 +103,7 @@ import static org.jooq.impl.Tools.removeGenerator;
|
||||
import static org.jooq.impl.Tools.unalias;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_UNALIAS_ALIASED_EXPRESSIONS;
|
||||
import static org.jooq.impl.Tools.SimpleDataKey.DATA_DML_TARGET_TABLE;
|
||||
import static org.jooq.impl.Tools.SimpleDataKey.DATA_DML_USING_TABLES;
|
||||
import static org.jooq.impl.Tools.SimpleDataKey.DATA_RENDERING_DATA_CHANGE_DELTA_TABLE;
|
||||
import static org.jooq.impl.Tools.SimpleDataKey.DATA_TOP_LEVEL_CTE;
|
||||
import static org.jooq.tools.StringUtils.defaultIfNull;
|
||||
@ -340,8 +341,9 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractRowCountQuery
|
||||
public final void accept(Context<?> ctx) {
|
||||
WithImpl w = with;
|
||||
|
||||
ctx.scopeStart()
|
||||
.data(DATA_DML_TARGET_TABLE, table);
|
||||
ctx.scopeStart();
|
||||
ctx.data(DATA_DML_TARGET_TABLE, table);
|
||||
ctx.data(DATA_DML_USING_TABLES, this instanceof DeleteQueryImpl<?> d ? d.$using() : null);
|
||||
|
||||
|
||||
|
||||
@ -672,6 +674,7 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractRowCountQuery
|
||||
|
||||
|
||||
|
||||
ctx.data().remove(DATA_DML_USING_TABLES);
|
||||
ctx.data().remove(DATA_DML_TARGET_TABLE);
|
||||
ctx.scopeEnd();
|
||||
}
|
||||
|
||||
@ -162,12 +162,7 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple
|
||||
|
||||
// Single record inserts can use the standard syntax in any dialect
|
||||
else if (rows == 1 && supportsValues(ctx)) {
|
||||
ctx.formatSeparator()
|
||||
.start(INSERT_VALUES)
|
||||
.visit(K_VALUES)
|
||||
.sql(' ');
|
||||
toSQL92Values(ctx);
|
||||
ctx.end(INSERT_VALUES);
|
||||
toSQLValues(ctx);
|
||||
}
|
||||
|
||||
// True SQL92 multi-record inserts aren't always supported
|
||||
@ -197,13 +192,14 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple
|
||||
|
||||
|
||||
|
||||
case MARIADB: {
|
||||
if (supportsValues(ctx))
|
||||
toSQLValues(ctx);
|
||||
else
|
||||
toSQLInsertSelect(ctx, insertSelect(ctx, GeneratorStatementType.INSERT));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -362,6 +358,20 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple
|
||||
|
||||
|
||||
|
||||
|
||||
// [#14742] MariaDB can't have (unaliased!) self-references of the INSERT
|
||||
// target table in INSERT INTO t VALUES ((SELECT .. FROM t)),
|
||||
// though other subqueries are possible
|
||||
// [#6583] While MySQL also has this limitation, it is already covered
|
||||
// for all DML statements, elsewhere
|
||||
case MARIADB:
|
||||
for (List<Field<?>> row : values.values())
|
||||
for (Field<?> value : row)
|
||||
if (value instanceof ScalarSubquery<?> s)
|
||||
if (Tools.containsTable(s.query.$from(), table, false))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
default:
|
||||
return true;
|
||||
|
||||
@ -227,6 +227,7 @@ import static org.jooq.impl.Tools.ExtendedDataKey.DATA_RENDER_TABLE;
|
||||
import static org.jooq.impl.Tools.ExtendedDataKey.DATA_TRANSFORM_ROWNUM_TO_LIMIT;
|
||||
import static org.jooq.impl.Tools.SimpleDataKey.DATA_COLLECTED_SEMI_ANTI_JOIN;
|
||||
import static org.jooq.impl.Tools.SimpleDataKey.DATA_DML_TARGET_TABLE;
|
||||
import static org.jooq.impl.Tools.SimpleDataKey.DATA_DML_USING_TABLES;
|
||||
import static org.jooq.impl.Tools.SimpleDataKey.DATA_OVERRIDE_ALIASES_IN_ORDER_BY;
|
||||
import static org.jooq.impl.Tools.SimpleDataKey.DATA_RENDERING_DATA_CHANGE_DELTA_TABLE;
|
||||
import static org.jooq.impl.Tools.SimpleDataKey.DATA_SELECT_ALIASES;
|
||||
@ -1423,6 +1424,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
@Override
|
||||
public final void accept(Context<?> ctx) {
|
||||
Table<?> dmlTable;
|
||||
List<Table<?>> dmlTables;
|
||||
|
||||
// [#6583] [#8609] [#14742] Work around MySQL's self-reference-in-DML-subquery restriction
|
||||
if (ctx.subqueryLevel() == 1
|
||||
@ -1433,6 +1435,23 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
ctx.visit(DSL.select(asterisk()).from(asTable("t")));
|
||||
}
|
||||
|
||||
// [#14742] MariaDB still has this bug: https://jira.mariadb.org/browse/MDEV-17954
|
||||
else if (ctx.subqueryLevel() == 1
|
||||
&& ctx.family() == MARIADB
|
||||
&& !TRUE.equals(ctx.data(DATA_INSERT_SELECT))
|
||||
&& (
|
||||
|
||||
// A USING clause can be generated when the target table is aliased
|
||||
(dmlTable = (Table<?>) ctx.data(DATA_DML_TARGET_TABLE)) != null
|
||||
&& Tools.aliased(dmlTable) != null
|
||||
&& containsUnaliasedTable(getFrom(), dmlTable)
|
||||
|
||||
// Or, explicitly
|
||||
|| (dmlTables = (List<Table<?>>) ctx.data(DATA_DML_USING_TABLES)) != null
|
||||
&& Tools.anyMatch(dmlTables, t -> containsUnaliasedTable(getFrom(), t)))) {
|
||||
ctx.visit(DSL.select(asterisk()).from(asTable("t")));
|
||||
}
|
||||
|
||||
// [#3564] Emulate DISTINCT ON queries at the top level
|
||||
else if (Tools.isNotEmpty(distinctOn) && EMULATE_DISTINCT_ON.contains(ctx.dialect())) {
|
||||
ctx.visit(distinctOnEmulation());
|
||||
|
||||
@ -818,6 +818,11 @@ final class Tools {
|
||||
*/
|
||||
DATA_DML_TARGET_TABLE,
|
||||
|
||||
/**
|
||||
* [#6583] [#14742] The target table on which a DML operation operates on.
|
||||
*/
|
||||
DATA_DML_USING_TABLES,
|
||||
|
||||
/**
|
||||
* [#8479] There is a WHERE clause to be emulated for ON DUPLICATE KEY
|
||||
*/
|
||||
@ -7169,6 +7174,12 @@ final class Tools {
|
||||
return traverseJoins(in, false, r -> r, search(search, t -> unwrap(t, unalias)));
|
||||
}
|
||||
|
||||
static final boolean containsTable(Iterable<? extends Table<?>> in, Table<?> search, boolean unalias) {
|
||||
|
||||
// [#6304] [#7626] [#14668] Improved alias discovery
|
||||
return traverseJoins(in, false, r -> r, search(search, t -> unwrap(t, unalias)));
|
||||
}
|
||||
|
||||
static final boolean containsUnaliasedTable(Table<?> in, Table<?> search) {
|
||||
|
||||
// [#6304] [#7626] [#14668] Improved alias discovery
|
||||
|
||||
Loading…
Reference in New Issue
Block a user