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 2018/06/29 18:41:59 UTC

[3/8] calcite git commit: [CALCITE-2303] In EXTRACT function, support MICROSECONDS, MILLISECONDS, EPOCH, ISODOW, ISOYEAR and DECADE time units (Sergey Nuyanzin)

[CALCITE-2303] In EXTRACT function, support MICROSECONDS, MILLISECONDS, EPOCH, ISODOW, ISOYEAR and DECADE time units (Sergey Nuyanzin)

Close apache/calcite#702


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

Branch: refs/heads/master
Commit: 03b7af4863359dd3bb0a4c84eb01d0e39f865cf6
Parents: b36a107
Author: snuyanzin <sn...@gmail.com>
Authored: Mon May 28 12:23:39 2018 +0300
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Jun 28 19:13:12 2018 -0700

----------------------------------------------------------------------
 core/src/main/codegen/templates/Parser.jj       | 12 ++-
 .../calcite/adapter/enumerable/RexImpTable.java | 35 +++-----
 .../calcite/sql/SqlIntervalQualifier.java       |  2 +
 .../calcite/sql/test/SqlOperatorBaseTest.java   | 91 +++++++++++++++++++-
 site/_docs/reference.md                         |  3 +
 5 files changed, 116 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/03b7af48/core/src/main/codegen/templates/Parser.jj
----------------------------------------------------------------------
diff --git a/core/src/main/codegen/templates/Parser.jj b/core/src/main/codegen/templates/Parser.jj
index aa224e6..6baa30b 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -4080,12 +4080,16 @@ SqlIntervalQualifier IntervalQualifier() :
 TimeUnit TimeUnit() :
 {}
 {
-    <SECOND> { return TimeUnit.SECOND; }
+    <MICROSECOND> { return TimeUnit.MICROSECOND; }
+|   <MILLISECOND> { return TimeUnit.MILLISECOND; }
+|   <SECOND> { return TimeUnit.SECOND; }
 |   <MINUTE> { return TimeUnit.MINUTE; }
 |   <HOUR> { return TimeUnit.HOUR; }
 |   <DAY> { return TimeUnit.DAY; }
 |   <DOW> { return TimeUnit.DOW; }
 |   <DOY> { return TimeUnit.DOY; }
+|   <ISODOW> { return TimeUnit.ISODOW; }
+|   <ISOYEAR> { return TimeUnit.ISOYEAR; }
 |   <WEEK> { return TimeUnit.WEEK; }
 |   <MONTH> { return TimeUnit.MONTH; }
 |   <QUARTER> { return TimeUnit.QUARTER; }
@@ -5704,6 +5708,8 @@ SqlPostfixOperator PostfixRowOperator() :
 |   < INTO: "INTO" >
 |   < INVOKER: "INVOKER" >
 |   < IS: "IS" >
+|   < ISODOW: "ISODOW" >
+|   < ISOYEAR: "ISOYEAR" >
 |   < ISOLATION: "ISOLATION" >
 |   < JAVA: "JAVA" >
 |   < JOIN: "JOIN" >
@@ -5751,6 +5757,7 @@ SqlPostfixOperator PostfixRowOperator() :
 |   < MESSAGE_TEXT: "MESSAGE_TEXT" >
 |   < METHOD: "METHOD" >
 |   < MICROSECOND: "MICROSECOND" >
+|   < MILLISECOND: "MILLISECOND" >
 |   < MILLENNIUM: "MILLENNIUM" >
 |   < MIN: "MIN" >
 |   < MINUTE: "MINUTE" >
@@ -6221,6 +6228,8 @@ String CommonNonReservedKeyWord() :
     |   <INSTANCE>
     |   <INSTANTIABLE>
     |   <INVOKER>
+    |   <ISODOW>
+    |   <ISOYEAR>
     |   <ISOLATION>
     |   <JAVA>
     |   <JSON>
@@ -6242,6 +6251,7 @@ String CommonNonReservedKeyWord() :
     |   <MESSAGE_LENGTH>
     |   <MESSAGE_OCTET_LENGTH>
     |   <MESSAGE_TEXT>
+    |   <MILLISECOND>
     |   <MILLENNIUM>
     |   <MINVALUE>
     |   <MORE_>

http://git-wip-us.apache.org/repos/asf/calcite/blob/03b7af48/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index 95ebe83..1ccc477 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -1995,7 +1995,10 @@ public class RexImpTable {
       case MONTH:
       case DAY:
       case DOW:
+      case DECADE:
       case DOY:
+      case ISODOW:
+      case ISOYEAR:
       case WEEK:
         switch (sqlTypeName) {
         case INTERVAL_YEAR:
@@ -2029,28 +2032,14 @@ public class RexImpTable {
           throw new AssertionError("unexpected " + sqlTypeName);
         }
         break;
-      case DECADE:
-        switch (sqlTypeName) {
-        case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
-          operand = Expressions.call(
-              BuiltInMethod.TIMESTAMP_WITH_LOCAL_TIME_ZONE_TO_TIMESTAMP.method,
-              operand,
-              Expressions.call(BuiltInMethod.TIME_ZONE.method, translator.getRoot()));
-          // fall through
-        case TIMESTAMP:
-          operand = Expressions.divide(operand,
-              Expressions.constant(TimeUnit.DAY.multiplier.longValue()));
-          // fall through
-        case DATE:
-          operand = Expressions.call(
-              BuiltInMethod.UNIX_DATE_EXTRACT.method,
-              Expressions.constant(TimeUnitRange.YEAR), operand);
-          return Expressions.divide(operand,
-              Expressions.constant(
-                  unit.multiplier.divideToIntegralValue(TimeUnit.YEAR.multiplier)
-                      .longValue()));
-        }
-        break;
+      case MILLISECOND:
+        return Expressions.modulo(
+              operand, Expressions.constant(TimeUnit.MINUTE.multiplier.longValue()));
+      case MICROSECOND:
+        operand = Expressions.modulo(
+              operand, Expressions.constant(TimeUnit.MINUTE.multiplier.longValue()));
+        return Expressions.multiply(
+              operand, Expressions.constant(TimeUnit.SECOND.multiplier.longValue()));
       case EPOCH:
         switch (sqlTypeName) {
         case DATE:
@@ -2128,6 +2117,8 @@ public class RexImpTable {
       return TimeUnit.HOUR.multiplier.longValue();
     case SECOND:
       return TimeUnit.MINUTE.multiplier.longValue();
+    case MILLISECOND:
+      return TimeUnit.SECOND.multiplier.longValue();
     case MONTH:
       return TimeUnit.YEAR.multiplier.longValue();
     case QUARTER:

http://git-wip-us.apache.org/repos/asf/calcite/blob/03b7af48/core/src/main/java/org/apache/calcite/sql/SqlIntervalQualifier.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlIntervalQualifier.java b/core/src/main/java/org/apache/calcite/sql/SqlIntervalQualifier.java
index 096b68c..2fafec7 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlIntervalQualifier.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlIntervalQualifier.java
@@ -131,6 +131,7 @@ public class SqlIntervalQualifier extends SqlNode {
   public SqlTypeName typeName() {
     switch (timeUnitRange) {
     case YEAR:
+    case ISOYEAR:
     case CENTURY:
     case DECADE:
     case MILLENNIUM:
@@ -141,6 +142,7 @@ public class SqlIntervalQualifier extends SqlNode {
     case QUARTER:
       return SqlTypeName.INTERVAL_MONTH;
     case DOW:
+    case ISODOW:
     case DOY:
     case DAY:
     case WEEK:

http://git-wip-us.apache.org/repos/asf/calcite/blob/03b7af48/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
index 1694864..7ab856b 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
@@ -5700,6 +5700,16 @@ public abstract class SqlOperatorBaseTest {
           "BIGINT NOT NULL");
 
       tester.checkScalar(
+          "extract(millisecond from interval '4-2' year to month)",
+          "0",
+          "BIGINT NOT NULL");
+
+      tester.checkScalar(
+          "extract(microsecond from interval '4-2' year to month)",
+          "0",
+          "BIGINT NOT NULL");
+
+      tester.checkScalar(
           "extract(minute from interval '4-2' year to month)",
           "0",
           "BIGINT NOT NULL");
@@ -5715,14 +5725,16 @@ public abstract class SqlOperatorBaseTest {
           "BIGINT NOT NULL");
     }
 
-    // Postgres doesn't support DOW, DOY and WEEK on INTERVAL YEAR MONTH type.
-    // SQL standard doesn't have extract units for DOW, DOY and WEEK.
+    // Postgres doesn't support DOW, ISODOW, DOY and WEEK on INTERVAL YEAR MONTH type.
+    // SQL standard doesn't have extract units for DOW, ISODOW, DOY and WEEK.
     tester.checkFails("^extract(doy from interval '4-2' year to month)^",
         INVALID_EXTRACT_UNIT_VALIDATION_ERROR, false);
     tester.checkFails("^extract(dow from interval '4-2' year to month)^",
         INVALID_EXTRACT_UNIT_VALIDATION_ERROR, false);
     tester.checkFails("^extract(week from interval '4-2' year to month)^",
         INVALID_EXTRACT_UNIT_VALIDATION_ERROR, false);
+    tester.checkFails("^extract(isodow from interval '4-2' year to month)^",
+        INVALID_EXTRACT_UNIT_VALIDATION_ERROR, false);
 
     tester.checkScalar(
         "extract(month from interval '4-2' year to month)",
@@ -5772,6 +5784,16 @@ public abstract class SqlOperatorBaseTest {
     }
 
     tester.checkScalar(
+        "extract(millisecond from interval '2 3:4:5.678' day to second)",
+        "5678",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
+        "extract(microsecond from interval '2 3:4:5.678' day to second)",
+        "5678000",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
         "extract(second from interval '2 3:4:5.678' day to second)",
         "5",
         "BIGINT NOT NULL");
@@ -5791,14 +5813,16 @@ public abstract class SqlOperatorBaseTest {
         "2",
         "BIGINT NOT NULL");
 
-    // Postgres doesn't support DOW, DOY and WEEK on INTERVAL DAY TIME type.
-    // SQL standard doesn't have extract units for DOW, DOY and WEEK.
+    // Postgres doesn't support DOW, ISODOW, DOY and WEEK on INTERVAL DAY TIME type.
+    // SQL standard doesn't have extract units for DOW, ISODOW, DOY and WEEK.
     tester.checkFails("extract(doy from interval '2 3:4:5.678' day to second)",
         INVALID_EXTRACT_UNIT_CONVERTLET_ERROR, true);
     tester.checkFails("extract(dow from interval '2 3:4:5.678' day to second)",
         INVALID_EXTRACT_UNIT_CONVERTLET_ERROR, true);
     tester.checkFails("extract(week from interval '2 3:4:5.678' day to second)",
         INVALID_EXTRACT_UNIT_CONVERTLET_ERROR, true);
+    tester.checkFails("extract(isodow from interval '2 3:4:5.678' day to second)",
+        INVALID_EXTRACT_UNIT_CONVERTLET_ERROR, true);
 
     tester.checkFails(
         "^extract(month from interval '2 3:4:5.678' day to second)^",
@@ -5822,6 +5846,13 @@ public abstract class SqlOperatorBaseTest {
         false);
 
     tester.checkFails(
+        "^extract(isoyear from interval '2 3:4:5.678' day to second)^",
+        "(?s)Cannot apply 'EXTRACT' to arguments of type 'EXTRACT\\(<INTERVAL "
+            + "ISOYEAR> FROM <INTERVAL DAY TO SECOND>\\)'\\. Supported "
+            + "form\\(s\\):.*",
+        false);
+
+    tester.checkFails(
         "^extract(century from interval '2 3:4:5.678' day to second)^",
         "(?s)Cannot apply 'EXTRACT' to arguments of type 'EXTRACT\\(<INTERVAL "
             + "CENTURY> FROM <INTERVAL DAY TO SECOND>\\)'\\. Supported "
@@ -5887,6 +5918,11 @@ public abstract class SqlOperatorBaseTest {
         "BIGINT NOT NULL");
 
     tester.checkScalar(
+        "extract(isoyear from date '2008-2-23')",
+        "2008",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
         "extract(doy from date '2008-2-23')",
         "54",
         "BIGINT NOT NULL");
@@ -5902,6 +5938,16 @@ public abstract class SqlOperatorBaseTest {
         "BIGINT NOT NULL");
 
     tester.checkScalar(
+        "extract(isodow from date '2008-2-23')",
+        "6",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
+        "extract(isodow from date '2008-2-24')",
+        "7",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
         "extract(week from date '2008-2-23')",
         "8",
         "BIGINT NOT NULL");
@@ -5960,6 +6006,16 @@ public abstract class SqlOperatorBaseTest {
         "BIGINT NOT NULL");
 
     tester.checkScalar(
+        "extract(millisecond from timestamp '2008-2-23 12:34:56')",
+        "56000",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
+        "extract(microsecond from timestamp '2008-2-23 12:34:56')",
+        "56000000",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
         "extract(minute from timestamp '2008-2-23 12:34:56')",
         "34",
         "BIGINT NOT NULL");
@@ -5989,6 +6045,11 @@ public abstract class SqlOperatorBaseTest {
         "2008",
         "BIGINT NOT NULL");
 
+    tester.checkScalar(
+        "extract(isoyear from timestamp '2008-2-23 12:34:56')",
+        "2008",
+        "BIGINT NOT NULL");
+
     // TODO: Not implemented in operator test execution code
     tester.checkFails(
         "extract(doy from timestamp '2008-2-23 12:34:56')",
@@ -6066,6 +6127,17 @@ public abstract class SqlOperatorBaseTest {
         "extract(second from interval '2 3:4:5.678' day to second)",
         "5",
         "BIGINT NOT NULL");
+
+    tester.checkScalar(
+        "extract(millisecond from interval '2 3:4:5.678' day to second)",
+        "5678",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
+        "extract(microsecond from interval '2 3:4:5.678' day to second)",
+        "5678000",
+        "BIGINT NOT NULL");
+
     tester.checkNull(
         "extract(month from cast(null as interval year))");
   }
@@ -6082,6 +6154,11 @@ public abstract class SqlOperatorBaseTest {
         "BIGINT NOT NULL");
 
     tester.checkScalar(
+        "extract(isoyear from date '2008-2-23')",
+        "2008",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
         "extract(month from date '2008-2-23')",
         "2",
         "BIGINT NOT NULL");
@@ -6109,6 +6186,12 @@ public abstract class SqlOperatorBaseTest {
 
     tester.checkNull(
         "extract(second from cast(null as time))");
+
+    tester.checkNull(
+        "extract(millisecond from cast(null as time))");
+
+    tester.checkNull(
+        "extract(microsecond from cast(null as time))");
   }
 
   @Test public void testArrayValueConstructor() {

http://git-wip-us.apache.org/repos/asf/calcite/blob/03b7af48/site/_docs/reference.md
----------------------------------------------------------------------
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index 8a0be4f..be3831f 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -550,7 +550,9 @@ INSTANTIABLE,
 **INTO**,
 INVOKER,
 **IS**,
+ISODOW,
 ISOLATION,
+ISOYEAR,
 JAVA,
 **JOIN**,
 JSON,
@@ -598,6 +600,7 @@ MESSAGE_TEXT,
 **METHOD**,
 MICROSECOND,
 MILLENNIUM,
+MILLISECOND,
 **MIN**,
 **MINUS**,
 **MINUTE**,