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 07:13:23 UTC

[3/5] calcite git commit: In TimeUnit add WEEK, QUARTER, MICROSECOND values, and change type of multiplier

In TimeUnit add WEEK, QUARTER, MICROSECOND values, and change type of multiplier


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

Branch: refs/heads/master
Commit: cf5d07bde81a7c6a82bdab34ec798d0bf01ac01c
Parents: eead3d2
Author: Julian Hyde <jh...@apache.org>
Authored: Mon Mar 7 15:46:31 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 7 21:25:01 2016 -0800

----------------------------------------------------------------------
 .../apache/calcite/avatica/util/TimeUnit.java   | 38 +++++++++++++-------
 .../calcite/avatica/util/TimeUnitRange.java     |  8 ++++-
 .../java/org/apache/calcite/rex/RexBuilder.java | 11 +++---
 .../sql2rel/StandardConvertletTable.java        | 33 ++++++++---------
 4 files changed, 52 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/cf5d07bd/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnit.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnit.java b/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnit.java
index b249232..574aa45 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnit.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnit.java
@@ -20,28 +20,42 @@ import java.math.BigDecimal;
 
 /**
  * Enumeration of time units used to construct an interval.
+ *
+ * <p>Only {@link #YEAR}, {@link #YEAR}, {@link #MONTH}, {@link #DAY},
+ * {@link #HOUR}, {@link #MINUTE}, {@link #SECOND} can be the unit of a SQL
+ * interval.
+ *
+ * <p>The others ({@link #QUARTER}, {@link #WEEK}, {@link #MILLISECOND} and
+ * {@link #MICROSECOND}) are convenient to use it internally, when converting to
+ * and from UNIX timestamps. And also may be arguments to the
+ * {@code TIMESTAMPADD} and {@code TIMESTAMPDIFF} functions.
  */
 public enum TimeUnit {
-  YEAR(true, ' ', 12 /* months */, null),
-  MONTH(true, '-', 1 /* months */, BigDecimal.valueOf(12)),
-  DAY(false, '-', DateTimeUtils.MILLIS_PER_DAY, null),
-  HOUR(false, ' ', DateTimeUtils.MILLIS_PER_HOUR, BigDecimal.valueOf(24)),
-  MINUTE(false, ':', DateTimeUtils.MILLIS_PER_MINUTE, BigDecimal.valueOf(60)),
-  SECOND(false, ':', DateTimeUtils.MILLIS_PER_SECOND, BigDecimal.valueOf(60)),
+  YEAR(true, ' ', BigDecimal.valueOf(12) /* months */, null),
+  MONTH(true, '-', BigDecimal.ONE /* months */, BigDecimal.valueOf(12)),
+  DAY(false, '-', BigDecimal.valueOf(DateTimeUtils.MILLIS_PER_DAY), null),
+  HOUR(false, ' ', BigDecimal.valueOf(DateTimeUtils.MILLIS_PER_HOUR),
+      BigDecimal.valueOf(24)),
+  MINUTE(false, ':', BigDecimal.valueOf(DateTimeUtils.MILLIS_PER_MINUTE),
+      BigDecimal.valueOf(60)),
+  SECOND(false, ':', BigDecimal.valueOf(DateTimeUtils.MILLIS_PER_SECOND),
+      BigDecimal.valueOf(60)),
 
-  /** Unlike the other units, MILLISECOND may not be the unit of a SQL interval.
-   * Still, it is convenient to use it internally, when converting to and from
-   * UNIX timestamps. */
-  MILLISECOND(false, '.', 1, BigDecimal.valueOf(1));
+  QUARTER(true, '*', BigDecimal.valueOf(3) /* months */, BigDecimal.valueOf(4)),
+  WEEK(false, '*', BigDecimal.valueOf(DateTimeUtils.MILLIS_PER_DAY * 7),
+      BigDecimal.valueOf(53)),
+  MILLISECOND(false, '.', BigDecimal.ONE, BigDecimal.valueOf(1000)),
+  MICROSECOND(false, '.', BigDecimal.ONE.scaleByPowerOfTen(-3),
+      BigDecimal.valueOf(1000000));
 
   public final boolean yearMonth;
   public final char separator;
-  public final long multiplier;
+  public final BigDecimal multiplier;
   private final BigDecimal limit;
 
   private static final TimeUnit[] CACHED_VALUES = values();
 
-  TimeUnit(boolean yearMonth, char separator, long multiplier,
+  TimeUnit(boolean yearMonth, char separator, BigDecimal multiplier,
       BigDecimal limit) {
     this.yearMonth = yearMonth;
     this.separator = separator;

http://git-wip-us.apache.org/repos/asf/calcite/blob/cf5d07bd/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnitRange.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnitRange.java b/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnitRange.java
index 4d9b322..ddfe9f7 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnitRange.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnitRange.java
@@ -36,7 +36,13 @@ public enum TimeUnitRange {
   HOUR_TO_SECOND(TimeUnit.HOUR, TimeUnit.SECOND),
   MINUTE(TimeUnit.MINUTE, null),
   MINUTE_TO_SECOND(TimeUnit.MINUTE, TimeUnit.SECOND),
-  SECOND(TimeUnit.SECOND, null);
+  SECOND(TimeUnit.SECOND, null),
+
+  // non-standard time units cannot participate in ranges
+  QUARTER(TimeUnit.QUARTER, null),
+  WEEK(TimeUnit.WEEK, null),
+  MILLISECOND(TimeUnit.MILLISECOND, null),
+  MICROSECOND(TimeUnit.MICROSECOND, null);
 
   public final TimeUnit startUnit;
   public final TimeUnit endUnit;

http://git-wip-us.apache.org/repos/asf/calcite/blob/cf5d07bd/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
index dd147a5..b0cc27e 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
@@ -525,7 +525,7 @@ public class RexBuilder {
         case INTERVAL_DAY_TIME:
           assert value instanceof BigDecimal;
           BigDecimal value2 = (BigDecimal) value;
-          final long multiplier =
+          final BigDecimal multiplier =
               literal.getType().getIntervalQualifier().getStartUnit()
                   .multiplier;
           typeName = type.getSqlTypeName();
@@ -534,8 +534,7 @@ public class RexBuilder {
           case INTEGER:
             typeName = SqlTypeName.BIGINT;
           }
-          value = value2.divide(BigDecimal.valueOf(multiplier), 0,
-              BigDecimal.ROUND_HALF_DOWN);
+          value = value2.divide(multiplier, 0, BigDecimal.ROUND_HALF_DOWN);
         }
         final RexLiteral literal2 =
             makeLiteral(value, type, typeName);
@@ -595,8 +594,7 @@ public class RexBuilder {
               .getFractionalSecondPrecision(typeFactory.getTypeSystem()),
           3);
     }
-    BigDecimal multiplier = BigDecimal.valueOf(endUnit.multiplier)
-        .divide(BigDecimal.TEN.pow(scale));
+    BigDecimal multiplier = endUnit.multiplier.scaleByPowerOfTen(-scale);
     RexNode value = decodeIntervalOrDecimal(exp);
     if (multiplier.longValue() != 1) {
       value = makeCall(
@@ -627,8 +625,7 @@ public class RexBuilder {
               .getFractionalSecondPrecision(typeFactory.getTypeSystem()),
           3);
     }
-    BigDecimal multiplier = BigDecimal.valueOf(endUnit.multiplier)
-        .divide(BigDecimal.TEN.pow(scale));
+    BigDecimal multiplier = endUnit.multiplier.scaleByPowerOfTen(-scale);
     RelDataType decimalType =
         getTypeFactory().createSqlType(SqlTypeName.DECIMAL,
             scale + intervalType.getPrecision(),

http://git-wip-us.apache.org/repos/asf/calcite/blob/cf5d07bd/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
index 99452bf..5d1957f 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
@@ -16,7 +16,6 @@
  */
 package org.apache.calcite.sql2rel;
 
-import org.apache.calcite.avatica.util.DateTimeUtils;
 import org.apache.calcite.avatica.util.TimeUnit;
 import org.apache.calcite.avatica.util.TimeUnitRange;
 import org.apache.calcite.plan.RelOptUtil;
@@ -465,8 +464,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
         RexLiteral castedInterval =
             cx.getRexBuilder().makeIntervalLiteral(
                 sourceValue.multiply(
-                    BigDecimal.valueOf(
-                        intervalQualifier.getStartUnit().multiplier),
+                    intervalQualifier.getStartUnit().multiplier,
                     MathContext.UNLIMITED),
                 intervalQualifier);
         return castToValidatedType(cx, call, castedInterval);
@@ -515,7 +513,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
       final SqlIntervalLiteral literal = call.operand(0);
       SqlIntervalLiteral.IntervalValue interval =
           (SqlIntervalLiteral.IntervalValue) literal.getValue();
-      long val =
+      BigDecimal val =
           interval.getIntervalQualifier().getStartUnit().multiplier;
       RexNode rexInterval = cx.convertExpression(literal);
 
@@ -530,7 +528,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
               zero);
 
       RexNode pad =
-          rexBuilder.makeExactLiteral(BigDecimal.valueOf(val - 1));
+          rexBuilder.makeExactLiteral(val.subtract(BigDecimal.ONE));
       RexNode cast = rexBuilder.makeReinterpretCast(
           rexInterval.getType(), pad, rexBuilder.makeLiteral(false));
       SqlOperator op =
@@ -545,8 +543,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
           : rexBuilder.makeCall(SqlStdOperatorTable.CASE,
               cond, sum, rexInterval);
 
-      RexNode factor =
-          rexBuilder.makeExactLiteral(BigDecimal.valueOf(val));
+      RexNode factor = rexBuilder.makeExactLiteral(val);
       RexNode div =
           rexBuilder.makeCall(
               SqlStdOperatorTable.DIVIDE_INTEGER,
@@ -596,7 +593,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
       case INTERVAL_DAY_TIME:
         break;
       case TIMESTAMP:
-        res = divide(rexBuilder, res, DateTimeUtils.MILLIS_PER_DAY);
+        res = divide(rexBuilder, res, TimeUnit.DAY.multiplier);
         // fall through
       case DATE:
         return rexBuilder.makeCall(resType, SqlStdOperatorTable.EXTRACT_DATE,
@@ -636,16 +633,16 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
             ImmutableList.of(rexBuilder.makeFlag(TimeUnitRange.MONTH), x));
     res = rexBuilder.makeCall(SqlStdOperatorTable.MINUS, res,
         rexBuilder.makeExactLiteral(BigDecimal.ONE));
-    res = divide(rexBuilder, res, 3);
+    res = divide(rexBuilder, res, TimeUnit.QUARTER.multiplier);
     res = rexBuilder.makeCall(SqlStdOperatorTable.PLUS, res,
         rexBuilder.makeExactLiteral(BigDecimal.ONE));
     return res;
   }
 
-  private static long getFactor(TimeUnit unit) {
+  private static BigDecimal getFactor(TimeUnit unit) {
     switch (unit) {
     case DAY:
-      return 1;
+      return BigDecimal.ONE;
     case HOUR:
       return TimeUnit.DAY.multiplier;
     case MINUTE:
@@ -653,7 +650,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
     case SECOND:
       return TimeUnit.MINUTE.multiplier;
     case YEAR:
-      return 1;
+      return BigDecimal.ONE;
     case MONTH:
       return TimeUnit.YEAR.multiplier;
     default:
@@ -662,20 +659,20 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
   }
 
   private RexNode mod(RexBuilder rexBuilder, RelDataType resType, RexNode res,
-      long val) {
-    if (val == 1L) {
+      BigDecimal val) {
+    if (val.equals(BigDecimal.ONE)) {
       return res;
     }
     return rexBuilder.makeCall(SqlStdOperatorTable.MOD, res,
-        rexBuilder.makeExactLiteral(BigDecimal.valueOf(val), resType));
+        rexBuilder.makeExactLiteral(val, resType));
   }
 
-  private RexNode divide(RexBuilder rexBuilder, RexNode res, long val) {
-    if (val == 1L) {
+  private RexNode divide(RexBuilder rexBuilder, RexNode res, BigDecimal val) {
+    if (val.equals(BigDecimal.ONE)) {
       return res;
     }
     return rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE_INTEGER, res,
-        rexBuilder.makeExactLiteral(BigDecimal.valueOf(val)));
+        rexBuilder.makeExactLiteral(val));
   }
 
   public RexNode convertDatetimeMinus(