[jOOQ/jOOQ#12194] MySQL DELETE .. USING with JOIN produces duplicate
table declarations in USING clause
This commit is contained in:
parent
8e358aac44
commit
9bc5fe43c0
@ -83,6 +83,7 @@ import static org.jooq.impl.Keywords.K_LIMIT;
|
||||
import static org.jooq.impl.Keywords.K_ORDER_BY;
|
||||
import static org.jooq.impl.Keywords.K_USING;
|
||||
import static org.jooq.impl.Keywords.K_WHERE;
|
||||
import static org.jooq.impl.Tools.containsDeclaredTable;
|
||||
import static org.jooq.impl.Tools.traverseJoins;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -253,11 +254,12 @@ final class DeleteQueryImpl<R extends Record> extends AbstractDMLQuery<R> implem
|
||||
if (!using.isEmpty() || multiTableJoin || specialDeleteAsSyntax && Tools.alias(t) != null) {
|
||||
TableList u;
|
||||
|
||||
if (REQUIRE_REPEAT_FROM_IN_USING.contains(ctx.dialect()) && !using.contains(t)) {
|
||||
|
||||
if (REQUIRE_REPEAT_FROM_IN_USING.contains(ctx.dialect()) && !containsDeclaredTable(using, t)) {
|
||||
u = new TableList(t);
|
||||
u.addAll(using);
|
||||
}
|
||||
else if (NO_SUPPORT_REPEAT_FROM_IN_USING.contains(ctx.dialect()) && using.contains(t)) {
|
||||
else if (NO_SUPPORT_REPEAT_FROM_IN_USING.contains(ctx.dialect()) && containsDeclaredTable(using, t)) {
|
||||
u = new TableList(using);
|
||||
u.remove(t);
|
||||
}
|
||||
|
||||
@ -104,9 +104,8 @@ import static org.jooq.impl.Keywords.K_PARTITION_BY;
|
||||
import static org.jooq.impl.Keywords.K_USING;
|
||||
import static org.jooq.impl.Names.N_JOIN;
|
||||
import static org.jooq.impl.QueryPartListView.wrap;
|
||||
import static org.jooq.impl.Tools.containsUnaliasedTable;
|
||||
import static org.jooq.impl.Tools.map;
|
||||
import static org.jooq.impl.Tools.search;
|
||||
import static org.jooq.impl.Tools.traverseJoins;
|
||||
import static org.jooq.impl.Tools.BooleanDataKey.DATA_COLLECT_SEMI_ANTI_JOIN;
|
||||
import static org.jooq.impl.Tools.DataKey.DATA_COLLECTED_SEMI_ANTI_JOIN;
|
||||
|
||||
@ -704,7 +703,7 @@ implements
|
||||
unaliased.set(i, (TableField<?, ?>) alias.wrapped().field(f));
|
||||
}
|
||||
|
||||
if (traverseJoins(lhs, false, r -> r, search(keyFields[0].getTable()))) {
|
||||
if (containsUnaliasedTable(lhs, keyFields[0].getTable())) {
|
||||
for (ForeignKey<?, ?> key : lhs.getReferences())
|
||||
if (key.getFields().containsAll(unaliased) && unaliased.containsAll(key.getFields()))
|
||||
return onKey(key);
|
||||
@ -713,7 +712,7 @@ implements
|
||||
if (key.getFields().containsAll(unaliased))
|
||||
return onKey(key);
|
||||
}
|
||||
else if (traverseJoins(rhs, false, r -> r, search(keyFields[0].getTable()))) {
|
||||
else if (containsUnaliasedTable(rhs, keyFields[0].getTable())) {
|
||||
for (ForeignKey<?, ?> key : rhs.getReferences())
|
||||
if (key.getFields().containsAll(unaliased) && unaliased.containsAll(key.getFields()))
|
||||
return onKey(key);
|
||||
@ -729,9 +728,9 @@ implements
|
||||
|
||||
@Override
|
||||
public final JoinTable onKey(ForeignKey<?, ?> key) {
|
||||
if (traverseJoins(lhs, false, r -> r, search(key.getTable())))
|
||||
if (containsUnaliasedTable(lhs, key.getTable()))
|
||||
return onKey(key, lhs, rhs);
|
||||
else if (traverseJoins(rhs, false, r -> r, search(key.getTable())))
|
||||
else if (containsUnaliasedTable(rhs, key.getTable()))
|
||||
return onKey(key, rhs, lhs);
|
||||
|
||||
throw onKeyException(OnKeyExceptionReason.NOT_FOUND, null, null);
|
||||
|
||||
@ -188,6 +188,7 @@ import static org.jooq.impl.Tools.aliasedFields;
|
||||
import static org.jooq.impl.Tools.anyMatch;
|
||||
import static org.jooq.impl.Tools.autoAlias;
|
||||
import static org.jooq.impl.Tools.camelCase;
|
||||
import static org.jooq.impl.Tools.containsUnaliasedTable;
|
||||
import static org.jooq.impl.Tools.fieldArray;
|
||||
import static org.jooq.impl.Tools.findAny;
|
||||
import static org.jooq.impl.Tools.hasAmbiguousNames;
|
||||
@ -197,7 +198,6 @@ import static org.jooq.impl.Tools.isWindow;
|
||||
import static org.jooq.impl.Tools.map;
|
||||
import static org.jooq.impl.Tools.qualify;
|
||||
import static org.jooq.impl.Tools.recordType;
|
||||
import static org.jooq.impl.Tools.search;
|
||||
import static org.jooq.impl.Tools.selectQueryImpl;
|
||||
// ...
|
||||
import static org.jooq.impl.Tools.traverseJoins;
|
||||
@ -1374,7 +1374,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
&& REQUIRES_DERIVED_TABLE_DML.contains(ctx.dialect())
|
||||
&& !TRUE.equals(ctx.data(DATA_INSERT_SELECT))
|
||||
&& (dmlTable = (Table<?>) ctx.data(DATA_DML_TARGET_TABLE)) != null
|
||||
&& containsTable(dmlTable)) {
|
||||
&& containsUnaliasedTable(getFrom(), dmlTable)) {
|
||||
ctx.visit(DSL.select(asterisk()).from(asTable("t")));
|
||||
}
|
||||
|
||||
@ -3795,10 +3795,6 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
|
||||
return traverseJoins(getFrom(), true, r -> !r, (r, t) -> r && t.fieldsRow().size() > 0);
|
||||
}
|
||||
|
||||
private final boolean containsTable(Table<?> table) {
|
||||
return traverseJoins(getFrom(), false, r -> r, search(table));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
final Class<? extends R> getRecordType0() {
|
||||
|
||||
@ -6131,15 +6131,29 @@ final class Tools {
|
||||
// TODO: In a new expression tree model, we'll support generic visitors of some sort
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
static final BiFunction<Boolean, Table<?>, Boolean> search(Table<?> table) {
|
||||
return (r, t) -> {
|
||||
static final boolean containsDeclaredTable(Table<?> in, Table<?> search) {
|
||||
return traverseJoins(in, false, r -> r, search(search, t -> t));
|
||||
}
|
||||
|
||||
// [#6304] [#7626] Improved alias discovery
|
||||
Table<?> t1 = defaultIfNull(Tools.aliased(table), table);
|
||||
Table<?> t2 = defaultIfNull(Tools.aliased(t), t);
|
||||
static final boolean containsDeclaredTable(Iterable<? extends Table<?>> in, Table<?> search) {
|
||||
return traverseJoins(in, false, r -> r, search(search, t -> t));
|
||||
}
|
||||
|
||||
return r || t1.equals(t2);
|
||||
};
|
||||
private static final BiFunction<Boolean, Table<?>, Boolean> search(Table<?> table, Function<? super Table<?>, ? extends Table<?>> f) {
|
||||
Table<?> unaliased = f.apply(table);
|
||||
return (r, t) -> r || unaliased.equals(f.apply(t));
|
||||
}
|
||||
|
||||
static final boolean containsUnaliasedTable(Table<?> in, Table<?> search) {
|
||||
|
||||
// [#6304] [#7626] Improved alias discovery
|
||||
return traverseJoins(in, false, r -> r, search(search, Tools::unalias));
|
||||
}
|
||||
|
||||
static final boolean containsUnaliasedTable(Iterable<? extends Table<?>> in, Table<?> search) {
|
||||
|
||||
// [#6304] [#7626] Improved alias discovery
|
||||
return traverseJoins(in, false, r -> r, search(search, Tools::unalias));
|
||||
}
|
||||
|
||||
static final void traverseJoins(Iterable<? extends Table<?>> i, Consumer<? super Table<?>> consumer) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user