/*
* (C) Copyright IBM Corp. 2010
*
* LICENSE: Eclipse Public License v1.0
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.ibm.gaiandb.udpdriver.client;
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.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Calendar;
import com.ibm.gaiandb.Logger;
import com.ibm.gaiandb.udpdriver.common.protocol.CloseRequest;
import com.ibm.gaiandb.udpdriver.common.protocol.ExecuteQueryRequest;
import com.ibm.gaiandb.udpdriver.common.protocol.ExecuteQueryResponse;
import com.ibm.gaiandb.udpdriver.common.protocol.Message;
import com.ibm.gaiandb.udpdriver.common.protocol.MessageFactory;
import com.ibm.gaiandb.udpdriver.common.protocol.MetaData;
import com.ibm.gaiandb.udpdriver.common.protocol.QueryRequest;
/**
* Implementation of java.sql.PreparedStatement
*
* @author lengelle
*
*/
public class UDPPreparedStatement extends UDPStatement implements PreparedStatement
{
// Use PROPRIETARY notice if class contains a main() method, otherwise use COPYRIGHT notice.
public static final String COPYRIGHT_NOTICE = "(c) Copyright IBM Corp. 2010";
private static final Logger logger = new Logger( "UDPPreparedStatement", 25 );
private String query;
private ParameterMetaData parameterMetaData;
private int[] parameterTypes;
private String[] parameterValues;
/**
* Instantiates a UDPPreparedStatement object.
*
* @param connection UDPConnection object that produced this statement
* @param sql SQL query
* @throws SQLException
*/
public UDPPreparedStatement( UDPConnection connection, String sql ) throws SQLException
{
super( connection );
query = sql;
queryID = this.createQueryId();
messageSequenceNumber = 0;
createNewEntryInMap();
prepareQuery(); // Initialize resultSetMetaData and parameterMetaData
if ( parameterMetaData.getParameterCount()!=0 )
{
parameterTypes = new int[ parameterMetaData.getParameterCount() ];
parameterValues = new String[ parameterMetaData.getParameterCount() ];
}
}
private void prepareQuery() throws SQLException
{
try
{
// Prepare and send a QueryRequest
QueryRequest queryRequest = MessageFactory.getQueryRequestMessage( queryID );
queryRequest.setSequenceNumber( messageSequenceNumber );
queryRequest.setStatementType( Message.PREPARED_STATEMENT );
queryRequest.setQuery( query );
MetaData metaData = sendQueryRequestAndReturnMetaData( queryRequest );
MessageFactory.returnMessage( queryRequest );
resultSetMetaData = new UDPResultSetMetaData( metaData );
parameterMetaData = new UDPParameterMetaData( metaData );
MessageFactory.returnMessage( metaData );
}
catch( Exception e )
{
throw new SQLException( "UDPPreparedStatement prepareQuery() failed. "+ e );
}
}
public void setInt( int parameterIndex, int theInt ) throws SQLException
{
// Careful : No security check in this version
parameterTypes[ parameterIndex-1 ] = Types.INTEGER;
parameterValues[ parameterIndex-1 ] = ""+theInt;
}
public void setString( int parameterIndex, String theString ) throws SQLException
{
// Careful : No security check in this version
parameterTypes[ parameterIndex-1 ] = Types.VARCHAR;
parameterValues[ parameterIndex-1 ] = theString;
}
public void setBytes( int parameterIndex, byte[] theBytes ) throws SQLException
{
// Careful : No security check in this version
parameterTypes[ parameterIndex-1 ] = Types.VARBINARY;
parameterValues[ parameterIndex-1 ] = new String( theBytes );
}
/* (non-Javadoc)
* @see java.sql.PreparedStatement#executeQuery()
*/
public ResultSet executeQuery() throws SQLException
{
try
{
// Build and send an ExecuteQueryRequest
ExecuteQueryRequest executeQueryRequest = MessageFactory.getExecuteQueryRequestMessage( queryID );
if ( resultSet == null )
{
executeQueryRequest.setSequenceNumber( ++messageSequenceNumber );
}
else
{
// If it is a re-execution, a NextValuesRequest message may have been sent
// in advance to the server. In this case the server is preparing, or has already
// prepared and sent back, a response with the previous sequence number + 1.
// The solution adopted here is to put a higher sequence number to make a gap between
// the latest sequence number sent and the new one.
messageSequenceNumber = resultSet.getMessageSequenceNumber();
executeQueryRequest.setSequenceNumber( messageSequenceNumber+=5 );
}
int parameterCount = parameterMetaData.getParameterCount();
if ( parameterCount > 0 )
{
if ( parameterTypes==null || parameterValues==null || parameterTypes.length!=parameterCount || parameterValues.length!=parameterCount )
{
throw new SQLException( "UDPPreparedStatement executeQuery() failed. PreparedStatement parameters are not correct." );
}
executeQueryRequest.setNumberOfParameters( parameterCount );
executeQueryRequest.setExecutiveParameterTypes( parameterTypes );
executeQueryRequest.setExecutiveParameters( parameterValues );
}
long clock1 = System.currentTimeMillis();
connection.sendMessage( executeQueryRequest.serializeMessage() );
MessageFactory.returnMessage( executeQueryRequest );
// Wait for an ExecuteQueryResponse
// DRV - 21/09/2011 - Removed use of adaptiveTimeout for ACITA 2011
// Reason: We need the client app timeout to be consistently higher than the inter-node timeout.
// Hence if a node disconnect at some point, partial results can still be retrieved from the remaining nodes and we don't just get a "Datagram lost" message...
Message message = connection.retreiveMessageFromMap(
queryID, ++messageSequenceNumber, Message.EXECUTE_QUERY_RESPONSE, getQueryTimeout()*1000 ); //UDPDriver.FIRST_TIMEOUT ); //adaptiveTimeout );
if ( message == null )
{
throw new SQLException( "Datagram lost on query execution !" );
}
ExecuteQueryResponse executeQueryResponse = ( ExecuteQueryResponse )message;
long clock2 = System.currentTimeMillis();
adaptiveTimeout = Math.max( adaptiveTimeout, ( ( clock2 - clock1 ) + UDPDriver.TIMEOUT_MARGIN ) );
if ( resultSet == null )
{
resultSet = new UDPResultSet( resultSetMetaData, this, executeQueryResponse );
}
else
{
resultSet.recycle( executeQueryResponse );
}
return resultSet;
}
catch( Exception e )
{
throw new SQLException( "UDPPreparedStatement executeQuery() failed. "+ e );
}
}
/* (non-Javadoc)
* @see java.sql.PreparedStatement#getMetaData()
*/
public ResultSetMetaData getMetaData() throws SQLException
{
return resultSetMetaData;
}
/* (non-Javadoc)
* @see java.sql.PreparedStatement#execute()
*/
public boolean execute() throws SQLException
{
resultSet = ( UDPResultSet ) executeQuery();
return true;
}
/* (non-Javadoc)
* @see com.ibm.gaiandb.udpdriver.client.UDPStatement#close()
*/
public void close() throws SQLException
{
try
{
if ( resultSet != null )
{
// Send a CLOSE_REQUEST to the server
// A NextValuesRequest message may have been sent
// in advance to the server. In this case the server is preparing, or has already
// prepared and sent back, a response with the previous sequence number + 1.
// The solution adopted here is to put a higher sequence number to make a gap between
// the latest sequence number sent and the new one.
CloseRequest closeRequest = MessageFactory.getCloseRequestMessage( queryID );
closeRequest.setSequenceNumber( resultSet.getMessageSequenceNumber() + 5 );
connection.sendMessage( closeRequest.serializeMessage() );
MessageFactory.returnMessage( closeRequest );
}
super.close();
resultSetMetaData = null;
query = null;
parameterMetaData = null;
parameterTypes = null;
parameterValues = null;
}
catch( Exception e )
{
throw new SQLException( "UDPPreparedStatement close() failed. "+ e );
}
}
public void addBatch() throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void clearParameters() throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public int executeUpdate() throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
return 0 ;
}
public ParameterMetaData getParameterMetaData() throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
return null ;
}
public void setArray( int parameterIndex, Array theArray )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setAsciiStream( int parameterIndex, InputStream x )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setAsciiStream( int parameterIndex, InputStream theInputStream,
int length ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setAsciiStream( int parameterIndex, InputStream x, long length )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setBigDecimal( int parameterIndex, BigDecimal theBigDecimal )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setBinaryStream( int parameterIndex, InputStream x )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setBinaryStream( int parameterIndex,
InputStream theInputStream, int length ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setBinaryStream( int parameterIndex, InputStream x, long length )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setBlob( int parameterIndex, Blob theBlob ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setBlob( int parameterIndex, InputStream inputStream )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setBlob( int parameterIndex, InputStream inputStream,
long length ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setBoolean( int parameterIndex, boolean theBoolean )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setByte( int parameterIndex, byte theByte ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setCharacterStream( int parameterIndex, Reader reader )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setCharacterStream( int parameterIndex, Reader reader,
int length ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setCharacterStream( int parameterIndex, Reader reader,
long length ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setClob( int parameterIndex, Clob theClob ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setClob( int parameterIndex, Reader reader )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setClob( int parameterIndex, Reader reader, long length )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setDate( int parameterIndex, Date theDate ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setDate( int parameterIndex, Date theDate, Calendar cal )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setDouble( int parameterIndex, double theDouble )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setFloat( int parameterIndex, float theFloat )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setLong( int parameterIndex, long theLong ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setNCharacterStream( int parameterIndex, Reader value )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setNCharacterStream( int parameterIndex, Reader value,
long length ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setNClob( int parameterIndex, NClob value ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setNClob( int parameterIndex, Reader reader )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setNClob( int parameterIndex, Reader reader, long length )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setNString( int parameterIndex, String value )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setNull( int parameterIndex, int sqlType ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setNull( int paramIndex, int sqlType, String typeName )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setObject( int parameterIndex, Object theObject )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setObject( int parameterIndex, Object theObject,
int targetSqlType ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setObject( int parameterIndex, Object theObject,
int targetSqlType, int scale ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setRef( int parameterIndex, Ref theRef ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setRowId( int parameterIndex, RowId x ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setSQLXML( int parameterIndex, SQLXML xmlObject )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setShort( int parameterIndex, short theShort )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setTime( int parameterIndex, Time theTime ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setTime( int parameterIndex, Time theTime, Calendar cal )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setTimestamp( int parameterIndex, Timestamp theTimestamp )
throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setTimestamp( int parameterIndex, Timestamp theTimestamp,
Calendar cal ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setURL( int parameterIndex, URL theURL ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
public void setUnicodeStream( int parameterIndex,
InputStream theInputStream, int length ) throws SQLException
{
logger.logAlways( "UDPPreparedStatement : Unimplemented method." );
}
}