net.sourceforge.jtds.jdbc
Class JtdsStatement

java.lang.Object
  extended bynet.sourceforge.jtds.jdbc.JtdsStatement
All Implemented Interfaces:
java.sql.Statement
Direct Known Subclasses:
JtdsPreparedStatement

public class JtdsStatement
extends java.lang.Object
implements java.sql.Statement

jTDS implementation of the java.sql.Statement interface.

NB. As allowed by the JDBC standard and like most other drivers, this implementation only allows one open result set at a time.

Implementation notes:

I experimented with allowing multiple open result sets as supported by the original jTDS but rejected this approach for the following reasons:

  1. It is more difficult to ensure that there are no memory leaks and that cursors are closed if multiple open sets are allowed.
  2. The use of one result set allows cursor and non cursor result sets to be derived from exeuteQuery() or execute() and getResultSet() in the same way that other drivers do.
In the event of an IO failure the setClosed() method forces this statement and associated result set to close preventing the propagation of errors. This class includes a finalize method which increases the chances of the statement being closed tidly in a pooled environment where the user has forgotten to explicitly close the statement before it goes out of scope.

Author:
Mike Hutchinson, Holger Rehn
See Also:
Statement, Connection.createStatement(), ResultSet

Field Summary
protected  java.util.ArrayList batchValues
          Batched SQL Statement array.
(package private) static int BOOLEAN
           
(package private) static int CLOSE_ALL_RESULTS
           
(package private) static int CLOSE_CURRENT_RESULT
           
private  int[] closed
          Meaning of the one and only array element at index : 0 - this statement is open 1 - this statement is currently being closed 2 - this statement is closed
protected  ColInfo[] colMetaData
          The cached column meta data.
protected  ConnectionJDBC2 connection
          The connection owning this statement object.
protected  JtdsResultSet currentResult
          The current ResultSet.
protected  java.lang.String cursorName
          The cursor name to be used for positioned updates.
(package private) static int DATALINK
           
(package private) static int DEFAULT_FETCH_SIZE
           
protected  boolean escapeProcessing
          True if SQL statements should be preprocessed.
(package private) static java.lang.Integer EXECUTE_FAILED
           
protected  int fetchDirection
          The fetch direction for result sets.
protected  int fetchSize
          The fetch size (default 100, only used by cursor ResultSets).
(package private) static java.lang.String GENKEYCOL
          Column name to be used for retrieving generated keys from the server: "_JTDS_GENE_RATED_KEYS_"
protected  CachedResultSet genKeyResultSet
          Dummy result set for getGeneratedKeys.
(package private) static int KEEP_CURRENT_RESULT
           
protected  int maxFieldSize
          The maximum field size (not used at present).
protected  int maxRows
          The maximum number of rows to return (not used at present).
protected  SQLDiagnostic messages
          SQL Diagnostic exceptions and warnings.
(package private) static int NO_GENERATED_KEYS
           
protected  java.util.ArrayList openResultSets
          List of open result sets.
protected  int queryTimeout
          The read query timeout in seconds
protected  java.util.LinkedList resultQueue
          List of queued results (update counts, possibly followed by a ResultSet).
protected  int resultSetConcurrency
          The concurrency of result sets created by this statement.
protected  int resultSetType
          The type of result sets created by this statement.
(package private) static int RETURN_GENERATED_KEYS
           
(package private) static java.lang.Integer SUCCESS_NO_INFO
           
protected  TdsCore tds
          The TDS object used for server access.
private  int updateCount
          The current update count.
 
Constructor Summary
(package private) JtdsStatement(ConnectionJDBC2 connection, int resultSetType, int resultSetConcurrency)
          Construct a new Statement object.
 
Method Summary
 void addBatch(java.lang.String sql)
           
(package private)  void addWarning(java.sql.SQLWarning w)
          Add an SQLWarning object to the statement warnings list.
protected  void cacheResults()
          Cache as many results as possible (up to the first ResultSet).
 void cancel()
           
protected  void checkCursorException(java.sql.SQLException e)
          Check that the exception is caused by the failure to open a cursor and not by a more serious SQL error.
protected  void checkOpen()
          Check that this statement is still open.
 void clearBatch()
           
 void clearWarnings()
           
 void close()
           
(package private)  void closeAllResultSets()
          Close all result sets.
(package private)  void closeCurrentResultSet()
          Close current result set (if any).
 boolean execute(java.lang.String sql)
           
 boolean execute(java.lang.String sql, int autoGeneratedKeys)
           
 boolean execute(java.lang.String sql, int[] columnIndexes)
           
 boolean execute(java.lang.String sql, java.lang.String[] columnNames)
           
 int[] executeBatch()
          Execute batch of SQL Statements.
private  boolean executeImpl(java.lang.String sql, int autoGeneratedKeys, boolean update)
          Implements the common functionality for plain statement execute(java.lang.String) and {#link #executeUpdate}: basic checks, cleaning up of previous results, setting up and executing the query and loading the first results.
protected  java.sql.SQLException executeMSBatch(int size, int executeSize, java.util.ArrayList counts)
          Execute the SQL batch on a MS server.
 java.sql.ResultSet executeQuery(java.lang.String sql)
           
protected  boolean executeSQL(java.lang.String sql, java.lang.String spName, ParamInfo[] params, boolean update, boolean useCursor)
          Executes any type of SQL.
protected  java.sql.ResultSet executeSQLQuery(java.lang.String sql, java.lang.String spName, ParamInfo[] params, boolean useCursor)
          Executes SQL to obtain a result set.
protected  java.sql.SQLException executeSybaseBatch(int size, int executeSize, java.util.ArrayList counts)
          Execute the SQL batch on a Sybase server.
 int executeUpdate(java.lang.String sql)
           
 int executeUpdate(java.lang.String sql, int autoGeneratedKeys)
           
 int executeUpdate(java.lang.String sql, int[] columnIndexes)
           
 int executeUpdate(java.lang.String sql, java.lang.String[] columnNames)
           
protected  void finalize()
          Called when this object goes out of scope to close any ResultSet object and this statement.
 java.sql.Connection getConnection()
           
(package private)  int getDefaultFetchSize()
          Retrieve the default fetch size for this statement.
 int getFetchDirection()
           
 int getFetchSize()
           
 java.sql.ResultSet getGeneratedKeys()
           
 int getMaxFieldSize()
           
 int getMaxRows()
           
(package private)  SQLDiagnostic getMessages()
          Get the statement's warnings list.
 boolean getMoreResults()
           
 boolean getMoreResults(int current)
           
 int getQueryTimeout()
           
 java.sql.ResultSet getResultSet()
           
 int getResultSetConcurrency()
           
 int getResultSetHoldability()
           
 int getResultSetType()
           
(package private)  TdsCore getTds()
          Get the Statement's TDS object.
 int getUpdateCount()
           
 java.sql.SQLWarning getWarnings()
           
 boolean isClosed()
           
(package private) static void notImplemented(java.lang.String method)
          Report that user tried to call a method which has not been implemented.
private  boolean processResults(boolean update)
          Queue up update counts into resultQueue until the end of the response is reached or a ResultSet is encountered.
protected  void reset()
          Resets the Statement, by cleaning up all queued and unprocessed results.
 void setCursorName(java.lang.String name)
           
 void setEscapeProcessing(boolean enable)
           
 void setFetchDirection(int direction)
           
 void setFetchSize(int rows)
           
 void setMaxFieldSize(int max)
           
 void setMaxRows(int max)
           
 void setQueryTimeout(int seconds)
           
protected  boolean useCursor(boolean returnKeys, java.lang.String sqlWord)
          Determines whether a cursor should be used based on the requested result set type and concurrency, whether a cursor name has been set, the useCursors connection property has been set, the first word in the SQL query is either SELECT or EXEC/EXECUTE and no generated keys are returned.
 
Methods inherited from class java.lang.Object
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

GENKEYCOL

static final java.lang.String GENKEYCOL
Column name to be used for retrieving generated keys from the server: "_JTDS_GENE_RATED_KEYS_"

See Also:
Constant Field Values

RETURN_GENERATED_KEYS

static final int RETURN_GENERATED_KEYS
See Also:
Constant Field Values

NO_GENERATED_KEYS

static final int NO_GENERATED_KEYS
See Also:
Constant Field Values

CLOSE_CURRENT_RESULT

static final int CLOSE_CURRENT_RESULT
See Also:
Constant Field Values

KEEP_CURRENT_RESULT

static final int KEEP_CURRENT_RESULT
See Also:
Constant Field Values

CLOSE_ALL_RESULTS

static final int CLOSE_ALL_RESULTS
See Also:
Constant Field Values

BOOLEAN

static final int BOOLEAN
See Also:
Constant Field Values

DATALINK

static final int DATALINK
See Also:
Constant Field Values

SUCCESS_NO_INFO

static final java.lang.Integer SUCCESS_NO_INFO

EXECUTE_FAILED

static final java.lang.Integer EXECUTE_FAILED

DEFAULT_FETCH_SIZE

static final int DEFAULT_FETCH_SIZE
See Also:
Constant Field Values

connection

protected ConnectionJDBC2 connection
The connection owning this statement object.


tds

protected TdsCore tds
The TDS object used for server access.


queryTimeout

protected int queryTimeout
The read query timeout in seconds


currentResult

protected JtdsResultSet currentResult
The current ResultSet.


updateCount

private int updateCount
The current update count.


fetchDirection

protected int fetchDirection
The fetch direction for result sets.


resultSetType

protected int resultSetType
The type of result sets created by this statement.


resultSetConcurrency

protected int resultSetConcurrency
The concurrency of result sets created by this statement.


fetchSize

protected int fetchSize
The fetch size (default 100, only used by cursor ResultSets).


cursorName

protected java.lang.String cursorName
The cursor name to be used for positioned updates.


maxFieldSize

protected int maxFieldSize
The maximum field size (not used at present).


maxRows

protected int maxRows
The maximum number of rows to return (not used at present).


escapeProcessing

protected boolean escapeProcessing
True if SQL statements should be preprocessed.


messages

protected final SQLDiagnostic messages
SQL Diagnostic exceptions and warnings.


batchValues

protected java.util.ArrayList batchValues
Batched SQL Statement array.


genKeyResultSet

protected CachedResultSet genKeyResultSet
Dummy result set for getGeneratedKeys.


resultQueue

protected final java.util.LinkedList resultQueue
List of queued results (update counts, possibly followed by a ResultSet).


openResultSets

protected java.util.ArrayList openResultSets
List of open result sets.


colMetaData

protected ColInfo[] colMetaData
The cached column meta data.


closed

private final int[] closed
Meaning of the one and only array element at index :
0 - this statement is open
1 - this statement is currently being closed
2 - this statement is closed

Constructor Detail

JtdsStatement

JtdsStatement(ConnectionJDBC2 connection,
              int resultSetType,
              int resultSetConcurrency)
        throws java.sql.SQLException
Construct a new Statement object.

Parameters:
connection - The parent connection.
resultSetType - The result set type for example TYPE_FORWARD_ONLY.
resultSetConcurrency - The concurrency for example CONCUR_READ_ONLY.
Method Detail

finalize

protected void finalize()
                 throws java.lang.Throwable
Called when this object goes out of scope to close any ResultSet object and this statement.

Throws:
java.lang.Throwable

getTds

TdsCore getTds()
Get the Statement's TDS object.

Returns:
The TDS support as a TdsCore Object.

getMessages

SQLDiagnostic getMessages()
Get the statement's warnings list.

Returns:
The warnings list as a SQLDiagnostic.

checkOpen

protected void checkOpen()
                  throws java.sql.SQLException
Check that this statement is still open.

Throws:
java.sql.SQLException - if statement closed.

checkCursorException

protected void checkCursorException(java.sql.SQLException e)
                             throws java.sql.SQLException
Check that the exception is caused by the failure to open a cursor and not by a more serious SQL error.

Parameters:
e - the exception returned by the cursor class
Throws:
java.sql.SQLException - if exception is not due to a cursor error

notImplemented

static void notImplemented(java.lang.String method)
                    throws java.sql.SQLException
Report that user tried to call a method which has not been implemented.

Parameters:
method - The method name to report in the error message.
Throws:
java.sql.SQLException

closeCurrentResultSet

void closeCurrentResultSet()
                     throws java.sql.SQLException
Close current result set (if any).

Throws:
java.sql.SQLException

closeAllResultSets

void closeAllResultSets()
                  throws java.sql.SQLException
Close all result sets.

Throws:
java.sql.SQLException

addWarning

void addWarning(java.sql.SQLWarning w)
Add an SQLWarning object to the statement warnings list.

Parameters:
w - The SQLWarning to add.

executeMSBatch

protected java.sql.SQLException executeMSBatch(int size,
                                               int executeSize,
                                               java.util.ArrayList counts)
                                        throws java.sql.SQLException
Execute the SQL batch on a MS server.

Parameters:
size - the total size of the batch
executeSize - the maximum number of statements to send in one request
counts - the returned update counts
Returns:
chained exceptions linked to a SQLException
Throws:
java.sql.SQLException - if a serious error occurs during execution

executeSybaseBatch

protected java.sql.SQLException executeSybaseBatch(int size,
                                                   int executeSize,
                                                   java.util.ArrayList counts)
                                            throws java.sql.SQLException
Execute the SQL batch on a Sybase server.

Sybase needs to have the SQL concatenated into one TDS language packet. This method will be overriden for PreparedStatements.

Parameters:
size - the total size of the batch
executeSize - the maximum number of statements to send in one request
counts - the returned update counts
Returns:
chained exceptions linked to a SQLException
Throws:
java.sql.SQLException - if a serious error occurs during execution

executeSQLQuery

protected java.sql.ResultSet executeSQLQuery(java.lang.String sql,
                                             java.lang.String spName,
                                             ParamInfo[] params,
                                             boolean useCursor)
                                      throws java.sql.SQLException
Executes SQL to obtain a result set.

Parameters:
sql - the SQL statement to execute
spName - optional stored procedure name
params - optional parameters
useCursor - whether a cursor should be created for the SQL
Returns:
the result set generated by the query
Throws:
java.sql.SQLException

executeSQL

protected boolean executeSQL(java.lang.String sql,
                             java.lang.String spName,
                             ParamInfo[] params,
                             boolean update,
                             boolean useCursor)
                      throws java.sql.SQLException
Executes any type of SQL.

Parameters:
sql - the SQL statement to execute
spName - optional stored procedure name
params - optional parameters
update - whether the caller is executeUpdate(java.lang.String)
useCursor - whether the requested result set type or concurrency or connection properties request usage of a cursor
Returns:
true if the first result is a result set
Throws:
java.sql.SQLException - if an error condition occurs

processResults

private boolean processResults(boolean update)
                        throws java.sql.SQLException
Queue up update counts into resultQueue until the end of the response is reached or a ResultSet is encountered. Calling processResults while a ResultSet is open will not close it, but will consume all remaining rows.

Parameters:
update - true if the method is called from within executeUpdate
Returns:
true if there are any results, false otherwise
Throws:
java.sql.SQLException - if an error condition occurs

cacheResults

protected void cacheResults()
                     throws java.sql.SQLException
Cache as many results as possible (up to the first ResultSet). Called by ResultSets when the end is reached.

Throws:
java.sql.SQLException

reset

protected void reset()
              throws java.sql.SQLException
Resets the Statement, by cleaning up all queued and unprocessed results. Called by all execute methods and close()

Throws:
java.sql.SQLException - if an error occurs

executeImpl

private boolean executeImpl(java.lang.String sql,
                            int autoGeneratedKeys,
                            boolean update)
                     throws java.sql.SQLException
Implements the common functionality for plain statement execute(java.lang.String) and {#link #executeUpdate}: basic checks, cleaning up of previous results, setting up and executing the query and loading the first results.

Parameters:
sql - an SQL INSERT, UPDATE or DELETE statement or an SQL statement that returns nothing, such as an SQL DDL statement
autoGeneratedKeys - a flag indicating whether auto-generated keys should be made available for retrieval
update - boolean flag indicating whether the caller is executeUpdate(java.lang.String) -- in this case an exception is thrown if the first result is not an update count and no cursor is created (direct execution)
Returns:
true if the first result is a ResultSet, false if it's an update count
Throws:
java.sql.SQLException
See Also:
execute(java.lang.String), executeUpdate(java.lang.String)

useCursor

protected boolean useCursor(boolean returnKeys,
                            java.lang.String sqlWord)
Determines whether a cursor should be used based on the requested result set type and concurrency, whether a cursor name has been set, the useCursors connection property has been set, the first word in the SQL query is either SELECT or EXEC/EXECUTE and no generated keys are returned.

Parameters:
returnKeys - indicates whether keys will be returned by the query
sqlWord - the first word in the SQL query; can be null if the caller is executeQuery(java.lang.String)
Returns:
true if a cursor should be used, false if not

getDefaultFetchSize

int getDefaultFetchSize()
Retrieve the default fetch size for this statement.

Returns:
the default fetch size for a new ResultSet

getFetchDirection

public int getFetchDirection()
                      throws java.sql.SQLException
Specified by:
getFetchDirection in interface java.sql.Statement
Throws:
java.sql.SQLException

getFetchSize

public int getFetchSize()
                 throws java.sql.SQLException
Specified by:
getFetchSize in interface java.sql.Statement
Throws:
java.sql.SQLException

getMaxFieldSize

public int getMaxFieldSize()
                    throws java.sql.SQLException
Specified by:
getMaxFieldSize in interface java.sql.Statement
Throws:
java.sql.SQLException

getMaxRows

public int getMaxRows()
               throws java.sql.SQLException
Specified by:
getMaxRows in interface java.sql.Statement
Throws:
java.sql.SQLException

getQueryTimeout

public int getQueryTimeout()
                    throws java.sql.SQLException
Specified by:
getQueryTimeout in interface java.sql.Statement
Throws:
java.sql.SQLException

getResultSetConcurrency

public int getResultSetConcurrency()
                            throws java.sql.SQLException
Specified by:
getResultSetConcurrency in interface java.sql.Statement
Throws:
java.sql.SQLException

getResultSetHoldability

public int getResultSetHoldability()
                            throws java.sql.SQLException
Specified by:
getResultSetHoldability in interface java.sql.Statement
Throws:
java.sql.SQLException

getResultSetType

public int getResultSetType()
                     throws java.sql.SQLException
Specified by:
getResultSetType in interface java.sql.Statement
Throws:
java.sql.SQLException

getUpdateCount

public int getUpdateCount()
                   throws java.sql.SQLException
Specified by:
getUpdateCount in interface java.sql.Statement
Throws:
java.sql.SQLException

cancel

public void cancel()
            throws java.sql.SQLException
Specified by:
cancel in interface java.sql.Statement
Throws:
java.sql.SQLException

clearBatch

public void clearBatch()
                throws java.sql.SQLException
Specified by:
clearBatch in interface java.sql.Statement
Throws:
java.sql.SQLException

clearWarnings

public void clearWarnings()
                   throws java.sql.SQLException
Specified by:
clearWarnings in interface java.sql.Statement
Throws:
java.sql.SQLException

close

public void close()
           throws java.sql.SQLException
Specified by:
close in interface java.sql.Statement
Throws:
java.sql.SQLException

getMoreResults

public boolean getMoreResults()
                       throws java.sql.SQLException
Specified by:
getMoreResults in interface java.sql.Statement
Throws:
java.sql.SQLException

executeBatch

public int[] executeBatch()
                   throws java.sql.SQLException,
                          java.sql.BatchUpdateException
Execute batch of SQL Statements.

The JDBC3 standard says that the behavior of this method must be consistent for any DBMS. As Sybase (and to a lesser extent SQL Server) will sometimes continue after a batch execution error, the only way to comply with the standard is to always return an array of update counts the same size as the batch list. Slots in the array beyond the last executed statement are set to EXECUTE_FAILED.

There is a problem with certain statements, returning more update counts than there are batch operations. (see bug [])

Specified by:
executeBatch in interface java.sql.Statement
Returns:
update counts as an int[]
Throws:
java.sql.SQLException
java.sql.BatchUpdateException

setFetchDirection

public void setFetchDirection(int direction)
                       throws java.sql.SQLException
Specified by:
setFetchDirection in interface java.sql.Statement
Throws:
java.sql.SQLException

setFetchSize

public void setFetchSize(int rows)
                  throws java.sql.SQLException
Specified by:
setFetchSize in interface java.sql.Statement
Throws:
java.sql.SQLException

setMaxFieldSize

public void setMaxFieldSize(int max)
                     throws java.sql.SQLException
Specified by:
setMaxFieldSize in interface java.sql.Statement
Throws:
java.sql.SQLException

setMaxRows

public void setMaxRows(int max)
                throws java.sql.SQLException
Specified by:
setMaxRows in interface java.sql.Statement
Throws:
java.sql.SQLException

setQueryTimeout

public void setQueryTimeout(int seconds)
                     throws java.sql.SQLException
Specified by:
setQueryTimeout in interface java.sql.Statement
Throws:
java.sql.SQLException

getMoreResults

public boolean getMoreResults(int current)
                       throws java.sql.SQLException
Specified by:
getMoreResults in interface java.sql.Statement
Throws:
java.sql.SQLException

setEscapeProcessing

public void setEscapeProcessing(boolean enable)
                         throws java.sql.SQLException
Specified by:
setEscapeProcessing in interface java.sql.Statement
Throws:
java.sql.SQLException

executeUpdate

public int executeUpdate(java.lang.String sql)
                  throws java.sql.SQLException
Specified by:
executeUpdate in interface java.sql.Statement
Throws:
java.sql.SQLException

addBatch

public void addBatch(java.lang.String sql)
              throws java.sql.SQLException
Specified by:
addBatch in interface java.sql.Statement
Throws:
java.sql.SQLException

setCursorName

public void setCursorName(java.lang.String name)
                   throws java.sql.SQLException
Specified by:
setCursorName in interface java.sql.Statement
Throws:
java.sql.SQLException

execute

public boolean execute(java.lang.String sql)
                throws java.sql.SQLException
Specified by:
execute in interface java.sql.Statement
Throws:
java.sql.SQLException

executeUpdate

public int executeUpdate(java.lang.String sql,
                         int autoGeneratedKeys)
                  throws java.sql.SQLException
Specified by:
executeUpdate in interface java.sql.Statement
Throws:
java.sql.SQLException

execute

public boolean execute(java.lang.String sql,
                       int autoGeneratedKeys)
                throws java.sql.SQLException
Specified by:
execute in interface java.sql.Statement
Throws:
java.sql.SQLException

executeUpdate

public int executeUpdate(java.lang.String sql,
                         int[] columnIndexes)
                  throws java.sql.SQLException
Specified by:
executeUpdate in interface java.sql.Statement
Throws:
java.sql.SQLException

execute

public boolean execute(java.lang.String sql,
                       int[] columnIndexes)
                throws java.sql.SQLException
Specified by:
execute in interface java.sql.Statement
Throws:
java.sql.SQLException

getConnection

public java.sql.Connection getConnection()
                                  throws java.sql.SQLException
Specified by:
getConnection in interface java.sql.Statement
Throws:
java.sql.SQLException

getGeneratedKeys

public java.sql.ResultSet getGeneratedKeys()
                                    throws java.sql.SQLException
Specified by:
getGeneratedKeys in interface java.sql.Statement
Throws:
java.sql.SQLException

getResultSet

public java.sql.ResultSet getResultSet()
                                throws java.sql.SQLException
Specified by:
getResultSet in interface java.sql.Statement
Throws:
java.sql.SQLException

getWarnings

public java.sql.SQLWarning getWarnings()
                                throws java.sql.SQLException
Specified by:
getWarnings in interface java.sql.Statement
Throws:
java.sql.SQLException

executeUpdate

public int executeUpdate(java.lang.String sql,
                         java.lang.String[] columnNames)
                  throws java.sql.SQLException
Specified by:
executeUpdate in interface java.sql.Statement
Throws:
java.sql.SQLException

execute

public boolean execute(java.lang.String sql,
                       java.lang.String[] columnNames)
                throws java.sql.SQLException
Specified by:
execute in interface java.sql.Statement
Throws:
java.sql.SQLException

executeQuery

public java.sql.ResultSet executeQuery(java.lang.String sql)
                                throws java.sql.SQLException
Specified by:
executeQuery in interface java.sql.Statement
Throws:
java.sql.SQLException

isClosed

public boolean isClosed()
                 throws java.sql.SQLException
Returns:
whether this JtdsStatement has been closed
Throws:
java.sql.SQLException


Generated on October 27 2012