diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java
index 7464a273eae7..406322d96de7 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/PhysTypeImpl.java
@@ -636,13 +636,13 @@ public Expression fieldReference(
public Expression fieldReference(
Expression expression, int field, Type storageType) {
- Type fieldType;
+ Class fieldType;
if (storageType == null) {
storageType = fieldClass(field);
fieldType = null;
} else {
fieldType = fieldClass(field);
- if (fieldType != java.sql.Date.class) {
+ if (!java.util.Date.class.isAssignableFrom(fieldType)) {
fieldType = null;
}
}
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 1a63068e9a3d..166fcc0be75a 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
@@ -1020,6 +1020,18 @@ public static Expression convert(Expression operand, Type fromType,
} else {
return Expressions.convert_(operand, toType);
}
+ } else if (fromType == java.sql.Time.class) {
+ if (toBox == Primitive.INT) {
+ return Expressions.call(BuiltInMethod.TIME_TO_INT.method, operand);
+ } else {
+ return Expressions.convert_(operand, toType);
+ }
+ } else if (fromType == java.sql.Timestamp.class) {
+ if (toBox == Primitive.LONG) {
+ return Expressions.call(BuiltInMethod.TIMESTAMP_TO_LONG.method, operand);
+ } else {
+ return Expressions.convert_(operand, toType);
+ }
} else if (toType == java.sql.Date.class) {
// E.g. from "int" or "Integer" to "java.sql.Date",
// generate "SqlFunctions.internalToDate".
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 7644d0a3eb33..6844df794a72 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -1610,6 +1610,7 @@ public static long toLong(Object o) {
return o instanceof Long ? (Long) o
: o instanceof Number ? toLong((Number) o)
: o instanceof String ? toLong((String) o)
+ : o instanceof java.util.Date ? toLong((java.util.Date) o)
: (Long) cannotConvert(o, long.class);
}
diff --git a/core/src/test/java/org/apache/calcite/test/ObjectArrayTableTest.java b/core/src/test/java/org/apache/calcite/test/ObjectArrayTableTest.java
new file mode 100644
index 000000000000..dd5e2772f4d7
--- /dev/null
+++ b/core/src/test/java/org/apache/calcite/test/ObjectArrayTableTest.java
@@ -0,0 +1,93 @@
+package org.apache.calcite.test;
+
+import org.apache.calcite.adapter.java.AbstractQueryableTable;
+import org.apache.calcite.jdbc.CalciteConnection;
+import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
+import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.EnumerableDefaults;
+import org.apache.calcite.linq4j.Linq4j;
+import org.apache.calcite.linq4j.QueryProvider;
+import org.apache.calcite.linq4j.Queryable;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeSystem;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.Table;
+import org.junit.Test;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ObjectArrayTableTest {
+
+ /** Test case for
+ * [CALCITE-1703]
+ * Functions on TIME and TIMESTAMP column can throw ClassCastException. */
+ @Test public void testJavaSqlDateColumnReference() throws SQLException {
+
+ try (
+ Connection connection = DriverManager.getConnection("jdbc:calcite:");
+ final CalciteConnection calciteConnection = connection.unwrap(CalciteConnection.class)
+ ) {
+ final SchemaPlus rootSchema = calciteConnection.getRootSchema();
+
+ final JavaTypeFactoryImpl typeFactory =
+ new JavaTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
+
+ final RelDataType rowType =typeFactory.createStructType(
+ Arrays.asList(
+ typeFactory.createJavaType(java.sql.Date.class),
+ typeFactory.createJavaType(java.sql.Time.class),
+ typeFactory.createJavaType(java.sql.Timestamp.class)
+ ),
+ Arrays.asList("dt", "tm", "ts")
+ );
+
+ final Enumerable