This is an automated email from the ASF dual-hosted git repository.
jhyde 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 247c7d4 [CALCITE-3049] When simplifying "IS NULL" and "IS NOT NULL",
simplify the operand first
247c7d4 is described below
commit 247c7d4f76a3d7d862ae6f4148cc8e6556efa497
Author: yuzhao.cyz <[email protected]>
AuthorDate: Sun May 5 06:21:14 2019 +0800
[CALCITE-3049] When simplifying "IS NULL" and "IS NOT NULL", simplify the
operand first
When simplifying "(x IS NULL) IS NOT NULL", remove redundant casts
before simplifying the operand.
Julian Hyde started work on this case, simplifying before and after,
and Danny Chan improved it by only simplifying before.
Close apache/calcite#1198
---
.../main/java/org/apache/calcite/rex/RexSimplify.java | 18 +++++++++++++++---
.../java/org/apache/calcite/test/RexProgramTest.java | 16 ++++++++++++++++
core/src/test/resources/sql/sub-query.iq | 6 +++---
3 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
index 101bea7..187b926 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
@@ -655,14 +655,14 @@ public class RexSimplify {
// x IS NULL ==> FALSE (if x is not nullable)
simplified = simplifyIsNull(a);
if (simplified != null) {
- return simplify(simplified, unknownAs);
+ return simplified;
}
break;
case IS_NOT_NULL:
// x IS NOT NULL ==> TRUE (if x is not nullable)
simplified = simplifyIsNotNull(a);
if (simplified != null) {
- return simplify(simplified, unknownAs);
+ return simplified;
}
break;
case IS_TRUE:
@@ -700,7 +700,7 @@ public class RexSimplify {
final RexNode arg = ((RexCall) a).operands.get(0);
return simplify(rexBuilder.makeCall(notKind, arg), UNKNOWN);
}
- RexNode a2 = simplify(a, UNKNOWN);
+ final RexNode a2 = simplify(a, UNKNOWN);
if (a != a2) {
return rexBuilder.makeCall(RexUtil.op(kind), ImmutableList.of(a2));
}
@@ -708,6 +708,12 @@ public class RexSimplify {
}
private RexNode simplifyIsNotNull(RexNode a) {
+ // Simplify the argument first,
+ // call ourselves recursively to see whether we can make more progress.
+ // For example, given
+ // "(CASE WHEN FALSE THEN 1 ELSE 2) IS NOT NULL" we first simplify the
+ // argument to "2", and only then we can simplify "2 IS NOT NULL" to
"TRUE".
+ a = simplify(a, UNKNOWN);
if (!a.getType().isNullable() && isSafeExpression(a)) {
return rexBuilder.makeLiteral(true);
}
@@ -751,6 +757,12 @@ public class RexSimplify {
}
private RexNode simplifyIsNull(RexNode a) {
+ // Simplify the argument first,
+ // call ourselves recursively to see whether we can make more progress.
+ // For example, given
+ // "(CASE WHEN FALSE THEN 1 ELSE 2) IS NULL" we first simplify the
+ // argument to "2", and only then we can simplify "2 IS NULL" to "FALSE".
+ a = simplify(a, UNKNOWN);
if (!a.getType().isNullable() && isSafeExpression(a)) {
return rexBuilder.makeLiteral(false);
}
diff --git a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
index 8f12c2a..d79c133 100644
--- a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
@@ -1954,6 +1954,22 @@ public class RexProgramTest extends
RexProgramBuilderBase {
checkSimplify(isNotNull(lt(i2, i3)), "true");
checkSimplify(isNotNull(lt(i0, one)), "IS NOT NULL($0)");
checkSimplify(isNotNull(lt(i0, null_)), "false");
+ // test simplify operand of case when expression
+ checkSimplify(
+ isNull(case_(falseLiteral, unaryPlus(i0), literal(-1))),
+ "false");
+ checkSimplify(
+ isNull(case_(trueLiteral, unaryPlus(i0), literal(-1))),
+ "IS NULL($0)");
+ checkSimplify(
+ isNotNull(case_(falseLiteral, unaryPlus(i0), literal(-1))),
+ "true");
+ checkSimplify(
+ isNotNull(case_(trueLiteral, unaryPlus(i0), literal(-1))),
+ "IS NOT NULL($0)");
+ // test simplify operand of redundant cast
+ checkSimplify(isNull(cast(i2, intType)), "false");
+ checkSimplify(isNotNull(cast(i2, intType)), "true");
}
/** Unit test for
diff --git a/core/src/test/resources/sql/sub-query.iq
b/core/src/test/resources/sql/sub-query.iq
index d639ae9..6a0cb4d 100644
--- a/core/src/test/resources/sql/sub-query.iq
+++ b/core/src/test/resources/sql/sub-query.iq
@@ -1856,11 +1856,11 @@ select sal from "scott".emp e
(11 rows)
!ok
-EnumerableCalc(expr#0..4=[{inputs}], expr#5=[NOT($t3)], expr#6=[IS NOT
NULL($t3)], expr#7=[OR($t5, $t6)], expr#8=[IS NOT TRUE($t7)], SAL=[$t1],
$condition=[$t8])
- EnumerableJoin(condition=[=($2, $4)], joinType=[left])
+EnumerableCalc(expr#0..4=[{inputs}], expr#5=[NOT($t4)], expr#6=[IS NOT
NULL($t4)], expr#7=[OR($t5, $t6)], expr#8=[IS NOT TRUE($t7)], SAL=[$t1],
$condition=[$t8])
+ EnumerableJoin(condition=[=($2, $3)], joinType=[left])
EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5], DEPTNO=[$t7])
EnumerableTableScan(table=[[scott, EMP]])
- EnumerableCalc(expr#0..2=[{inputs}], expr#3=[true], expr#4=[10],
expr#5=[=($t4, $t0)], cs=[$t3], DEPTNO=[$t0], $condition=[$t5])
+ EnumerableCalc(expr#0..2=[{inputs}], expr#3=[true], expr#4=[10],
expr#5=[=($t4, $t0)], DEPTNO=[$t0], $f1=[$t3], $condition=[$t5])
EnumerableTableScan(table=[[scott, DEPT]])
!plan