You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by se...@apache.org on 2019/03/08 20:02:08 UTC
[calcite] branch master updated: [CALCITE-2818] EXTRACT returns
wrong results for DATE and TIMESTAMP values before epoch (Haisheng Yuan)
This is an automated email from the ASF dual-hosted git repository.
sereda 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 5ee592a [CALCITE-2818] EXTRACT returns wrong results for DATE and TIMESTAMP values before epoch (Haisheng Yuan)
5ee592a is described below
commit 5ee592a19bf377438aa100dbc19d40ae8b2e2cd9
Author: Haisheng Yuan <h....@alibaba-inc.com>
AuthorDate: Wed Feb 27 15:54:04 2019 -0600
[CALCITE-2818] EXTRACT returns wrong results for DATE and TIMESTAMP values before epoch (Haisheng Yuan)
---
.../calcite/adapter/enumerable/RexImpTable.java | 13 ++---
.../calcite/sql/test/SqlOperatorBaseTest.java | 67 ++++++++++++++++++++++
core/src/test/resources/sql/misc.iq | 12 ++--
3 files changed, 79 insertions(+), 13 deletions(-)
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 dcab895..1237ad2 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
@@ -2236,8 +2236,8 @@ public class RexImpTable {
Expressions.call(BuiltInMethod.TIME_ZONE.method, translator.getRoot()));
// fall through
case TIMESTAMP:
- operand = Expressions.divide(operand,
- Expressions.constant(TimeUnit.DAY.multiplier.longValue()));
+ operand = Expressions.call(BuiltInMethod.FLOOR_DIV.method,
+ operand, Expressions.constant(TimeUnit.DAY.multiplier.longValue()));
// fall through
case DATE:
return Expressions.call(BuiltInMethod.UNIX_DATE_EXTRACT.method,
@@ -2247,11 +2247,9 @@ public class RexImpTable {
}
break;
case MILLISECOND:
- return Expressions.modulo(
- operand, Expressions.constant(TimeUnit.MINUTE.multiplier.longValue()));
+ return mod(operand, TimeUnit.MINUTE.multiplier.longValue());
case MICROSECOND:
- operand = Expressions.modulo(
- operand, Expressions.constant(TimeUnit.MINUTE.multiplier.longValue()));
+ operand = mod(operand, TimeUnit.MINUTE.multiplier.longValue());
return Expressions.multiply(
operand, Expressions.constant(TimeUnit.SECOND.multiplier.longValue()));
case EPOCH:
@@ -2317,7 +2315,8 @@ public class RexImpTable {
if (factor == 1L) {
return operand;
} else {
- return Expressions.modulo(operand, Expressions.constant(factor));
+ return Expressions.call(BuiltInMethod.FLOOR_MOD.method,
+ operand, Expressions.constant(factor));
}
}
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 bb9c880..0e876bc 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
@@ -6723,6 +6723,73 @@ public abstract class SqlOperatorBaseTest {
"extract(microsecond from cast(null as time))");
}
+ @Test public void testExtractWithDatesBeforeUnixEpoch() {
+ tester.checkScalar(
+ "extract(year from TIMESTAMP '1970-01-01 00:00:00')",
+ "1970",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(year from TIMESTAMP '1969-12-31 10:13:17')",
+ "1969",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(quarter from TIMESTAMP '1969-12-31 08:13:17')",
+ "4",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(quarter from TIMESTAMP '1969-5-31 21:13:17')",
+ "2",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(month from TIMESTAMP '1969-12-31 00:13:17')",
+ "12",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(day from TIMESTAMP '1969-12-31 12:13:17')",
+ "31",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(week from TIMESTAMP '1969-2-23 01:23:45')",
+ "8",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(doy from TIMESTAMP '1969-12-31 21:13:17.357')",
+ "365",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(dow from TIMESTAMP '1969-12-31 01:13:17.357')",
+ "4",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(decade from TIMESTAMP '1969-12-31 21:13:17.357')",
+ "196",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(century from TIMESTAMP '1969-12-31 21:13:17.357')",
+ "20",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(hour from TIMESTAMP '1969-12-31 21:13:17.357')",
+ "21",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(minute from TIMESTAMP '1969-12-31 21:13:17.357')",
+ "13",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(second from TIMESTAMP '1969-12-31 21:13:17.357')",
+ "17",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(millisecond from TIMESTAMP '1969-12-31 21:13:17.357')",
+ "17357",
+ "BIGINT NOT NULL");
+ tester.checkScalar(
+ "extract(microsecond from TIMESTAMP '1969-12-31 21:13:17.357')",
+ "17357000",
+ "BIGINT NOT NULL");
+ }
+
@Test public void testArrayValueConstructor() {
tester.setFor(SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR);
tester.checkScalar(
diff --git a/core/src/test/resources/sql/misc.iq b/core/src/test/resources/sql/misc.iq
index aada308..c692f42 100644
--- a/core/src/test/resources/sql/misc.iq
+++ b/core/src/test/resources/sql/misc.iq
@@ -2109,14 +2109,14 @@ and "sqlTimestamp" < {ts '1998-01-01 00:00:00'};
!ok
# [CALCITE-1188] NullPointerException in EXTRACT with WHERE ... IN clause if field has null value
-select extract(YEAR from "sqlTimestamp") Y
+select "sqlTimestamp" T
from "everyTypes"
where extract(YEAR from "sqlTimestamp") IN (1969, 1970);
-+------+
-| Y |
-+------+
-| 1970 |
-+------+
++---------------------+
+| T |
++---------------------+
+| 1970-01-01 00:00:00 |
++---------------------+
(1 row)
!ok