[jOOQ/jOOQ#2682] [jOOQ/jOOQ#15632] Support DELETE .. USING

This commit is contained in:
Lukas Eder 2023-09-26 09:24:17 +02:00
parent 6ef4abdbbb
commit fa8a665b05
3 changed files with 141 additions and 125 deletions

View File

@ -82,6 +82,7 @@ import static org.jooq.impl.DSL.noCondition;
import static org.jooq.impl.DSL.row;
import static org.jooq.impl.DSL.select;
import static org.jooq.impl.DSL.trueCondition;
import static org.jooq.impl.InlineDerivedTable.transformInlineDerivedTables;
import static org.jooq.impl.Internal.hash;
import static org.jooq.impl.Keywords.K_DELETE;
import static org.jooq.impl.Keywords.K_FROM;
@ -253,11 +254,28 @@ implements
public final void accept(Context<?> ctx) {
ctx.scopeStart(this);
// [#2682] [#15632] Apply inline derived tables to the target table (TODO: Apply also to USING, etc.)
// [#2682] [#15632] Apply inline derived tables to the target table
// [#15632] TODO: Check if this behaves correctly with aliases
Table<?> t = InlineDerivedTable.inlineDerivedTable(ctx, table(ctx));
if (t instanceof InlineDerivedTable<?> i) {
copy(d -> d.addConditions(i.condition), i.table).accept0(ctx);
Table<?> t = table(ctx);
Table<?> i = InlineDerivedTable.inlineDerivedTable(ctx, t);
InlineDerivedTable<?> j = i instanceof InlineDerivedTable ? (InlineDerivedTable<?>) i : null;
ConditionProviderImpl where = new ConditionProviderImpl();
TableList u = transformInlineDerivedTables(ctx, using, where);
if (j != null || u != using) {
copy(
d -> {
if (j != null) {
d.addConditions(j.condition);
}
if (u != using) {
d.addConditions(where);
d.using.clear();
d.using.addAll(u);
}
},
(Table<?>) (j != null ? j.table : t)
).accept0(ctx);
}
else
accept0(ctx);
@ -437,11 +455,11 @@ implements
// XXX: Query Object Model
// -------------------------------------------------------------------------
final DeleteQueryImpl<R> copy(Consumer<? super DeleteQueryImpl<R>> finisher) {
final DeleteQueryImpl<R> copy(Consumer<? super DeleteQueryImpl<?>> finisher) {
return copy(finisher, table);
}
final <O extends Record> DeleteQueryImpl<O> copy(Consumer<? super DeleteQueryImpl<O>> finisher, Table<O> t) {
final <O extends Record> DeleteQueryImpl<O> copy(Consumer<? super DeleteQueryImpl<?>> finisher, Table<O> t) {
DeleteQueryImpl<O> r = new DeleteQueryImpl<>(configuration(), with, t);
r.using.addAll(using);
r.condition.addConditions(extractCondition(condition));

View File

@ -40,6 +40,7 @@ package org.jooq.impl;
import static org.jooq.impl.DSL.selectFrom;
import static org.jooq.impl.DSL.table;
import static org.jooq.impl.Tools.anyMatch;
import org.jooq.Condition;
import org.jooq.Context;
@ -70,6 +71,121 @@ final class InlineDerivedTable<R extends Record> extends DerivedTable<R> {
this.condition = condition;
}
static final boolean hasInlineDerivedTables(Context<?> ctx, Table<?> t) {
return InlineDerivedTable.inlineDerivedTable(ctx, t) != null
|| t instanceof JoinTable && (hasInlineDerivedTables(ctx, ((JoinTable<?>) t).lhs) || hasInlineDerivedTables(ctx, ((JoinTable<?>) t).rhs));
}
static final boolean hasInlineDerivedTables(Context<?> ctx, TableList tablelist) {
return anyMatch(tablelist, t -> hasInlineDerivedTables(ctx, t));
}
static final TableList transformInlineDerivedTables(Context<?> ctx, TableList tablelist, ConditionProviderImpl where) {
if (!hasInlineDerivedTables(ctx, tablelist))
return tablelist;
TableList result = new TableList();
for (Table<?> table : tablelist)
transformInlineDerivedTable0(ctx, table, result, where);
return result;
}
static final void transformInlineDerivedTable0(
Context<?> ctx,
Table<?> table,
TableList result,
ConditionProviderImpl where
) {
Table<?> t = InlineDerivedTable.inlineDerivedTable(ctx, table);
if (t != null) {
if (t instanceof InlineDerivedTable<?> i) {
result.add(i.table);
where.addConditions(i.condition);
}
else
result.add(t);
}
else if (table instanceof JoinTable)
result.add(transformInlineDerivedTables0(ctx, table, where, false));
else
result.add(table);
}
static final Table<?> transformInlineDerivedTables0(
Context<?> ctx,
Table<?> table,
ConditionProviderImpl where,
boolean keepDerivedTable
) {
Table<?> t = InlineDerivedTable.inlineDerivedTable(ctx, table);
if (t != null) {
if (t instanceof InlineDerivedTable<?> i) {
if (keepDerivedTable) {
// [#2682] An explicit path join that produces an InlineDerivedTable (e.g. due to a Policy)
if (TableImpl.path(i.table) != null) {
where.addConditions(((TableImpl<?>) i.table).pathCondition());
return selectFrom(Tools.unwrap(i.table).as(i.table)).asTable(i.table);
}
else
return i.query().asTable(i.table);
}
where.addConditions(i.condition);
return i.table;
}
else
return t;
}
else if (table instanceof JoinTable<?> j) {
Table<?> lhs;
Table<?> rhs;
ConditionProviderImpl w = new ConditionProviderImpl();
switch (j.type) {
case LEFT_OUTER_JOIN:
case LEFT_ANTI_JOIN:
case LEFT_SEMI_JOIN:
case STRAIGHT_JOIN:
case CROSS_APPLY:
case OUTER_APPLY:
case NATURAL_LEFT_OUTER_JOIN: {
lhs = transformInlineDerivedTables0(ctx, j.lhs, where, keepDerivedTable);
rhs = transformInlineDerivedTables0(ctx, j.rhs, w, true);
break;
}
case RIGHT_OUTER_JOIN:
case NATURAL_RIGHT_OUTER_JOIN: {
lhs = transformInlineDerivedTables0(ctx, j.lhs, w, true);
rhs = transformInlineDerivedTables0(ctx, j.rhs, where, keepDerivedTable);
break;
}
case FULL_OUTER_JOIN:
case NATURAL_FULL_OUTER_JOIN: {
lhs = transformInlineDerivedTables0(ctx, j.lhs, w, true);
rhs = transformInlineDerivedTables0(ctx, j.rhs, w, true);
break;
}
default: {
lhs = transformInlineDerivedTables0(ctx, j.lhs, where, keepDerivedTable);
rhs = transformInlineDerivedTables0(ctx, j.rhs, where, keepDerivedTable);
break;
}
}
return j.transform(lhs, rhs, w.hasWhere() ? w : j.condition);
}
else
return table;
}
static final <R extends Record> Table<R> inlineDerivedTable(Context<?> ctx, Table<R> t) {

View File

@ -163,6 +163,7 @@ import static org.jooq.impl.DSL.unquotedName;
import static org.jooq.impl.DSL.xmlagg;
import static org.jooq.impl.DSL.xmlattributes;
import static org.jooq.impl.DSL.xmlelement;
import static org.jooq.impl.InlineDerivedTable.transformInlineDerivedTables;
import static org.jooq.impl.Internal.isub;
import static org.jooq.impl.JSONArrayAgg.EMULATE_WITH_GROUP_CONCAT;
import static org.jooq.impl.JSONArrayAgg.patchOracleArrayAggBug;
@ -2784,14 +2785,6 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
return r;
}
private static final boolean hasInlineDerivedTables(Context<?> ctx, Table<?> t) {
return InlineDerivedTable.inlineDerivedTable(ctx, t) != null
|| t instanceof JoinTable && (hasInlineDerivedTables(ctx, ((JoinTable<?>) t).lhs) || hasInlineDerivedTables(ctx, ((JoinTable<?>) t).rhs));
}
private static final boolean hasInlineDerivedTables(Context<?> ctx, TableList tablelist) {
return anyMatch(tablelist, t -> hasInlineDerivedTables(ctx, t));
}
@ -2826,117 +2819,6 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
private static final TableList transformInlineDerivedTables(Context<?> ctx, TableList tablelist, ConditionProviderImpl where) {
if (!hasInlineDerivedTables(ctx, tablelist))
return tablelist;
TableList result = new TableList();
for (Table<?> table : tablelist)
transformInlineDerivedTable0(ctx, table, result, where);
return result;
}
private static final void transformInlineDerivedTable0(
Context<?> ctx,
Table<?> table,
TableList result,
ConditionProviderImpl where
) {
Table<?> t = InlineDerivedTable.inlineDerivedTable(ctx, table);
if (t != null) {
if (t instanceof InlineDerivedTable<?> i) {
result.add(i.table);
where.addConditions(i.condition);
}
else
result.add(t);
}
else if (table instanceof JoinTable)
result.add(transformInlineDerivedTables0(ctx, table, where, false));
else
result.add(table);
}
private static final Table<?> transformInlineDerivedTables0(
Context<?> ctx,
Table<?> table,
ConditionProviderImpl where,
boolean keepDerivedTable
) {
Table<?> t = InlineDerivedTable.inlineDerivedTable(ctx, table);
if (t != null) {
if (t instanceof InlineDerivedTable<?> i) {
if (keepDerivedTable) {
// [#2682] An explicit path join that produces an InlineDerivedTable (e.g. due to a Policy)
if (TableImpl.path(i.table) != null) {
where.addConditions(((TableImpl<?>) i.table).pathCondition());
return selectFrom(Tools.unwrap(i.table).as(i.table)).asTable(i.table);
}
else
return i.query().asTable(i.table);
}
where.addConditions(i.condition);
return i.table;
}
else
return t;
}
else if (table instanceof JoinTable<?> j) {
Table<?> lhs;
Table<?> rhs;
ConditionProviderImpl w = new ConditionProviderImpl();
switch (j.type) {
case LEFT_OUTER_JOIN:
case LEFT_ANTI_JOIN:
case LEFT_SEMI_JOIN:
case STRAIGHT_JOIN:
case CROSS_APPLY:
case OUTER_APPLY:
case NATURAL_LEFT_OUTER_JOIN: {
lhs = transformInlineDerivedTables0(ctx, j.lhs, where, keepDerivedTable);
rhs = transformInlineDerivedTables0(ctx, j.rhs, w, true);
break;
}
case RIGHT_OUTER_JOIN:
case NATURAL_RIGHT_OUTER_JOIN: {
lhs = transformInlineDerivedTables0(ctx, j.lhs, w, true);
rhs = transformInlineDerivedTables0(ctx, j.rhs, where, keepDerivedTable);
break;
}
case FULL_OUTER_JOIN:
case NATURAL_FULL_OUTER_JOIN: {
lhs = transformInlineDerivedTables0(ctx, j.lhs, w, true);
rhs = transformInlineDerivedTables0(ctx, j.rhs, w, true);
break;
}
default: {
lhs = transformInlineDerivedTables0(ctx, j.lhs, where, keepDerivedTable);
rhs = transformInlineDerivedTables0(ctx, j.rhs, where, keepDerivedTable);
break;
}
}
return j.transform(lhs, rhs, w.hasWhere() ? w : j.condition);
}
else
return table;
}