
org.apache.drill.jdbc.impl.DrillResultSetImpl Maven / Gradle / Ivy
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.drill.jdbc.impl;
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.SQLFeatureNotSupportedException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Map;
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 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;
import org.apache.drill.exec.client.DrillClient;
import org.apache.drill.exec.proto.UserBitShared.QueryId;
import org.apache.drill.exec.proto.UserBitShared.QueryResult.QueryState;
import org.apache.drill.exec.proto.UserBitShared.QueryType;
import org.apache.drill.exec.proto.helper.QueryIdHelper;
import org.apache.drill.exec.record.RecordBatchLoader;
import org.apache.drill.exec.rpc.ConnectionThrottle;
import org.apache.drill.exec.rpc.user.QueryDataBatch;
import org.apache.drill.exec.rpc.user.UserResultsListener;
import org.apache.drill.jdbc.AlreadyClosedSqlException;
import org.apache.drill.jdbc.DrillResultSet;
import org.apache.drill.jdbc.ExecutionCanceledSqlException;
import org.apache.drill.jdbc.SchemaChangeListener;
import com.google.common.collect.Queues;
/**
* Drill's implementation of {@link ResultSet}.
*/
class DrillResultSetImpl extends AvaticaResultSet implements DrillResultSet {
@SuppressWarnings("unused")
private static final org.slf4j.Logger logger =
org.slf4j.LoggerFactory.getLogger(DrillResultSetImpl.class);
private final DrillConnectionImpl connection;
SchemaChangeListener changeListener;
final ResultsListener resultsListener;
private final DrillClient client;
// TODO: Resolve: Since is barely manipulated here in DrillResultSetImpl,
// move down into DrillCursor and have this.clean() have cursor clean it.
final RecordBatchLoader batchLoader;
final DrillCursor cursor;
boolean hasPendingCancelationNotification;
DrillResultSetImpl(AvaticaStatement statement, AvaticaPrepareResult prepareResult,
ResultSetMetaData resultSetMetaData, TimeZone timeZone) {
super(statement, prepareResult, resultSetMetaData, timeZone);
connection = (DrillConnectionImpl) statement.getConnection();
client = connection.getClient();
final int batchQueueThrottlingThreshold =
client.getConfig().getInt(
ExecConstants.JDBC_BATCH_QUEUE_THROTTLING_THRESHOLD );
resultsListener = new ResultsListener(batchQueueThrottlingThreshold);
batchLoader = new RecordBatchLoader(client.getAllocator());
cursor = new DrillCursor(this);
}
/**
* Throws AlreadyClosedSqlException or QueryCanceledSqlException if this
* ResultSet is closed.
*
* @throws ExecutionCanceledSqlException if ResultSet is closed because of
* 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()}
*/
private void throwIfClosed() throws AlreadyClosedSqlException,
ExecutionCanceledSqlException,
SQLException {
if ( isClosed() ) {
if ( hasPendingCancelationNotification ) {
hasPendingCancelationNotification = false;
throw new ExecutionCanceledSqlException(
"SQL statement execution canceled; ResultSet now closed." );
}
else {
throw new AlreadyClosedSqlException( "ResultSet is already closed." );
}
}
}
// Note: Using dynamic proxies would reduce the quantity (450?) of method
// overrides by eliminating those that exist solely to check whether the
// object is closed. It would also eliminate the need to throw non-compliant
// RuntimeExceptions when Avatica's method declarations won't let us throw
// proper SQLExceptions. (Check performance before applying to frequently
// called ResultSet.)
@Override
protected void cancel() {
hasPendingCancelationNotification = true;
cleanup();
close();
}
synchronized void cleanup() {
if (resultsListener.getQueryId() != null && ! resultsListener.completed) {
client.cancelQuery(resultsListener.getQueryId());
}
resultsListener.close();
batchLoader.clear();
}
////////////////////////////////////////
// ResultSet-defined methods (in same order as in ResultSet):
// No isWrapperFor(Class>) (it doesn't throw SQLException if already closed).
// No unwrap(Class) (it doesn't throw SQLException if already closed).
// (Not delegated.)
@Override
public boolean next() throws SQLException {
throwIfClosed();
// TODO: Resolve following comments (possibly obsolete because of later
// addition of preceding call to throwIfClosed. Also, NOTE that the
// following check, and maybe some throwIfClosed() calls, probably must
// synchronize on the statement, per the comment on AvaticaStatement's
// openResultSet:
// Next may be called after close has been called (for example after a user
// cancellation) which in turn sets the cursor to null. So we must check
// before we call next.
// TODO: handle next() after close is called in the Avatica code.
if (super.cursor != null) {
return super.next();
} else {
return false;
}
}
@Override
public void close() {
// Note: No already-closed exception for close().
super.close();
}
@Override
public boolean wasNull() throws SQLException {
throwIfClosed();
return super.wasNull();
}
// Methods for accessing results by column index
@Override
public String getString( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getString( columnIndex );
}
@Override
public boolean getBoolean( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getBoolean( columnIndex );
}
@Override
public byte getByte( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getByte( columnIndex );
}
@Override
public short getShort( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getShort( columnIndex );
}
@Override
public int getInt( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getInt( columnIndex );
}
@Override
public long getLong( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getLong( columnIndex );
}
@Override
public float getFloat( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getFloat( columnIndex );
}
@Override
public double getDouble( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getDouble( columnIndex );
}
@Override
public BigDecimal getBigDecimal( int columnIndex,
int scale ) throws SQLException {
throwIfClosed();
return super.getBigDecimal( columnIndex, scale );
}
@Override
public byte[] getBytes( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getBytes( columnIndex );
}
@Override
public Date getDate( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getDate( columnIndex );
}
@Override
public Time getTime( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getTime( columnIndex );
}
@Override
public Timestamp getTimestamp( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getTimestamp( columnIndex );
}
@Override
public InputStream getAsciiStream( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getAsciiStream( columnIndex );
}
@Override
public InputStream getUnicodeStream( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getUnicodeStream( columnIndex );
}
@Override
public InputStream getBinaryStream( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getBinaryStream( columnIndex );
}
// Methods for accessing results by column label
@Override
public String getString( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getString( columnLabel );
}
@Override
public boolean getBoolean( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getBoolean( columnLabel );
}
@Override
public byte getByte( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getByte( columnLabel );
}
@Override
public short getShort( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getShort( columnLabel );
}
@Override
public int getInt( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getInt( columnLabel );
}
@Override
public long getLong( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getLong( columnLabel );
}
@Override
public float getFloat( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getFloat( columnLabel );
}
@Override
public double getDouble( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getDouble( columnLabel );
}
@Override
public BigDecimal getBigDecimal( String columnLabel,
int scale ) throws SQLException {
throwIfClosed();
return super.getBigDecimal( columnLabel, scale );
}
@Override
public byte[] getBytes( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getBytes( columnLabel );
}
@Override
public Date getDate( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getDate( columnLabel );
}
@Override
public Time getTime( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getTime( columnLabel );
}
@Override
public Timestamp getTimestamp( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getTimestamp( columnLabel );
}
@Override
public InputStream getAsciiStream( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getAsciiStream( columnLabel );
}
@Override
public InputStream getUnicodeStream( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getUnicodeStream( columnLabel );
}
@Override
public InputStream getBinaryStream( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getBinaryStream( columnLabel );
}
// Advanced features:
@Override
public SQLWarning getWarnings() throws SQLException {
throwIfClosed();
return super.getWarnings();
}
@Override
public void clearWarnings() throws SQLException {
throwIfClosed();
super.clearWarnings();
}
@Override
public String getCursorName() throws SQLException {
throwIfClosed();
try {
return super.getCursorName();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
// (Not delegated.)
@Override
public ResultSetMetaData getMetaData() throws SQLException {
throwIfClosed();
return super.getMetaData();
}
@Override
public Object getObject( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getObject( columnIndex );
}
@Override
public Object getObject( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getObject( columnLabel );
}
//----------------------------------------------------------------
@Override
public int findColumn( String columnLabel ) throws SQLException {
throwIfClosed();
return super.findColumn( columnLabel );
}
//--------------------------JDBC 2.0-----------------------------------
//---------------------------------------------------------------------
// Getters and Setters
//---------------------------------------------------------------------
@Override
public Reader getCharacterStream( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getCharacterStream( columnIndex );
}
@Override
public Reader getCharacterStream( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getCharacterStream( columnLabel );
}
@Override
public BigDecimal getBigDecimal( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getBigDecimal( columnIndex );
}
@Override
public BigDecimal getBigDecimal( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getBigDecimal( columnLabel );
}
//---------------------------------------------------------------------
// Traversal/Positioning
//---------------------------------------------------------------------
@Override
public boolean isBeforeFirst() throws SQLException {
throwIfClosed();
return super.isBeforeFirst();
}
@Override
public boolean isAfterLast() throws SQLException {
throwIfClosed();
return super.isAfterLast();
}
@Override
public boolean isFirst() throws SQLException {
throwIfClosed();
return super.isFirst();
}
@Override
public boolean isLast() throws SQLException {
throwIfClosed();
try {
return super.isLast();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void beforeFirst() throws SQLException {
throwIfClosed();
try {
super.beforeFirst();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void afterLast() throws SQLException {
throwIfClosed();
try {
super.afterLast();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public boolean first() throws SQLException {
throwIfClosed();
try {
return super.first();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public boolean last() throws SQLException {
throwIfClosed();
try {
return super.last();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public int getRow() throws SQLException {
throwIfClosed();
// Map Avatica's erroneous zero-based row numbers to 1-based, and return 0
// after end, per JDBC:
return isAfterLast() ? 0 : 1 + super.getRow();
}
@Override
public boolean absolute( int row ) throws SQLException {
throwIfClosed();
try {
return super.absolute( row );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public boolean relative( int rows ) throws SQLException {
throwIfClosed();
try {
return super.relative( rows );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public boolean previous() throws SQLException {
throwIfClosed();
try {
return super.previous();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
//---------------------------------------------------------------------
// Properties
//---------------------------------------------------------------------
@Override
public void setFetchDirection( int direction ) throws SQLException {
throwIfClosed();
super.setFetchDirection( direction );
}
@Override
public int getFetchDirection() throws SQLException {
throwIfClosed();
return super.getFetchDirection();
}
@Override
public void setFetchSize( int rows ) throws SQLException {
throwIfClosed();
super.setFetchSize( rows );
}
@Override
public int getFetchSize() throws SQLException {
throwIfClosed();
return super.getFetchSize();
}
@Override
public int getType() throws SQLException {
throwIfClosed();
return super.getType();
}
@Override
public int getConcurrency() throws SQLException {
throwIfClosed();
return super.getConcurrency();
}
//---------------------------------------------------------------------
// Updates
//---------------------------------------------------------------------
@Override
public boolean rowUpdated() throws SQLException {
throwIfClosed();
return super.rowUpdated();
}
@Override
public boolean rowInserted() throws SQLException {
throwIfClosed();
return super.rowInserted();
}
@Override
public boolean rowDeleted() throws SQLException {
throwIfClosed();
return super.rowDeleted();
}
@Override
public void updateNull( int columnIndex ) throws SQLException {
throwIfClosed();
try {
super.updateNull( columnIndex );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBoolean( int columnIndex, boolean x ) throws SQLException {
throwIfClosed();
try {
super.updateBoolean( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateByte( int columnIndex, byte x ) throws SQLException {
throwIfClosed();
try {
super.updateByte( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateShort( int columnIndex, short x ) throws SQLException {
throwIfClosed();
try {
super.updateShort( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateInt( int columnIndex, int x ) throws SQLException {
throwIfClosed();
try {
super.updateInt( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateLong( int columnIndex, long x ) throws SQLException {
throwIfClosed();
try {
super.updateLong( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateFloat( int columnIndex, float x ) throws SQLException {
throwIfClosed();
try {
super.updateFloat( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateDouble( int columnIndex, double x ) throws SQLException {
throwIfClosed();
try {
super.updateDouble( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBigDecimal( int columnIndex,
BigDecimal x ) throws SQLException {
throwIfClosed();
try {
super.updateBigDecimal( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateString( int columnIndex, String x ) throws SQLException {
throwIfClosed();
try {
super.updateString( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBytes( int columnIndex, byte[] x ) throws SQLException {
throwIfClosed();
try {
super.updateBytes( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateDate( int columnIndex, Date x ) throws SQLException {
throwIfClosed();
try {
super.updateDate( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateTime( int columnIndex, Time x ) throws SQLException {
throwIfClosed();
try {
super.updateTime( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateTimestamp( int columnIndex, Timestamp x ) throws SQLException {
throwIfClosed();
try {
super.updateTimestamp( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateAsciiStream( int columnIndex, InputStream x,
int length ) throws SQLException {
throwIfClosed();
try {
super.updateAsciiStream( columnIndex, x, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBinaryStream( int columnIndex, InputStream x,
int length ) throws SQLException {
throwIfClosed();
try {
super.updateBinaryStream( columnIndex, x, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateCharacterStream( int columnIndex, Reader x,
int length ) throws SQLException {
throwIfClosed();
try {
super.updateCharacterStream( columnIndex, x, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateObject( int columnIndex, Object x,
int scaleOrLength ) throws SQLException {
throwIfClosed();
try {
super.updateObject( columnIndex, x, scaleOrLength );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateObject( int columnIndex, Object x ) throws SQLException {
throwIfClosed();
try {
super.updateObject( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateNull( String columnLabel ) throws SQLException {
throwIfClosed();
try {
super.updateNull( columnLabel );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBoolean( String columnLabel, boolean x ) throws SQLException {
throwIfClosed();
try {
super.updateBoolean( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateByte( String columnLabel, byte x ) throws SQLException {
throwIfClosed();
try {
super.updateByte( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateShort( String columnLabel, short x ) throws SQLException {
throwIfClosed();
try {
super.updateShort( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateInt( String columnLabel, int x ) throws SQLException {
throwIfClosed();
try {
super.updateInt( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateLong( String columnLabel, long x ) throws SQLException {
throwIfClosed();
try {
super.updateLong( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateFloat( String columnLabel, float x ) throws SQLException {
throwIfClosed();
try {
super.updateFloat( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateDouble( String columnLabel, double x ) throws SQLException {
throwIfClosed();
try {
super.updateDouble( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBigDecimal( String columnLabel,
BigDecimal x ) throws SQLException {
throwIfClosed();
try {
super.updateBigDecimal( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateString( String columnLabel, String x ) throws SQLException {
throwIfClosed();
try {
super.updateString( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBytes( String columnLabel, byte[] x ) throws SQLException {
throwIfClosed();
try {
super.updateBytes( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateDate( String columnLabel, Date x ) throws SQLException {
throwIfClosed();
try {
super.updateDate( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateTime( String columnLabel, Time x ) throws SQLException {
throwIfClosed();
try {
super.updateTime( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateTimestamp( String columnLabel, Timestamp x ) throws SQLException {
throwIfClosed();
try {
super.updateTimestamp( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateAsciiStream( String columnLabel, InputStream x,
int length ) throws SQLException {
throwIfClosed();
try {
super.updateAsciiStream( columnLabel, x, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBinaryStream( String columnLabel, InputStream x,
int length ) throws SQLException {
throwIfClosed();
try {
super.updateBinaryStream( columnLabel, x, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateCharacterStream( String columnLabel, Reader reader,
int length ) throws SQLException {
throwIfClosed();
try {
super.updateCharacterStream( columnLabel, reader, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateObject( String columnLabel, Object x,
int scaleOrLength ) throws SQLException {
throwIfClosed();
try {
super.updateObject( columnLabel, x, scaleOrLength );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateObject( String columnLabel, Object x ) throws SQLException {
throwIfClosed();
try {
super.updateObject( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void insertRow() throws SQLException {
throwIfClosed();
try {
super.insertRow();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateRow() throws SQLException {
throwIfClosed();
try {
super.updateRow();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void deleteRow() throws SQLException {
throwIfClosed();
try {
super.deleteRow();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void refreshRow() throws SQLException {
throwIfClosed();
try {
super.refreshRow();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void cancelRowUpdates() throws SQLException {
throwIfClosed();
try {
super.cancelRowUpdates();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void moveToInsertRow() throws SQLException {
throwIfClosed();
try {
super.moveToInsertRow();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void moveToCurrentRow() throws SQLException {
throwIfClosed();
try {
super.moveToCurrentRow();
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public AvaticaStatement getStatement() {
try {
throwIfClosed();
} catch (AlreadyClosedSqlException e) {
// Can't throw any SQLException because AvaticaConnection's
// getStatement() is missing "throws SQLException".
throw new RuntimeException(e.getMessage(), e);
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
return super.getStatement();
}
@Override
public Object getObject( int columnIndex,
Map> map ) throws SQLException {
throwIfClosed();
return super.getObject( columnIndex, map );
}
@Override
public Ref getRef( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getRef( columnIndex );
}
@Override
public Blob getBlob( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getBlob( columnIndex );
}
@Override
public Clob getClob( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getClob( columnIndex );
}
@Override
public Array getArray( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getArray( columnIndex );
}
@Override
public Object getObject( String columnLabel,
Map> map ) throws SQLException {
throwIfClosed();
return super.getObject( columnLabel, map );
}
@Override
public Ref getRef( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getRef( columnLabel );
}
@Override
public Blob getBlob( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getBlob( columnLabel );
}
@Override
public Clob getClob( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getClob( columnLabel );
}
@Override
public Array getArray( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getArray( columnLabel );
}
@Override
public Date getDate( int columnIndex, Calendar cal ) throws SQLException {
throwIfClosed();
return super.getDate( columnIndex, cal );
}
@Override
public Date getDate( String columnLabel, Calendar cal ) throws SQLException {
throwIfClosed();
return super.getDate( columnLabel, cal );
}
@Override
public Time getTime( int columnIndex, Calendar cal ) throws SQLException {
throwIfClosed();
return super.getTime( columnIndex, cal );
}
@Override
public Time getTime( String columnLabel, Calendar cal ) throws SQLException {
throwIfClosed();
return super.getTime( columnLabel, cal );
}
@Override
public Timestamp getTimestamp( int columnIndex, Calendar cal ) throws SQLException {
throwIfClosed();
return super.getTimestamp( columnIndex, cal );
}
@Override
public Timestamp getTimestamp( String columnLabel,
Calendar cal ) throws SQLException {
throwIfClosed();
return super.getTimestamp( columnLabel, cal );
}
//-------------------------- JDBC 3.0 ----------------------------------------
@Override
public URL getURL( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getURL( columnIndex );
}
@Override
public URL getURL( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getURL( columnLabel );
}
@Override
public void updateRef( int columnIndex, Ref x ) throws SQLException {
throwIfClosed();
try {
super.updateRef( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateRef( String columnLabel, Ref x ) throws SQLException {
throwIfClosed();
try {
super.updateRef( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBlob( int columnIndex, Blob x ) throws SQLException {
throwIfClosed();
try {
super.updateBlob( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBlob( String columnLabel, Blob x ) throws SQLException {
throwIfClosed();
try {
super.updateBlob( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateClob( int columnIndex, Clob x ) throws SQLException {
throwIfClosed();
try {
super.updateClob( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateClob( String columnLabel, Clob x ) throws SQLException {
throwIfClosed();
try {
super.updateClob( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateArray( int columnIndex, Array x ) throws SQLException {
throwIfClosed();
try {
super.updateArray( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateArray( String columnLabel, Array x ) throws SQLException {
throwIfClosed();
try {
super.updateArray( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
//------------------------- JDBC 4.0 -----------------------------------
@Override
public RowId getRowId( int columnIndex ) throws SQLException {
throwIfClosed();
try {
return super.getRowId( columnIndex );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public RowId getRowId( String columnLabel ) throws SQLException {
throwIfClosed();
try {
return super.getRowId( columnLabel );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateRowId( int columnIndex, RowId x ) throws SQLException {
throwIfClosed();
try {
super.updateRowId( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateRowId( String columnLabel, RowId x ) throws SQLException {
throwIfClosed();
try {
super.updateRowId( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public int getHoldability() throws SQLException {
throwIfClosed();
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 {
throwIfClosed();
try {
super.updateNString( columnIndex, nString );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateNString( String columnLabel,
String nString ) throws SQLException {
throwIfClosed();
try {
super.updateNString( columnLabel, nString );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateNClob( int columnIndex, NClob nClob ) throws SQLException {
throwIfClosed();
try {
super.updateNClob( columnIndex, nClob );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateNClob( String columnLabel, NClob nClob ) throws SQLException {
throwIfClosed();
try {
super.updateNClob( columnLabel, nClob );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public NClob getNClob( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getNClob( columnIndex );
}
@Override
public NClob getNClob( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getNClob( columnLabel );
}
@Override
public SQLXML getSQLXML( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getSQLXML( columnIndex );
}
@Override
public SQLXML getSQLXML( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getSQLXML( columnLabel );
}
@Override
public void updateSQLXML( int columnIndex,
SQLXML xmlObject ) throws SQLException {
throwIfClosed();
try {
super.updateSQLXML( columnIndex, xmlObject );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateSQLXML( String columnLabel,
SQLXML xmlObject ) throws SQLException {
throwIfClosed();
try {
super.updateSQLXML( columnLabel, xmlObject );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public String getNString( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getNString( columnIndex );
}
@Override
public String getNString( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getNString( columnLabel );
}
@Override
public Reader getNCharacterStream( int columnIndex ) throws SQLException {
throwIfClosed();
return super.getNCharacterStream( columnIndex );
}
@Override
public Reader getNCharacterStream( String columnLabel ) throws SQLException {
throwIfClosed();
return super.getNCharacterStream( columnLabel );
}
@Override
public void updateNCharacterStream( int columnIndex, Reader x,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateNCharacterStream( columnIndex, x, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateNCharacterStream( String columnLabel, Reader reader,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateNCharacterStream( columnLabel, reader, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateAsciiStream( int columnIndex, InputStream x,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateAsciiStream( columnIndex, x, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBinaryStream( int columnIndex, InputStream x,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateBinaryStream( columnIndex, x, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateCharacterStream( int columnIndex, Reader x,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateCharacterStream( columnIndex, x, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateAsciiStream( String columnLabel, InputStream x,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateAsciiStream( columnLabel, x, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBinaryStream( String columnLabel, InputStream x,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateBinaryStream( columnLabel, x, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateCharacterStream( String columnLabel, Reader reader,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateCharacterStream( columnLabel, reader, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBlob( int columnIndex, InputStream inputStream,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateBlob( columnIndex, inputStream, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBlob( String columnLabel, InputStream inputStream,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateBlob( columnLabel, inputStream, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateClob( int columnIndex, Reader reader,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateClob( columnIndex, reader, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateClob( String columnLabel, Reader reader,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateClob( columnLabel, reader, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateNClob( int columnIndex, Reader reader,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateNClob( columnIndex, reader, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateNClob( String columnLabel, Reader reader,
long length ) throws SQLException {
throwIfClosed();
try {
super.updateNClob( columnLabel, reader, length );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
//---
@Override
public void updateNCharacterStream( int columnIndex,
Reader x ) throws SQLException {
throwIfClosed();
try {
super.updateNCharacterStream( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateNCharacterStream( String columnLabel,
Reader reader ) throws SQLException {
throwIfClosed();
try {
super.updateNCharacterStream( columnLabel, reader );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateAsciiStream( int columnIndex,
InputStream x ) throws SQLException {
throwIfClosed();
try {
super.updateAsciiStream( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBinaryStream( int columnIndex,
InputStream x ) throws SQLException {
throwIfClosed();
try {
super.updateBinaryStream( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateCharacterStream( int columnIndex,
Reader x ) throws SQLException {
throwIfClosed();
try {
super.updateCharacterStream( columnIndex, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateAsciiStream( String columnLabel,
InputStream x ) throws SQLException {
throwIfClosed();
try {
super.updateAsciiStream( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBinaryStream( String columnLabel,
InputStream x ) throws SQLException {
throwIfClosed();
try {
super.updateBinaryStream( columnLabel, x );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateCharacterStream( String columnLabel,
Reader reader ) throws SQLException {
throwIfClosed();
try {
super.updateCharacterStream( columnLabel, reader );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBlob( int columnIndex,
InputStream inputStream ) throws SQLException {
throwIfClosed();
try {
super.updateBlob( columnIndex, inputStream );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateBlob( String columnLabel,
InputStream inputStream ) throws SQLException {
throwIfClosed();
try {
super.updateBlob( columnLabel, inputStream );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateClob( int columnIndex, Reader reader ) throws SQLException {
throwIfClosed();
try {
super.updateClob( columnIndex, reader );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateClob( String columnLabel, Reader reader ) throws SQLException {
throwIfClosed();
try {
super.updateClob( columnLabel, reader );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateNClob( int columnIndex, Reader reader ) throws SQLException {
throwIfClosed();
try {
super.updateNClob( columnIndex, reader );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
@Override
public void updateNClob( String columnLabel, Reader reader ) throws SQLException {
throwIfClosed();
try {
super.updateNClob( columnLabel, reader );
}
catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e.getMessage(), e);
}
}
//------------------------- JDBC 4.1 -----------------------------------
@Override
public T getObject( int columnIndex, Class type ) throws SQLException {
throwIfClosed();
return super.getObject( columnIndex, type );
}
@Override
public T getObject( String columnLabel, Class type ) throws SQLException {
throwIfClosed();
return super.getObject( columnLabel, type );
}
////////////////////////////////////////
// DrillResultSet methods:
public String getQueryId() throws SQLException {
throwIfClosed();
if (resultsListener.getQueryId() != null) {
return QueryIdHelper.getQueryId(resultsListener.getQueryId());
} else {
return null;
}
}
////////////////////////////////////////
@Override
protected DrillResultSetImpl execute() throws SQLException{
client.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 org.slf4j.Logger logger =
org.slf4j.LoggerFactory.getLogger(ResultsListener.class);
private static volatile int nextInstanceId = 1;
/** (Just for logging.) */
private final int instanceId;
private final int batchQueueThrottlingThreshold;
/** (Just for logging.) */
private volatile QueryId queryId;
/** (Just for logging.) */
private int lastReceivedBatchNumber;
/** (Just for logging.) */
private int lastDequeuedBatchNumber;
private volatile UserException executionFailureException;
// TODO: Revisit "completed". Determine and document exactly what it
// means. Some uses imply that it means that incoming messages indicate
// that the _query_ has _terminated_ (not necessarily _completing_
// normally), while some uses imply that it's some other state of the
// ResultListener. Some uses seem redundant.)
volatile boolean completed = false;
/** Whether throttling of incoming data is active. */
private final AtomicBoolean throttled = new AtomicBoolean( false );
private volatile ConnectionThrottle throttle;
private volatile boolean closed = false;
// TODO: Rename. It's obvious it's a latch--but what condition or action
// does it represent or control?
private CountDownLatch latch = new CountDownLatch(1);
private AtomicBoolean receivedMessage = new AtomicBoolean(false);
final LinkedBlockingDeque batchQueue =
Queues.newLinkedBlockingDeque();
/**
* ...
* @param batchQueueThrottlingThreshold
* queue size threshold for throttling server
*/
ResultsListener( int batchQueueThrottlingThreshold ) {
instanceId = nextInstanceId++;
this.batchQueueThrottlingThreshold = batchQueueThrottlingThreshold;
logger.debug( "[#{}] Query listener created.", instanceId );
}
/**
* Starts throttling if not currently throttling.
* @param throttle the "throttlable" object to throttle
* @return true if actually started (wasn't throttling already)
*/
private boolean startThrottlingIfNot( ConnectionThrottle throttle ) {
final boolean started = throttled.compareAndSet( false, true );
if ( started ) {
this.throttle = throttle;
throttle.setAutoRead(false);
}
return started;
}
/**
* Stops throttling if currently throttling.
* @return true if actually stopped (was throttling)
*/
private boolean stopThrottlingIfSo() {
final boolean stopped = throttled.compareAndSet( true, false );
if ( stopped ) {
throttle.setAutoRead(true);
throttle = null;
}
return stopped;
}
// TODO: Doc.: Release what if what is first relative to what?
private boolean releaseIfFirst() {
if (receivedMessage.compareAndSet(false, true)) {
latch.countDown();
return true;
}
return false;
}
@Override
public void queryIdArrived(QueryId queryId) {
logger.debug( "[#{}] Received query ID: {}.",
instanceId, QueryIdHelper.getQueryId( queryId ) );
this.queryId = queryId;
}
@Override
public void submissionFailed(UserException ex) {
logger.debug( "Received query failure:", instanceId, ex );
this.executionFailureException = ex;
completed = true;
close();
logger.info( "[#{}] Query failed: ", instanceId, ex );
}
@Override
public void dataArrived(QueryDataBatch result, ConnectionThrottle throttle) {
lastReceivedBatchNumber++;
logger.debug( "[#{}] Received query data batch #{}: {}.",
instanceId, lastReceivedBatchNumber, result );
// If we're in a closed state, just release the message.
if (closed) {
result.release();
// TODO: Revisit member completed: Is ResultListener really completed
// after only one data batch after being closed?
completed = true;
return;
}
// We're active; let's add to the queue.
batchQueue.add(result);
// Throttle server if queue size has exceed threshold.
if (batchQueue.size() > batchQueueThrottlingThreshold ) {
if ( startThrottlingIfNot( throttle ) ) {
logger.debug( "[#{}] Throttling started at queue size {}.",
instanceId, batchQueue.size() );
}
}
releaseIfFirst();
}
@Override
public void queryCompleted(QueryState state) {
logger.debug( "[#{}] Received query completion: {}.", instanceId, state );
releaseIfFirst();
completed = true;
}
QueryId getQueryId() {
return queryId;
}
/**
* Gets the next batch of query results from the queue.
* @return the next batch, or {@code null} after last batch has been returned
* @throws UserException
* if the query failed
* @throws InterruptedException
* if waiting on the queue was interrupted
*/
QueryDataBatch getNext() throws UserException, InterruptedException {
while (true) {
if (executionFailureException != null) {
logger.debug( "[#{}] Dequeued query failure exception: {}.",
instanceId, executionFailureException );
throw executionFailureException;
}
if (completed && batchQueue.isEmpty()) {
return null;
} else {
QueryDataBatch qdb = batchQueue.poll(50, TimeUnit.MILLISECONDS);
if (qdb != null) {
lastDequeuedBatchNumber++;
logger.debug( "[#{}] Dequeued query data batch #{}: {}.",
instanceId, lastDequeuedBatchNumber, qdb );
// Unthrottle server if queue size has dropped enough below threshold:
if ( batchQueue.size() < batchQueueThrottlingThreshold / 2
|| batchQueue.size() == 0 // (in case threshold < 2)
) {
if ( stopThrottlingIfSo() ) {
logger.debug( "[#{}] Throttling stopped at queue size {}.",
instanceId, batchQueue.size() );
}
}
return qdb;
}
}
}
}
void close() {
logger.debug( "[#{}] Query listener closing.", instanceId );
closed = true;
if ( stopThrottlingIfSo() ) {
logger.debug( "[#{}] Throttling stopped at close() (at queue size {}).",
instanceId, batchQueue.size() );
}
while (!batchQueue.isEmpty()) {
QueryDataBatch qdb = batchQueue.poll();
if (qdb != null && qdb.getData() != null) {
qdb.getData().release();
}
}
// Close may be called before the first result is received and therefore
// when the main thread is blocked waiting for the result. In that case
// we want to unblock the main thread.
latch.countDown(); // TODO: Why not call releaseIfFirst as used elsewhere?
completed = true;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy