[jOOQ/jOOQ#2682] Support outer joins with policies

This commit is contained in:
Lukas Eder 2023-09-22 17:30:45 +02:00
parent 67aa9616f4
commit 54d663bcba
4 changed files with 71 additions and 17 deletions

View File

@ -57,6 +57,22 @@ package org.jooq;

View File

@ -187,13 +187,18 @@ abstract class JoinTable<J extends JoinTable<J>> extends AbstractJoinTable<J> {
this.using = new QueryPartList<>();
}
@SuppressWarnings("unchecked")
@Deprecated
final J transform(Table<?> newLhs, Table<?> newRhs) {
if (lhs == newLhs && rhs == newRhs)
return transform(newLhs, newRhs, condition);
}
@SuppressWarnings("unchecked")
@Deprecated
final J transform(Table<?> newLhs, Table<?> newRhs, ConditionProviderImpl newCondition) {
if (lhs == newLhs && rhs == newRhs && condition == newCondition)
return (J) this;
return construct(newLhs, lhsPartitionBy, rhsPartitionBy, newRhs, condition, using);
return construct(newLhs, lhsPartitionBy, rhsPartitionBy, newRhs, newCondition, using);
}
// ------------------------------------------------------------------------

View File

@ -156,6 +156,7 @@ import static org.jooq.impl.DSL.regexpReplaceAll;
import static org.jooq.impl.DSL.row;
import static org.jooq.impl.DSL.rowNumber;
// ...
import static org.jooq.impl.DSL.selectFrom;
import static org.jooq.impl.DSL.table;
import static org.jooq.impl.DSL.trueCondition;
import static org.jooq.impl.DSL.unquotedName;
@ -2846,7 +2847,12 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
return result;
}
private static final void transformInlineDerivedTable0(Context<?> ctx, Table<?> table, TableList result, ConditionProviderImpl where) {
private static final void transformInlineDerivedTable0(
Context<?> ctx,
Table<?> table,
TableList result,
ConditionProviderImpl where
) {
Table<?> t = inlineDerivedTable(ctx, table);
if (t != null) {
@ -2863,13 +2869,26 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
result.add(table);
}
private static final Table<?> transformInlineDerivedTables0(Context<?> ctx, Table<?> table, ConditionProviderImpl where, boolean keepDerivedTable) {
private static final Table<?> transformInlineDerivedTables0(
Context<?> ctx,
Table<?> table,
ConditionProviderImpl where,
boolean keepDerivedTable
) {
Table<?> t = inlineDerivedTable(ctx, table);
if (t != null) {
if (t instanceof InlineDerivedTable<?> i) {
if (keepDerivedTable)
return i.query().asTable(i.table);
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;
@ -2880,6 +2899,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
else if (table instanceof JoinTable<?> j) {
Table<?> lhs;
Table<?> rhs;
ConditionProviderImpl w = new ConditionProviderImpl();
switch (j.type) {
case LEFT_OUTER_JOIN:
@ -2888,30 +2908,34 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
case STRAIGHT_JOIN:
case CROSS_APPLY:
case OUTER_APPLY:
case NATURAL_LEFT_OUTER_JOIN:
case NATURAL_LEFT_OUTER_JOIN: {
lhs = transformInlineDerivedTables0(ctx, j.lhs, where, keepDerivedTable);
rhs = transformInlineDerivedTables0(ctx, j.rhs, where, true);
rhs = transformInlineDerivedTables0(ctx, j.rhs, w, true);
break;
}
case RIGHT_OUTER_JOIN:
case NATURAL_RIGHT_OUTER_JOIN:
lhs = transformInlineDerivedTables0(ctx, j.lhs, where, true);
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, where, true);
rhs = transformInlineDerivedTables0(ctx, j.rhs, where, true);
case NATURAL_FULL_OUTER_JOIN: {
lhs = transformInlineDerivedTables0(ctx, j.lhs, w, true);
rhs = transformInlineDerivedTables0(ctx, j.rhs, w, true);
break;
}
default:
default: {
lhs = transformInlineDerivedTables0(ctx, j.lhs, where, keepDerivedTable);
rhs = transformInlineDerivedTables0(ctx, j.rhs, where, keepDerivedTable);
break;
}
}
return j.transform(lhs, rhs);
return j.transform(lhs, rhs, w.hasWhere() ? w : j.condition);
}
else
return table;

View File

@ -62,6 +62,7 @@ import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.GeneratorStatementType;
import org.jooq.Name;
// ...
import org.jooq.Record;
import org.jooq.RowId;
import org.jooq.Table;
@ -206,14 +207,22 @@ implements
static final void accept2(Context<?> ctx, Table<?> table, Name unqualifiedName) {
ctx.data(DATA_OMIT_CLAUSE_EVENT_EMISSION, true, c -> {
if (c.qualify() && table != null && !FALSE.equals(ctx.data(DATA_RENDER_TABLE)))
if (c.qualify() && table != null && !FALSE.equals(ctx.data(DATA_RENDER_TABLE))) {
// [#15629] In some cases (e.g. outer joins), where an InlineDerivedTable can't be
// inlined and must generate a derived table, we mustn't fully qualify fields.
if (table instanceof TableImpl && ((TableImpl<?>) table).where != null)
c.qualify(false, c2 -> c2.visit(table).sql('.'));
else
c.visit(table).sql('.');
}
c.visit(unqualifiedName);
});