[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

Reply via email to