You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2016/03/08 21:05:23 UTC

calcite git commit: [CALCITE-1130] Add support for operators IS_NULL and IS_NOT_NULL in RexImplicationChecker (Amogh Margoor)

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 <am...@qubole.com>
Authored: Tue Mar 8 01:02:17 2016 -0500
Committer: Julian Hyde <jh...@apache.org>
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);
     }