Categories:
Audio (13)
Biotech (29)
Bytecode (36)
Database (77)
Framework (7)
Game (7)
General (507)
Graphics (53)
I/O (35)
IDE (2)
JAR Tools (101)
JavaBeans (21)
JDBC (121)
JDK (426)
JSP (20)
Logging (108)
Mail (58)
Messaging (8)
Network (84)
PDF (97)
Report (7)
Scripting (84)
Security (32)
Server (121)
Servlet (26)
SOAP (24)
Testing (54)
Web (15)
XML (309)
Collections:
Other Resources:
jTDS JDBC Driver Source Code Files
jTDS JDBC Driver Source Code Files are provided in the source package file, jtds-1.3.1-fyi.zip.
You can browse jTDS JDBC Driver Source Code files below:
✍: FYIcenter.com
⏎ net/sourceforge/jtds/jdbc/JtdsStatement.java
// jTDS JDBC Driver for Microsoft SQL Server and Sybase // Copyright (C) 2004 The jTDS Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA package net.sourceforge.jtds.jdbc; import java.sql.BatchUpdateException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Types; import java.util.ArrayList; import java.util.LinkedList; import java.util.concurrent.atomic.AtomicInteger; /** * jTDS implementation of the java.sql.Statement interface.<p> * NB. As allowed by the JDBC standard and like most other drivers, * this implementation only allows one open result set at a time. * <p> * Implementation notes: * <p> * I experimented with allowing multiple open result sets as supported * by the original jTDS but rejected this approach for the following * reasons: * <ol> * <li>It is more difficult to ensure that there are no memory leaks and that * cursors are closed if multiple open sets are allowed. * <li>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. * </ol> * 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. * * @see * java.sql.Statement * * @see * java.sql.Connection#createStatement() * * @see * java.sql.ResultSet * * @author * Mike Hutchinson, Holger Rehn */ public class JtdsStatement implements java.sql.Statement { /** * Column name to be used for retrieving generated keys from the server: * "_JTDS_GENE_RATED_KEYS_" */ static final String GENKEYCOL = "_JTDS_GENE_R_ATED_KEYS_"; /* * Constants used for backwards compatibility with JDK 1.3 */ static final int RETURN_GENERATED_KEYS = 1; static final int NO_GENERATED_KEYS = 2; static final int CLOSE_CURRENT_RESULT = 1; static final int KEEP_CURRENT_RESULT = 2; static final int CLOSE_ALL_RESULTS = 3; static final int BOOLEAN = 16; static final int DATALINK = 70; static final Integer SUCCESS_NO_INFO = new Integer(-2); static final Integer EXECUTE_FAILED = new Integer(-3); static final int DEFAULT_FETCH_SIZE = 100; /** The connection owning this statement object. */ protected JtdsConnection connection; /** The TDS object used for server access. */ protected TdsCore tds; /** The read query timeout in seconds */ protected int queryTimeout; /** The current <code>ResultSet</code>. */ protected JtdsResultSet currentResult; /** The current update count. */ private int updateCount = -1; /** The fetch direction for result sets. */ protected int fetchDirection = ResultSet.FETCH_FORWARD; /** The type of result sets created by this statement. */ protected int resultSetType = ResultSet.TYPE_FORWARD_ONLY; /** The concurrency of result sets created by this statement. */ protected int resultSetConcurrency = ResultSet.CONCUR_READ_ONLY; /** The fetch size (default 100, only used by cursor * <code>ResultSet</code>s). */ protected int fetchSize = DEFAULT_FETCH_SIZE; /** The cursor name to be used for positioned updates. */ protected String cursorName; /** The maximum field size (not used at present). */ protected int maxFieldSize; /** The maximum number of rows to return (not used at present). */ protected int maxRows; /** True if SQL statements should be preprocessed. */ protected boolean escapeProcessing = true; /** SQL Diagnostic exceptions and warnings. */ protected final SQLDiagnostic messages; /** Batched SQL Statement array. */ protected ArrayList batchValues; /** Dummy result set for getGeneratedKeys. */ protected CachedResultSet genKeyResultSet; /** * List of queued results (update counts, possibly followed by a * <code>ResultSet</code>). */ protected final LinkedList resultQueue = new LinkedList(); /** List of open result sets. */ protected ArrayList openResultSets; /** The cached column meta data. */ protected ColInfo[] colMetaData; /** * <table> * <tr> * <td>0</td> * <td>- this statement is open</td> * </tr> * <tr> * <td>1</td> * <td>- this statement is currently being closed</td> * </tr> * <tr> * <td>2</td> * <td>- this statement is closed</td> * </tr> * </table> */ private final AtomicInteger _Closed = new AtomicInteger(); /** * Construct a new Statement object. * * @param connection The parent connection. * @param resultSetType The result set type for example TYPE_FORWARD_ONLY. * @param resultSetConcurrency The concurrency for example CONCUR_READ_ONLY. */ JtdsStatement(JtdsConnection connection, int resultSetType, int resultSetConcurrency) throws SQLException { // // This is a good point to do common validation of the result set type // if (resultSetType < ResultSet.TYPE_FORWARD_ONLY || resultSetType > ResultSet.TYPE_SCROLL_SENSITIVE + 1) { String method; if (this instanceof JtdsCallableStatement) { method = "prepareCall"; } else if (this instanceof JtdsPreparedStatement) { method = "prepareStatement"; } else { method = "createStatement"; } throw new SQLException( Messages.get("error.generic.badparam", "resultSetType", method), "HY092"); } // // Ditto for the result set concurrency // if (resultSetConcurrency < ResultSet.CONCUR_READ_ONLY || resultSetConcurrency > ResultSet.CONCUR_UPDATABLE + 2) { String method; if (this instanceof JtdsCallableStatement) { method = "prepareCall"; } else if (this instanceof JtdsPreparedStatement) { method = "prepareStatement"; } else { method = "createStatement"; } throw new SQLException( Messages.get("error.generic.badparam", "resultSetConcurrency", method), "HY092"); } this.connection = connection; this.resultSetType = resultSetType; this.resultSetConcurrency = resultSetConcurrency; tds = connection.getCachedTds(); if (tds == null) { messages = new SQLDiagnostic(connection.getServerType()); tds = new TdsCore(this.connection, messages); } else { messages = tds.getMessages(); } } /** * Called when this object goes out of scope to close any * <code>ResultSet</code> object and this statement. */ protected void finalize() throws Throwable { super.finalize(); try { close(); } catch (SQLException e) { // Ignore errors } } /** * Get the Statement's TDS object. * * @return The TDS support as a <code>TdsCore</core> Object. */ TdsCore getTds() { return tds; } /** * Get the statement's warnings list. * * @return The warnings list as a <code>SQLDiagnostic</code>. */ SQLDiagnostic getMessages() { return messages; } /** * Check that this statement is still open. * * @throws SQLException if statement closed. */ protected void checkOpen() throws SQLException { if (isClosed()) throw new SQLException( Messages.get("error.generic.closed", "Statement"), "HY010"); } /** * Check that the exception is caused by the failure to open a * cursor and not by a more serious SQL error. * * @param e the exception returned by the cursor class * @throws SQLException if exception is not due to a cursor error */ protected void checkCursorException(SQLException e) throws SQLException{ if (connection == null || connection.isClosed() || "HYT00".equals(e.getSQLState()) || "HY008".equals(e.getSQLState())) { // Serious error or timeout so return exception to caller throw e; } if (connection.getServerType() == Driver.SYBASE) { // Allow retry for Sybase return; } // // Check cursor specific errors and ranges for SQL Server // int error = e.getErrorCode(); if (error >= 16900 && error <= 16999) { // Errors in this range are all related to the cursor API. // This is true for all versions of SQL Server. return; } if (error == 6819) { // A FOR XML clause was found return; } if (error == 8654) { // A inrow textptr exists return; } if (error == 8162) { // Formal parameter '%.*ls' was defined as OUTPUT but the actual // parameter not declared OUTPUT. This happens when trying to // execute a stored procedure with output parameters via a cursor. return; } // // More serious error we should rethrow the error and // not allow the driver to re-execute sql. // throw e; } /** * Report that user tried to call a method which has not been implemented. * * @param method The method name to report in the error message. * @throws SQLException */ static void notImplemented(String method) throws SQLException { throw new SQLException( Messages.get("error.generic.notimp", method), "HYC00"); } /** * Close current result set (if any). */ void closeCurrentResultSet() throws SQLException { try { if (currentResult != null) { currentResult.close(); } // } catch (SQLException e) { // Ignore } finally { currentResult = null; } } /** * Close all result sets. */ void closeAllResultSets() throws SQLException { try { if (openResultSets != null) { for (int i = 0; i < openResultSets.size(); i++) { JtdsResultSet rs = (JtdsResultSet) openResultSets.get(i); if (rs != null) { rs.close(); } } } closeCurrentResultSet(); } finally { openResultSets = null; } } /** * Add an SQLWarning object to the statement warnings list. * * @param w The SQLWarning to add. */ void addWarning(SQLWarning w) { messages.addWarning(w); } /** * Execute the SQL batch on a MS server. * * @param size the total size of the batch * @param executeSize the maximum number of statements to send in one request * @param counts the returned update counts * @return chained exceptions linked to a <code>SQLException</code> * @throws SQLException if a serious error occurs during execution */ protected SQLException executeMSBatch(int size, int executeSize, ArrayList counts) throws SQLException { SQLException sqlEx = null; for (int i = 0; i < size;) { Object value = batchValues.get(i); ++i; // Execute batch now if max size reached or end of batch boolean executeNow = (i % executeSize == 0) || i == size; tds.startBatch(); tds.executeSQL((String) value, null, null, false, 0, -1, -1, executeNow); // If the batch has been sent, process the results if (executeNow) { sqlEx = tds.getBatchCounts(counts, sqlEx); // If a serious error then we stop execution now as count // is too small. if (sqlEx != null && counts.size() != i) { break; } } } return sqlEx; } /** * Execute the SQL batch on a Sybase server. * <p/> * Sybase needs to have the SQL concatenated into one TDS language packet. This method will be overriden for * <code>PreparedStatements</code>. * * @param size the total size of the batch * @param executeSize the maximum number of statements to send in one request * @param counts the returned update counts * @return chained exceptions linked to a <code>SQLException</code> * @throws SQLException if a serious error occurs during execution */ protected SQLException executeSybaseBatch(int size, int executeSize, ArrayList counts) throws SQLException { StringBuilder sql = new StringBuilder(size * 32); // Make buffer reasonable size SQLException sqlEx = null; for (int i = 0; i < size;) { Object value = batchValues.get(i); ++i; // Execute batch now if max size reached or end of batch boolean executeNow = (i % executeSize == 0) || i == size; sql.append((String) value).append(' '); if (executeNow) { tds.executeSQL(sql.toString(), null, null, false, 0, -1, -1, true); sql.setLength(0); // If the batch has been sent, process the results sqlEx = tds.getBatchCounts(counts, sqlEx); // If a serious error or a server error then we stop // execution now as count is too small. if (sqlEx != null && counts.size() != i) { break; } } } return sqlEx; } /** * Executes SQL to obtain a result set. * * @param sql the SQL statement to execute * @param spName optional stored procedure name * @param params optional parameters * @param useCursor whether a cursor should be created for the SQL * @return the result set generated by the query */ protected ResultSet executeSQLQuery(String sql, String spName, ParamInfo[] params, boolean useCursor) throws SQLException { String warningMessage = null; // // Try to open a cursor result set if required // if (useCursor) { try { if (connection.getServerType() == Driver.SQLSERVER) { currentResult = new MSCursorResultSet(this, sql, spName, params, resultSetType, resultSetConcurrency); return currentResult; } else { // Use client side cursor for Sybase currentResult = new CachedResultSet(this, sql, spName, params, resultSetType, resultSetConcurrency); return currentResult; } } catch (SQLException e) { checkCursorException(e); warningMessage = '[' + e.getSQLState() + "] " + e.getMessage(); } } // // Could not open a cursor (or was not requested) so try a direct select // if (spName != null && connection.getUseMetadataCache() && connection.getPrepareSql() == TdsCore.PREPARE && colMetaData != null && connection.getServerType() == Driver.SQLSERVER) { // There is cached meta data available for this // prepared statement tds.setColumns(colMetaData); tds.executeSQL(sql, spName, params, true, queryTimeout, maxRows, maxFieldSize, true); } else { tds.executeSQL(sql, spName, params, false, queryTimeout, maxRows, maxFieldSize, true); } // Update warning chain if cursor was downgraded before processing results if (warningMessage != null) { addWarning(new SQLWarning( Messages.get("warning.cursordowngraded", warningMessage), "01000")); } // Ignore update counts preceding the result set. All drivers seem to // do this. while (!tds.getMoreResults() && !tds.isEndOfResponse()); // check for server side errors messages.checkErrors(); if (tds.isResultSet()) { currentResult = new JtdsResultSet(this, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, tds.getColumns()); } else { throw new SQLException( Messages.get("error.statement.noresult"), "24000"); } return currentResult; } /** * Executes any type of SQL. * * @param sql the SQL statement to execute * @param spName optional stored procedure name * @param params optional parameters * @param update whether the caller is {@link #executeUpdate} * @param useCursor whether the requested result set type or concurrency * or connection properties request usage of a cursor * @return <code>true</code> if the first result is a result set * @throws SQLException if an error condition occurs */ protected boolean executeSQL(String sql, String spName, ParamInfo[] params, boolean update, boolean useCursor) throws SQLException { String warningMessage = null; // // For SQL Server, try to open a cursor result set if required // (and possible). // if (connection.getServerType() == Driver.SQLSERVER && !update && useCursor) { try { currentResult = new MSCursorResultSet(this, sql, spName, params, resultSetType, resultSetConcurrency); return true; } catch (SQLException e) { checkCursorException(e); warningMessage = '[' + e.getSQLState() + "] " + e.getMessage(); } } // // We are talking to a Sybase server or we could not open a cursor // or we did not have a SELECT so just execute the SQL normally. // tds.executeSQL(sql, spName, params, false, queryTimeout, maxRows, maxFieldSize, true); if (warningMessage != null) { // Update warning chain if cursor was downgraded addWarning(new SQLWarning(Messages.get( "warning.cursordowngraded", warningMessage), "01000")); } if (processResults(update)) { Object nextResult = resultQueue.removeFirst(); // Next result is an update count if (nextResult instanceof Integer) { updateCount = ((Integer) nextResult).intValue(); return false; } // Next result is a ResultSet. Set currentResult and remove it. currentResult = (JtdsResultSet) nextResult; return true; } else { return false; } } /** * Queue up update counts into {@link #resultQueue} until the end of the * response is reached or a <code>ResultSet</code> is encountered. Calling * <code>processResults</code> while a <code>ResultSet</code> is open will * not close it, but will consume all remaining rows. * * @param update * <code>true</code> if the method is called from within * <code>executeUpdate</code> * * @return * <code>true</code> if there are any results, <code>false</code> otherwise * * @throws SQLException * if an error condition occurs */ private boolean processResults( boolean update ) throws SQLException { if( ! resultQueue.isEmpty() ) throw new IllegalStateException( "There should be no queued results." ); while( !tds.isEndOfResponse() ) { if( !tds.getMoreResults() ) { if( tds.isUpdateCount() ) { if( update && connection.getLastUpdateCount() ) { resultQueue.clear(); } resultQueue.addLast( new Integer( tds.getUpdateCount() ) ); } } else { // get column layout of the resultset ColInfo[] columns = tds.getColumns(); // ensure this is the generated key by checking column layout if( columns.length == 1 && columns[0].name.equals( GENKEYCOL ) ) { // fix column name columns[0].name = "ID"; // drop previously received generated keys genKeyResultSet = null; /* * FIXME: If there already was a ResultSet holding generated keys * we should just add an additional row instead, but this is only * possible if we are able to buffer rows to disk to prevent high * memory consumption. * * Note: This would only apply if column layout is identical. */ // add all generated keys in the resultset (possible memory leak) while( tds.getNextRow() ) { if( genKeyResultSet == null ) { // start new ResultSet, containing the first generated key genKeyResultSet = new CachedResultSet( this, tds.getColumns(), tds.getRowData() ); } else { // add additional generated key genKeyResultSet.addRow( tds.getRowData() ); } } } else { if( update && resultQueue.isEmpty() ) { // throw exception but queue up any previous ones SQLException ex = new SQLException( Messages.get( "error.statement.nocount" ), "07000" ); ex.setNextException( messages.exceptions ); throw ex; } // this also clears computed data in TdsCore Object[] computed = tds.getComputedRowData(); if( computed != null ) { // create computed result set resultQueue.add( new CachedResultSet( this, tds.getComputedColumns(), computed ) ); } else { resultQueue.add( new JtdsResultSet( this, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, tds.getColumns() ) ); } break; } } } // Check for server side errors getMessages().checkErrors(); return !resultQueue.isEmpty(); } /** * Cache as many results as possible (up to the first * <code>ResultSet</code>). Called by <code>ResultSet</code>s when the * end is reached. */ protected void cacheResults() throws SQLException { // Cache results processResults(false); } /** * Resets the <code>Statement</code>, by cleaning up all queued and * unprocessed results. Called by all execute methods and {@link #close()} * * @throws SQLException * if an error occurs */ protected void reset() throws SQLException { updateCount = -1; resultQueue.clear(); genKeyResultSet = null; // consume all response tokens // REVIEW: shouldn't we issue a cancel first to stop the server from sending more data? tds.clearResponseQueue(); // don't throw old exceptions, they belong to a previous execution messages.clearWarnings(); messages.exceptions = null; closeAllResultSets(); } /** * Implements the common functionality for plain statement {@link #execute} * and {#link #executeUpdate}: basic checks, cleaning up of previous * results, setting up and executing the query and loading the first * results. * * @param sql an SQL <code>INSERT</code>, <code>UPDATE</code> or * <code>DELETE</code> statement or an SQL statement that * returns nothing, such as an SQL DDL statement * @param autoGeneratedKeys a flag indicating whether auto-generated keys * should be made available for retrieval * @param update boolean flag indicating whether the caller is * {@link #executeUpdate} -- in this case an exception is * thrown if the first result is not an update count and no * cursor is created (direct execution) * @return <code>true</code> if the first result is a * <code>ResultSet</code>, <code>false</code> if it's an update * count * @see #execute * @see #executeUpdate */ private boolean executeImpl(String sql, int autoGeneratedKeys, boolean update) throws SQLException { reset(); if (sql == null || sql.length() == 0) { throw new SQLException(Messages.get("error.generic.nosql"), "HY000"); } String sqlWord = ""; if (escapeProcessing) { String tmp[] = SQLParser.parse(sql, null, connection, false); if (tmp[1].length() != 0) { throw new SQLException( Messages.get("error.statement.badsql"), "07000"); } sql = tmp[0]; sqlWord = tmp[2]; } else { // Escape processing turned off so // see if we can extract "insert" from start of statement sql = sql.trim(); if (sql.length() > 5) { sqlWord = sql.substring(0,6).toLowerCase(); } } boolean returnKeys; if (autoGeneratedKeys == RETURN_GENERATED_KEYS) { // REVIEW: how would this fail and why? // // this will fail if we execute multiple statements at once and the first isn't an INSERT // returnKeys = "insert".equals(sqlWord); returnKeys = true; } else if (autoGeneratedKeys == NO_GENERATED_KEYS) { returnKeys = false; } else { throw new SQLException( Messages.get("error.generic.badoption", Integer.toString(autoGeneratedKeys), "autoGeneratedKeys"), "HY092"); } if (returnKeys) { if (connection.getServerType() == Driver.SQLSERVER && connection.getDatabaseMajorVersion() >= 8) { sql += " SELECT SCOPE_IDENTITY() AS " + GENKEYCOL; } else { sql += " SELECT @@IDENTITY AS " + GENKEYCOL; } } return executeSQL(sql, null, null, update, !update && useCursor(returnKeys, 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 * <code>useCursors</code> connection property has been set, the first * word in the SQL query is either SELECT or EXEC/EXECUTE and no generated * keys are returned. * * @param returnKeys indicates whether keys will be returned by the query * @param sqlWord the first word in the SQL query; can be * <code>null</code> if the caller is * {@link #executeQuery} * @return <code>true</code> if a cursor should be used, <code>false</code> * if not */ protected boolean useCursor(boolean returnKeys, String sqlWord) { return (resultSetType != ResultSet.TYPE_FORWARD_ONLY || resultSetConcurrency != ResultSet.CONCUR_READ_ONLY || connection.getUseCursors() || cursorName != null) && !returnKeys && (sqlWord == null || "select".equals(sqlWord) || sqlWord.startsWith("exec")); } /** * Retrieve the default fetch size for this statement. * * @return the default fetch size for a new <code>ResultSet</code> */ int getDefaultFetchSize() { return (0 < maxRows && maxRows < DEFAULT_FETCH_SIZE) ? maxRows : DEFAULT_FETCH_SIZE; } // ------------------ java.sql.Statement methods ---------------------- public int getFetchDirection() throws SQLException { checkOpen(); return fetchDirection; } public int getFetchSize() throws SQLException { checkOpen(); return fetchSize; } public int getMaxFieldSize() throws SQLException { checkOpen(); return maxFieldSize; } public int getMaxRows() throws SQLException { checkOpen(); return maxRows; } public int getQueryTimeout() throws SQLException { checkOpen(); return queryTimeout; } public int getResultSetConcurrency() throws SQLException { checkOpen(); return resultSetConcurrency; } public int getResultSetHoldability() throws SQLException { checkOpen(); return JtdsResultSet.HOLD_CURSORS_OVER_COMMIT; } public int getResultSetType() throws SQLException { checkOpen(); return resultSetType; } public int getUpdateCount() throws SQLException { checkOpen(); return updateCount; } public void cancel() throws SQLException { checkOpen(); if (tds != null) { tds.cancel(false); } } public void clearBatch() throws SQLException { checkOpen(); if (batchValues != null) { batchValues.clear(); } } public void clearWarnings() throws SQLException { checkOpen(); messages.clearWarnings(); } @Override public void close() throws SQLException { // set to 'now closing' if( _Closed.compareAndSet( 0, 1 ) ) { SQLException releaseEx = null; try { /* The re-initialization has been added in revision [1196], replacing * most of the error handling done before. * * The problem is, that in releaseTds() we completely consume the * response queue, including error tokens produced in response to a * previous statement. But we don't want to throw an exception from * close() just because a previous statement failed, as in: * * st.executeUpdate( "create table #Bug559 (A int, unique (A))" ); * try * { * st.executeUpdate( "select 1;insert into #Bug559 values(1);insert into #Bug559 values(1)" ); * fail(); * } * catch( SQLException e ) * { * // expected, executeUpdate() cannot return a resultset * } * st.close(); // <- unique constraint violation error before [1196] * * Here, the second insert fails because of a unique constraint * violation. But the driver will already have aborted execution * because the first statement returns a resultset which is not * allowed when calling executeUpdate(), so close() would then throw * the unique constraint violation error. * * Since we are closing the Statement, all we care about are errors * that are directly related to closing, not previous SQL statements. */ // drop previous errors and warnings and consume all response tokens reset(); try { if( ! connection.isClosed() ) { connection.releaseTds( tds ); } // check for server side errors tds.getMessages().checkErrors(); } catch( SQLException ex ) { // remember any exception thrown releaseEx = ex; } finally { // set closed flag, closeAllResultSets() still required statement // to be 'open' _Closed.set( 2 ); // clean up everything tds = null; connection.removeStatement( this ); connection = null; } } finally { // re-throw statement close exception if( releaseEx != null ) { throw releaseEx; } } } } public boolean getMoreResults() throws SQLException { checkOpen(); return getMoreResults(CLOSE_ALL_RESULTS); } /** * Execute batch of SQL Statements. * <p/> * 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 <code>EXECUTE_FAILED</code>. <p/> * * There is a problem with certain statements, returning more update counts * than there are batch operations. (see bug []) * * @return update counts as an <code>int[]</code> */ public int[] executeBatch() throws SQLException, BatchUpdateException { checkOpen(); reset(); if (batchValues == null || batchValues.size() == 0) { return new int[0]; } int size = batchValues.size(); int executeSize = connection.getBatchSize(); executeSize = (executeSize == 0) ? Integer.MAX_VALUE : executeSize; SQLException sqlEx; ArrayList counts = new ArrayList(size); try { // Lock the connection, making sure the batch executes atomically. This is especially important in the // case of prepared statement batches (where we don't want the prepares rolled back before being executed) // but should also provide some level of sanity in the general case. synchronized (connection) { if (connection.getServerType() == Driver.SYBASE && connection.getTdsVersion() == Driver.TDS50) { sqlEx = executeSybaseBatch(size, executeSize, counts); } else { sqlEx = executeMSBatch(size, executeSize, counts); } } // Ensure array is the same size as the original statement list int updateCounts[] = new int[size]; // Copy the update counts into the int array int results = counts.size(); for (int i = 0; i < results && i < size; i++) { updateCounts[i] = ((Integer) counts.get(i)).intValue(); } // Pad any remaining slots with EXECUTE_FAILED for (int i = results; i < updateCounts.length; i++) { updateCounts[i] = EXECUTE_FAILED.intValue(); } // See if we should return an exception if (sqlEx != null) { BatchUpdateException batchEx = new BatchUpdateException(sqlEx.getMessage(), sqlEx.getSQLState(), sqlEx.getErrorCode(), updateCounts); // Chain any other exceptions batchEx.setNextException(sqlEx.getNextException()); throw batchEx; } return updateCounts; } catch (BatchUpdateException ex) { // If it's a BatchUpdateException let it go throw ex; } catch (SQLException ex) { // An SQLException can only occur while sending the batch // (getBatchCounts() doesn't throw SQLExceptions), so we have to // end the batch and return the partial results // FIXME What should we send here to flush out the batch? // Come to think of it, is there any circumstance under which this // could actually happen without the connection getting closed? // No counts will have been returned either as last packet will not // have been sent. throw new BatchUpdateException(ex.getMessage(), ex.getSQLState(), ex.getErrorCode(), new int[0]); } finally { clearBatch(); } } public void setFetchDirection(int direction) throws SQLException { checkOpen(); switch (direction) { case ResultSet.FETCH_UNKNOWN: case ResultSet.FETCH_REVERSE: case ResultSet.FETCH_FORWARD: fetchDirection = direction; break; default: throw new SQLException( Messages.get("error.generic.badoption", Integer.toString(direction), "direction"), "24000"); } } public void setFetchSize(int rows) throws SQLException { checkOpen(); if (rows < 0) { throw new SQLException( Messages.get("error.generic.optltzero", "setFetchSize"), "HY092"); } else if (maxRows > 0 && rows > maxRows) { throw new SQLException( Messages.get("error.statement.gtmaxrows"), "HY092"); } if (rows == 0) { rows = getDefaultFetchSize(); } fetchSize = rows; } public void setMaxFieldSize(int max) throws SQLException { checkOpen(); if (max < 0) { throw new SQLException( Messages.get("error.generic.optltzero", "setMaxFieldSize"), "HY092"); } maxFieldSize = max; } public void setMaxRows(int max) throws SQLException { checkOpen(); if (max < 0) { throw new SQLException( Messages.get("error.generic.optltzero", "setMaxRows"), "HY092"); } if (max > 0 && max < fetchSize) { // Just for consistency with setFetchSize() fetchSize = max; } maxRows = max; } public void setQueryTimeout(int seconds) throws SQLException { checkOpen(); if (seconds < 0) { throw new SQLException( Messages.get("error.generic.optltzero", "setQueryTimeout"), "HY092"); } queryTimeout = seconds; } public boolean getMoreResults(int current) throws SQLException { checkOpen(); switch (current) { case CLOSE_ALL_RESULTS: updateCount = -1; closeAllResultSets(); break; case CLOSE_CURRENT_RESULT: updateCount = -1; closeCurrentResultSet(); break; case KEEP_CURRENT_RESULT: updateCount = -1; // If there is an open result set it is transferred to // the list of open result sets. For JtdsResultSet // result sets we cache the remaining data. For CachedResultSet // result sets the data is already cached. if (openResultSets == null) { openResultSets = new ArrayList(); } if (currentResult instanceof MSCursorResultSet || currentResult instanceof CachedResultSet) { // NB. Due to restrictions on the way API cursors are // created, MSCursorResultSet can never be followed by // any other result sets, update counts or return variables. openResultSets.add(currentResult); } else if (currentResult != null) { currentResult.cacheResultSetRows(); openResultSets.add(currentResult); } currentResult = null; break; default: throw new SQLException( Messages.get("error.generic.badoption", Integer.toString(current), "current"), "HY092"); } // Check for server side errors messages.checkErrors(); // Dequeue any results if (!resultQueue.isEmpty() || processResults(false)) { Object nextResult = resultQueue.removeFirst(); // Next result is an update count if (nextResult instanceof Integer) { updateCount = ((Integer) nextResult).intValue(); return false; } // Next result is a ResultSet. Set currentResult and remove it. currentResult = (JtdsResultSet) nextResult; return true; } else { return false; } } public void setEscapeProcessing(boolean enable) throws SQLException { checkOpen(); escapeProcessing = enable; } public int executeUpdate(String sql) throws SQLException { return executeUpdate(sql, NO_GENERATED_KEYS); } public void addBatch(String sql) throws SQLException { checkOpen(); if (sql == null) { throw new NullPointerException(); } if (batchValues == null) { batchValues = new ArrayList(); } if (escapeProcessing) { String tmp[] = SQLParser.parse(sql, null, connection, false); if (tmp[1].length() != 0) { throw new SQLException( Messages.get("error.statement.badsql"), "07000"); } sql = tmp[0]; } batchValues.add(sql); } public void setCursorName(String name) throws SQLException { checkOpen(); cursorName = name; if (name != null) { // Reset statement type to JDBC 1 default. resultSetType = ResultSet.TYPE_FORWARD_ONLY; fetchSize = 1; // Needed for positioned updates } } public boolean execute(String sql) throws SQLException { checkOpen(); return executeImpl(sql, NO_GENERATED_KEYS, false); } public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { checkOpen(); executeImpl(sql, autoGeneratedKeys, true); int res = getUpdateCount(); return res == -1 ? 0 : res; } public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { checkOpen(); return executeImpl(sql, autoGeneratedKeys, false); } public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { checkOpen(); if (columnIndexes == null) { throw new SQLException( Messages.get("error.generic.nullparam", "executeUpdate"),"HY092"); } else if (columnIndexes.length != 1) { throw new SQLException( Messages.get("error.generic.needcolindex", "executeUpdate"),"HY092"); } return executeUpdate(sql, RETURN_GENERATED_KEYS); } public boolean execute(String sql, int[] columnIndexes) throws SQLException { checkOpen(); if (columnIndexes == null) { throw new SQLException( Messages.get("error.generic.nullparam", "execute"),"HY092"); } else if (columnIndexes.length != 1) { throw new SQLException( Messages.get("error.generic.needcolindex", "execute"),"HY092"); } return executeImpl(sql, RETURN_GENERATED_KEYS, false); } @Override public Connection getConnection() throws SQLException { checkOpen(); return connection; } @Override public ResultSet getGeneratedKeys() throws SQLException { checkOpen(); if( genKeyResultSet == null ) { // create and return an empty result set genKeyResultSet = new CachedResultSet( this, new String[] { "ID" }, new int[] { Types.INTEGER } ); } // non't allow manipulation genKeyResultSet.setConcurrency( ResultSet.CONCUR_READ_ONLY ); return genKeyResultSet; } public ResultSet getResultSet() throws SQLException { checkOpen(); // if (currentResult instanceof MSCursorResultSet || currentResult instanceof CachedResultSet) { return currentResult; } // // See if we are returning a forward read only resultset // if (currentResult == null || (resultSetType == ResultSet.TYPE_FORWARD_ONLY && resultSetConcurrency == ResultSet.CONCUR_READ_ONLY)) { return currentResult; } // // OK Now create a CachedResultSet based on the existng result set. // currentResult = new CachedResultSet(currentResult, true); return currentResult; } public SQLWarning getWarnings() throws SQLException { checkOpen(); return messages.getWarnings(); } public int executeUpdate(String sql, String[] columnNames) throws SQLException { checkOpen(); if (columnNames == null) { throw new SQLException( Messages.get("error.generic.nullparam", "executeUpdate"),"HY092"); } else if (columnNames.length != 1) { throw new SQLException( Messages.get("error.generic.needcolname", "executeUpdate"),"HY092"); } return executeUpdate(sql, RETURN_GENERATED_KEYS); } public boolean execute(String sql, String[] columnNames) throws SQLException { checkOpen(); if (columnNames == null) { throw new SQLException( Messages.get("error.generic.nullparam", "execute"),"HY092"); } else if (columnNames.length != 1) { throw new SQLException( Messages.get("error.generic.needcolname", "execute"),"HY092"); } return executeImpl(sql, RETURN_GENERATED_KEYS, false); } public ResultSet executeQuery(String sql) throws SQLException { checkOpen(); reset(); if (sql == null || sql.length() == 0) { throw new SQLException(Messages.get("error.generic.nosql"), "HY000"); } if (escapeProcessing) { String tmp[] = SQLParser.parse(sql, null, connection, false); if (tmp[1].length() != 0) { throw new SQLException( Messages.get("error.statement.badsql"), "07000"); } sql = tmp[0]; } return executeSQLQuery(sql, null, null, useCursor(false, null)); } /** * @return * whether this {@link JtdsStatement} has been closed */ @Override public boolean isClosed() throws SQLException { return _Closed.get() == 2; } /* (non-Javadoc) * @see java.sql.Statement#isPoolable() */ public boolean isPoolable() throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.Statement#setPoolable(boolean) */ public void setPoolable(boolean poolable) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.Wrapper#isWrapperFor(java.lang.Class) */ public boolean isWrapperFor(Class arg0) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } @Override public <T> T unwrap(Class<T> iface) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } //// JDBC4.1 demarcation, do NOT put any JDBC3/4.0 code below this line //// @Override public void closeOnCompletion() throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } @Override public boolean isCloseOnCompletion() throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } }
⏎ net/sourceforge/jtds/jdbc/JtdsStatement.java
Or download all of them as a single archive file:
File name: jtds-1.3.1-fyi.zip File size: 323160 bytes Release date: 2013-06-08 Download
⇐ What Is jtds-1.3.1-dist.zip?
2016-11-26, 7833👍, 0💬
Popular Posts:
ASM is an all purpose Java bytecode manipulation and analysis framework. It can be used to modify ex...
JDK 11 java.rmi.jmod is the JMOD file for JDK 11 RMI (Remote Method Invocation) module. JDK 11 RMI m...
Apache Avalon began in 1999 as the Java Apache Server Framework and in late 2002 separated from the ...
How to download and install javamail-1_2.zip? The JavaMail API is a set of abstract APIs that model ...
What Is commons-net-ftp-2.0.jar? commons-net-ftp-2.0.jar is the JAR file for Apache Commons Net FTP ...