Skip to content

Commit

Permalink
DRILL-3566: Fix: PreparedStatement.executeQuery() got ClassCastExcept…
Browse files Browse the repository at this point in the history
…ion.

Main:
Restored DrillResultSetImpl(...)'s statement parameter from overly
restrictive DrillStatementImpl to AvaticaStatement and removed caller
cast that was throwing.  (Relatedly, adjusted getStatement() and moved
internal casting from statement to connection.)

Added basic test of querying via PreparedStatement.  [PreparedStatementTest]
Added some case test of statement-creation methods.  [ConnectionTest]

Removed now-unneeded DrillPrepareResult cast.
Eliminated redundant getConnection() and getClient calls, intermediate variables, etc.
Fixed comment error.

this closes #143
  • Loading branch information
dsbos authored and adeneche committed Sep 8, 2015
1 parent 7a864a4 commit 6db7c05
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 27 deletions.
Expand Up @@ -103,9 +103,7 @@ public DrillResultSetImpl newResultSet(AvaticaStatement statement,
TimeZone timeZone) {
final ResultSetMetaData metaData =
newResultSetMetaData(statement, prepareResult.getColumnList());
return new DrillResultSetImpl( (DrillStatementImpl) statement,
(DrillPrepareResult) prepareResult,
metaData, timeZone);
return new DrillResultSetImpl(statement, prepareResult, metaData, timeZone);
}

@Override
Expand Down
Expand Up @@ -30,7 +30,8 @@
* Implementation of {@link java.sql.PreparedStatement} for Drill.
*
* <p>
* This class has sub-classes which implement JDBC 3.0 and JDBC 4.0 APIs; it is instantiated using
* This class has sub-classes which implement JDBC 3.0 and JDBC 4.0 APIs; it is
* instantiated using
* {@link net.hydromatic.avatica.AvaticaFactory#newPreparedStatement}.
* </p>
*/
Expand Down
Expand Up @@ -43,6 +43,7 @@

import net.hydromatic.avatica.AvaticaPrepareResult;
import net.hydromatic.avatica.AvaticaResultSet;
import net.hydromatic.avatica.AvaticaStatement;

import org.apache.drill.common.exceptions.UserException;
import org.apache.drill.exec.ExecConstants;
Expand Down Expand Up @@ -75,7 +76,7 @@ class DrillResultSetImpl extends AvaticaResultSet implements DrillResultSet {
private static final org.slf4j.Logger logger =
org.slf4j.LoggerFactory.getLogger(DrillResultSetImpl.class);

private final DrillStatementImpl statement;
private final DrillConnectionImpl connection;

SchemaChangeListener changeListener;
final ResultsListener resultsListener;
Expand All @@ -87,18 +88,16 @@ class DrillResultSetImpl extends AvaticaResultSet implements DrillResultSet {
boolean hasPendingCancelationNotification;


DrillResultSetImpl(DrillStatementImpl statement, AvaticaPrepareResult prepareResult,
DrillResultSetImpl(AvaticaStatement statement, AvaticaPrepareResult prepareResult,
ResultSetMetaData resultSetMetaData, TimeZone timeZone) {
super(statement, prepareResult, resultSetMetaData, timeZone);
this.statement = statement;
connection = (DrillConnectionImpl) statement.getConnection();
client = connection.getClient();
final int batchQueueThrottlingThreshold =
this.getStatement().getConnection().getClient().getConfig().getInt(
client.getConfig().getInt(
ExecConstants.JDBC_BATCH_QUEUE_THROTTLING_THRESHOLD );
resultsListener = new ResultsListener( batchQueueThrottlingThreshold );
DrillConnection c = (DrillConnection) statement.getConnection();
DrillClient client = c.getClient();
resultsListener = new ResultsListener(batchQueueThrottlingThreshold);
batchLoader = new RecordBatchLoader(client.getAllocator());
this.client = client;
cursor = new DrillCursor(this);
}

Expand All @@ -107,7 +106,7 @@ class DrillResultSetImpl extends AvaticaResultSet implements DrillResultSet {
* ResultSet is closed.
*
* @throws ExecutionCanceledSqlException if ResultSet is closed because of
* cancelation and no QueryCanceledSqlException had been thrown yet
* cancelation and no QueryCanceledSqlException has been thrown yet
* for this ResultSet
* @throws AlreadyClosedSqlException if ResultSet is closed
* @throws SQLException if error in calling {@link #isClosed()}
Expand Down Expand Up @@ -850,9 +849,9 @@ public void moveToCurrentRow() throws SQLException {
}

@Override
public DrillStatementImpl getStatement() {
// Note: No already-closed exception for close().
return statement;
public AvaticaStatement getStatement() {
// Note: No already-closed exception for getStatement().
return super.getStatement();
}

@Override
Expand Down Expand Up @@ -1334,10 +1333,7 @@ public String getQueryId() throws SQLException {

@Override
protected DrillResultSetImpl execute() throws SQLException{
DrillConnectionImpl connection = (DrillConnectionImpl) statement.getConnection();

connection.getClient().runQuery(QueryType.SQL, this.prepareResult.getSql(),
resultsListener);
client.runQuery(QueryType.SQL, this.prepareResult.getSql(), resultsListener);
connection.getDriver().handler.onStatementExecute(statement, null);

super.execute();
Expand Down
203 changes: 202 additions & 1 deletion exec/jdbc/src/test/java/org/apache/drill/jdbc/ConnectionTest.java
Expand Up @@ -21,15 +21,20 @@

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertTrue;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

Expand All @@ -44,6 +49,7 @@ public class ConnectionTest extends JdbcTestBase {

private static ExecutorService executor;


@BeforeClass
public static void setUpConnection() throws SQLException {
// (Note: Can't use JdbcTest's connect(...) because JdbcTest closes
Expand All @@ -60,6 +66,201 @@ public static void tearDownConnection() throws SQLException {
executor.shutdown();
}

private static void emitSupportExceptionWarning() {
System.err.println(
"Note: Still throwing older-Avatica UnsupportedOperationException"
+ " instead of less-noncompliant SQLFeatureNotSupportedException" );
}


////////////////////////////////////////
// Basic tests of statement creation methods (not necessarily executing
// statements):

//////////
// Simplest cases of createStatement, prepareStatement, prepareCall:

@Test
public void testCreateStatementBasicCaseWorks() throws SQLException {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery( "VALUES 1" );
assertTrue( rs.next() );
}

@Test
public void testPrepareStatementBasicCaseWorks() throws SQLException {
PreparedStatement stmt = connection.prepareStatement( "VALUES 1" );
ResultSet rs = stmt.executeQuery();
assertTrue( rs.next() );
}

@Test( expected = SQLFeatureNotSupportedException.class )
public void testPrepareCallThrows() throws SQLException {
try {
connection.prepareCall( "VALUES 1" );
}
catch ( UnsupportedOperationException e) {
// TODO(DRILL-2769): Purge this mapping when right exception is thrown.
emitSupportExceptionWarning();
throw new SQLFeatureNotSupportedException(
"Note: Still throwing UnsupportedOperationException ", e );
}
}

//////////
// createStatement(int, int):

@Test
public void testCreateStatement_overload2_supportedCase_returns() throws SQLException {
connection.createStatement( ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY );
}

@Test( expected = SQLFeatureNotSupportedException.class )
@Ignore( "until unsupported characteristics are rejected" )
public void testCreateStatement_overload2_unsupportedType1_throws() throws SQLException {
connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY );
}

@Test( expected = SQLFeatureNotSupportedException.class )
@Ignore( "until unsupported characteristics are rejected" )
public void testCreateStatement_overload2_unsupportedType2_throws() throws SQLException {
connection.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_READ_ONLY);
}

@Test( expected = SQLFeatureNotSupportedException.class )
@Ignore( "until unsupported characteristics are rejected" )
public void testCreateStatement_overload2_unsupportedConcurrency_throws() throws SQLException {
connection.createStatement( ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE );
}


//////////
// prepareStatement(String, int, int, int):

@Test
public void testPrepareStatement_overload2_supportedCase_returns() throws SQLException {
connection.prepareStatement( "VALUES 1",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY );
}

@Test( expected = SQLFeatureNotSupportedException.class )
@Ignore( "until unsupported characteristics are rejected" )
public void testPrepareStatement_overload2_unsupportedType1_throws() throws SQLException {
connection.prepareStatement( "VALUES 1",
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY );
}

@Test( expected = SQLFeatureNotSupportedException.class )
@Ignore( "until unsupported characteristics are rejected" )
public void testPrepareStatement_overload2_unsupportedType2_throws() throws SQLException {
connection.prepareStatement( "VALUES 1",
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_READ_ONLY );
}

@Test( expected = SQLFeatureNotSupportedException.class )
@Ignore( "until unsupported characteristics are rejected" )
public void testPrepareStatement_overload2_unsupportedConcurrency_throws() throws SQLException {
connection.prepareStatement( "VALUES 1",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE );
}


//////////
// createStatement(int, int, int) (case not covered with
// createStatement(int, int)):


@Test( expected = SQLFeatureNotSupportedException.class )
@Ignore( "until unsupported characteristics are rejected" )
public void testCreateStatement_overload3_unsupportedHoldability_throws() throws SQLException {
connection.createStatement( ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_AT_COMMIT);
}


//////////
// prepareStatement(int, int, int) (case not covered with
// prepareStatement(int, int)):

@Test( expected = SQLFeatureNotSupportedException.class )
@Ignore( "until unsupported characteristics are rejected" )
public void testPrepareStatement_overload3_unsupportedHoldability_throws() throws SQLException {
connection.prepareStatement( "VALUES 1",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_AT_COMMIT );
}

//////////
// prepareCall(String, int, int, int):

@Test( expected = SQLFeatureNotSupportedException.class )
public void testCreateCall_overload3_throws() throws SQLException {
try {
connection.prepareCall( "VALUES 1",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY,
ResultSet.HOLD_CURSORS_OVER_COMMIT );
}
catch ( UnsupportedOperationException e) {
// TODO(DRILL-2769): Purge this mapping when right exception is thrown.
emitSupportExceptionWarning();
throw new SQLFeatureNotSupportedException(
"Note: Still throwing UnsupportedOperationException ", e );
}
}

//////////
// remaining prepareStatement(...):

@Test( expected = SQLFeatureNotSupportedException.class )
public void testPrepareStatement_overload4_throws() throws SQLException {
try {
connection.prepareStatement( "VALUES 1", Statement.RETURN_GENERATED_KEYS );
}
catch ( UnsupportedOperationException e) {
// TODO(DRILL-2769): Purge this mapping when right exception is thrown.
emitSupportExceptionWarning();
throw new SQLFeatureNotSupportedException(
"Note: Still throwing UnsupportedOperationException ", e );
}
}

@Test( expected = SQLFeatureNotSupportedException.class )
public void testPrepareStatement_overload5_throws() throws SQLException {
try {
connection.prepareStatement( "VALUES 1", new int[] { 1 } );
}
catch ( UnsupportedOperationException e) {
// TODO(DRILL-2769): Purge this mapping when right exception is thrown.
emitSupportExceptionWarning();
throw new SQLFeatureNotSupportedException(
"Note: Still throwing UnsupportedOperationException ", e );
}
}

@Test( expected = SQLFeatureNotSupportedException.class )
public void testPrepareStatement_overload6_throws() throws SQLException {
try {
connection.prepareStatement( "VALUES 1 AS colA", new String[] { "colA" } );
}
catch ( UnsupportedOperationException e) {
// TODO(DRILL-2769): Purge this mapping when right exception is thrown.
emitSupportExceptionWarning();
throw new SQLFeatureNotSupportedException(
"Note: Still throwing UnsupportedOperationException ", e );
}
}


////////////////////////////////////////
// Network timeout methods:
Expand Down
Expand Up @@ -43,7 +43,8 @@
// (e.g., the reusing of connections, the automatic interception of test
// failures and resetting of connections, etc.).
public class JdbcTestBase extends ExecTest {
static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(JdbcTestBase.class);
@SuppressWarnings("unused")
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(JdbcTestBase.class);

@Rule
public final TestRule watcher = new TestWatcher() {
Expand Down

0 comments on commit 6db7c05

Please sign in to comment.