This is an automated email from the ASF dual-hosted git repository.
xiong 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 802fce3c41 [CALCITE-6873] FilterProjectTransposeRule should not push
the Filter past the Project when the Filter contains a Subquery with correlation
802fce3c41 is described below
commit 802fce3c41be76fca899ddb8c856d72c754d1520
Author: Xiong Duan <[email protected]>
AuthorDate: Wed Mar 5 14:47:10 2025 +0800
[CALCITE-6873] FilterProjectTransposeRule should not push the Filter past
the Project when the Filter contains a Subquery with correlation
---
.../main/java/org/apache/calcite/rex/RexUtil.java | 15 +++++++
.../org/apache/calcite/test/RelOptRulesTest.java | 22 ++++++++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 51 ++++++++++++++++++++++
3 files changed, 88 insertions(+)
diff --git a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
index 2d1e78fb3e..d30a9d8a2b 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
@@ -2826,6 +2826,21 @@ private CorrelationFinder() {
@Override public Void visitCorrelVariable(RexCorrelVariable var) {
throw Util.FoundOne.NULL;
}
+
+ @Override public Void visitSubQuery(RexSubQuery subQuery) {
+ if (!deep) {
+ return null;
+ }
+
+ for (RexNode operand : subQuery.operands) {
+ operand.accept(this);
+ }
+
+ if (!RelOptUtil.getVariablesUsed(subQuery.rel).isEmpty()) {
+ throw Util.FoundOne.NULL;
+ }
+ return null;
+ }
}
/** Shuttle that fixes up an expression to match changes in nullability of
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 baf8fd7183..42d5f6149f 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -521,6 +521,28 @@ private static boolean skipItem(RexNode expr) {
}
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6873">[CALCITE-6873]
+ * FilterProjectTransposeRule should not push the Filter past the Project
+ * when the Filter contains a Subquery with correlation</a>. */
+ @Test void testFilterProjectTransposeRule2() {
+ final String sql = "select * from (select deptno from emp) as d\n"
+ + "where NOT EXISTS (\n"
+ + " select count(*) from emp e where e.deptno = d.deptno)";
+ sql(sql)
+ .withRule(CoreRules.FILTER_PROJECT_TRANSPOSE)
+ .checkUnchanged();
+ }
+
+ @Test void testFilterProjectTransposeRule3() {
+ final String sql = "select * from (select deptno from emp) as d\n"
+ + "where NOT EXISTS (\n"
+ + " select count(*) from emp e)";
+ sql(sql)
+ .withRule(CoreRules.FILTER_PROJECT_TRANSPOSE)
+ .check();
+ }
+
/** Test case for
* <a
href="https://issues.apache.org/jira/browse/CALCITE-6031">[CALCITE-6031]
* Add the planner rule that pushes the Filter past a Sample</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 153864230c..ca64c718e6 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -5245,6 +5245,57 @@ LogicalProject(EMPNO=[$0])
LogicalFilter(condition=[=($cor0.DEPTNO, $0)])
LogicalProject(TWICEDEPTNO=[*($0, 2)])
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testFilterProjectTransposeRule2">
+ <Resource name="sql">
+ <![CDATA[select * from (select deptno from emp) as d
+where NOT EXISTS (
+ select count(*) from emp e where e.deptno = d.deptno)]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(DEPTNO=[$0])
+ LogicalFilter(condition=[NOT(EXISTS({
+LogicalAggregate(group=[{}], EXPR$0=[COUNT()])
+ LogicalProject($f0=[0])
+ LogicalFilter(condition=[=($7, $cor0.DEPTNO)])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+}))], variablesSet=[[$cor0]])
+ LogicalProject(DEPTNO=[$7])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testFilterProjectTransposeRule3">
+ <Resource name="sql">
+ <![CDATA[select * from (select deptno from emp) as d
+where NOT EXISTS (
+ select count(*) from emp e)]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(DEPTNO=[$0])
+ LogicalFilter(condition=[NOT(EXISTS({
+LogicalAggregate(group=[{}], EXPR$0=[COUNT()])
+ LogicalProject($f0=[0])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+}))])
+ LogicalProject(DEPTNO=[$7])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(DEPTNO=[$0])
+ LogicalProject(DEPTNO=[$7])
+ LogicalFilter(condition=[NOT(EXISTS({
+LogicalAggregate(group=[{}], EXPR$0=[COUNT()])
+ LogicalProject($f0=[0])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+}))])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
</Resource>
</TestCase>