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;