This is an automated email from the ASF dual-hosted git repository.
silun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new 2029412cdc [CALCITE-7401] Multi-level correlated subqueries cause an
out-of-range error in the TopDownGeneralDecorrelator
2029412cdc is described below
commit 2029412cdcc0518e3dee3891c468501344e103e0
Author: Silun Dong <[email protected]>
AuthorDate: Wed Jan 28 23:07:48 2026 +0800
[CALCITE-7401] Multi-level correlated subqueries cause an out-of-range
error in the TopDownGeneralDecorrelator
---
.../sql2rel/TopDownGeneralDecorrelator.java | 23 +++++++++++++++-------
core/src/test/resources/sql/new-decorr.iq | 17 ++++++++++++++++
2 files changed, 33 insertions(+), 7 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/sql2rel/TopDownGeneralDecorrelator.java
b/core/src/main/java/org/apache/calcite/sql2rel/TopDownGeneralDecorrelator.java
index 72401e3426..068ec441e5 100644
---
a/core/src/main/java/org/apache/calcite/sql2rel/TopDownGeneralDecorrelator.java
+++
b/core/src/main/java/org/apache/calcite/sql2rel/TopDownGeneralDecorrelator.java
@@ -17,6 +17,7 @@
package org.apache.calcite.sql2rel;
import org.apache.calcite.linq4j.function.Experimental;
+import org.apache.calcite.plan.RelOptCostImpl;
import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.plan.Strong;
import org.apache.calcite.plan.hep.HepPlanner;
@@ -66,6 +67,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
@@ -122,10 +124,10 @@ public class TopDownGeneralDecorrelator implements
ReflectiveVisitor {
private final NavigableSet<CorDef> corDefs;
// a map from RelNode to whether existing correlated expressions (according
to corDefs).
- private final Map<RelNode, Boolean> hasCorrelatedExpressions;
+ private final IdentityHashMap<RelNode, Boolean> hasCorrelatedExpressions;
// a map from RelNode to its UnnestedQuery.
- private final Map<RelNode, UnnestedQuery> mapRelToUnnestedQuery;
+ private final IdentityHashMap<RelNode, UnnestedQuery> mapRelToUnnestedQuery;
private final boolean hasParent;
@@ -155,8 +157,8 @@ private TopDownGeneralDecorrelator(
RelBuilder builder,
boolean hasParent,
@Nullable Set<CorDef> parentCorDefs,
- @Nullable Map<RelNode, Boolean> parentHasCorrelatedExpressions,
- @Nullable Map<RelNode, UnnestedQuery> parentMapRelToUnnestedQuery) {
+ @Nullable IdentityHashMap<RelNode, Boolean>
parentHasCorrelatedExpressions,
+ @Nullable IdentityHashMap<RelNode, UnnestedQuery>
parentMapRelToUnnestedQuery) {
this.builder = builder;
this.hasParent = hasParent;
this.corDefs = new TreeSet<>();
@@ -164,10 +166,10 @@ private TopDownGeneralDecorrelator(
this.corDefs.addAll(parentCorDefs);
}
this.hasCorrelatedExpressions = parentHasCorrelatedExpressions == null
- ? new HashMap<>()
+ ? new IdentityHashMap<>()
: parentHasCorrelatedExpressions;
this.mapRelToUnnestedQuery = parentMapRelToUnnestedQuery == null
- ? new HashMap<>()
+ ? new IdentityHashMap<>()
: parentMapRelToUnnestedQuery;
}
@@ -202,7 +204,14 @@ public static RelNode decorrelateQuery(RelNode rel,
RelBuilder builder) {
CoreRules.FILTER_INTO_JOIN,
CoreRules.FILTER_CORRELATE))
.build();
- HepPlanner prePlanner = new HepPlanner(preProgram);
+ // In scenarios with nested correlations, equivalent nodes at different
nesting levels bind
+ // to different outer variables and therefore have different decorrelation
information. We
+ // need to avoid equivalent nodes in the plan sharing the same object (in
the form of a DAG)
+ // to prevent corruption of entries in mapRelToUnnestedQuery and
hasCorrelatedExpressions.
+ // So we set noDag config of HepPlanner to TRUE.
+ HepPlanner prePlanner =
+ new HepPlanner(preProgram, null, true,
+ null, RelOptCostImpl.FACTORY);
prePlanner.setRoot(rel);
RelNode preparedRel = prePlanner.findBestExp();
diff --git a/core/src/test/resources/sql/new-decorr.iq
b/core/src/test/resources/sql/new-decorr.iq
index 529bca6d1b..9677fae713 100644
--- a/core/src/test/resources/sql/new-decorr.iq
+++ b/core/src/test/resources/sql/new-decorr.iq
@@ -235,4 +235,21 @@ select 1 in (values(null), (null));
!ok
+# [CALCITE-7401] Multi-level correlated subqueries cause an out-of-range error
in the TopDownGeneralDecorrelator
+# This case comes from sub-query.iq [CALCITE-5789]
+select deptno from dept d1 where exists (
+ select 1 from dept d2 where d2.deptno = d1.deptno and exists (
+ select 1 from dept d3 where d3.deptno = d2.deptno and d3.dname = d1.dname));
++--------+
+| DEPTNO |
++--------+
+| 10 |
+| 20 |
+| 30 |
+| 40 |
++--------+
+(4 rows)
+
+!ok
+
# End new-decorr.iq