[CALCITE-1673] In CSV adapter, query with ORDER BY or GROUP BY on TIMESTAMP column throws CompileException (Gangadhar Kairi)
Rework to use the same solution as in [CALCITE-1569]; clean up tests (Julian Hyde) Close apache/calcite#389 Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/8e0d76bb Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/8e0d76bb Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/8e0d76bb Branch: refs/heads/master Commit: 8e0d76bb98bf201373fad769c54b6e17f9383bd7 Parents: 58217cb Author: kaiga01 <[email protected]> Authored: Wed Mar 8 00:40:24 2017 +0530 Committer: Julian Hyde <[email protected]> Committed: Thu Mar 9 13:56:43 2017 -0800 ---------------------------------------------------------------------- .../adapter/enumerable/RexToLixTranslator.java | 23 ++++++-- .../java/org/apache/calcite/test/CsvTest.java | 62 ++++++++++++++++++++ 2 files changed, 79 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/8e0d76bb/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 b8dc1a9..80127b1 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 @@ -873,9 +873,7 @@ public class RexToLixTranslator { } else if (toType == java.sql.Date.class) { // E.g. from "int" or "Integer" to "java.sql.Date", // generate "SqlFunctions.internalToDate". - Boolean isPrimitiveInt = fromPrimitive == Primitive.INT; - Boolean isBoxInt = fromBox == Primitive.INT; - if (isPrimitiveInt || isBoxInt) { + if (isA(fromType, Primitive.INT)) { return Expressions.call(BuiltInMethod.INTERNAL_TO_DATE.method, operand); } else { return Expressions.convert_(operand, java.sql.Date.class); @@ -883,12 +881,20 @@ public class RexToLixTranslator { } else if (toType == java.sql.Time.class) { // E.g. from "int" or "Integer" to "java.sql.Time", // generate "SqlFunctions.internalToTime". - return Expressions.call(BuiltInMethod.INTERNAL_TO_TIME.method, operand); + if (isA(fromType, Primitive.INT)) { + return Expressions.call(BuiltInMethod.INTERNAL_TO_TIME.method, operand); + } else { + return Expressions.convert_(operand, java.sql.Time.class); + } } else if (toType == java.sql.Timestamp.class) { // E.g. from "long" or "Long" to "java.sql.Timestamp", // generate "SqlFunctions.internalToTimestamp". - return Expressions.call(BuiltInMethod.INTERNAL_TO_TIMESTAMP.method, - operand); + if (isA(fromType, Primitive.LONG)) { + return Expressions.call(BuiltInMethod.INTERNAL_TO_TIMESTAMP.method, + operand); + } else { + return Expressions.convert_(operand, java.sql.Timestamp.class); + } } else if (toType == BigDecimal.class) { if (fromBox != null) { // E.g. from "Integer" to "BigDecimal". @@ -958,6 +964,11 @@ public class RexToLixTranslator { return Expressions.convert_(operand, toType); } + static boolean isA(Type fromType, Primitive primitive) { + return Primitive.of(fromType) == primitive + || Primitive.ofBox(fromType) == primitive; + } + public Expression translateConstructor( List<RexNode> operandList, SqlKind kind) { switch (kind) { http://git-wip-us.apache.org/repos/asf/calcite/blob/8e0d76bb/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java ---------------------------------------------------------------------- diff --git a/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java b/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java index 47c9213..78a396f 100644 --- a/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java +++ b/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java @@ -41,6 +41,7 @@ import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; +import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; @@ -52,6 +53,7 @@ import java.util.concurrent.Callable; import static org.hamcrest.CoreMatchers.anyOf; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.isA; import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; @@ -517,6 +519,66 @@ public class CsvTest { } /** Test case for + * <a href="https://issues.apache.org/jira/browse/CALCITE-1673">[CALCITE-1673] + * Query with ORDER BY or GROUP BY on TIMESTAMP column throws + * CompileException</a>. */ + @Test public void testTimestampGroupBy() throws SQLException { + Properties info = new Properties(); + info.put("model", jsonPath("bug")); + // Use LIMIT to ensure that results are deterministic without ORDER BY + final String sql = "select \"EMPNO\", \"JOINTIMES\"\n" + + "from (select * from \"DATE\" limit 1)\n" + + "group by \"EMPNO\",\"JOINTIMES\""; + try (Connection connection = + DriverManager.getConnection("jdbc:calcite:", info); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(sql)) { + assertThat(resultSet.next(), is(true)); + final Timestamp timestamp = resultSet.getTimestamp(2); + Assert.assertThat(timestamp, isA(java.sql.Timestamp.class)); + // Note: This logic is time zone specific, but the same time zone is + // used in the CSV adapter and this test, so they should cancel out. + Assert.assertThat(timestamp, + is(java.sql.Timestamp.valueOf("1996-08-03 00:01:02.0"))); + } + } + + /** As {@link #testTimestampGroupBy()} but with ORDER BY. */ + @Test public void testTimestampOrderBy() throws SQLException { + Properties info = new Properties(); + info.put("model", jsonPath("bug")); + final String sql = "select \"EMPNO\",\"JOINTIMES\" from \"DATE\"\n" + + "order by \"JOINTIMES\""; + try (Connection connection = + DriverManager.getConnection("jdbc:calcite:", info); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(sql)) { + assertThat(resultSet.next(), is(true)); + final Timestamp timestamp = resultSet.getTimestamp(2); + Assert.assertThat(timestamp, + is(java.sql.Timestamp.valueOf("1996-08-03 00:01:02"))); + } + } + + /** As {@link #testTimestampGroupBy()} but with ORDER BY as well as GROUP + * BY. */ + @Test public void testTimestampGroupByAndOrderBy() throws SQLException { + Properties info = new Properties(); + info.put("model", jsonPath("bug")); + final String sql = "select \"EMPNO\", \"JOINTIMES\" from \"DATE\"\n" + + "group by \"EMPNO\",\"JOINTIMES\" order by \"JOINTIMES\""; + try (Connection connection = + DriverManager.getConnection("jdbc:calcite:", info); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(sql)) { + assertThat(resultSet.next(), is(true)); + final Timestamp timestamp = resultSet.getTimestamp(2); + Assert.assertThat(timestamp, + is(java.sql.Timestamp.valueOf("1996-08-03 00:01:02"))); + } + } + + /** Test case for * <a href="https://issues.apache.org/jira/browse/CALCITE-1031">[CALCITE-1031] * In prepared statement, CsvScannableTable.scan is called twice</a>. To see * the bug, place a breakpoint in CsvScannableTable.scan, and note that it is
