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 2015/04/06 09:20:12 UTC
incubator-calcite git commit: [CALCITE-307] Implement CAST between
date-time types
Repository: incubator-calcite
Updated Branches:
refs/heads/master 241f77e25 -> 38a4dd416
[CALCITE-307] Implement CAST between date-time types
Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/38a4dd41
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/38a4dd41
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/38a4dd41
Branch: refs/heads/master
Commit: 38a4dd416287e60d607e9194ee2de317a25706f9
Parents: 241f77e
Author: Julian Hyde <jh...@apache.org>
Authored: Sun Apr 5 23:37:37 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Sun Apr 5 23:37:37 2015 -0700
----------------------------------------------------------------------
.../adapter/enumerable/RexToLixTranslator.java | 30 ++++++++++++++++
.../java/org/apache/calcite/rex/RexBuilder.java | 11 +++---
.../apache/calcite/runtime/SqlFunctions.java | 15 ++++++++
.../org/apache/calcite/util/BuiltInMethod.java | 2 ++
.../calcite/sql/test/SqlOperatorBaseTest.java | 24 +++++--------
.../apache/calcite/test/SqlFunctionsTest.java | 38 +++++++++++++++++---
core/src/test/resources/sql/misc.oq | 26 +++++++-------
7 files changed, 108 insertions(+), 38 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/38a4dd41/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
index aceafa5..9e7502d 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
@@ -236,6 +236,12 @@ public class RexToLixTranslator {
case VARCHAR:
convert =
Expressions.call(BuiltInMethod.STRING_TO_DATE.method, operand);
+ break;
+ case TIMESTAMP:
+ convert = Expressions.convert_(
+ Expressions.call(BuiltInMethod.FLOOR_DIV.method,
+ operand, Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)),
+ int.class);
}
break;
case TIME:
@@ -244,6 +250,14 @@ public class RexToLixTranslator {
case VARCHAR:
convert =
Expressions.call(BuiltInMethod.STRING_TO_TIME.method, operand);
+ break;
+ case TIMESTAMP:
+ convert = Expressions.convert_(
+ Expressions.call(
+ BuiltInMethod.FLOOR_MOD.method,
+ operand,
+ Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)),
+ int.class);
}
break;
case TIMESTAMP:
@@ -252,6 +266,22 @@ public class RexToLixTranslator {
case VARCHAR:
convert =
Expressions.call(BuiltInMethod.STRING_TO_TIMESTAMP.method, operand);
+ break;
+ case DATE:
+ convert = Expressions.multiply(
+ Expressions.convert_(operand, long.class),
+ Expressions.constant(DateTimeUtils.MILLIS_PER_DAY));
+ break;
+ case TIME:
+ convert =
+ Expressions.add(
+ Expressions.multiply(
+ Expressions.convert_(
+ Expressions.call(BuiltInMethod.CURRENT_DATE.method, root),
+ long.class),
+ Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)),
+ Expressions.convert_(operand, long.class));
+ break;
}
break;
case BOOLEAN:
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/38a4dd41/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 f66f62e..32b16dc 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
@@ -467,12 +467,15 @@ public class RexBuilder {
RexLiteral literal = (RexLiteral) exp;
Comparable value = literal.getValue();
if (RexLiteral.valueMatchesType(value, sqlType, false)
+ && (type.getSqlTypeName() == literal.getTypeName()
+ || !SqlTypeFamily.DATETIME.getTypeNames().contains(
+ literal.getTypeName()))
&& (!(value instanceof NlsString)
- || (type.getPrecision()
- >= ((NlsString) value).getValue().length()))
+ || (type.getPrecision()
+ >= ((NlsString) value).getValue().length()))
&& (!(value instanceof ByteString)
- || (type.getPrecision()
- >= ((ByteString) value).length()))) {
+ || (type.getPrecision()
+ >= ((ByteString) value).length()))) {
switch (literal.getTypeName()) {
case CHAR:
if (value instanceof NlsString) {
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/38a4dd41/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index 256d15a..58a13fe 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -933,6 +933,21 @@ public class SqlFunctions {
return x == y ? 0 : x ? 1 : -1;
}
+ /** Divide, rounding towards negative infinity. */
+ public static long floorDiv(long x, long y) {
+ long r = x / y;
+ // if the signs are different and modulo not zero, round down
+ if ((x ^ y) < 0 && (r * y != x)) {
+ r--;
+ }
+ return r;
+ }
+
+ /** Modulo, always returning a non-negative result. */
+ public static long floorMod(long x, long y) {
+ return x - floorDiv(x, y) * y;
+ }
+
/** CAST(FLOAT AS VARCHAR). */
public static String toString(float x) {
if (x == 0) {
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/38a4dd41/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
index b5f2725..2bcf628 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -234,6 +234,8 @@ public enum BuiltInMethod {
int.class),
CHAR_LENGTH(SqlFunctions.class, "charLength", String.class),
STRING_CONCAT(SqlFunctions.class, "concat", String.class, String.class),
+ FLOOR_DIV(SqlFunctions.class, "floorDiv", long.class, long.class),
+ FLOOR_MOD(SqlFunctions.class, "floorMod", long.class, long.class),
FLOOR(SqlFunctions.class, "floor", int.class, int.class),
CEIL(SqlFunctions.class, "ceil", int.class, int.class),
OVERLAY(SqlFunctions.class, "overlay", String.class, String.class, int.class),
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/38a4dd41/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 8b0c0c1..2f76859 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
@@ -1087,12 +1087,10 @@ public abstract class SqlOperatorBaseTest {
"DATE NOT NULL");
// timestamp <-> time
- if (enable) {
- tester.checkScalar(
- "cast(TIMESTAMP '1945-02-24 12:42:25.34' as TIME)",
- "12:42:25",
- "TIME(0) NOT NULL");
- }
+ tester.checkScalar(
+ "cast(TIMESTAMP '1945-02-24 12:42:25.34' as TIME)",
+ "12:42:25",
+ "TIME(0) NOT NULL");
// time <-> string
checkCastToString("TIME '12:42:25'", null, "12:42:25");
@@ -1107,16 +1105,10 @@ public abstract class SqlOperatorBaseTest {
new SimpleDateFormat("yyyy-MM-dd").format(
getCalendarNotTooNear(Calendar.DAY_OF_MONTH).getTime());
- if (enable) {
- tester.checkScalar(
- "cast(DATE '1945-02-24' as TIMESTAMP)",
- "1945-02-24 00:00:00",
- "TIMESTAMP(0) NOT NULL");
- }
-
- if (!enable) {
- return;
- }
+ tester.checkScalar(
+ "cast(DATE '1945-02-24' as TIMESTAMP)",
+ "1945-02-24 00:00:00",
+ "TIMESTAMP(0) NOT NULL");
// Note: Casting to time(0) should lose date info and fractional
// seconds, then casting back to timestamp should initialize to
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/38a4dd41/core/src/test/java/org/apache/calcite/test/SqlFunctionsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/SqlFunctionsTest.java b/core/src/test/java/org/apache/calcite/test/SqlFunctionsTest.java
index 9f82294..97f8e59 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlFunctionsTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlFunctionsTest.java
@@ -45,6 +45,8 @@ import static org.apache.calcite.avatica.util.DateTimeUtils.ymdToJulian;
import static org.apache.calcite.avatica.util.DateTimeUtils.ymdToUnixDate;
import static org.apache.calcite.runtime.SqlFunctions.charLength;
import static org.apache.calcite.runtime.SqlFunctions.concat;
+import static org.apache.calcite.runtime.SqlFunctions.floorDiv;
+import static org.apache.calcite.runtime.SqlFunctions.floorMod;
import static org.apache.calcite.runtime.SqlFunctions.greater;
import static org.apache.calcite.runtime.SqlFunctions.initcap;
import static org.apache.calcite.runtime.SqlFunctions.lesser;
@@ -332,8 +334,10 @@ public class SqlFunctionsTest {
assertThat(SqlFunctions.floor((long) x, (long) y), is((long) result));
assertThat(SqlFunctions.floor((short) x, (short) y), is((short) result));
assertThat(SqlFunctions.floor((byte) x, (byte) y), is((byte) result));
- assertThat(SqlFunctions.floor(BigDecimal.valueOf(x), BigDecimal.valueOf(y)),
- is(BigDecimal.valueOf(result)));
+ assertThat(
+ SqlFunctions.floor(BigDecimal.valueOf(x), BigDecimal.valueOf(y)), is(
+ BigDecimal.valueOf(
+ result)));
}
@Test public void testCeil() {
@@ -350,8 +354,10 @@ public class SqlFunctionsTest {
assertThat(SqlFunctions.ceil((long) x, (long) y), is((long) result));
assertThat(SqlFunctions.ceil((short) x, (short) y), is((short) result));
assertThat(SqlFunctions.ceil((byte) x, (byte) y), is((byte) result));
- assertThat(SqlFunctions.ceil(BigDecimal.valueOf(x), BigDecimal.valueOf(y)),
- is(BigDecimal.valueOf(result)));
+ assertThat(
+ SqlFunctions.ceil(BigDecimal.valueOf(x), BigDecimal.valueOf(y)), is(
+ BigDecimal.valueOf(
+ result)));
}
/** Unit test for
@@ -443,6 +449,30 @@ public class SqlFunctionsTest {
assertEquals(2, digitCount(99));
assertEquals(3, digitCount(100));
}
+
+ @Test public void testFloorDiv() {
+ assertThat(floorDiv(13, 3), equalTo(4L));
+ assertThat(floorDiv(12, 3), equalTo(4L));
+ assertThat(floorDiv(11, 3), equalTo(3L));
+ assertThat(floorDiv(-13, 3), equalTo(-5L));
+ assertThat(floorDiv(-12, 3), equalTo(-4L));
+ assertThat(floorDiv(-11, 3), equalTo(-4L));
+ assertThat(floorDiv(0, 3), equalTo(0L));
+ assertThat(floorDiv(1, 3), equalTo(0L));
+ assertThat(floorDiv(-1, 3), equalTo(-1L));
+ }
+
+ @Test public void testFloorMod() {
+ assertThat(floorMod(13, 3), equalTo(1L));
+ assertThat(floorMod(12, 3), equalTo(0L));
+ assertThat(floorMod(11, 3), equalTo(2L));
+ assertThat(floorMod(-13, 3), equalTo(2L));
+ assertThat(floorMod(-12, 3), equalTo(0L));
+ assertThat(floorMod(-11, 3), equalTo(1L));
+ assertThat(floorMod(0, 3), equalTo(0L));
+ assertThat(floorMod(1, 3), equalTo(1L));
+ assertThat(floorMod(-1, 3), equalTo(2L));
+ }
}
// End SqlFunctionsTest.java
http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/38a4dd41/core/src/test/resources/sql/misc.oq
----------------------------------------------------------------------
diff --git a/core/src/test/resources/sql/misc.oq b/core/src/test/resources/sql/misc.oq
index 63422cf..dbd1fbc 100644
--- a/core/src/test/resources/sql/misc.oq
+++ b/core/src/test/resources/sql/misc.oq
@@ -33,9 +33,8 @@ from "hr"."emps";
!ok
-# CALCITE-307 CAST(timestamp AS DATE) gives ClassCastException
-# Based on DRILL-1051
-!if (false) {
+# [CALCITE-307] CAST(timestamp AS DATE) gives ClassCastException
+# Based on [DRILL-1051]
with data(c_row, c_timestamp) as (select * from (values
(1, TIMESTAMP '1997-01-02 03:04:05'),
(2, TIMESTAMP '1997-01-02 00:00:00'),
@@ -61,9 +60,9 @@ with data(c_row, c_timestamp) as (select * from (values
(23, TIMESTAMP '1996-03-01 17:32:01')))
select cast(c_timestamp as varchar(20)), cast(c_timestamp as date) from data where c_row <> 12;
-+------------+------------+
-| EXPR$0 | EXPR$1 |
-+------------+------------+
++---------------------+------------+
+| EXPR$0 | EXPR$1 |
++---------------------+------------+
| 1997-01-02 03:04:05 | 1997-01-02 |
| 1997-01-02 00:00:00 | 1997-01-02 |
| 2001-09-22 18:19:20 | 2001-09-22 |
@@ -75,22 +74,21 @@ select cast(c_timestamp as varchar(20)), cast(c_timestamp as date) from data whe
| 1997-02-14 17:32:01 | 1997-02-14 |
| 1997-02-15 17:32:01 | 1997-02-15 |
| 1997-02-16 17:32:01 | 1997-02-16 |
-| 0097-02-16 17:32:01 | 0097-02-17 |
-| 0597-02-16 17:32:01 | 0597-02-13 |
-| 1097-02-16 17:32:01 | 1097-02-09 |
-| 1697-02-16 17:32:01 | 1697-02-15 |
-| 1797-02-16 17:32:01 | 1797-02-15 |
+| 0097-02-14 17:32:01 | 0097-02-14 |
+| 0597-02-18 17:32:01 | 0597-02-18 |
+| 1097-02-22 17:32:01 | 1097-02-22 |
+| 1697-02-16 17:32:01 | 1697-02-16 |
+| 1797-02-16 17:32:01 | 1797-02-16 |
| 1897-02-16 17:32:01 | 1897-02-16 |
| 1997-02-16 17:32:01 | 1997-02-16 |
| 2097-02-16 17:32:01 | 2097-02-16 |
| 1996-02-28 17:32:01 | 1996-02-28 |
| 1996-02-29 17:32:01 | 1996-02-29 |
| 1996-03-01 17:32:01 | 1996-03-01 |
-+------------+------------+
-22 rows selected
++---------------------+------------+
+(22 rows)
!ok
-!}
# [DRILL-1149]
select *, upper("name")