From 54d663bcba6a30e58c10a87a6715a6dbeb42bf16 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 22 Sep 2023 17:30:45 +0200 Subject: [PATCH] [jOOQ/jOOQ#2682] Support outer joins with policies --- .../main/java/org/jooq/PolicyStatement.java | 16 ++++++ .../main/java/org/jooq/impl/JoinTable.java | 11 ++-- .../java/org/jooq/impl/SelectQueryImpl.java | 50 ++++++++++++++----- .../java/org/jooq/impl/TableFieldImpl.java | 11 +++- 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/PolicyStatement.java b/jOOQ/src/main/java/org/jooq/PolicyStatement.java index 60d6b6f9a9..70fe35cb61 100644 --- a/jOOQ/src/main/java/org/jooq/PolicyStatement.java +++ b/jOOQ/src/main/java/org/jooq/PolicyStatement.java @@ -57,6 +57,22 @@ package org.jooq; + + + + + + + + + + + + + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/JoinTable.java b/jOOQ/src/main/java/org/jooq/impl/JoinTable.java index 19a3ac0128..e850d40de6 100755 --- a/jOOQ/src/main/java/org/jooq/impl/JoinTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/JoinTable.java @@ -187,13 +187,18 @@ abstract class JoinTable> extends AbstractJoinTable { 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); } // ------------------------------------------------------------------------ diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java index e6405e8142..7ae813ce87 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java @@ -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 extends AbstractResultQuery 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 extends AbstractResultQuery 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 extends AbstractResultQuery 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 extends AbstractResultQuery 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; diff --git a/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java b/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java index de407a5bda..a811c5015e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java @@ -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); });