You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@drill.apache.org by ve...@apache.org on 2016/08/08 21:50:55 UTC
drill git commit: DRILL-4732: Update JDBC driver to use the new
prepared statement APIs on DrillClient
Repository: drill
Updated Branches:
refs/heads/master 14f6ec7dd -> e02aa596f
DRILL-4732: Update JDBC driver to use the new prepared statement APIs on DrillClient
this closes #532
Project: http://git-wip-us.apache.org/repos/asf/drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/e02aa596
Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/e02aa596
Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/e02aa596
Branch: refs/heads/master
Commit: e02aa596fa64f38bce773fd108f15032f8086601
Parents: 14f6ec7
Author: vkorukanti <ve...@dremio.com>
Authored: Mon Jun 20 14:40:05 2016 -0700
Committer: vkorukanti <ve...@dremio.com>
Committed: Mon Aug 8 14:49:14 2016 -0700
----------------------------------------------------------------------
.../org/apache/drill/common/types/Types.java | 112 +++------
.../jdbc/impl/DrillColumnMetaDataList.java | 58 ++++-
.../drill/jdbc/impl/DrillConnectionImpl.java | 42 +++-
.../drill/jdbc/impl/DrillPrepareResult.java | 16 +-
.../drill/jdbc/impl/DrillResultSetImpl.java | 12 +-
.../jdbc/impl/DrillResultSetMetaDataImpl.java | 3 +-
.../drill/jdbc/PreparedStatementTest.java | 226 ++++++++++++++-----
...69UnsupportedReportsUseSqlExceptionTest.java | 2 +-
8 files changed, 327 insertions(+), 144 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/drill/blob/e02aa596/common/src/main/java/org/apache/drill/common/types/Types.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/drill/common/types/Types.java b/common/src/main/java/org/apache/drill/common/types/Types.java
index 504b876..ed77ccd 100644
--- a/common/src/main/java/org/apache/drill/common/types/Types.java
+++ b/common/src/main/java/org/apache/drill/common/types/Types.java
@@ -163,84 +163,42 @@ public class Types {
}
/***
- * Gets JDBC type code for given Drill RPC-/protobuf-level type.
+ * Gets JDBC type code for given SQL data type name.
*/
- public static int getJdbcTypeCode(final MajorType type) {
- if (type.getMode() == DataMode.REPEATED || type.getMinorType() == MinorType.LIST) {
- return java.sql.Types.ARRAY;
- }
-
- switch (type.getMinorType()) {
- case BIGINT:
- return java.sql.Types.BIGINT;
- case BIT:
- return java.sql.Types.BOOLEAN;
- case DATE:
- return java.sql.Types.DATE;
- case DECIMAL9:
- case DECIMAL18:
- case DECIMAL28DENSE:
- case DECIMAL28SPARSE:
- case DECIMAL38DENSE:
- case DECIMAL38SPARSE:
- return java.sql.Types.DECIMAL;
- case FIXED16CHAR:
- return java.sql.Types.NCHAR;
- case FIXEDBINARY:
- return java.sql.Types.BINARY;
- case FIXEDCHAR:
- return java.sql.Types.NCHAR;
- case FLOAT4:
- return java.sql.Types.FLOAT;
- case FLOAT8:
- return java.sql.Types.DOUBLE;
- case INT:
- return java.sql.Types.INTEGER;
- case MAP:
- return java.sql.Types.STRUCT;
- case MONEY:
- return java.sql.Types.DECIMAL;
- case NULL:
- return java.sql.Types.NULL;
- case INTERVAL:
- case INTERVALYEAR:
- case INTERVALDAY:
- return java.sql.Types.OTHER; // JDBC (4.1) has nothing for INTERVAL
- case LATE:
- return java.sql.Types.OTHER;
- case SMALLINT:
- return java.sql.Types.SMALLINT;
- case TIME:
- return java.sql.Types.TIME;
- case TIMESTAMPTZ:
- case TIMESTAMP:
- return java.sql.Types.TIMESTAMP;
- case TIMETZ:
- return java.sql.Types.TIME;
- case TINYINT:
- return java.sql.Types.TINYINT;
- case UINT1:
- return java.sql.Types.TINYINT;
- case UINT2:
- return java.sql.Types.SMALLINT;
- case UINT4:
- return java.sql.Types.INTEGER;
- case UINT8:
- return java.sql.Types.BIGINT;
- case VAR16CHAR:
- return java.sql.Types.NVARCHAR;
- case VARBINARY:
- return java.sql.Types.VARBINARY;
- case VARCHAR:
- return java.sql.Types.VARCHAR;
- case UNION:
- return java.sql.Types.OTHER;
- default:
- // TODO: This isn't really an unsupported-operation/-type case; this
- // is an unexpected, code-out-of-sync-with-itself case, so use an
- // exception intended for that.
- throw new UnsupportedOperationException(
- "Unexpected/unhandled MinorType value " + type.getMinorType() );
+ public static int getJdbcTypeCode(final String sqlTypeName) {
+
+ switch (sqlTypeName) {
+ case "ANY": return java.sql.Types.OTHER;
+ case "ARRAY": return java.sql.Types.ARRAY;
+ case "BIGINT": return java.sql.Types.BIGINT;
+ case "BINARY VARYING": return java.sql.Types.VARBINARY;
+ case "BINARY": return java.sql.Types.BINARY;
+ case "BOOLEAN": return java.sql.Types.BOOLEAN;
+ case "CHARACTER VARYING": return java.sql.Types.VARCHAR;
+ case "CHARACTER": return java.sql.Types.NCHAR;
+ case "DATE": return java.sql.Types.DATE;
+ case "DECIMAL": return java.sql.Types.DECIMAL;
+ case "DOUBLE": return java.sql.Types.DOUBLE;
+ case "FLOAT": return java.sql.Types.FLOAT;
+ case "INTEGER": return java.sql.Types.INTEGER;
+ case "INTERVAL": return java.sql.Types.OTHER; // JDBC (4.1) has nothing for INTERVAL
+ case "MAP": return java.sql.Types.STRUCT;
+ case "NATIONAL CHARACTER VARYING": return java.sql.Types.NVARCHAR;
+ case "NATIONAL CHARACTER": return java.sql.Types.NCHAR;
+ case "NULL": return java.sql.Types.NULL;
+ case "SMALLINT": return java.sql.Types.SMALLINT;
+ case "TIME WITH TIME ZONE": // fall through
+ case "TIME": return java.sql.Types.TIME;
+ case "TIMESTAMP WITH TIME ZONE": // fall through
+ case "TIMESTAMP": return java.sql.Types.TIMESTAMP;
+ case "TINYINT": return java.sql.Types.TINYINT;
+ case "UNION": return java.sql.Types.OTHER;
+ default:
+ // TODO: This isn't really an unsupported-operation/-type case; this
+ // is an unexpected, code-out-of-sync-with-itself case, so use an
+ // exception intended for that.
+ throw new UnsupportedOperationException(
+ "Unexpected/unhandled SqlType value " + sqlTypeName );
}
}
http://git-wip-us.apache.org/repos/asf/drill/blob/e02aa596/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillColumnMetaDataList.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillColumnMetaDataList.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillColumnMetaDataList.java
index d23e56f..a3e37ae 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillColumnMetaDataList.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillColumnMetaDataList.java
@@ -28,12 +28,16 @@ import net.hydromatic.avatica.ColumnMetaData;
import net.hydromatic.avatica.ColumnMetaData.AvaticaType;
import net.hydromatic.avatica.ColumnMetaData.Rep;
-import org.apache.drill.common.types.TypeProtos.DataMode;
import org.apache.drill.common.types.TypeProtos.MajorType;
import org.apache.drill.common.types.Types;
+import org.apache.drill.exec.proto.UserProtos.ColumnSearchability;
+import org.apache.drill.exec.proto.UserProtos.ColumnUpdatability;
+import org.apache.drill.exec.proto.UserProtos.ResultColumnMetadata;
import org.apache.drill.exec.record.BatchSchema;
import org.apache.drill.exec.record.MaterializedField;
+import com.google.common.collect.ImmutableList;
+
public class DrillColumnMetaDataList extends BasicList<ColumnMetaData>{
static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DrillColumnMetaDataList.class);
@@ -51,13 +55,61 @@ public class DrillColumnMetaDataList extends BasicList<ColumnMetaData>{
/**
* Gets AvaticaType carrying both JDBC {@code java.sql.Type.*} type code
+ * and SQL type name for given SQL type name.
+ */
+ private static AvaticaType getAvaticaType(String sqlTypeName) {
+ final int jdbcTypeId = Types.getJdbcTypeCode(sqlTypeName);
+ return ColumnMetaData.scalar( jdbcTypeId, sqlTypeName,
+ Rep.BOOLEAN /* dummy value, unused */ );
+ }
+
+ /**
+ * Update the metadata with given metadata received from server.
+ * @param metadata
+ */
+ public void updateColumnMetaData(List<ResultColumnMetadata> metadata) {
+ final List<ColumnMetaData> newColumns = new ArrayList<>(metadata.size());
+ int offset = 0;
+ for(ResultColumnMetadata m : metadata) {
+
+ final AvaticaType bundledSqlDataType = getAvaticaType(m.getDataType());
+
+ newColumns.add(new ColumnMetaData(
+ offset,
+ m.getAutoIncrement(),
+ m.getCaseSensitivity(),
+ m.getSearchability() != ColumnSearchability.NONE,
+ m.getIsCurrency(),
+ m.getIsNullable() ? ResultSetMetaData.columnNullable : ResultSetMetaData.columnNoNulls,
+ m.getSigned(),
+ m.getDisplaySize(),
+ m.getLabel(),
+ m.getColumnName(),
+ m.getSchemaName(),
+ m.getPrecision(),
+ m.getScale(),
+ m.getTableName(),
+ m.getCatalogName(),
+ bundledSqlDataType,
+ m.getUpdatability() == ColumnUpdatability.READ_ONLY,
+ m.getUpdatability() == ColumnUpdatability.WRITABLE,
+ m.getUpdatability() == ColumnUpdatability.WRITABLE,
+ m.getClassName()
+ ));
+ offset++;
+ }
+ columns = ImmutableList.copyOf(newColumns);
+ }
+
+ /**
+ * Gets AvaticaType carrying both JDBC {@code java.sql.Type.*} type code
* and SQL type name for given RPC-level type (from batch schema).
*/
private static AvaticaType getAvaticaType( MajorType rpcDateType ) {
final String sqlTypeName = Types.getSqlTypeName( rpcDateType );
- final int jdbcTypeId = Types.getJdbcTypeCode( rpcDateType );
+ final int jdbcTypeId = Types.getJdbcTypeCode( sqlTypeName );
return ColumnMetaData.scalar( jdbcTypeId, sqlTypeName,
- Rep.BOOLEAN /* dummy value, unused */ );
+ Rep.BOOLEAN /* dummy value, unused */ );
}
public void updateColumnMetaData(String catalogName, String schemaName,
http://git-wip-us.apache.org/repos/asf/drill/blob/e02aa596/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillConnectionImpl.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillConnectionImpl.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillConnectionImpl.java
index ab73a14..855a27e 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillConnectionImpl.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillConnectionImpl.java
@@ -17,7 +17,6 @@
*/
package org.apache.drill.jdbc.impl;
-import java.io.IOException;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
@@ -30,6 +29,7 @@ import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLNonTransientConnectionException;
+import java.sql.SQLTimeoutException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
@@ -54,6 +54,9 @@ import org.apache.drill.exec.client.DrillClient;
import org.apache.drill.exec.exception.OutOfMemoryException;
import org.apache.drill.exec.memory.BufferAllocator;
import org.apache.drill.exec.memory.RootAllocatorFactory;
+import org.apache.drill.exec.proto.UserProtos.CreatePreparedStatementResp;
+import org.apache.drill.exec.proto.UserProtos.RequestStatus;
+import org.apache.drill.exec.rpc.DrillRpcFuture;
import org.apache.drill.exec.rpc.RpcException;
import org.apache.drill.exec.server.Drillbit;
import org.apache.drill.exec.server.RemoteServiceSet;
@@ -362,12 +365,47 @@ class DrillConnectionImpl extends AvaticaConnection
int resultSetHoldability) throws SQLException {
throwIfClosed();
try {
- DrillPrepareResult prepareResult = new DrillPrepareResult(sql);
+ DrillRpcFuture<CreatePreparedStatementResp> respFuture = client.createPreparedStatement(sql);
+
+ CreatePreparedStatementResp resp;
+ try {
+ resp = respFuture.get();
+ } catch (InterruptedException e) {
+ // Preserve evidence that the interruption occurred so that code higher up
+ // on the call stack can learn of the interruption and respond to it if it
+ // wants to.
+ Thread.currentThread().interrupt();
+
+ throw new SQLException( "Interrupted", e );
+ }
+
+ final RequestStatus status = resp.getStatus();
+ if (status != RequestStatus.OK) {
+ final String errMsgFromServer = resp.getError() != null ? resp.getError().getMessage() : "";
+
+ if (status == RequestStatus.TIMEOUT) {
+ logger.error("Request timed out to create prepare statement: {}", errMsgFromServer);
+ throw new SQLTimeoutException("Failed to create prepared statement: " + errMsgFromServer);
+ }
+
+ if (status == RequestStatus.FAILED) {
+ logger.error("Failed to create prepared statement: {}", errMsgFromServer);
+ throw new SQLException("Failed to create prepared statement: " + errMsgFromServer);
+ }
+
+ logger.error("Failed to create prepared statement. Unknown status: {}, Error: {}", status, errMsgFromServer);
+ throw new SQLException(String.format(
+ "Failed to create prepared statement. Unknown status: %s, Error: %s", status, errMsgFromServer));
+ }
+
+ DrillPrepareResult prepareResult = new DrillPrepareResult(sql, resp.getPreparedStatement());
DrillPreparedStatementImpl statement =
(DrillPreparedStatementImpl) factory.newPreparedStatement(
this, prepareResult, resultSetType, resultSetConcurrency,
resultSetHoldability);
return statement;
+ } catch (SQLException e) {
+ throw e;
} catch (RuntimeException e) {
throw Helper.INSTANCE.createException("Error while preparing statement [" + sql + "]", e);
} catch (Exception e) {
http://git-wip-us.apache.org/repos/asf/drill/blob/e02aa596/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillPrepareResult.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillPrepareResult.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillPrepareResult.java
index 6870673..4042ead 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillPrepareResult.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillPrepareResult.java
@@ -17,6 +17,8 @@
*/
package org.apache.drill.jdbc.impl;
+import org.apache.drill.exec.proto.UserProtos.PreparedStatement;
+
import java.util.Collections;
import java.util.List;
@@ -29,10 +31,17 @@ class DrillPrepareResult implements AvaticaPrepareResult{
final String sql;
final DrillColumnMetaDataList columns = new DrillColumnMetaDataList();
+ final PreparedStatement preparedStatement;
DrillPrepareResult(String sql) {
- super();
this.sql = sql;
+ this.preparedStatement = null;
+ }
+
+ DrillPrepareResult(String sql, PreparedStatement preparedStatement) {
+ this.sql = sql;
+ this.preparedStatement = preparedStatement;
+ columns.updateColumnMetaData(preparedStatement.getColumnsList());
}
@Override
@@ -45,6 +54,11 @@ class DrillPrepareResult implements AvaticaPrepareResult{
return sql;
}
+
+ public PreparedStatement getPreparedStatement() {
+ return preparedStatement;
+ }
+
@Override
public List<AvaticaParameter> getParameterList() {
return Collections.emptyList();
http://git-wip-us.apache.org/repos/asf/drill/blob/e02aa596/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetImpl.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetImpl.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetImpl.java
index a2083d3..778504e 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetImpl.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetImpl.java
@@ -1897,7 +1897,17 @@ class DrillResultSetImpl extends AvaticaResultSet implements DrillResultSet {
@Override
protected DrillResultSetImpl execute() throws SQLException{
- client.runQuery(QueryType.SQL, this.prepareResult.getSql(), resultsListener);
+ final DrillPrepareResult drillPrepareResult = ((DrillPrepareResult)prepareResult);
+ /**
+ * {@link DrillPrepareResult} is created both for normal queries and prepared queries.
+ * If the prepared statement exists submit the query as prepared statement, otherwise
+ * regular submission.
+ */
+ if (drillPrepareResult.getPreparedStatement() != null) {
+ client.executePreparedStatement(drillPrepareResult.getPreparedStatement().getServerHandle(), resultsListener);
+ } else {
+ client.runQuery(QueryType.SQL, this.prepareResult.getSql(), resultsListener);
+ }
connection.getDriver().handler.onStatementExecute(statement, null);
super.execute();
http://git-wip-us.apache.org/repos/asf/drill/blob/e02aa596/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetMetaDataImpl.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetMetaDataImpl.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetMetaDataImpl.java
index 79a3455..9847555 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetMetaDataImpl.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillResultSetMetaDataImpl.java
@@ -51,7 +51,8 @@ public class DrillResultSetMetaDataImpl extends AvaticaResultSetMetaData {
SQLException {
// Statement.isClosed() call is to avoid exception from getResultSet().
if (statement.isClosed()
- || statement.getResultSet().isClosed()) {
+ || (statement.getResultSet() != null // result set doesn't exist for prepared statement cases
+ && statement.getResultSet().isClosed())) {
throw new AlreadyClosedSqlException(
"ResultSetMetaData's ResultSet is already closed." );
}
http://git-wip-us.apache.org/repos/asf/drill/blob/e02aa596/exec/jdbc/src/test/java/org/apache/drill/jdbc/PreparedStatementTest.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/test/java/org/apache/drill/jdbc/PreparedStatementTest.java b/exec/jdbc/src/test/java/org/apache/drill/jdbc/PreparedStatementTest.java
index bea309f..225c690 100644
--- a/exec/jdbc/src/test/java/org/apache/drill/jdbc/PreparedStatementTest.java
+++ b/exec/jdbc/src/test/java/org/apache/drill/jdbc/PreparedStatementTest.java
@@ -17,24 +17,41 @@
*/
package org.apache.drill.jdbc;
+import static java.sql.ResultSetMetaData.columnNoNulls;
+import static java.sql.Types.BIGINT;
+import static java.sql.Types.DATE;
+import static java.sql.Types.DECIMAL;
+import static java.sql.Types.INTEGER;
+import static java.sql.Types.TIMESTAMP;
+import static java.sql.Types.VARCHAR;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.hamcrest.CoreMatchers.*;
+import org.apache.drill.exec.planner.physical.PlannerSettings;
+import org.apache.drill.exec.store.ischema.InfoSchemaConstants;
import org.hamcrest.Matcher;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
-import org.apache.drill.jdbc.Driver;
+import com.google.common.collect.ImmutableList;
+
+import java.math.BigDecimal;
import java.sql.Clob;
import java.sql.Connection;
+import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.util.List;
/**
@@ -56,74 +73,165 @@ public class PreparedStatementTest extends JdbcTestBase {
public static void setUpConnection() throws SQLException {
Driver.load();
connection = DriverManager.getConnection( "jdbc:drill:zk=local" );
+ try(Statement stmt = connection.createStatement()) {
+ stmt.execute(String.format("alter session set `%s` = true", PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY));
+ }
}
@AfterClass
public static void tearDownConnection() throws SQLException {
+ if (connection != null) {
+ try (Statement stmt = connection.createStatement()) {
+ stmt.execute(String.format("alter session set `%s` = false", PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY));
+ }
+ }
connection.close();
}
-
//////////
// Basic querying-works test:
/** Tests that basic executeQuery() (with query statement) works. */
@Test
public void testExecuteQueryBasicCaseWorks() throws SQLException {
- PreparedStatement stmt = connection.prepareStatement( "VALUES 11" );
- ResultSet rs = stmt.executeQuery();
- assertThat( "Unexpected column count",
- rs.getMetaData().getColumnCount(), equalTo( 1 ) );
- assertTrue( "No expected first row", rs.next() );
- assertThat( rs.getInt( 1 ), equalTo( 11 ) );
- assertFalse( "Unexpected second row", rs.next() );
+ try (PreparedStatement stmt = connection.prepareStatement( "VALUES 11" )) {
+ try(ResultSet rs = stmt.executeQuery()) {
+ assertThat("Unexpected column count",
+ rs.getMetaData().getColumnCount(), equalTo(1)
+ );
+ assertTrue("No expected first row", rs.next());
+ assertThat(rs.getInt(1), equalTo(11));
+ assertFalse("Unexpected second row", rs.next());
+ }
+ }
}
+ @Test
+ public void testQueryMetadataInPreparedStatement() throws SQLException {
+ try(PreparedStatement stmt = connection.prepareStatement(
+ "SELECT " +
+ "cast(1 as INTEGER ) as int_field, " +
+ "cast(12384729 as BIGINT ) as bigint_field, " +
+ "'varchar_value' as varchar_field, " +
+ "timestamp '2008-2-23 10:00:20.123' as ts_field, " +
+ "date '2008-2-23' as date_field, " +
+ "cast('99999912399.4567' as decimal(18, 5)) as decimal_field" +
+ " FROM sys.version")) {
- //////////
- // Parameters-not-implemented tests:
+ List<ExpectedColumnResult> exp = ImmutableList.of(
+ new ExpectedColumnResult("int_field", INTEGER, columnNoNulls, 0, 0, true, Integer.class.getName()),
+ new ExpectedColumnResult("bigint_field", BIGINT, columnNoNulls, 0, 0, true, Long.class.getName()),
+ new ExpectedColumnResult("varchar_field", VARCHAR, columnNoNulls, 65536, 0, false, String.class.getName()),
+ new ExpectedColumnResult("ts_field", TIMESTAMP, columnNoNulls, 0, 0, false, Timestamp.class.getName()),
+ new ExpectedColumnResult("date_field", DATE, columnNoNulls, 0, 0, false, Date.class.getName()),
+ new ExpectedColumnResult("decimal_field", DECIMAL, columnNoNulls, 18, 5, true, BigDecimal.class.getName())
+ );
- /** Tests that basic case of trying to set parameter says not supported. */
- @Test( expected = SQLFeatureNotSupportedException.class )
- public void testParamSettingSaysUnsupported() throws SQLException {
- PreparedStatement prepStmt = connection.prepareStatement( "VALUES ?, ?" );
- try {
- prepStmt.setInt( 0, 123456789 );
+ ResultSetMetaData prepareMetadata = stmt.getMetaData();
+ verifyMetadata(prepareMetadata, exp);
+
+ try (ResultSet rs = stmt.executeQuery()) {
+ ResultSetMetaData executeMetadata = rs.getMetaData();
+ verifyMetadata(executeMetadata, exp);
+
+ assertTrue("No expected first row", rs.next());
+ assertThat(rs.getInt(1), equalTo(1));
+ assertThat(rs.getLong(2), equalTo(12384729L));
+ assertThat(rs.getString(3), equalTo("varchar_value"));
+ assertThat(rs.getTimestamp(4), equalTo(Timestamp.valueOf("2008-2-23 10:00:20.123")));
+ assertThat(rs.getDate(5), equalTo(Date.valueOf("2008-2-23")));
+ assertThat(rs.getBigDecimal(6), equalTo(new BigDecimal("99999912399.45670")));
+ assertFalse("Unexpected second row", rs.next());
+ }
}
- catch ( final SQLFeatureNotSupportedException e ) {
- assertThat(
- "Check whether params.-unsupported wording changed or checks changed.",
- e.toString(), PARAMETERS_NOT_SUPPORTED_MSG_MATCHER );
- throw e;
+ }
+
+ private static void verifyMetadata(ResultSetMetaData act, List<ExpectedColumnResult> exp) throws SQLException {
+ assertEquals(exp.size(), act.getColumnCount());
+ for(ExpectedColumnResult e : exp) {
+ boolean found = false;
+ for(int i=1; i<=act.getColumnCount(); i++) {
+ found = e.isEqualsTo(act, i);
+ if (found) {
+ break;
+ }
+ }
+ assertTrue("Failed to find the expected column metadata: " + e, found);
}
}
- /** Tests that "not supported" has priority over "bad index" check. */
- @Test( expected = SQLFeatureNotSupportedException.class )
- public void testParamSettingWithImpossibleIndexSaysUnsupported() throws SQLException {
- PreparedStatement prepStmt = connection.prepareStatement( "VALUES ?, ?" );
- try {
- prepStmt.setString( -1, "some value" );
+ private static class ExpectedColumnResult {
+ final String columnName;
+ final int type;
+ final int nullable;
+ final int precision;
+ final int scale;
+ final boolean signed;
+ final String className;
+
+ ExpectedColumnResult(String columnName, int type, int nullable, int precision, int scale, boolean signed,
+ String className) {
+ this.columnName = columnName;
+ this.type = type;
+ this.nullable = nullable;
+ this.precision = precision;
+ this.scale = scale;
+ this.signed = signed;
+ this.className = className;
}
- catch ( final SQLFeatureNotSupportedException e ) {
- assertThat(
- "Check whether params.-unsupported wording changed or checks changed.",
- e.toString(), PARAMETERS_NOT_SUPPORTED_MSG_MATCHER );
- throw e;
+
+ boolean isEqualsTo(ResultSetMetaData metadata, int colNum) throws SQLException {
+ return
+ metadata.getCatalogName(colNum).equals(InfoSchemaConstants.IS_CATALOG_NAME) &&
+ metadata.getSchemaName(colNum).isEmpty() &&
+ metadata.getTableName(colNum).isEmpty() &&
+ metadata.getColumnName(colNum).equals(columnName) &&
+ metadata.getColumnLabel(colNum).equals(columnName) &&
+ metadata.getColumnType(colNum) == type &&
+ metadata.isNullable(colNum) == nullable &&
+ // There is an existing bug where query results doesn't contain the precision for VARCHAR field.
+ //metadata.getPrecision(colNum) == precision &&
+ metadata.getScale(colNum) == scale &&
+ metadata.isSigned(colNum) == signed &&
+ metadata.getColumnDisplaySize(colNum) == 10 &&
+ metadata.getColumnClassName(colNum).equals(className) &&
+ metadata.isSearchable(colNum) &&
+ metadata.isAutoIncrement(colNum) == false &&
+ metadata.isCaseSensitive(colNum) == false &&
+ metadata.isReadOnly(colNum) &&
+ metadata.isWritable(colNum) == false &&
+ metadata.isDefinitelyWritable(colNum) == false &&
+ metadata.isCurrency(colNum) == false;
+ }
+
+ @Override
+ public String toString() {
+ return "ExpectedColumnResult[" +
+ "columnName='" + columnName + '\'' +
+ ", type='" + type + '\'' +
+ ", nullable=" + nullable +
+ ", precision=" + precision +
+ ", scale=" + scale +
+ ", signed=" + signed +
+ ", className='" + className + '\'' +
+ ']';
}
}
- /** Tests that "not supported" has priority over "bad index" check. */
- @Test( expected = SQLFeatureNotSupportedException.class )
- public void testParamSettingWithInconsistentIndexSaysUnsupported() throws SQLException {
- PreparedStatement prepStmt = connection.prepareStatement( "VALUES ?, ?" );
+ //////////
+ // Parameters-not-implemented tests:
+
+ /** Tests that basic case of trying to create a prepare statement with parameters. */
+ @Test( expected = SQLException.class )
+ public void testSqlQueryWithParamNotSupported() throws SQLException {
+
try {
- prepStmt.setBytes( 4, null );
+ connection.prepareStatement( "VALUES ?, ?" );
}
- catch ( final SQLFeatureNotSupportedException e ) {
+ catch ( final SQLException e ) {
assertThat(
"Check whether params.-unsupported wording changed or checks changed.",
- e.toString(), PARAMETERS_NOT_SUPPORTED_MSG_MATCHER );
+ e.toString(), containsString("Illegal use of dynamic parameter") );
throw e;
}
}
@@ -132,15 +240,16 @@ public class PreparedStatementTest extends JdbcTestBase {
* check. */
@Test( expected = SQLFeatureNotSupportedException.class )
public void testParamSettingWhenNoParametersIndexSaysUnsupported() throws SQLException {
- PreparedStatement prepStmt = connection.prepareStatement( "VALUES 1" );
- try {
- prepStmt.setBytes( 4, null );
- }
- catch ( final SQLFeatureNotSupportedException e ) {
- assertThat(
- "Check whether params.-unsupported wording changed or checks changed.",
- e.toString(), PARAMETERS_NOT_SUPPORTED_MSG_MATCHER );
- throw e;
+ try(PreparedStatement prepStmt = connection.prepareStatement( "VALUES 1" )) {
+ try {
+ prepStmt.setBytes(4, null);
+ } catch (final SQLFeatureNotSupportedException e) {
+ assertThat(
+ "Check whether params.-unsupported wording changed or checks changed.",
+ e.toString(), PARAMETERS_NOT_SUPPORTED_MSG_MATCHER
+ );
+ throw e;
+ }
}
}
@@ -148,15 +257,16 @@ public class PreparedStatementTest extends JdbcTestBase {
* check. */
@Test( expected = SQLFeatureNotSupportedException.class )
public void testParamSettingWhenUnsupportedTypeSaysUnsupported() throws SQLException {
- PreparedStatement prepStmt = connection.prepareStatement( "VALUES 1" );
- try {
- prepStmt.setClob( 2, (Clob) null );
- }
- catch ( final SQLFeatureNotSupportedException e ) {
- assertThat(
- "Check whether params.-unsupported wording changed or checks changed.",
- e.toString(), PARAMETERS_NOT_SUPPORTED_MSG_MATCHER );
- throw e;
+ try(PreparedStatement prepStmt = connection.prepareStatement( "VALUES 1" )) {
+ try {
+ prepStmt.setClob(2, (Clob) null);
+ } catch (final SQLFeatureNotSupportedException e) {
+ assertThat(
+ "Check whether params.-unsupported wording changed or checks changed.",
+ e.toString(), PARAMETERS_NOT_SUPPORTED_MSG_MATCHER
+ );
+ throw e;
+ }
}
}
http://git-wip-us.apache.org/repos/asf/drill/blob/e02aa596/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/Drill2769UnsupportedReportsUseSqlExceptionTest.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/Drill2769UnsupportedReportsUseSqlExceptionTest.java b/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/Drill2769UnsupportedReportsUseSqlExceptionTest.java
index a673d87..8bc03aa 100644
--- a/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/Drill2769UnsupportedReportsUseSqlExceptionTest.java
+++ b/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/Drill2769UnsupportedReportsUseSqlExceptionTest.java
@@ -398,7 +398,7 @@ public class Drill2769UnsupportedReportsUseSqlExceptionTest extends JdbcTestBase
}
protected PreparedStatement getJdbcObject() throws SQLException {
- return factoryConnection.prepareStatement(null);
+ return factoryConnection.prepareStatement("VALUES 1");
}
} // class PlainStatementChecker