You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by ch...@apache.org on 2019/07/30 02:24:51 UTC

[calcite] branch master updated: [CALCITE-2496] Return 0 in case of extract(milli/micro/nanosecond from datel) (Sergey Nuyanzin, Chunwei Lei)

This is an automated email from the ASF dual-hosted git repository.

chunwei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/master by this push:
     new ccad6f9  [CALCITE-2496] Return 0 in case of extract(milli/micro/nanosecond from datel) (Sergey Nuyanzin, Chunwei Lei)
ccad6f9 is described below

commit ccad6f982fc0d6bd45424e602ec0432a1bcecda7
Author: Chunwei Lei <ch...@apache.org>
AuthorDate: Thu Jul 25 16:03:25 2019 +0800

    [CALCITE-2496] Return 0 in case of extract(milli/micro/nanosecond from datel) (Sergey Nuyanzin, Chunwei Lei)
---
 core/src/main/codegen/templates/Parser.jj          | 10 +++--
 .../calcite/adapter/enumerable/RexImpTable.java    |  8 +++-
 .../calcite/sql/test/SqlOperatorBaseTest.java      | 52 ++++++++++++++++++++++
 3 files changed, 65 insertions(+), 5 deletions(-)

diff --git a/core/src/main/codegen/templates/Parser.jj b/core/src/main/codegen/templates/Parser.jj
index 0344aeb..c87289a 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -4208,12 +4208,12 @@ SqlIntervalQualifier IntervalQualifier() :
 
 /**
  * Parses time unit for EXTRACT, CEIL and FLOOR functions.
+ * Note that it does't include NANOSECOND and MICROSECOND.
  */
 TimeUnit TimeUnit() :
 {}
 {
-    <MICROSECOND> { return TimeUnit.MICROSECOND; }
-|   <MILLISECOND> { return TimeUnit.MILLISECOND; }
+    <MILLISECOND> { return TimeUnit.MILLISECOND; }
 |   <SECOND> { return TimeUnit.SECOND; }
 |   <MINUTE> { return TimeUnit.MINUTE; }
 |   <HOUR> { return TimeUnit.HOUR; }
@@ -4787,7 +4787,11 @@ SqlNode BuiltinFunctionCall() :
             TimeUnit unit;
         }
         <LPAREN>
-        unit = TimeUnit()
+        (
+            <NANOSECOND> { unit = TimeUnit.NANOSECOND; }
+        |   <MICROSECOND> { unit = TimeUnit.MICROSECOND; }
+        |   unit = TimeUnit()
+        )
         { args = startList(new SqlIntervalQualifier(unit, null, getPos())); }
         <FROM>
         e = Expression(ExprContext.ACCEPT_SUB_QUERY) { args.add(e); }
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 24fd420..2aba884 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
@@ -2141,6 +2141,7 @@ public class RexImpTable {
         case MONTH:
           return Expressions.call(floorMethod, tur,
               call(operand, type, TimeUnit.DAY));
+        case NANOSECOND:
         default:
           return call(operand, type, timeUnitRange.startUnit);
         }
@@ -2392,11 +2393,14 @@ public class RexImpTable {
         }
         break;
       case MILLISECOND:
-        return mod(operand, TimeUnit.MINUTE.multiplier.longValue());
       case MICROSECOND:
+      case NANOSECOND:
+        if (sqlTypeName == SqlTypeName.DATE) {
+          return Expressions.constant(0L);
+        }
         operand = mod(operand, TimeUnit.MINUTE.multiplier.longValue());
         return Expressions.multiply(
-            operand, Expressions.constant(TimeUnit.SECOND.multiplier.longValue()));
+            operand, Expressions.constant((long) (1 / unit.multiplier.doubleValue())));
       case EPOCH:
         switch (sqlTypeName) {
         case DATE:
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 ee0ed1f..bc3e958 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
@@ -6759,6 +6759,11 @@ public abstract class SqlOperatorBaseTest {
           "BIGINT NOT NULL");
 
       tester.checkScalar(
+          "extract(nanosecond 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");
@@ -6843,6 +6848,11 @@ public abstract class SqlOperatorBaseTest {
         "BIGINT NOT NULL");
 
     tester.checkScalar(
+        "extract(nanosecond from interval '2 3:4:5.678' day to second)",
+        "5678000000",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
         "extract(second from interval '2 3:4:5.678' day to second)",
         "5",
         "BIGINT NOT NULL");
@@ -6929,6 +6939,21 @@ public abstract class SqlOperatorBaseTest {
         "BIGINT NOT NULL");
 
     tester.checkScalar(
+        "extract(millisecond from date '2008-2-23')",
+        "0",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
+        "extract(microsecond from date '2008-2-23')",
+        "0",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
+        "extract(nanosecond from date '2008-2-23')",
+        "0",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
         "extract(minute from date '9999-2-23')",
         "0",
         "BIGINT NOT NULL");
@@ -7067,6 +7092,11 @@ public abstract class SqlOperatorBaseTest {
         "BIGINT NOT NULL");
 
     tester.checkScalar(
+        "extract(nanosecond from timestamp '2008-2-23 12:34:56')",
+        "56000000000",
+        "BIGINT NOT NULL");
+
+    tester.checkScalar(
         "extract(minute from timestamp '2008-2-23 12:34:56')",
         "34",
         "BIGINT NOT NULL");
@@ -7191,6 +7221,11 @@ public abstract class SqlOperatorBaseTest {
         "5678000",
         "BIGINT NOT NULL");
 
+    tester.checkScalar(
+        "extract(nanosecond from interval '2 3:4:5.678' day to second)",
+        "5678000000",
+        "BIGINT NOT NULL");
+
     tester.checkNull(
         "extract(month from cast(null as interval year))");
   }
@@ -7245,9 +7280,18 @@ public abstract class SqlOperatorBaseTest {
 
     tester.checkNull(
         "extract(microsecond from cast(null as time))");
+
+    tester.checkNull(
+        "extract(nanosecond from cast(null as time))");
   }
 
   @Test public void testExtractWithDatesBeforeUnixEpoch() {
+
+    tester.checkScalar(
+            "extract(millisecond from TIMESTAMP '1969-12-31 21:13:17.357')",
+            "17357",
+            "BIGINT NOT NULL");
+
     tester.checkScalar(
         "extract(year from TIMESTAMP '1970-01-01 00:00:00')",
         "1970",
@@ -7454,6 +7498,10 @@ public abstract class SqlOperatorBaseTest {
         "(?s)Cannot apply 'FLOOR' to arguments .*", false);
     tester.checkFails("^floor('abcde' to minute)^",
         "(?s)Cannot apply 'FLOOR' to arguments .*", false);
+    tester.checkFails("^floor(timestamp '2015-02-19 12:34:56.78' to microsecond)^",
+            "(?s)Encountered \"microsecond\" at .*", false);
+    tester.checkFails("^floor(timestamp '2015-02-19 12:34:56.78' to nanosecond)^",
+            "(?s)Encountered \"nanosecond\" at .*", false);
     tester.checkScalar(
         "floor(time '12:34:56' to minute)", "12:34:00", "TIME(0) NOT NULL");
     tester.checkScalar("floor(timestamp '2015-02-19 12:34:56.78' to second)",
@@ -7481,6 +7529,10 @@ public abstract class SqlOperatorBaseTest {
         "(?s)Cannot apply 'CEIL' to arguments .*", false);
     tester.checkFails("^ceil('abcde' to minute)^",
         "(?s)Cannot apply 'CEIL' to arguments .*", false);
+    tester.checkFails("^ceil(timestamp '2015-02-19 12:34:56.78' to microsecond)^",
+            "(?s)Encountered \"microsecond\" at .*", false);
+    tester.checkFails("^ceil(timestamp '2015-02-19 12:34:56.78' to nanosecond)^",
+            "(?s)Encountered \"nanosecond\" at .*", false);
     tester.checkScalar("ceil(time '12:34:56' to minute)",
         "12:35:00", "TIME(0) NOT NULL");
     tester.checkScalar("ceil(time '12:59:56' to minute)",