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/08/01 00:43:15 UTC

[38/50] [abbrv] incubator-calcite git commit: [CALCITE-730] ClassCastException in table from CloneSchema

[CALCITE-730] ClassCastException in table from CloneSchema


Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/bf86ef9d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/bf86ef9d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/bf86ef9d

Branch: refs/heads/branch-release
Commit: bf86ef9d225df1fe1aa30b67239e5bb764ff35f3
Parents: a27bb57
Author: Julian Hyde <jh...@apache.org>
Authored: Fri May 15 21:37:35 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Fri May 15 21:38:57 2015 -0700

----------------------------------------------------------------------
 .../apache/calcite/avatica/ColumnMetaData.java  |  51 +++++++++
 .../apache/calcite/adapter/jdbc/JdbcTable.java  |  19 ++--
 .../apache/calcite/adapter/jdbc/JdbcUtils.java  |  16 +--
 .../java/org/apache/calcite/test/JdbcTest.java  | 111 +++++++++++++------
 4 files changed, 146 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/bf86ef9d/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java b/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java
index e0a50b6..2d7821e 100644
--- a/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java
+++ b/avatica/src/main/java/org/apache/calcite/avatica/ColumnMetaData.java
@@ -25,7 +25,9 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
 
 import java.lang.reflect.Type;
 import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.sql.Types;
@@ -221,6 +223,55 @@ public class ColumnMetaData {
       final Rep rep = VALUE_MAP.get(clazz);
       return rep != null ? rep : OBJECT;
     }
+
+    /** Returns the value of a column of this type from a result set. */
+    public Object jdbcGet(ResultSet resultSet, int i) throws SQLException {
+      switch (this) {
+      case PRIMITIVE_BOOLEAN:
+        return resultSet.getBoolean(i);
+      case PRIMITIVE_BYTE:
+        return resultSet.getByte(i);
+      case PRIMITIVE_SHORT:
+        return resultSet.getShort(i);
+      case PRIMITIVE_INT:
+        return resultSet.getInt(i);
+      case PRIMITIVE_LONG:
+        return resultSet.getLong(i);
+      case PRIMITIVE_FLOAT:
+        return resultSet.getFloat(i);
+      case PRIMITIVE_DOUBLE:
+        return resultSet.getDouble(i);
+      case BOOLEAN:
+        final boolean aBoolean = resultSet.getBoolean(i);
+        return resultSet.wasNull() ? null : aBoolean;
+      case BYTE:
+        final byte aByte = resultSet.getByte(i);
+        return resultSet.wasNull() ? null : aByte;
+      case SHORT:
+        final short aShort = resultSet.getShort(i);
+        return resultSet.wasNull() ? null : aShort;
+      case INTEGER:
+        final int anInt = resultSet.getInt(i);
+        return resultSet.wasNull() ? null : anInt;
+      case LONG:
+        final long aLong = resultSet.getLong(i);
+        return resultSet.wasNull() ? null : aLong;
+      case FLOAT:
+        final float aFloat = resultSet.getFloat(i);
+        return resultSet.wasNull() ? null : aFloat;
+      case DOUBLE:
+        final double aDouble = resultSet.getDouble(i);
+        return resultSet.wasNull() ? null : aDouble;
+      case JAVA_SQL_DATE:
+        return resultSet.getDate(i);
+      case JAVA_SQL_TIME:
+        return resultSet.getTime(i);
+      case JAVA_SQL_TIMESTAMP:
+        return resultSet.getTimestamp(i);
+      default:
+        return resultSet.getObject(i);
+      }
+    }
   }
 
   /** Base class for a column type. */

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/bf86ef9d/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java
index 976e311..fe6da60 100644
--- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java
@@ -19,12 +19,12 @@ package org.apache.calcite.adapter.jdbc;
 import org.apache.calcite.DataContext;
 import org.apache.calcite.adapter.java.AbstractQueryableTable;
 import org.apache.calcite.adapter.java.JavaTypeFactory;
+import org.apache.calcite.avatica.ColumnMetaData;
 import org.apache.calcite.jdbc.CalciteConnection;
 import org.apache.calcite.linq4j.Enumerable;
 import org.apache.calcite.linq4j.Enumerator;
 import org.apache.calcite.linq4j.QueryProvider;
 import org.apache.calcite.linq4j.Queryable;
-import org.apache.calcite.linq4j.tree.Primitive;
 import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.type.RelDataType;
@@ -108,16 +108,19 @@ class JdbcTable extends AbstractQueryableTable
     return protoRowType.apply(typeFactory);
   }
 
-  private List<Pair<Primitive, Integer>> fieldClasses(
+  private List<Pair<ColumnMetaData.Rep, Integer>> fieldClasses(
       final JavaTypeFactory typeFactory) {
     final RelDataType rowType = protoRowType.apply(typeFactory);
     return Lists.transform(rowType.getFieldList(),
-        new Function<RelDataTypeField, Pair<Primitive, Integer>>() {
-          public Pair<Primitive, Integer> apply(RelDataTypeField field) {
-            RelDataType type = field.getType();
-            Class clazz = (Class) typeFactory.getJavaClass(type);
-            return Pair.of(Util.first(Primitive.of(clazz), Primitive.OTHER),
-                type.getSqlTypeName().getJdbcOrdinal());
+        new Function<RelDataTypeField, Pair<ColumnMetaData.Rep, Integer>>() {
+          public Pair<ColumnMetaData.Rep, Integer>
+          apply(RelDataTypeField field) {
+            final RelDataType type = field.getType();
+            final Class clazz = (Class) typeFactory.getJavaClass(type);
+            final ColumnMetaData.Rep rep =
+                Util.first(ColumnMetaData.Rep.of(clazz),
+                    ColumnMetaData.Rep.OBJECT);
+            return Pair.of(rep, type.getSqlTypeName().getJdbcOrdinal());
           }
         });
   }

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/bf86ef9d/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java
index d4643af..da5eef8 100644
--- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java
+++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java
@@ -16,10 +16,10 @@
  */
 package org.apache.calcite.adapter.jdbc;
 
+import org.apache.calcite.avatica.ColumnMetaData;
 import org.apache.calcite.avatica.util.DateTimeUtils;
 import org.apache.calcite.linq4j.function.Function0;
 import org.apache.calcite.linq4j.function.Function1;
-import org.apache.calcite.linq4j.tree.Primitive;
 import org.apache.calcite.sql.SqlDialect;
 import org.apache.calcite.util.ImmutableNullableList;
 import org.apache.calcite.util.IntList;
@@ -110,26 +110,26 @@ final class JdbcUtils {
   public static class ObjectArrayRowBuilder implements Function0<Object[]> {
     private final ResultSet resultSet;
     private final int columnCount;
-    private final Primitive[] primitives;
+    private final ColumnMetaData.Rep[] reps;
     private final int[] types;
 
-    public ObjectArrayRowBuilder(
-        ResultSet resultSet, Primitive[] primitives, int[] types)
+    public ObjectArrayRowBuilder(ResultSet resultSet, ColumnMetaData.Rep[] reps,
+        int[] types)
         throws SQLException {
       this.resultSet = resultSet;
-      this.primitives = primitives;
+      this.reps = reps;
       this.types = types;
       this.columnCount = resultSet.getMetaData().getColumnCount();
     }
 
     public static Function1<ResultSet, Function0<Object[]>> factory(
-        final List<Pair<Primitive, Integer>> list) {
+        final List<Pair<ColumnMetaData.Rep, Integer>> list) {
       return new Function1<ResultSet, Function0<Object[]>>() {
         public Function0<Object[]> apply(ResultSet resultSet) {
           try {
             return new ObjectArrayRowBuilder(
                 resultSet,
-                Pair.left(list).toArray(new Primitive[list.size()]),
+                Pair.left(list).toArray(new ColumnMetaData.Rep[list.size()]),
                 IntList.toArray(Pair.right(list)));
           } catch (SQLException e) {
             throw new RuntimeException(e);
@@ -167,7 +167,7 @@ final class JdbcUtils {
       case Types.DATE:
         return shift(resultSet.getDate(i + 1));
       }
-      return primitives[i].jdbcGet(resultSet, i + 1);
+      return reps[i].jdbcGet(resultSet, i + 1);
     }
 
     private static Timestamp shift(Timestamp v) {

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/bf86ef9d/core/src/test/java/org/apache/calcite/test/JdbcTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index 874d21a..0b1ecbf 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -656,8 +656,8 @@ public class JdbcTest {
   /** Table macro that takes a MAP as a parameter.
    *
    * <p>Test case for
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-588">CALCITE-588</a>,
-   * "Allow TableMacro to consume Maps and Collections". */
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-588">[CALCITE-588]
+   * Allow TableMacro to consume Maps and Collections</a>. */
   @Test public void testTableMacroMap()
       throws SQLException, ClassNotFoundException {
     Connection connection =
@@ -1686,8 +1686,8 @@ public class JdbcTest {
   /** Tests 3-way AND.
    *
    * <p>With
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-127">[CALCITE-127],
-   * "EnumerableCalcRel can't support 3+ AND conditions"</a>, the last condition
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-127">[CALCITE-127]
+   * EnumerableCalcRel can't support 3+ AND conditions</a>, the last condition
    * is ignored and rows with deptno=10 are wrongly returned.</p>
    */
   @Test public void testAnd3() {
@@ -1723,8 +1723,8 @@ public class JdbcTest {
   }
 
   /** Test case for
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-281">CALCITE-281</a>,
-   * "SQL type of EXTRACT is BIGINT but it is implemented as int". */
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-281">[CALCITE-281]
+   * SQL type of EXTRACT is BIGINT but it is implemented as int</a>. */
   @Test public void testExtract() {
     CalciteAssert.that()
         .with(CalciteAssert.Config.JDBC_FOODMART)
@@ -1757,8 +1757,8 @@ public class JdbcTest {
   }
 
   /** Test case for
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-387">CALCITE-387</a>,
-   * "CompileException when cast TRUE to nullable boolean". */
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-387">[CALCITE-387]
+   * CompileException when cast TRUE to nullable boolean</a>. */
   @Test public void testTrue() {
     final CalciteAssert.AssertThat that = CalciteAssert.that();
     that.query("select case when deptno = 10 then null else true end as x\n"
@@ -1800,8 +1800,8 @@ public class JdbcTest {
   /** A join that has both equi and non-equi conditions.
    *
    * <p>Test case for
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-371">CALCITE-371</a>,
-   * "Cannot implement JOIN whose ON clause contains mixed equi and theta". */
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-371">[CALCITE-371]
+   * Cannot implement JOIN whose ON clause contains mixed equi and theta</a>. */
   @Test public void testEquiThetaJoin() {
     CalciteAssert.hr()
         .query("select e.\"empid\", d.\"name\", e.\"name\"\n"
@@ -1835,8 +1835,8 @@ public class JdbcTest {
   }
 
   /** Test case for
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-35">CALCITE-35</a>,
-   * "Support parenthesized sub-clause in JOIN". */
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-35">[CALCITE-35]
+   * Support parenthesized sub-clause in JOIN</a>. */
   @Ignore
   @Test public void testJoinJoin() {
     CalciteAssert.that()
@@ -2255,8 +2255,8 @@ public class JdbcTest {
    * plan.
    *
    * <p>Test case for (not yet fixed)
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-92">CALCITE-92</a>,
-   * "Project should be optimized away, not converted to EnumerableCalcRel".</p>
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-92">[CALCITE-92]
+   * Project should be optimized away, not converted to EnumerableCalcRel</a>.
    */
   @Ignore
   @Test public void testNoCalcBetweenJoins() throws IOException {
@@ -2368,8 +2368,8 @@ public class JdbcTest {
   }
 
   /** Test case for (not yet fixed)
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-99">CALCITE-99</a>,
-   * "Recognize semi-join that has high selectivity and push it down". */
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-99">[CALCITE-99]
+   * Recognize semi-join that has high selectivity and push it down</a>. */
   @Ignore
   @Test public void testExplainJoin4() throws IOException {
     withFoodMartQuery(5217)
@@ -2926,7 +2926,8 @@ public class JdbcTest {
   }
 
   /** Tests sorting by an expression not in the '*' select clause. Test case for
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-176">CALCITE-176</a>. */
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-176">[CALCITE-176]
+   * ORDER BY expression doesn't work with SELECT *</a>. */
   @Test public void testOrderStarByExpr() {
     CalciteAssert.hr()
         .query("select * from \"hr\".\"emps\"\n"
@@ -3084,9 +3085,9 @@ public class JdbcTest {
   }
 
   /** Limit implemented using {@link Queryable#take}. Test case for
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-96">CALCITE-96</a>,
-   * "LIMIT against a table in a clone schema causes
-   * UnsupportedOperationException". */
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-96">[CALCITE-96]
+   * LIMIT against a table in a clone schema causes
+   * UnsupportedOperationException</a>. */
   @Test public void testLimitOnQueryableTable() {
     CalciteAssert.that()
         .with(CalciteAssert.Config.FOODMART_CLONE)
@@ -3097,8 +3098,8 @@ public class JdbcTest {
   }
 
   /** Limit implemented using {@link Queryable#take}. Test case for
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-70">CALCITE-70</a>,
-   * "Joins seem to be very expensive in memory". */
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-70">[CALCITE-70]
+   * Joins seem to be very expensive in memory</a>. */
   @Test public void testSelfJoinCount() {
     CalciteAssert.that()
         .with(CalciteAssert.Config.JDBC_FOODMART)
@@ -3228,9 +3229,9 @@ public class JdbcTest {
   }
 
   /** Test case for
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-403">CALCITE-403</a>,
-   * "Enumerable gives NullPointerException with NOT on nullable
-   * expression". */
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-403">[CALCITE-403]
+   * Enumerable gives NullPointerException with NOT on nullable
+   * expression</a>. */
   @Test public void testHavingNot() throws IOException {
     withFoodMartQuery(6597).runs();
   }
@@ -4088,8 +4089,8 @@ public class JdbcTest {
   /** Tests windowed aggregation with no ORDER BY clause.
    *
    * <p>Test case for
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-285">CALCITE-285</a>,
-   * "Window functions throw exception without ORDER BY".
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-285">[CALCITE-285]
+   * Window functions throw exception without ORDER BY</a>.
    *
    * <p>Note:</p>
    *
@@ -4376,8 +4377,8 @@ public class JdbcTest {
   }
 
   /** Test case for
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-313">CALCITE-313</a>,
-   * "Query decorrelation fails". */
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-313">[CALCITE-313]
+   * Query decorrelation fails</a>. */
   @Test public void testJoinInCorrelatedSubquery() {
     CalciteAssert.hr()
         .query("select *\n"
@@ -4806,8 +4807,8 @@ public class JdbcTest {
    * allow Jackson's comments extension.
    *
    * <p>Test case for
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-160">CALCITE-160</a>,
-   * "Allow comments in schema definitions".</p> */
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-160">[CALCITE-160]
+   * Allow comments in schema definitions</a>. */
   @Test public void testModelWithComment() {
     final String model =
         FOODMART_MODEL.replace("schemas:", "/* comment */ schemas:");
@@ -5146,8 +5147,9 @@ public class JdbcTest {
               public Object apply(CalciteConnection a0) {
                 try {
                   a0.createStatement()
-                      .executeQuery("select * from \"hr\".\"emps\" "
-                          + "where \"deptno\" = 10");
+                      .executeQuery(
+                          "select * from \"hr\".\"emps\" "
+                              + "where \"deptno\" = 10");
                   assertEquals(1, objects.size());
                   return null;
                 } catch (SQLException e) {
@@ -6051,8 +6053,8 @@ public class JdbcTest {
   /** Tests case-insensitive resolution of sub-query columns.
    *
    * <p>Test case for
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-555">[CALCITE-555],
-   * "Case-insensitive matching of sub-query columns fails"</a>. */
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-555">[CALCITE-555]
+   * Case-insensitive matching of sub-query columns fails</a>. */
   @Test public void testLexCaseInsensitiveSubQueryField() {
     CalciteAssert.that()
         .with(Lex.MYSQL)
@@ -6374,6 +6376,45 @@ public class JdbcTest {
 
   }
 
+  /** Test case for
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-730">[CALCITE-730]
+   * ClassCastException in table from CloneSchema</a>. */
+  @Test public void testNullableNumericColumnInCloneSchema() {
+    CalciteAssert.model("{\n"
+            + "  version: '1.0',\n"
+            + "  defaultSchema: 'SCOTT_CLONE',\n"
+            + "  schemas: [ {\n"
+            + "    name: 'SCOTT_CLONE',\n"
+            + "    type: 'custom',\n"
+            + "    factory: 'org.apache.calcite.adapter.clone.CloneSchema$Factory',\n"
+            + "    operand: {\n"
+            + "      jdbcDriver: '" + JdbcTest.SCOTT.driver + "',\n"
+            + "      jdbcUser: '" + JdbcTest.SCOTT.username + "',\n"
+            + "      jdbcPassword: '" + JdbcTest.SCOTT.password + "',\n"
+            + "      jdbcUrl: '" + JdbcTest.SCOTT.url + "',\n"
+            + "      jdbcSchema: 'SCOTT'\n"
+            + "   } } ]\n"
+            + "}")
+        .query("select * from emp")
+        .returns(
+            new Function<ResultSet, Void>() {
+              public Void apply(ResultSet input) {
+                final StringBuilder buf = new StringBuilder();
+                try {
+                  final int columnCount = input.getMetaData().getColumnCount();
+                  while (input.next()) {
+                    for (int i = 0; i < columnCount; i++) {
+                      buf.append(input.getObject(i + 1));
+                    }
+                  }
+                  return null;
+                } catch (SQLException e) {
+                  throw Throwables.propagate(e);
+                }
+              }
+            });
+  }
+
   // Disable checkstyle, so it doesn't complain about fields like "customer_id".
   //CHECKSTYLE: OFF