Skip to content

Commit b7e71a6

Browse files
committed
[CALCITE-6874] FilterCalcMergeRule/ProjectCalcMergeRule should not merge a Filter/Project to Calc when it contains Subquery
1 parent 0ff9fcf commit b7e71a6

File tree

4 files changed

+73
-4
lines changed

4 files changed

+73
-4
lines changed

core/src/main/java/org/apache/calcite/rel/rules/FilterCalcMergeRule.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.calcite.rex.RexBuilder;
2525
import org.apache.calcite.rex.RexProgram;
2626
import org.apache.calcite.rex.RexProgramBuilder;
27+
import org.apache.calcite.rex.RexUtil;
2728
import org.apache.calcite.tools.RelBuilderFactory;
2829

2930
import org.immutables.value.Value;
@@ -105,8 +106,9 @@ public interface Config extends RelRule.Config {
105106
default Config withOperandFor(Class<? extends Filter> filterClass,
106107
Class<? extends Calc> calcClass) {
107108
return withOperandSupplier(b0 ->
108-
b0.operand(filterClass).oneInput(b1 ->
109-
b1.operand(calcClass).anyInputs()))
109+
b0.operand(filterClass)
110+
.predicate(filter -> !RexUtil.SubQueryFinder.containsSubQuery(filter))
111+
.oneInput(b1 -> b1.operand(calcClass).anyInputs()))
110112
.as(Config.class);
111113
}
112114
}

core/src/main/java/org/apache/calcite/rel/rules/ProjectCalcMergeRule.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.apache.calcite.rex.RexOver;
2929
import org.apache.calcite.rex.RexProgram;
3030
import org.apache.calcite.rex.RexProgramBuilder;
31+
import org.apache.calcite.rex.RexUtil;
3132
import org.apache.calcite.tools.RelBuilderFactory;
3233
import org.apache.calcite.util.Pair;
3334

@@ -120,8 +121,9 @@ public interface Config extends RelRule.Config {
120121
default Config withOperandFor(Class<? extends Project> projectClass,
121122
Class<? extends Calc> calcClass) {
122123
return withOperandSupplier(b0 ->
123-
b0.operand(projectClass).oneInput(b1 ->
124-
b1.operand(calcClass).anyInputs()))
124+
b0.operand(projectClass)
125+
.predicate(project -> !RexUtil.SubQueryFinder.containsSubQuery(project))
126+
.oneInput(b1 -> b1.operand(calcClass).anyInputs()))
125127
.as(Config.class);
126128
}
127129
}

core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9711,6 +9711,37 @@ private void checkJoinAssociateRuleWithTopAlwaysTrueCondition(boolean allowAlway
97119711
.check();
97129712
}
97139713

9714+
/**
9715+
* Test case for
9716+
* <a href="https://issues.apache.org/jira/browse/CALCITE-6874">[CALCITE-6874]
9717+
* FilterCalcMergeRule/ProjectCalcMergeRule should not merge a Filter/Project to Calc
9718+
* when it contains Subquery</a>. */
9719+
@Test void testFilterCalcMergeRule() {
9720+
final String sql = "select deptno from sales.emp where\n"
9721+
+ "exists (select deptno from sales.emp where empno < 20)\n";
9722+
HepProgram program = new HepProgramBuilder()
9723+
.addRuleInstance(CoreRules.PROJECT_FILTER_TRANSPOSE)
9724+
.addRuleInstance(CoreRules.PROJECT_TO_CALC)
9725+
.build();
9726+
sql(sql)
9727+
.withPre(program)
9728+
.withRule(CoreRules.FILTER_CALC_MERGE)
9729+
.checkUnchanged();
9730+
}
9731+
9732+
@Test void testProjectCalcMergeRule() {
9733+
final String sql = "select exists (select deptno from sales.emp)\n"
9734+
+ "from (select deptno from sales.emp where empno < 20)\n";
9735+
HepProgram program = new HepProgramBuilder()
9736+
.addRuleInstance(CoreRules.PROJECT_FILTER_TRANSPOSE)
9737+
.addRuleInstance(CoreRules.FILTER_TO_CALC)
9738+
.build();
9739+
sql(sql)
9740+
.withPre(program)
9741+
.withRule(CoreRules.PROJECT_CALC_MERGE)
9742+
.checkUnchanged();
9743+
}
9744+
97149745
/**
97159746
* Test case of
97169747
* <a href="https://issues.apache.org/jira/browse/CALCITE-6850">[CALCITE-6850]

core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5100,6 +5100,23 @@ MyProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], C
51005100
MultiJoin(joinFilter=[true], isFullOuterJoin=[false], joinTypes=[[INNER, LEFT]], outerJoinConditions=[[NULL, =($7, $9)]], projFields=[[{0, 1, 2, 3, 4, 5, 6, 7, 8}, {0, 1}]], postJoinFilter=[>($9, 3)])
51015101
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
51025102
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
5103+
]]>
5104+
</Resource>
5105+
</TestCase>
5106+
<TestCase name="testFilterCalcMergeRule">
5107+
<Resource name="sql">
5108+
<![CDATA[select deptno from sales.emp where
5109+
exists (select deptno from sales.emp where empno < 20)
5110+
]]>
5111+
</Resource>
5112+
<Resource name="planBefore">
5113+
<![CDATA[
5114+
LogicalFilter(condition=[EXISTS({
5115+
LogicalFilter(condition=[<($0, 20)])
5116+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
5117+
})])
5118+
LogicalCalc(expr#0..8=[{inputs}], DEPTNO=[$t7])
5119+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
51035120
]]>
51045121
</Resource>
51055122
</TestCase>
@@ -8643,6 +8660,23 @@ LogicalProject(EXPR$0=[*($0, 2)], SS0=[$1])
86438660
LogicalAggregate(group=[{}], SUM_SAL=[SUM($0)], agg#1=[$SUM0($0)])
86448661
LogicalProject(SAL=[$5])
86458662
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
8663+
]]>
8664+
</Resource>
8665+
</TestCase>
8666+
<TestCase name="testProjectCalcMergeRule">
8667+
<Resource name="sql">
8668+
<![CDATA[select exists (select deptno from sales.emp)
8669+
from (select deptno from sales.emp where empno < 20)
8670+
]]>
8671+
</Resource>
8672+
<Resource name="planBefore">
8673+
<![CDATA[
8674+
LogicalProject(EXPR$0=[EXISTS({
8675+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
8676+
})])
8677+
LogicalCalc(expr#0=[{inputs}], expr#1=[20], expr#2=[<($t0, $t1)], EMPNO=[$t0], $condition=[$t2])
8678+
LogicalProject(EMPNO=[$0])
8679+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
86468680
]]>
86478681
</Resource>
86488682
</TestCase>

0 commit comments

Comments
 (0)