You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by vl...@apache.org on 2019/01/09 05:53:59 UTC
[calcite] branch master updated: [CALCITE-2344] Avoid inferring
$0=null predicate from $0 IS NULL when $0 is not nullable
This is an automated email from the ASF dual-hosted git repository.
vladimirsitnikov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push:
new 5ff5765 [CALCITE-2344] Avoid inferring $0=null predicate from $0 IS NULL when $0 is not nullable
5ff5765 is described below
commit 5ff57651c7bdbc61ecbc212293c21ae90d3d370f
Author: Laurent Goujon <la...@apache.org>
AuthorDate: Thu May 31 08:27:29 2018 -0700
[CALCITE-2344] Avoid inferring $0=null predicate from $0 IS NULL when $0 is not nullable
fixes #714
---
.../java/org/apache/calcite/plan/RelOptUtil.java | 2 +-
.../main/java/org/apache/calcite/rex/RexUtil.java | 11 +++--
.../org/apache/calcite/test/RelOptRulesTest.java | 42 +++++++++++++++++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 48 ++++++++++++++++++++++
4 files changed, 96 insertions(+), 7 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
index 0e68a11..1c69c15 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
@@ -377,7 +377,7 @@ public abstract class RelOptUtil {
+ "set type is " + expectedRowType.getFullTypeString()
+ "\nexpression type is " + actualRowType.getFullTypeString()
+ "\nset is " + equivalenceClass.toString()
- + "\nexpression is " + newRel.toString();
+ + "\nexpression is " + RelOptUtil.toString(newRel);
throw new AssertionError(s);
}
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 053d950..9308577 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
@@ -367,18 +367,17 @@ public class RexUtil {
return;
}
final List<RexNode> operands = ((RexCall) predicate).getOperands();
- if (operands.size() != 2 && predicate.getKind() == SqlKind.EQUALS) {
- decompose(excludeSet, predicate);
- return;
- }
- // if it reaches here, we have rexNode equals rexNode
final RexNode left;
final RexNode right;
if (predicate.getKind() == SqlKind.EQUALS) {
left = operands.get(0);
right = operands.get(1);
- } else {
+ } else { // is null
left = operands.get(0);
+ if (!left.getType().isNullable()) {
+ // There's no sense in inferring $0=null when $0 is not nullable
+ return;
+ }
right = rexBuilder.makeNullLiteral(left.getType());
}
// Note that literals are immutable too, and they can only be compared
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 0f59cb6..9dca7b1 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -3269,6 +3269,48 @@ public class RelOptRulesTest extends RelOptTestBase {
.check();
}
+ /** Test case for DX-11490
+ * Make sure the planner doesn't fail over wrong push down
+ * of is null */
+ @Test public void testIsNullPushDown() {
+ HepProgramBuilder preBuilder = new HepProgramBuilder();
+ preBuilder.addRuleInstance(ProjectToWindowRule.PROJECT);
+
+ HepProgramBuilder builder = new HepProgramBuilder();
+ builder.addRuleInstance(ReduceExpressionsRule.PROJECT_INSTANCE);
+ builder.addRuleInstance(ReduceExpressionsRule.FILTER_INSTANCE);
+ HepPlanner hepPlanner = new HepPlanner(builder.build());
+
+ final String sql = "select empno, deptno, w_count from (\n"
+ + " select empno, deptno, count(empno) over (w) w_count\n"
+ + " from emp\n"
+ + " window w as (partition by deptno order by empno)\n"
+ + ") sub_query where w_count is null";
+ sql(sql)
+ .withPre(preBuilder.build())
+ .with(hepPlanner)
+ .check();
+ }
+
+ @Test public void testIsNullPushDown2() {
+ HepProgramBuilder preBuilder = new HepProgramBuilder();
+ preBuilder.addRuleInstance(ProjectToWindowRule.PROJECT);
+
+ HepProgramBuilder builder = new HepProgramBuilder();
+ builder.addRuleInstance(ReduceExpressionsRule.PROJECT_INSTANCE);
+ builder.addRuleInstance(ReduceExpressionsRule.FILTER_INSTANCE);
+ HepPlanner hepPlanner = new HepPlanner(builder.build());
+
+ final String sql = "select empno, deptno, w_count from (\n"
+ + " select empno, deptno, count(empno) over (ROWS BETWEEN 10 PRECEDING AND 1 PRECEDING) w_count\n"
+ + " from emp\n"
+ + ") sub_query where w_count is null";
+ sql(sql)
+ .withPre(preBuilder.build())
+ .with(hepPlanner)
+ .check();
+ }
+
/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-750">[CALCITE-750]
* Allow windowed aggregate on top of regular aggregate</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 743dac5..76da50b 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -197,6 +197,54 @@ LogicalProject(EXPR$0=[COUNT() OVER (PARTITION BY $0 ORDER BY $0 RANGE BETWEEN U
]]>
</Resource>
</TestCase>
+ <TestCase name="testIsNullPushDown">
+ <Resource name="sql">
+ <![CDATA[select w_count from (
+ select count(*) over (w) w_count
+ from emp
+ window w as (partition by empno order by empno)
+) sub_query where w_count is null)]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(EMPNO=[$0], DEPTNO=[$1], W_COUNT=[$2])
+ LogicalValues(tuples=[[]])
+]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(EMPNO=[$0], DEPTNO=[$1], W_COUNT=[$2])
+ LogicalFilter(condition=[IS NULL($2)])
+ LogicalProject(EMPNO=[$0], DEPTNO=[$7], $2=[$9])
+ LogicalWindow(window#0=[window(partition {7} order by [0] range between UNBOUNDED PRECEDING and CURRENT ROW aggs [COUNT($0)])])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testIsNullPushDown2">
+ <Resource name="sql">
+ <![CDATA[select w_count from (
+ select count(*) over (w) w_count
+ from emp
+ window w as (partition by empno order by empno)
+) sub_query where w_count is null)]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(EMPNO=[$0], DEPTNO=[$1], W_COUNT=[$2])
+ LogicalValues(tuples=[[]])
+]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(EMPNO=[$0], DEPTNO=[$1], W_COUNT=[$2])
+ LogicalFilter(condition=[IS NULL($2)])
+ LogicalWindow(window#0=[window(partition {} order by [] rows between $2 PRECEDING and $3 PRECEDING aggs [COUNT($0)])])
+ LogicalProject(EMPNO=[$0], DEPTNO=[$7])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ </TestCase>
<TestCase name="testProjectToWindowRuleForMultipleWindows">
<Resource name="sql">
<![CDATA[select