diff --git a/jOOQ/src/main/java/org/jooq/Context.java b/jOOQ/src/main/java/org/jooq/Context.java index 2e32f0ad65..eb1f985627 100644 --- a/jOOQ/src/main/java/org/jooq/Context.java +++ b/jOOQ/src/main/java/org/jooq/Context.java @@ -181,11 +181,23 @@ public interface Context> extends Scope { C scopeMarkStart(QueryPart part); /** - * Register a "special" query part in the scope. + * Register a "special" query part in the scope, reusing the object from a + * higher scope, if available. */ @NotNull C scopeRegister(QueryPart part); + /** + * Register a "special" query part in the scope, allowing to force + * registering the object in the new scope, if a higher scope already has + * the object. + *

+ * [#10992] This is necessary to allow for hiding identifiers from nested + * scopes. + */ + @NotNull + C scopeRegister(QueryPart part, boolean forceNew); + /** * Mark the end of a scoped query part. */ diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java b/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java index b1e15c9a92..0fccab6097 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java @@ -572,7 +572,12 @@ abstract class AbstractContext> extends AbstractScope imple } @Override - public /* non-final */ C scopeRegister(QueryPart part) { + public final C scopeRegister(QueryPart part) { + return scopeRegister(part, false); + } + + @Override + public /* non-final */ C scopeRegister(QueryPart part, boolean forceNew) { return (C) this; } diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java index c2abb98f2e..42a653f3f0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java @@ -189,7 +189,7 @@ class DefaultRenderContext extends AbstractContext implements Ren } @Override - public RenderContext scopeRegister(QueryPart part) { + public RenderContext scopeRegister(QueryPart part, boolean forceNew) { if (scopeStack.inScope()) { if (part instanceof TableImpl) { Table root = (Table) part; @@ -201,7 +201,10 @@ class DefaultRenderContext extends AbstractContext implements Ren root = child; } - ScopeStackElement e = scopeStack.getOrCreate(root); + ScopeStackElement e = forceNew + ? scopeStack.create(root) + : scopeStack.getOrCreate(root); + if (e.joinNode == null) e.joinNode = new JoinNode(root); diff --git a/jOOQ/src/main/java/org/jooq/impl/ScopeStack.java b/jOOQ/src/main/java/org/jooq/impl/ScopeStack.java index a293a8e1b8..41a4087c23 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ScopeStack.java +++ b/jOOQ/src/main/java/org/jooq/impl/ScopeStack.java @@ -158,12 +158,16 @@ final class ScopeStack implements Iterable { final V getOrCreate(K key) { List list = list(key); V result = get0(list); + return result != null ? result : create0(list); + } - if (result == null) { - result = constructor.create(scopeLevel); - set0(list, result); - } + final V create(K key) { + return create0(list(key)); + } + private final V create0(List list) { + V result = constructor.create(scopeLevel); + set0(list, result); return result; } diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java index a5e4ccb285..bc39e21dc6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java @@ -1537,7 +1537,7 @@ final class SelectQueryImpl extends AbstractResultQuery imp registerTable(context, ((JoinTable) table).rhs); } else if (table instanceof TableImpl) - context.scopeRegister(table); + context.scopeRegister(table, true); } private final void pushWindow(Context context) {