This is an automated email from the ASF dual-hosted git repository.

zhenchen 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 c251de4eca [CALCITE-7395] ProjectMergeRule incorrectly merges PROJECTs 
with correlation variables
c251de4eca is described below

commit c251de4eca57bc7fe60a27cd2cdb6a776fad8c1c
Author: Zhen Chen <[email protected]>
AuthorDate: Sat Jan 24 20:25:27 2026 +0800

    [CALCITE-7395] ProjectMergeRule incorrectly merges PROJECTs with 
correlation variables
---
 .../org/apache/calcite/rel/rules/ProjectMergeRule.java |  7 +++++++
 .../java/org/apache/calcite/test/CoreQuidemTest2.java  |  1 -
 .../java/org/apache/calcite/test/RelOptRulesTest.java  | 12 ++++++++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml        | 18 ++++++++++++++++++
 4 files changed, 37 insertions(+), 1 deletion(-)

diff --git 
a/core/src/main/java/org/apache/calcite/rel/rules/ProjectMergeRule.java 
b/core/src/main/java/org/apache/calcite/rel/rules/ProjectMergeRule.java
index 4608a8c8bc..8441699ad4 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ProjectMergeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ProjectMergeRule.java
@@ -92,6 +92,13 @@ public ProjectMergeRule(boolean force, ProjectFactory 
projectFactory) {
     final Project bottomProject = call.rel(1);
     final RelBuilder relBuilder = call.builder();
 
+    // Do not merge projects if any of them has correlation variables.
+    // Merging would lose the correlation context needed for proper query 
execution.
+    if (!topProject.getVariablesSet().isEmpty()
+        || !bottomProject.getVariablesSet().isEmpty()) {
+      return;
+    }
+
     // If one or both projects are permutations, short-circuit the complex 
logic
     // of building a RexProgram.
     final Permutation topPermutation = topProject.getPermutation();
diff --git a/core/src/test/java/org/apache/calcite/test/CoreQuidemTest2.java 
b/core/src/test/java/org/apache/calcite/test/CoreQuidemTest2.java
index f0887b7189..865aec400a 100644
--- a/core/src/test/java/org/apache/calcite/test/CoreQuidemTest2.java
+++ b/core/src/test/java/org/apache/calcite/test/CoreQuidemTest2.java
@@ -46,7 +46,6 @@ public static void main(String[] args) throws Exception {
 
     // TODO: The following files involves UNNEST and LEFT_MARK JOIN
     paths.remove("sql/measure.iq");
-    paths.remove("sql/unnest.iq");
     paths.remove("sql/some.iq");
     paths.remove("sql/sub-query.iq");
     paths.remove("sql/measure-paper.iq");
diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java 
b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
index 94bb87651f..f9cedb9d81 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -12165,6 +12165,18 @@ private void 
checkLoptOptimizeJoinRule(LoptOptimizeJoinRule rule) {
         .check();
   }
 
+  /** Test case of
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7395";>[CALCITE-7395]
+   * ProjectMergeRule incorrectly merges PROJECTs with correlation 
variables</a>. */
+  @Test void testProjectMergeRuleWithCorrelation() {
+    final String sql = "SELECT ARRAY(SELECT y + 1 FROM UNNEST(s.x) y)\n"
+        + "FROM (SELECT ARRAY[1,2,3] as x) s";
+
+    sql(sql)
+        .withRule(CoreRules.PROJECT_MERGE)
+        .checkUnchanged();
+  }
+
   /** Test case of
    * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7369";>[CALCITE-7369]
    * ProjectToWindowRule loses column alias when optimizing OVER window 
queries</a>. */
diff --git 
a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml 
b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
index 67e86d45b6..785bce7839 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -11821,6 +11821,24 @@ LogicalProject(DEPTNO=[$0])
     LogicalAggregate(group=[{}], DUMMY=[COUNT()])
       LogicalProject(EMPNO=[$0])
         LogicalTableScan(table=[[scott, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testProjectMergeRuleWithCorrelation">
+    <Resource name="sql">
+      <![CDATA[SELECT ARRAY(SELECT y + 1 FROM UNNEST(s.x) y)
+FROM (SELECT ARRAY[1,2,3] as x) s]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(variablesSet=[[$cor0]], EXPR$0=[ARRAY({
+LogicalProject(EXPR$0=[+($0, 1)])
+  Uncollect
+    LogicalProject(X=[$cor0.X])
+      LogicalValues(tuples=[[{ 0 }]])
+})])
+  LogicalProject(X=[ARRAY(1, 2, 3)])
+    LogicalValues(tuples=[[{ 0 }]])
 ]]>
     </Resource>
   </TestCase>

Reply via email to