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/27 21:04:01 UTC

calcite git commit: [CALCITE-1659] Simplifying CAST('YYYY-MM-DD hh:mm:ss.SSS' as TIMESTAMP) should round the sub-second fraction (Remus Rusanu)

Repository: calcite
Updated Branches:
  refs/heads/master 73e437fe5 -> bb6ae0acf


[CALCITE-1659] Simplifying CAST('YYYY-MM-DD hh:mm:ss.SSS' as TIMESTAMP) should round the sub-second fraction (Remus Rusanu)

Previously the code incorrectly used the type's scale; now it uses the type's precision.

Make ZonelessTimestamp digest contain relevant sub-second fraction.

Close apache/calcite#384


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

Branch: refs/heads/master
Commit: bb6ae0acf76d7890d545b64c29b0d0d60ed43190
Parents: 73e437f
Author: Remus Rusanu <re...@apache.org>
Authored: Sun Feb 26 04:07:06 2017 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Feb 27 11:36:36 2017 -0800

----------------------------------------------------------------------
 .../java/org/apache/calcite/rex/RexBuilder.java | 35 ++++++++++++--------
 .../apache/calcite/util/ZonelessTimestamp.java  |  6 +++-
 core/src/test/resources/sql/misc.iq             | 22 ++++++++++++
 3 files changed, 48 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/bb6ae0ac/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 743b678..3e34ec9 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
@@ -474,6 +474,21 @@ public class RexBuilder {
   }
 
   /**
+   * Rounds the time part of a TIME or TIMESTAMP value to the given precision.
+   *
+   * @param timestamp The value to be rounded, will change in place
+   * @param precision the desired precision
+   */
+  private void roundTime(Calendar timestamp, long precision) {
+    if (precision == RelDataType.PRECISION_NOT_SPECIFIED) {
+      precision = 0;
+    }
+    final long pow = DateTimeUtils.powerX(10, 3 - precision);
+    final long timeMs = SqlFunctions.round(timestamp.getTimeInMillis(), pow);
+    timestamp.setTimeInMillis(timeMs);
+  }
+
+  /**
    * Creates a call to the CAST operator, expanding if possible, and optionally
    * also preserving nullability.
    *
@@ -498,19 +513,6 @@ public class RexBuilder {
       SqlTypeName typeName = literal.getTypeName();
       if (canRemoveCastFromLiteral(type, value, typeName)) {
         switch (typeName) {
-        case TIMESTAMP:
-        case TIME:
-          assert value instanceof Calendar;
-          final Calendar calendar = (Calendar) value;
-          int scale = type.getScale();
-          if (scale == RelDataType.SCALE_NOT_SPECIFIED) {
-            scale = 0;
-          }
-          calendar.setTimeInMillis(
-              SqlFunctions.round(
-                  calendar.getTimeInMillis(),
-                  DateTimeUtils.powerX(10, 3 - scale)));
-          break;
         case INTERVAL_DAY:
         case INTERVAL_DAY_HOUR:
         case INTERVAL_DAY_MINUTE:
@@ -845,7 +847,8 @@ public class RexBuilder {
       SqlTypeName typeName) {
     // All literals except NULL have NOT NULL types.
     type = typeFactory.createTypeWithNullability(type, o == null);
-    if (typeName == SqlTypeName.CHAR) {
+    switch (typeName) {
+    case CHAR:
       // Character literals must have a charset and collation. Populate
       // from the type if necessary.
       assert o instanceof NlsString;
@@ -860,6 +863,10 @@ public class RexBuilder {
             type.getCharset().name(),
             type.getCollation());
       }
+      break;
+    case TIME:
+    case TIMESTAMP:
+      roundTime((Calendar) o, type.getPrecision());
     }
     return new RexLiteral(o, type, typeName);
   }

http://git-wip-us.apache.org/repos/asf/calcite/blob/bb6ae0ac/core/src/main/java/org/apache/calcite/util/ZonelessTimestamp.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/util/ZonelessTimestamp.java b/core/src/main/java/org/apache/calcite/util/ZonelessTimestamp.java
index 40a7281..e58f687 100644
--- a/core/src/main/java/org/apache/calcite/util/ZonelessTimestamp.java
+++ b/core/src/main/java/org/apache/calcite/util/ZonelessTimestamp.java
@@ -85,7 +85,11 @@ public class ZonelessTimestamp extends ZonelessDatetime {
     // Remove trailing '.0' so that format is consistent with SQL spec for
     // CAST(TIMESTAMP(0) TO VARCHAR). E.g. "1969-12-31 16:00:00.0"
     // becomes "1969-12-31 16:00:00"
-    return ts.toString().substring(0, 19);
+    String sts = ts.toString();
+    if (sts.length() > 19 && ts.getNanos() == 0) {
+      sts = sts.substring(0, 19);
+    }
+    return sts;
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/calcite/blob/bb6ae0ac/core/src/test/resources/sql/misc.iq
----------------------------------------------------------------------
diff --git a/core/src/test/resources/sql/misc.iq b/core/src/test/resources/sql/misc.iq
index b28caac..93da331 100644
--- a/core/src/test/resources/sql/misc.iq
+++ b/core/src/test/resources/sql/misc.iq
@@ -1862,4 +1862,26 @@ EnumerableAggregate(group=[{}], C=[COUNT()])
   EnumerableValues(tuples=[[]])
 !plan
 
+# [CALCITE-1659] Simplifying CAST('YYYY-MM-DD hh:mm:ss.SSS' as TIMESTAMP)
+# should round the sub-second fraction
+select TIMESTAMP '2016-02-26 19:06:00.123456789',
+  CAST('2016-02-26 19:06:00.123' as TIMESTAMP),
+  CAST('2016-02-26 19:06:00.123' as TIMESTAMP(0)),
+  CAST('2016-02-26 19:06:00.123' as TIMESTAMP(1)),
+  CAST('2016-02-26 19:06:00.123' as TIMESTAMP(2)),
+  CAST('2016-02-26 19:06:00.123' as TIMESTAMP(3)),
+  CAST('2016-02-26 19:06:00.123' as TIMESTAMP(6)),
+  CAST('2016-02-26 19:06:00.123' as TIMESTAMP(9));
++---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+
+| EXPR$0              | EXPR$1              | EXPR$2              | EXPR$3              | EXPR$4              | EXPR$5              | EXPR$6              | EXPR$7              |
++---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+
+| 2016-02-26 19:06:00 | 2016-02-26 19:06:00 | 2016-02-26 19:06:00 | 2016-02-26 19:06:00 | 2016-02-26 19:06:00 | 2016-02-26 19:06:00 | 2016-02-26 19:06:00 | 2016-02-26 19:06:00 |
++---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+
+(1 row)
+
+!ok
+EnumerableCalc(expr#0=[{inputs}], expr#1=[2016-02-26 19:06:00.123], expr#2=[2016-02-26 19:06:00], expr#3=[2016-02-26 19:06:00.1], expr#4=[2016-02-26 19:06:00.12], expr#5=[2016-02-26 19:06:00.123], expr#6=[2016-02-26 19:06:00.123], EXPR$0=[$t1], EXPR$1=[$t2], EXPR$2=[$t2], EXPR$3=[$t3], EXPR$4=[$t4], EXPR$5=[$t1], EXPR$6=[$t5], EXPR$7=[$t6])
+  EnumerableValues(tuples=[[{ 0 }]])
+!plan
+
 # End misc.iq