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

mbudiu 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 aca1ed91e7 [CALCITE-7326] FILTER_CORRELATE rule loses correlation 
variable context in HepPlanner
aca1ed91e7 is described below

commit aca1ed91e7c301b83db820077cd786a0bea501b6
Author: Mihai Budiu <[email protected]>
AuthorDate: Wed Dec 10 17:47:16 2025 -0800

    [CALCITE-7326] FILTER_CORRELATE rule loses correlation variable context in 
HepPlanner
    
    Signed-off-by: Mihai Budiu <[email protected]>
---
 .../calcite/rel/rules/FilterCorrelateRule.java     | 17 ++++++++++-
 .../calcite/rel/rel2sql/RelToSqlConverterTest.java | 33 ++++++++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git 
a/core/src/main/java/org/apache/calcite/rel/rules/FilterCorrelateRule.java 
b/core/src/main/java/org/apache/calcite/rel/rules/FilterCorrelateRule.java
index ab60bd9acd..4c13baa173 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/FilterCorrelateRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/FilterCorrelateRule.java
@@ -70,12 +70,24 @@ public FilterCorrelateRule(RelFactories.FilterFactory 
filterFactory,
     final Filter filter = call.rel(0);
     final Correlate corr = call.rel(1);
 
-    final List<RexNode> aboveFilters =
+    List<RexNode> aboveFilters =
         RelOptUtil.conjunctions(filter.getCondition());
 
     final List<RexNode> leftFilters = new ArrayList<>();
     final List<RexNode> rightFilters = new ArrayList<>();
 
+    // Do not consider moving predicates that contain correlation variables
+    final List<RexNode> ineligible = new ArrayList<>();
+    final List<RexNode> eligible = new ArrayList<>();
+    for (RexNode f : aboveFilters) {
+      if (RexUtil.containsCorrelation(f)) {
+        ineligible.add(f);
+      } else {
+        eligible.add(f);
+      }
+    }
+    aboveFilters = eligible;
+
     // Try to push down above filters. These are typically where clause
     // filters. They can be pushed down if they are not on the NULL
     // generating side.
@@ -89,6 +101,9 @@ public FilterCorrelateRule(RelFactories.FilterFactory 
filterFactory,
         leftFilters,
         rightFilters);
 
+    // Add back the ineligible filters
+    aboveFilters.addAll(ineligible);
+
     if (leftFilters.isEmpty()
         && rightFilters.isEmpty()) {
       // no filters got pushed
diff --git 
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java 
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
index 6189182132..915db7da6e 100644
--- 
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
+++ 
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
@@ -38,8 +38,10 @@
 import org.apache.calcite.rel.rules.AggregateJoinTransposeRule;
 import org.apache.calcite.rel.rules.AggregateProjectMergeRule;
 import org.apache.calcite.rel.rules.CoreRules;
+import org.apache.calcite.rel.rules.FilterCorrelateRule;
 import org.apache.calcite.rel.rules.FilterJoinRule;
 import org.apache.calcite.rel.rules.FullToLeftAndRightJoinRule;
+import org.apache.calcite.rel.rules.JoinToCorrelateRule;
 import org.apache.calcite.rel.rules.ProjectOverSumToSum0Rule;
 import org.apache.calcite.rel.rules.ProjectToWindowRule;
 import org.apache.calcite.rel.rules.PruneEmptyRules;
@@ -11054,6 +11056,37 @@ private void checkLiteral2(String expression, String 
expected) {
         .ok(expected);
   }
 
+  /** Test case of
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7326";>[CALCITE-7326]
+   * FILTER_CORRELATE rule loses correlation variable context in 
HepPlanner</a>. */
+  @Test void testFilterCorrelateMissingVariableCor() {
+    final String sql = "SELECT E.EMPNO\n"
+        + "FROM EMP E\n"
+        + "JOIN DEPT D ON E.DEPTNO = D.DEPTNO\n"
+        + "WHERE D.DEPTNO = (\n"
+        + "  SELECT MIN(D_INNER.DEPTNO)\n"
+        + "  FROM DEPT D_INNER\n"
+        + "  WHERE D_INNER.DEPTNO = E.DEPTNO)";
+    final String expected = "SELECT \"$cor1\".\"EMPNO\"\n"
+        + "FROM \"SCOTT\".\"EMP\" AS \"$cor1\",\n"
+        + "LATERAL (SELECT *\nFROM \"SCOTT\".\"DEPT\"\n"
+        + "WHERE \"$cor1\".\"DEPTNO\" = \"DEPTNO\") AS \"t\"\n"
+        + "WHERE \"t\".\"DEPTNO\" = (((SELECT MIN(\"DEPTNO\")\n"
+        + "FROM \"SCOTT\".\"DEPT\"\nWHERE \"DEPTNO\" = 
\"$cor1\".\"DEPTNO\")))";
+    HepProgramBuilder builder = new HepProgramBuilder();
+    builder.addRuleClass(JoinToCorrelateRule.class);
+    builder.addRuleClass(FilterCorrelateRule.class);
+    HepPlanner hepPlanner = new HepPlanner(builder.build());
+    RuleSet rules =
+        RuleSets.ofList(CoreRules.JOIN_TO_CORRELATE,
+            CoreRules.FILTER_CORRELATE);
+    sql(sql)
+        .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT)
+        .withCalcite()
+        .optimize(rules, hepPlanner)
+        .ok(expected);
+  }
+
   /** Fluid interface to run tests. */
   static class Sql {
     private final CalciteAssert.SchemaSpec schemaSpec;

Reply via email to