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 2017/02/23 16:50:55 UTC

[6/6] calcite git commit: [CALCITE-1601] DateRangeRules loses OR filters

[CALCITE-1601] DateRangeRules loses OR filters


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/095acb10
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/095acb10
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/095acb10

Branch: refs/heads/master
Commit: 095acb1004c4432b6eb11390f61227ee58dd78db
Parents: ee289e4
Author: Julian Hyde <jh...@apache.org>
Authored: Tue Feb 21 14:13:19 2017 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Feb 22 22:17:37 2017 -0800

----------------------------------------------------------------------
 .../calcite/rel/rules/DateRangeRules.java       | 41 +++++++++++++++++++-
 .../calcite/rel/rules/DateRangeRulesTest.java   | 24 ++++++++++++
 2 files changed, 64 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/095acb10/core/src/main/java/org/apache/calcite/rel/rules/DateRangeRules.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/DateRangeRules.java b/core/src/main/java/org/apache/calcite/rel/rules/DateRangeRules.java
index 9fc71b8..a052140 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/DateRangeRules.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/DateRangeRules.java
@@ -39,6 +39,7 @@ import org.apache.calcite.util.Bug;
 
 import com.google.common.base.Predicate;
 import com.google.common.collect.BoundType;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableRangeSet;
 import com.google.common.collect.ImmutableSet;
@@ -47,8 +48,10 @@ import com.google.common.collect.RangeSet;
 import com.google.common.collect.TreeRangeSet;
 
 import java.math.BigDecimal;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Deque;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.List;
@@ -189,6 +192,7 @@ public abstract class DateRangeRules {
     private final RexBuilder rexBuilder;
     private final TimeUnitRange timeUnit;
     private final Map<String, RangeSet<Calendar>> operandRanges;
+    private final Deque<RexCall> calls = new ArrayDeque<>();
 
     public ExtractShuttle(RexBuilder rexBuilder, TimeUnitRange timeUnit,
         Map<String, RangeSet<Calendar>> operandRanges) {
@@ -222,8 +226,43 @@ public abstract class DateRangeRules {
                 (RexLiteral) op1);
           }
         }
+      default:
+        calls.push(call);
+        try {
+          return super.visitCall(call);
+        } finally {
+          calls.pop();
+        }
+      }
+    }
+
+    @Override protected List<RexNode> visitList(List<? extends RexNode> exprs,
+        boolean[] update) {
+      if (exprs.isEmpty()) {
+        return ImmutableList.of(); // a bit more efficient
+      }
+      switch (calls.peek().getKind()) {
+      case AND:
+        return super.visitList(exprs, update);
+      default:
+        final Map<String, RangeSet<Calendar>> save =
+            ImmutableMap.copyOf(operandRanges);
+        final ImmutableList.Builder<RexNode> clonedOperands =
+            ImmutableList.builder();
+        for (RexNode operand : exprs) {
+          RexNode clonedOperand = operand.accept(this);
+          if ((clonedOperand != operand) && (update != null)) {
+            update[0] = true;
+          }
+          clonedOperands.add(clonedOperand);
+
+          // Restore the state. For an operator such as "OR", an argument
+          // cannot inherit the previous argument's state.
+          operandRanges.clear();
+          operandRanges.putAll(save);
+        }
+        return clonedOperands.build();
       }
-      return super.visitCall(call);
     }
 
     boolean isExtractCall(RexNode e) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/095acb10/core/src/test/java/org/apache/calcite/rel/rules/DateRangeRulesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/rel/rules/DateRangeRulesTest.java b/core/src/test/java/org/apache/calcite/rel/rules/DateRangeRulesTest.java
index 6ef898e..63a84f1 100644
--- a/core/src/test/java/org/apache/calcite/rel/rules/DateRangeRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/rel/rules/DateRangeRulesTest.java
@@ -95,6 +95,30 @@ public class DateRangeRulesTest {
             + " >=($8, 2014-06-01), <($8, 2014-07-01))"));
   }
 
+  /** Test case for
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-1601">[CALCITE-1601]
+   * DateRangeRules loses OR filters</a>. */
+  @Test public void testExtractYearAndMonthFromDateColumn2() {
+    final Fixture2 f = new Fixture2();
+    final String s1 = "AND("
+        + "AND(>=($8, 2000-01-01), <($8, 2001-01-01)),"
+        + " OR("
+        + "AND(>=($8, 2000-02-01), <($8, 2000-03-01)), "
+        + "AND(>=($8, 2000-03-01), <($8, 2000-04-01)), "
+        + "AND(>=($8, 2000-05-01), <($8, 2000-06-01))))";
+    final String s2 = "AND(>=($8, 2000-01-01), <($8, 2001-01-01),"
+        + " OR("
+        + "AND(>=($8, 2000-02-01), <($8, 2000-03-01)), "
+        + "AND(>=($8, 2000-03-01), <($8, 2000-04-01)), "
+        + "AND(>=($8, 2000-05-01), <($8, 2000-06-01))))";
+    final RexNode e =
+        f.and(f.eq(f.exYear, f.literal(2000)),
+            f.or(f.eq(f.exMonth, f.literal(2)),
+                f.eq(f.exMonth, f.literal(3)),
+                f.eq(f.exMonth, f.literal(5))));
+    checkDateRange(f, e, is(s1), is(s2));
+  }
+
   @Test public void testExtractYearAndDayFromDateColumn() {
     final Fixture2 f = new Fixture2();
     checkDateRange(f,