DRILL-2447: Add already-closed checks to remaining ResultSet methods. Extended coverage from just selected methods to all methods. Added wrapper methods checking state before delegating. (Couldn't implement at just a few choke points because Avatica makes them private and doesn't provide hooks.) [DrillResultSetImpl]
Defined DrillResultSet.getQueryId() to throw SQLException as other methods do. [DrillResultSet] Re-enabled ResultSet test methods. (Also re-enabled other test methods that pass now with DRILL-2782 changes. [Drill2489CallsAfterCloseThrowExceptionsTest] Project: http://git-wip-us.apache.org/repos/asf/drill/repo Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/4dc476d5 Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/4dc476d5 Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/4dc476d5 Branch: refs/heads/master Commit: 4dc476d540bc4d091105f4b017732b70e59d26e3 Parents: 064af80 Author: dbarclay <dbarc...@maprtech.com> Authored: Fri Apr 24 16:48:55 2015 -0700 Committer: Hanifi Gunes <hgu...@maprtech.com> Committed: Wed Jun 24 14:40:45 2015 -0700 ---------------------------------------------------------------------- .../org/apache/drill/jdbc/DrillResultSet.java | 22 +- .../drill/jdbc/impl/DrillResultSetImpl.java | 1257 +++++++++++++++++- ...l2489CallsAfterCloseThrowExceptionsTest.java | 239 +--- 3 files changed, 1244 insertions(+), 274 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/drill/blob/4dc476d5/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillResultSet.java ---------------------------------------------------------------------- diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillResultSet.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillResultSet.java index e0a7763..858fd61 100644 --- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillResultSet.java +++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillResultSet.java @@ -17,27 +17,9 @@ */ package org.apache.drill.jdbc; -import java.io.InputStream; -import java.io.Reader; import java.math.BigDecimal; -import java.net.URL; -import java.sql.Array; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Date; -import java.sql.NClob; -import java.sql.Ref; import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.RowId; import java.sql.SQLException; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.Calendar; -import java.util.Map; /** @@ -49,8 +31,10 @@ public interface DrillResultSet extends ResultSet { /** * Gets the ID of the associated query (the query whose results this ResultSet * presents). + * + * @throws SQLException if this method is called on a closed result set */ - String getQueryId(); + String getQueryId() throws SQLException; /** * {@inheritDoc} http://git-wip-us.apache.org/repos/asf/drill/blob/4dc476d5/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 31593bf..1b37dc1 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 @@ -17,18 +17,31 @@ */ package org.apache.drill.jdbc.impl; +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.NClob; +import java.sql.Ref; import java.sql.ResultSetMetaData; +import java.sql.RowId; import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; import java.util.TimeZone; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; 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; @@ -72,6 +85,7 @@ class DrillResultSetImpl extends AvaticaResultSet implements DrillResultSet { final DrillCursor cursor; boolean hasPendingCancelationNotification; + DrillResultSetImpl(DrillStatementImpl statement, AvaticaPrepareResult prepareResult, ResultSetMetaData resultSetMetaData, TimeZone timeZone) { super(statement, prepareResult, resultSetMetaData, timeZone); @@ -87,10 +101,6 @@ class DrillResultSetImpl extends AvaticaResultSet implements DrillResultSet { cursor = new DrillCursor(this); } - public DrillStatementImpl getStatement() { - return statement; - } - /** * Throws AlreadyClosedSqlException or QueryCanceledSqlException if this * ResultSet is closed. @@ -115,13 +125,6 @@ class DrillResultSetImpl extends AvaticaResultSet implements DrillResultSet { } @Override - public ResultSetMetaData getMetaData() throws SQLException { - checkNotClosed(); - return super.getMetaData(); - } - - - @Override protected void cancel() { hasPendingCancelationNotification = true; cleanup(); @@ -136,6 +139,10 @@ class DrillResultSetImpl extends AvaticaResultSet implements DrillResultSet { batchLoader.clear(); } + //////////////////////////////////////// + // ResultSet-defined methods (in same order as in ResultSet): + + // (Not delegated.) @Override public boolean next() throws SQLException { checkNotClosed(); @@ -157,46 +164,1210 @@ class DrillResultSetImpl extends AvaticaResultSet implements DrillResultSet { } @Override - protected DrillResultSetImpl execute() throws SQLException{ - DrillConnectionImpl connection = (DrillConnectionImpl) statement.getConnection(); + public void close() { + // Note: No already-closed exception for close(). + super.close(); + } - connection.getClient().runQuery(QueryType.SQL, this.prepareResult.getSql(), - resultsListener); - connection.getDriver().handler.onStatementExecute(statement, null); + @Override + public boolean wasNull() throws SQLException { + checkNotClosed(); + return super.wasNull(); + } - super.execute(); + // Methods for accessing results by column index + @Override + public String getString( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getString( columnIndex ); + } - // don't return with metadata until we've achieved at least one return message. - try { - // TODO: Revisit: Why reaching directly into ResultsListener rather than - // calling some wait method? - resultsListener.latch.await(); - } 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(); + @Override + public boolean getBoolean( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getBoolean( columnIndex ); + } - // Not normally expected--Drill doesn't interrupt in this area (right?)-- - // but JDBC client certainly could. - throw new SQLException( "Interrupted", e ); - } + @Override + public byte getByte( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getByte( columnIndex ); + } - // Read first (schema-only) batch to initialize result-set metadata from - // (initial) schema before Statement.execute...(...) returns result set: - cursor.loadInitialSchema(); + @Override + public short getShort( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getShort( columnIndex ); + } - return this; + @Override + public int getInt( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getInt( columnIndex ); } - public String getQueryId() { - if (resultsListener.getQueryId() != null) { - return QueryIdHelper.getQueryId(resultsListener.getQueryId()); - } else { - return null; - } + @Override + public long getLong( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getLong( columnIndex ); + } + + @Override + public float getFloat( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getFloat( columnIndex ); + } + + @Override + public double getDouble( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getDouble( columnIndex ); + } + + @Override + public BigDecimal getBigDecimal( int columnIndex, int scale ) throws SQLException { + checkNotClosed(); + return super.getBigDecimal( columnIndex, scale ); + } + + @Override + public byte[] getBytes( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getBytes( columnIndex ); + } + + @Override + public Date getDate( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getDate( columnIndex ); + } + + @Override + public Time getTime( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getTime( columnIndex ); + } + + @Override + public Timestamp getTimestamp( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getTimestamp( columnIndex ); + } + + @Override + public InputStream getAsciiStream( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getAsciiStream( columnIndex ); + } + + @Override + public InputStream getUnicodeStream( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getUnicodeStream( columnIndex ); + } + + @Override + public InputStream getBinaryStream( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getBinaryStream( columnIndex ); + } + + // Methods for accessing results by column label + @Override + public String getString( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getString( columnLabel ); + } + + @Override + public boolean getBoolean( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getBoolean( columnLabel ); + } + + @Override + public byte getByte( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getByte( columnLabel ); + } + + @Override + public short getShort( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getShort( columnLabel ); + } + + @Override + public int getInt( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getInt( columnLabel ); + } + + @Override + public long getLong( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getLong( columnLabel ); + } + + @Override + public float getFloat( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getFloat( columnLabel ); + } + + @Override + public double getDouble( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getDouble( columnLabel ); + } + + @Override + public BigDecimal getBigDecimal( String columnLabel, int scale ) throws SQLException { + checkNotClosed(); + return super.getBigDecimal( columnLabel, scale ); + } + + @Override + public byte[] getBytes( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getBytes( columnLabel ); + } + + @Override + public Date getDate( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getDate( columnLabel ); + } + + @Override + public Time getTime( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getTime( columnLabel ); + } + + @Override + public Timestamp getTimestamp( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getTimestamp( columnLabel ); + } + + @Override + public InputStream getAsciiStream( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getAsciiStream( columnLabel ); + } + + @Override + public InputStream getUnicodeStream( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getUnicodeStream( columnLabel ); + } + + @Override + public InputStream getBinaryStream( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getBinaryStream( columnLabel ); + } + + // Advanced features: + @Override + public SQLWarning getWarnings() throws SQLException { + checkNotClosed(); + return super.getWarnings(); + } + + @Override + public void clearWarnings() throws SQLException { + checkNotClosed(); + super.clearWarnings(); + } + + @Override + public String getCursorName() throws SQLException { + checkNotClosed(); + return super.getCursorName(); + } + + // (Not delegated.) + @Override + public ResultSetMetaData getMetaData() throws SQLException { + checkNotClosed(); + return super.getMetaData(); + } + + @Override + public Object getObject( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getObject( columnIndex ); + } + + @Override + public Object getObject( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getObject( columnLabel ); + } + + //---------------------------------------------------------------- + @Override + public int findColumn( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.findColumn( columnLabel ); + } + + //--------------------------JDBC 2.0----------------------------------- + //--------------------------------------------------------------------- + // Getters and Setters + //--------------------------------------------------------------------- + @Override + public Reader getCharacterStream( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getCharacterStream( columnIndex ); + } + + @Override + public Reader getCharacterStream( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getCharacterStream( columnLabel ); + } + + @Override + public BigDecimal getBigDecimal( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getBigDecimal( columnIndex ); + } + + @Override + public BigDecimal getBigDecimal( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getBigDecimal( columnLabel ); + } + + //--------------------------------------------------------------------- + // Traversal/Positioning + //--------------------------------------------------------------------- + @Override + public boolean isBeforeFirst() throws SQLException { + checkNotClosed(); + return super.isBeforeFirst(); + } + + @Override + public boolean isAfterLast() throws SQLException { + checkNotClosed(); + return super.isAfterLast(); + } + + @Override + public boolean isFirst() throws SQLException { + checkNotClosed(); + return super.isFirst(); + } + + @Override + public boolean isLast() throws SQLException { + checkNotClosed(); + return super.isLast(); + } + + @Override + public void beforeFirst() throws SQLException { + checkNotClosed(); + super.beforeFirst(); + } + + @Override + public void afterLast() throws SQLException { + checkNotClosed(); + super.afterLast(); + } + + @Override + public boolean first() throws SQLException { + checkNotClosed(); + return super.first(); + } + + @Override + public boolean last() throws SQLException { + checkNotClosed(); + return super.last(); + } + + @Override + public int getRow() throws SQLException { + checkNotClosed(); + return super.getRow(); + } + + @Override + public boolean absolute( int row ) throws SQLException { + checkNotClosed(); + return super.absolute( row ); + } + + @Override + public boolean relative( int rows ) throws SQLException { + checkNotClosed(); + return super.relative( rows ); } + @Override + public boolean previous() throws SQLException { + checkNotClosed(); + return super.previous(); + } + + //--------------------------------------------------------------------- + // Properties + //--------------------------------------------------------------------- + + @Override + public void setFetchDirection( int direction ) throws SQLException { + checkNotClosed(); + super.setFetchDirection( direction ); + } + + @Override + public int getFetchDirection() throws SQLException { + checkNotClosed(); + return super.getFetchDirection(); + } + + @Override + public void setFetchSize( int rows ) throws SQLException { + checkNotClosed(); + super.setFetchSize( rows ); + } + + @Override + public int getFetchSize() throws SQLException { + checkNotClosed(); + return super.getFetchSize(); + } + + @Override + public int getType() throws SQLException { + checkNotClosed(); + return super.getType(); + } + + @Override + public int getConcurrency() throws SQLException { + checkNotClosed(); + return super.getConcurrency(); + } + + //--------------------------------------------------------------------- + // Updates + //--------------------------------------------------------------------- + @Override + public boolean rowUpdated() throws SQLException { + checkNotClosed(); + return super.rowUpdated(); + } + + @Override + public boolean rowInserted() throws SQLException { + checkNotClosed(); + return super.rowInserted(); + } + + @Override + public boolean rowDeleted() throws SQLException { + checkNotClosed(); + return super.rowDeleted(); + } + + @Override + public void updateNull( int columnIndex ) throws SQLException { + checkNotClosed(); + super.updateNull( columnIndex ); + } + + @Override + public void updateBoolean( int columnIndex, boolean x ) throws SQLException { + checkNotClosed(); + super.updateBoolean( columnIndex, x ); + } + + @Override + public void updateByte( int columnIndex, byte x ) throws SQLException { + checkNotClosed(); + super.updateByte( columnIndex, x ); + } + + @Override + public void updateShort( int columnIndex, short x ) throws SQLException { + checkNotClosed(); + super.updateShort( columnIndex, x ); + } + + @Override + public void updateInt( int columnIndex, int x ) throws SQLException { + checkNotClosed(); + super.updateInt( columnIndex, x ); + } + + @Override + public void updateLong( int columnIndex, long x ) throws SQLException { + checkNotClosed(); + super.updateLong( columnIndex, x ); + } + + @Override + public void updateFloat( int columnIndex, float x ) throws SQLException { + checkNotClosed(); + super.updateFloat( columnIndex, x ); + } + + @Override + public void updateDouble( int columnIndex, double x ) throws SQLException { + checkNotClosed(); + super.updateDouble( columnIndex, x ); + } + + @Override + public void updateBigDecimal( int columnIndex, BigDecimal x ) throws SQLException { + checkNotClosed(); + super.updateBigDecimal( columnIndex, x ); + } + + @Override + public void updateString( int columnIndex, String x ) throws SQLException { + checkNotClosed(); + super.updateString( columnIndex, x ); + } + + @Override + public void updateBytes( int columnIndex, byte[] x ) throws SQLException { + checkNotClosed(); + super.updateBytes( columnIndex, x ); + } + + @Override + public void updateDate( int columnIndex, Date x ) throws SQLException { + checkNotClosed(); + super.updateDate( columnIndex, x ); + } + + @Override + public void updateTime( int columnIndex, Time x ) throws SQLException { + checkNotClosed(); + super.updateTime( columnIndex, x ); + } + + @Override + public void updateTimestamp( int columnIndex, Timestamp x ) throws SQLException { + checkNotClosed(); + super.updateTimestamp( columnIndex, x ); + } + + @Override + public void updateAsciiStream( int columnIndex, InputStream x, int length ) throws SQLException { + checkNotClosed(); + super.updateAsciiStream( columnIndex, x, length ); + } + + @Override + public void updateBinaryStream( int columnIndex, InputStream x, int length ) throws SQLException { + checkNotClosed(); + super.updateBinaryStream( columnIndex, x, length ); + } + + @Override + public void updateCharacterStream( int columnIndex, Reader x, int length ) throws SQLException { + checkNotClosed(); + super.updateCharacterStream( columnIndex, x, length ); + } + + @Override + public void updateObject( int columnIndex, Object x, int scaleOrLength ) throws SQLException { + checkNotClosed(); + super.updateObject( columnIndex, x, scaleOrLength ); + } + + @Override + public void updateObject( int columnIndex, Object x ) throws SQLException { + checkNotClosed(); + super.updateObject( columnIndex, x ); + } + + @Override + public void updateNull( String columnLabel ) throws SQLException { + checkNotClosed(); + super.updateNull( columnLabel ); + } + + @Override + public void updateBoolean( String columnLabel, boolean x ) throws SQLException { + checkNotClosed(); + super.updateBoolean( columnLabel, x ); + } + + @Override + public void updateByte( String columnLabel, byte x ) throws SQLException { + checkNotClosed(); + super.updateByte( columnLabel, x ); + } + + @Override + public void updateShort( String columnLabel, short x ) throws SQLException { + checkNotClosed(); + super.updateShort( columnLabel, x ); + } + + @Override + public void updateInt( String columnLabel, int x ) throws SQLException { + checkNotClosed(); + super.updateInt( columnLabel, x ); + } + + @Override + public void updateLong( String columnLabel, long x ) throws SQLException { + checkNotClosed(); + super.updateLong( columnLabel, x ); + } + + @Override + public void updateFloat( String columnLabel, float x ) throws SQLException { + checkNotClosed(); + super.updateFloat( columnLabel, x ); + } + + @Override + public void updateDouble( String columnLabel, double x ) throws SQLException { + checkNotClosed(); + super.updateDouble( columnLabel, x ); + } + + @Override + public void updateBigDecimal( String columnLabel, BigDecimal x ) throws SQLException { + checkNotClosed(); + super.updateBigDecimal( columnLabel, x ); + } + + @Override + public void updateString( String columnLabel, String x ) throws SQLException { + checkNotClosed(); + super.updateString( columnLabel, x ); + } + + @Override + public void updateBytes( String columnLabel, byte[] x ) throws SQLException { + checkNotClosed(); + super.updateBytes( columnLabel, x ); + } + + @Override + public void updateDate( String columnLabel, Date x ) throws SQLException { + checkNotClosed(); + super.updateDate( columnLabel, x ); + } + + @Override + public void updateTime( String columnLabel, Time x ) throws SQLException { + checkNotClosed(); + super.updateTime( columnLabel, x ); + } + + @Override + public void updateTimestamp( String columnLabel, Timestamp x ) throws SQLException { + checkNotClosed(); + super.updateTimestamp( columnLabel, x ); + } + + @Override + public void updateAsciiStream( String columnLabel, InputStream x, int length ) throws SQLException { + checkNotClosed(); + super.updateAsciiStream( columnLabel, x, length ); + } + + @Override + public void updateBinaryStream( String columnLabel, InputStream x, int length ) throws SQLException { + checkNotClosed(); + super.updateBinaryStream( columnLabel, x, length ); + } + + @Override + public void updateCharacterStream( String columnLabel, Reader reader, int length ) throws SQLException { + checkNotClosed(); + super.updateCharacterStream( columnLabel, reader, length ); + } + + @Override + public void updateObject( String columnLabel, Object x, int scaleOrLength ) throws SQLException { + checkNotClosed(); + super.updateObject( columnLabel, x, scaleOrLength ); + } + + @Override + public void updateObject( String columnLabel, Object x ) throws SQLException { + checkNotClosed(); + super.updateObject( columnLabel, x ); + } + + @Override + public void insertRow() throws SQLException { + checkNotClosed(); + super.insertRow(); + } + + @Override + public void updateRow() throws SQLException { + checkNotClosed(); + super.updateRow(); + } + + @Override + public void deleteRow() throws SQLException { + checkNotClosed(); + super.deleteRow(); + } + + @Override + public void refreshRow() throws SQLException { + checkNotClosed(); + super.refreshRow(); + } + + @Override + public void cancelRowUpdates() throws SQLException { + checkNotClosed(); + super.cancelRowUpdates(); + } + + @Override + public void moveToInsertRow() throws SQLException { + checkNotClosed(); + super.moveToInsertRow(); + } + + @Override + public void moveToCurrentRow() throws SQLException { + checkNotClosed(); + super.moveToCurrentRow(); + } + + @Override + public DrillStatementImpl getStatement() { + // Note: No already-closed exception for close(). + return statement; + } + + @Override + public Object getObject( int columnIndex, java.util.Map<String,Class<?>> map ) throws SQLException { + checkNotClosed(); + return super.getObject( columnIndex, map ); + } + + @Override + public Ref getRef( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getRef( columnIndex ); + } + + @Override + public Blob getBlob( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getBlob( columnIndex ); + } + + @Override + public Clob getClob( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getClob( columnIndex ); + } + + @Override + public Array getArray( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getArray( columnIndex ); + } + + @Override + public Object getObject( String columnLabel, java.util.Map<String,Class<?>> map ) throws SQLException { + checkNotClosed(); + return super.getObject( columnLabel, map ); + } + + @Override + public Ref getRef( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getRef( columnLabel ); + } + + @Override + public Blob getBlob( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getBlob( columnLabel ); + } + + @Override + public Clob getClob( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getClob( columnLabel ); + } + + @Override + public Array getArray( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getArray( columnLabel ); + } + + @Override + public Date getDate( int columnIndex, Calendar cal ) throws SQLException { + checkNotClosed(); + return super.getDate( columnIndex, cal ); + } + + @Override + public Date getDate( String columnLabel, Calendar cal ) throws SQLException { + checkNotClosed(); + return super.getDate( columnLabel, cal ); + } + + @Override + public Time getTime( int columnIndex, Calendar cal ) throws SQLException { + checkNotClosed(); + return super.getTime( columnIndex, cal ); + } + + @Override + public Time getTime( String columnLabel, Calendar cal ) throws SQLException { + checkNotClosed(); + return super.getTime( columnLabel, cal ); + } + + @Override + public Timestamp getTimestamp( int columnIndex, Calendar cal ) throws SQLException { + checkNotClosed(); + return super.getTimestamp( columnIndex, cal ); + } + + @Override + public Timestamp getTimestamp( String columnLabel, Calendar cal ) throws SQLException { + checkNotClosed(); + return super.getTimestamp( columnLabel, cal ); + } + + //-------------------------- JDBC 3.0 ---------------------------------------- + + @Override + public java.net.URL getURL( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getURL( columnIndex ); + } + + @Override + public java.net.URL getURL( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getURL( columnLabel ); + } + + @Override + public void updateRef( int columnIndex, Ref x ) throws SQLException { + checkNotClosed(); + super.updateRef( columnIndex, x ); + } + + @Override + public void updateRef( String columnLabel, Ref x ) throws SQLException { + checkNotClosed(); + super.updateRef( columnLabel, x ); + } + + @Override + public void updateBlob( int columnIndex, Blob x ) throws SQLException { + checkNotClosed(); + super.updateBlob( columnIndex, x ); + } + + @Override + public void updateBlob( String columnLabel, Blob x ) throws SQLException { + checkNotClosed(); + super.updateBlob( columnLabel, x ); + } + + @Override + public void updateClob( int columnIndex, Clob x ) throws SQLException { + checkNotClosed(); + super.updateClob( columnIndex, x ); + } + + @Override + public void updateClob( String columnLabel, Clob x ) throws SQLException { + checkNotClosed(); + super.updateClob( columnLabel, x ); + } + + @Override + public void updateArray( int columnIndex, Array x ) throws SQLException { + checkNotClosed(); + super.updateArray( columnIndex, x ); + } + + @Override + public void updateArray( String columnLabel, Array x ) throws SQLException { + checkNotClosed(); + super.updateArray( columnLabel, x ); + } + + //------------------------- JDBC 4.0 ----------------------------------- + @Override + public RowId getRowId( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getRowId( columnIndex ); + } + + @Override + public RowId getRowId( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getRowId( columnLabel ); + } + + @Override + public void updateRowId( int columnIndex, RowId x ) throws SQLException { + checkNotClosed(); + super.updateRowId( columnIndex, x ); + } + + @Override + public void updateRowId( String columnLabel, RowId x ) throws SQLException { + checkNotClosed(); + super.updateRowId( columnLabel, x ); + } + + @Override + public int getHoldability() throws SQLException { + checkNotClosed(); + return super.getHoldability(); + } + + @Override + public boolean isClosed() throws SQLException { + // Note: No already-closed exception for isClosed(). + return super.isClosed(); + } + + @Override + public void updateNString( int columnIndex, String nString ) throws SQLException { + checkNotClosed(); + super.updateNString( columnIndex, nString ); + } + + @Override + public void updateNString( String columnLabel, String nString ) throws SQLException { + checkNotClosed(); + super.updateNString( columnLabel, nString ); + } + + @Override + public void updateNClob( int columnIndex, NClob nClob ) throws SQLException { + checkNotClosed(); + super.updateNClob( columnIndex, nClob ); + } + + @Override + public void updateNClob( String columnLabel, NClob nClob ) throws SQLException { + checkNotClosed(); + super.updateNClob( columnLabel, nClob ); + } + + @Override + public NClob getNClob( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getNClob( columnIndex ); + } + + @Override + public NClob getNClob( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getNClob( columnLabel ); + } + + @Override + public SQLXML getSQLXML( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getSQLXML( columnIndex ); + } + + @Override + public SQLXML getSQLXML( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getSQLXML( columnLabel ); + } + + @Override + public void updateSQLXML( int columnIndex, SQLXML xmlObject ) throws SQLException { + checkNotClosed(); + super.updateSQLXML( columnIndex, xmlObject ); + } + + @Override + public void updateSQLXML( String columnLabel, SQLXML xmlObject ) throws SQLException { + checkNotClosed(); + super.updateSQLXML( columnLabel, xmlObject ); + } + + @Override + public String getNString( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getNString( columnIndex ); + } + + @Override + public String getNString( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getNString( columnLabel ); + } + + @Override + public Reader getNCharacterStream( int columnIndex ) throws SQLException { + checkNotClosed(); + return super.getNCharacterStream( columnIndex ); + } + + @Override + public Reader getNCharacterStream( String columnLabel ) throws SQLException { + checkNotClosed(); + return super.getNCharacterStream( columnLabel ); + } + + @Override + public void updateNCharacterStream( int columnIndex, Reader x, long length ) throws SQLException { + checkNotClosed(); + super.updateNCharacterStream( columnIndex, x, length ); + } + + @Override + public void updateNCharacterStream( String columnLabel, Reader reader, long length ) throws SQLException { + checkNotClosed(); + super.updateNCharacterStream( columnLabel, reader, length ); + } + + @Override + public void updateAsciiStream( int columnIndex, InputStream x, long length ) throws SQLException { + checkNotClosed(); + super.updateAsciiStream( columnIndex, x, length ); + } + + @Override + public void updateBinaryStream( int columnIndex, InputStream x, long length ) throws SQLException { + checkNotClosed(); + super.updateBinaryStream( columnIndex, x, length ); + } + + @Override + public void updateCharacterStream( int columnIndex, Reader x, long length ) throws SQLException { + checkNotClosed(); + super.updateCharacterStream( columnIndex, x, length ); + } + + @Override + public void updateAsciiStream( String columnLabel, InputStream x, long length ) throws SQLException { + checkNotClosed(); + super.updateAsciiStream( columnLabel, x, length ); + } + + @Override + public void updateBinaryStream( String columnLabel, InputStream x, long length ) throws SQLException { + checkNotClosed(); + super.updateBinaryStream( columnLabel, x, length ); + } + + @Override + public void updateCharacterStream( String columnLabel, Reader reader, long length ) throws SQLException { + checkNotClosed(); + super.updateCharacterStream( columnLabel, reader, length ); + } + + @Override + public void updateBlob( int columnIndex, InputStream inputStream, long length ) throws SQLException { + checkNotClosed(); + super.updateBlob( columnIndex, inputStream, length ); + } + + @Override + public void updateBlob( String columnLabel, InputStream inputStream, long length ) throws SQLException { + checkNotClosed(); + super.updateBlob( columnLabel, inputStream, length ); + } + + @Override + public void updateClob( int columnIndex, Reader reader, long length ) throws SQLException { + checkNotClosed(); + super.updateClob( columnIndex, reader, length ); + } + + @Override + public void updateClob( String columnLabel, Reader reader, long length ) throws SQLException { + checkNotClosed(); + super.updateClob( columnLabel, reader, length ); + } + + @Override + public void updateNClob( int columnIndex, Reader reader, long length ) throws SQLException { + checkNotClosed(); + super.updateNClob( columnIndex, reader, length ); + } + + @Override + public void updateNClob( String columnLabel, Reader reader, long length ) throws SQLException { + checkNotClosed(); + super.updateNClob( columnLabel, reader, length ); + } + + //--- + @Override + public void updateNCharacterStream( int columnIndex, Reader x ) throws SQLException { + checkNotClosed(); + super.updateNCharacterStream( columnIndex, x ); + } + + @Override + public void updateNCharacterStream( String columnLabel, Reader reader ) throws SQLException { + checkNotClosed(); + super.updateNCharacterStream( columnLabel, reader ); + } + + @Override + public void updateAsciiStream( int columnIndex, InputStream x ) throws SQLException { + checkNotClosed(); + super.updateAsciiStream( columnIndex, x ); + } + + @Override + public void updateBinaryStream( int columnIndex, InputStream x ) throws SQLException { + checkNotClosed(); + super.updateBinaryStream( columnIndex, x ); + } + + @Override + public void updateCharacterStream( int columnIndex, Reader x ) throws SQLException { + checkNotClosed(); + super.updateCharacterStream( columnIndex, x ); + } + + @Override + public void updateAsciiStream( String columnLabel, InputStream x ) throws SQLException { + checkNotClosed(); + super.updateAsciiStream( columnLabel, x ); + } + + @Override + public void updateBinaryStream( String columnLabel, InputStream x ) throws SQLException { + checkNotClosed(); + super.updateBinaryStream( columnLabel, x ); + } + + @Override + public void updateCharacterStream( String columnLabel, Reader reader ) throws SQLException { + checkNotClosed(); + super.updateCharacterStream( columnLabel, reader ); + } + + @Override + public void updateBlob( int columnIndex, InputStream inputStream ) throws SQLException { + checkNotClosed(); + super.updateBlob( columnIndex, inputStream ); + } + + @Override + public void updateBlob( String columnLabel, InputStream inputStream ) throws SQLException { + checkNotClosed(); + super.updateBlob( columnLabel, inputStream ); + } + + @Override + public void updateClob( int columnIndex, Reader reader ) throws SQLException { + checkNotClosed(); + super.updateClob( columnIndex, reader ); + } + + @Override + public void updateClob( String columnLabel, Reader reader ) throws SQLException { + checkNotClosed(); + super.updateClob( columnLabel, reader ); + } + + @Override + public void updateNClob( int columnIndex, Reader reader ) throws SQLException { + checkNotClosed(); + super.updateNClob( columnIndex, reader ); + } + + @Override + public void updateNClob( String columnLabel, Reader reader ) throws SQLException { + checkNotClosed(); + super.updateNClob( columnLabel, reader ); + } + + //------------------------- JDBC 4.1 ----------------------------------- + @Override + public <T> T getObject( int columnIndex, Class<T> type ) throws SQLException { + checkNotClosed(); + return super.getObject( columnIndex, type ); + } + + @Override + public <T> T getObject( String columnLabel, Class<T> type ) throws SQLException { + checkNotClosed(); + return super.getObject( columnLabel, type ); + } + + + //////////////////////////////////////// + // DrillResultSet methods: + + public String getQueryId() throws SQLException { + checkNotClosed(); + if (resultsListener.getQueryId() != null) { + return QueryIdHelper.getQueryId(resultsListener.getQueryId()); + } else { + return null; + } + } + + + //////////////////////////////////////// + + @Override + protected DrillResultSetImpl execute() throws SQLException{ + DrillConnectionImpl connection = (DrillConnectionImpl) statement.getConnection(); + + connection.getClient().runQuery(QueryType.SQL, this.prepareResult.getSql(), + resultsListener); + connection.getDriver().handler.onStatementExecute(statement, null); + + super.execute(); + + // don't return with metadata until we've achieved at least one return message. + try { + // TODO: Revisit: Why reaching directly into ResultsListener rather than + // calling some wait method? + resultsListener.latch.await(); + } 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(); + + // Not normally expected--Drill doesn't interrupt in this area (right?)-- + // but JDBC client certainly could. + throw new SQLException( "Interrupted", e ); + } + + // Read first (schema-only) batch to initialize result-set metadata from + // (initial) schema before Statement.execute...(...) returns result set: + cursor.loadInitialSchema(); + + return this; + } + + + //////////////////////////////////////// + // ResultsListener: + static class ResultsListener implements UserResultsListener { private static final Logger logger = getLogger( ResultsListener.class );