Repository: calcite Updated Branches: refs/heads/master 50c4b0619 -> 82c3b293b
[CALCITE-1130] Add support for operators IS_NULL and IS_NOT_NULL in RexImplicationChecker (Amogh Margoor) Close apache/calcite#207 Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/82c3b293 Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/82c3b293 Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/82c3b293 Branch: refs/heads/master Commit: 82c3b293b172364058cc29dada5794659db4e389 Parents: 50c4b06 Author: Amogh Margoor <[email protected]> Authored: Tue Mar 8 01:02:17 2016 -0500 Committer: Julian Hyde <[email protected]> Committed: Tue Mar 8 10:04:09 2016 -0800 ---------------------------------------------------------------------- .../calcite/plan/RexImplicationChecker.java | 32 ++++++++++++++++--- .../calcite/test/RexImplicationCheckerTest.java | 33 ++++++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/82c3b293/core/src/main/java/org/apache/calcite/plan/RexImplicationChecker.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/plan/RexImplicationChecker.java b/core/src/main/java/org/apache/calcite/plan/RexImplicationChecker.java index 60655bf..27dbd34 100644 --- a/core/src/main/java/org/apache/calcite/plan/RexImplicationChecker.java +++ b/core/src/main/java/org/apache/calcite/plan/RexImplicationChecker.java @@ -300,7 +300,8 @@ public class RexImplicationChecker { && !(isEquivalentOp(fKind, sKind2) && isEquivalentOp(fKind2, sKind))) { return false; } else if (firstLen == 1 && secondLen == 1 - && fKind != SqlKind.EQUALS && !isEquivalentOp(fKind, sKind)) { + && fKind != SqlKind.EQUALS && !isSupportedUnaryOperators(sKind) + && !isEquivalentOp(fKind, sKind)) { return false; } else if (firstLen == 1 && secondLen == 2 && fKind != SqlKind.EQUALS) { return false; @@ -310,7 +311,7 @@ public class RexImplicationChecker { // x > 30 and x < 40 implies x < 70 // But disallow cases like // x > 30 and x > 40 implies x < 70 - if (!isOppositeOp(fKind, fKind2) + if (!isOppositeOp(fKind, fKind2) && !isSupportedUnaryOperators(sKind) && !(isEquivalentOp(fKind, fKind2) && isEquivalentOp(fKind, sKind))) { return false; } @@ -320,6 +321,16 @@ public class RexImplicationChecker { return true; } + private boolean isSupportedUnaryOperators(SqlKind kind) { + switch (kind) { + case IS_NOT_NULL: + case IS_NULL: + return true; + default: + return false; + } + } + private boolean isEquivalentOp(SqlKind fKind, SqlKind sKind) { switch (sKind) { case GREATER_THAN: @@ -400,14 +411,27 @@ public class RexImplicationChecker { case LESS_THAN_OR_EQUAL: case EQUALS: case NOT_EQUALS: - updateUsage(call); + updateBinaryOpUsage(call); + break; + case IS_NULL: + case IS_NOT_NULL: + updateUnaryOpUsage(call); break; default: } return super.visitCall(call); } - private void updateUsage(RexCall call) { + private void updateUnaryOpUsage(RexCall call) { + final List<RexNode> operands = call.getOperands(); + RexNode first = removeCast(operands.get(0)); + + if (first.isA(SqlKind.INPUT_REF)) { + updateUsage(call.getOperator(), (RexInputRef) first, null); + } + } + + private void updateBinaryOpUsage(RexCall call) { final List<RexNode> operands = call.getOperands(); RexNode first = removeCast(operands.get(0)); RexNode second = removeCast(operands.get(1)); http://git-wip-us.apache.org/repos/asf/calcite/blob/82c3b293/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java b/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java index f55628f..fd06d5b 100644 --- a/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java +++ b/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java @@ -239,6 +239,31 @@ public class RexImplicationCheckerTest { f.checkImplies(f.and(node3, node4), f.and(node5, node6)); } + @Test public void testNotNull() { + final Fixture f = new Fixture(); + final RexNode node1 = f.eq(f.str, f.rexBuilder.makeLiteral("en")); + final RexNode node2 = f.notNull(f.str); + final RexNode node3 = f.gt(f.str, f.rexBuilder.makeLiteral("abc")); + f.checkImplies(node1, node2); + f.checkNotImplies(node2, node1); + f.checkImplies(node3, node2); + //TODO: Tough one + //f.checkImplies(node2, node2); + } + + @Test public void testIsNull() { + final Fixture f = new Fixture(); + final RexNode node1 = f.eq(f.str, f.rexBuilder.makeLiteral("en")); + final RexNode node2 = f.notNull(f.str); + final RexNode node3 = f.isNull(f.str); + f.checkNotImplies(node2, node3); + f.checkNotImplies(node3, node2); + f.checkNotImplies(node1, node3); + f.checkNotImplies(node3, node1); + //TODO: + //f.checkImplies(node3, node3); + } + /** Contains all the nourishment a test case could possibly need. * * <p>We put the data in here, rather than as fields in the test case, so that @@ -373,6 +398,14 @@ public class RexImplicationCheckerTest { node2); } + RexNode notNull(RexNode node1) { + return rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, node1); + } + + RexNode isNull(RexNode node2) { + return rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, node2); + } + RexNode and(RexNode node1, RexNode node2) { return rexBuilder.makeCall(SqlStdOperatorTable.AND, node1, node2); }
