/EQEmuJSM/mysql-connector-java-5.1.13/src/com/mysql/jdbc/StatementImpl.java
Java | 2330 lines | 1351 code | 443 blank | 536 comment | 346 complexity | 65431cd0d5b3185453b3403960574e3e MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, Apache-2.0
Large files files are truncated, but you can click here to view the full file
- /*
- Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- The MySQL Connector/J is licensed under the terms of the GPL,
- like most MySQL Connectors. There are special exceptions to the
- terms and conditions of the GPL as it is applied to this software,
- see the FLOSS License Exception available on mysql.com.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; version 2 of the
- License.
- This program 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 General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- 02110-1301 USA
- */
- package com.mysql.jdbc;
- import java.io.InputStream;
- import java.math.BigInteger;
- import java.sql.BatchUpdateException;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.SQLWarning;
- import java.sql.Types;
- import java.util.ArrayList;
- import java.util.Calendar;
- import java.util.GregorianCalendar;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Set;
- import java.util.TimerTask;
- import com.mysql.jdbc.exceptions.MySQLStatementCancelledException;
- import com.mysql.jdbc.exceptions.MySQLTimeoutException;
- import com.mysql.jdbc.profiler.ProfilerEvent;
- import com.mysql.jdbc.profiler.ProfilerEventHandler;
- /**
- * A Statement object is used for executing a static SQL statement and obtaining
- * the results produced by it.
- *
- * <p>
- * Only one ResultSet per Statement can be open at any point in time. Therefore,
- * if the reading of one ResultSet is interleaved with the reading of another,
- * each must have been generated by different Statements. All statement execute
- * methods implicitly close a statement's current ResultSet if an open one
- * exists.
- * </p>
- *
- * @author Mark Matthews
- * @version $Id: Statement.java 4624 2005-11-28 14:24:29 -0600 (Mon, 28 Nov
- * 2005) mmatthews $
- *
- * @see java.sql.Statement
- * @see ResultSetInternalMethods
- */
- public class StatementImpl implements Statement {
- protected static final String PING_MARKER = "/* ping */";
- /**
- * Thread used to implement query timeouts...Eventually we could be more
- * efficient and have one thread with timers, but this is a straightforward
- * and simple way to implement a feature that isn't used all that often.
- */
- class CancelTask extends TimerTask {
- long connectionId = 0;
- SQLException caughtWhileCancelling = null;
- StatementImpl toCancel;
-
- CancelTask(StatementImpl cancellee) throws SQLException {
- connectionId = connection.getIO().getThreadId();
- toCancel = cancellee;
- }
- public void run() {
- Thread cancelThread = new Thread() {
- public void run() {
- if (connection.getQueryTimeoutKillsConnection()) {
- try {
- toCancel.wasCancelled = true;
- toCancel.wasCancelledByTimeout = true;
- connection.realClose(false, false, true,
- new MySQLStatementCancelledException(Messages.getString("Statement.ConnectionKilledDueToTimeout")));
- } catch (NullPointerException npe) {
- // not worth guarding against
- } catch (SQLException sqlEx) {
- caughtWhileCancelling = sqlEx;
- }
- } else {
- Connection cancelConn = null;
- java.sql.Statement cancelStmt = null;
-
- try {
- synchronized (cancelTimeoutMutex) {
- cancelConn = connection.duplicate();
- cancelStmt = cancelConn.createStatement();
- cancelStmt.execute("KILL QUERY " + connectionId);
- toCancel.wasCancelled = true;
- toCancel.wasCancelledByTimeout = true;
- }
- } catch (SQLException sqlEx) {
- caughtWhileCancelling = sqlEx;
- } catch (NullPointerException npe) {
- // Case when connection closed while starting to cancel
- // We can't easily synchronize this, because then one thread
- // can't cancel() a running query
-
- // ignore, we shouldn't re-throw this, because the connection's
- // already closed, so the statement has been timed out.
- } finally {
- if (cancelStmt != null) {
- try {
- cancelStmt.close();
- } catch (SQLException sqlEx) {
- throw new RuntimeException(sqlEx.toString());
- }
- }
-
- if (cancelConn != null) {
- try {
- cancelConn.close();
- } catch (SQLException sqlEx) {
- throw new RuntimeException(sqlEx.toString());
- }
- }
-
- toCancel = null;
- }
- }
- }
- };
- cancelThread.start();
- }
- }
- /** Mutex to prevent race between returning query results and noticing
- that we're timed-out or cancelled. */
- protected Object cancelTimeoutMutex = new Object();
- /** Used to generate IDs when profiling. */
- protected static int statementCounter = 1;
- public final static byte USES_VARIABLES_FALSE = 0;
- public final static byte USES_VARIABLES_TRUE = 1;
- public final static byte USES_VARIABLES_UNKNOWN = -1;
- protected boolean wasCancelled = false;
- protected boolean wasCancelledByTimeout = false;
- /** Holds batched commands */
- protected List batchedArgs;
- /** The character converter to use (if available) */
- protected SingleByteCharsetConverter charConverter = null;
- /** The character encoding to use (if available) */
- protected String charEncoding = null;
- /** The connection that created us */
- protected MySQLConnection connection = null;
- protected long connectionId = 0;
- /** The catalog in use */
- protected String currentCatalog = null;
- /** Should we process escape codes? */
- protected boolean doEscapeProcessing = true;
- /** If we're profiling, where should events go to? */
- protected ProfilerEventHandler eventSink = null;
- /** The number of rows to fetch at a time (currently ignored) */
- private int fetchSize = 0;
- /** Has this statement been closed? */
- protected boolean isClosed = false;
- /** The auto_increment value for the last insert */
- protected long lastInsertId = -1;
- /** The max field size for this statement */
- protected int maxFieldSize = MysqlIO.getMaxBuf();
- /**
- * The maximum number of rows to return for this statement (-1 means _all_
- * rows)
- */
- protected int maxRows = -1;
- /** Has someone changed this for this statement? */
- protected boolean maxRowsChanged = false;
- /** Set of currently-open ResultSets */
- protected Set openResults = new HashSet();
- /** Are we in pedantic mode? */
- protected boolean pedantic = false;
- /**
- * Where this statement was created, only used if profileSql or
- * useUsageAdvisor set to true.
- */
- protected Throwable pointOfOrigin;
- /** Should we profile? */
- protected boolean profileSQL = false;
- /** The current results */
- protected ResultSetInternalMethods results = null;
- /** The concurrency for this result set (updatable or not) */
- protected int resultSetConcurrency = 0;
- /** The type of this result set (scroll sensitive or in-sensitive) */
- protected int resultSetType = 0;
- /** Used to identify this statement when profiling. */
- protected int statementId;
- /** The timeout for a query */
- protected int timeoutInMillis = 0;
- /** The update count for this statement */
- protected long updateCount = -1;
- /** Should we use the usage advisor? */
- protected boolean useUsageAdvisor = false;
- /** The warnings chain. */
- protected SQLWarning warningChain = null;
- /**
- * Should this statement hold results open over .close() irregardless of
- * connection's setting?
- */
- protected boolean holdResultsOpenOverClose = false;
- protected ArrayList batchedGeneratedKeys = null;
- protected boolean retrieveGeneratedKeys = false;
- protected boolean continueBatchOnError = false;
- protected PingTarget pingTarget = null;
-
- protected boolean useLegacyDatetimeCode;
-
- private ExceptionInterceptor exceptionInterceptor;
-
- /** Whether or not the last query was of the form ON DUPLICATE KEY UPDATE */
- protected boolean lastQueryIsOnDupKeyUpdate = false;
-
- /**
- * Constructor for a Statement.
- *
- * @param c
- * the Connection instantation that creates us
- * @param catalog
- * the database name in use when we were created
- *
- * @throws SQLException
- * if an error occurs.
- */
- public StatementImpl(MySQLConnection c, String catalog) throws SQLException {
- if ((c == null) || c.isClosed()) {
- throw SQLError.createSQLException(
- Messages.getString("Statement.0"), //$NON-NLS-1$
- SQLError.SQL_STATE_CONNECTION_NOT_OPEN, null); //$NON-NLS-1$ //$NON-NLS-2$
- }
- this.connection = c;
- this.connectionId = this.connection.getId();
- this.exceptionInterceptor = this.connection
- .getExceptionInterceptor();
- this.currentCatalog = catalog;
- this.pedantic = this.connection.getPedantic();
- this.continueBatchOnError = this.connection.getContinueBatchOnError();
- this.useLegacyDatetimeCode = this.connection.getUseLegacyDatetimeCode();
-
- if (!this.connection.getDontTrackOpenResources()) {
- this.connection.registerStatement(this);
- }
- //
- // Adjust, if we know it
- //
- if (this.connection != null) {
- this.maxFieldSize = this.connection.getMaxAllowedPacket();
- int defaultFetchSize = this.connection.getDefaultFetchSize();
- if (defaultFetchSize != 0) {
- setFetchSize(defaultFetchSize);
- }
- }
- if (this.connection.getUseUnicode()) {
- this.charEncoding = this.connection.getEncoding();
- this.charConverter = this.connection.getCharsetConverter(this.charEncoding);
- }
- boolean profiling = this.connection.getProfileSql()
- || this.connection.getUseUsageAdvisor() || this.connection.getLogSlowQueries();
- if (this.connection.getAutoGenerateTestcaseScript() || profiling) {
- this.statementId = statementCounter++;
- }
- if (profiling) {
- this.pointOfOrigin = new Throwable();
- this.profileSQL = this.connection.getProfileSql();
- this.useUsageAdvisor = this.connection.getUseUsageAdvisor();
- this.eventSink = ProfilerEventHandlerFactory.getInstance(this.connection);
- }
- int maxRowsConn = this.connection.getMaxRows();
- if (maxRowsConn != -1) {
- setMaxRows(maxRowsConn);
- }
-
- this.holdResultsOpenOverClose = this.connection.getHoldResultsOpenOverStatementClose();
- }
- /**
- * DOCUMENT ME!
- *
- * @param sql
- * DOCUMENT ME!
- *
- * @throws SQLException
- * DOCUMENT ME!
- */
- public synchronized void addBatch(String sql) throws SQLException {
- if (this.batchedArgs == null) {
- this.batchedArgs = new ArrayList();
- }
- if (sql != null) {
- this.batchedArgs.add(sql);
- }
- }
- /**
- * Cancels this Statement object if both the DBMS and driver support
- * aborting an SQL statement. This method can be used by one thread to
- * cancel a statement that is being executed by another thread.
- */
- public void cancel() throws SQLException {
- if (!this.isClosed &&
- this.connection != null &&
- this.connection.versionMeetsMinimum(5, 0, 0)) {
- Connection cancelConn = null;
- java.sql.Statement cancelStmt = null;
- try {
- cancelConn = this.connection.duplicate();
- cancelStmt = cancelConn.createStatement();
- cancelStmt.execute("KILL QUERY "
- + this.connection.getIO().getThreadId());
- this.wasCancelled = true;
- } finally {
- if (cancelStmt != null) {
- cancelStmt.close();
- }
- if (cancelConn != null) {
- cancelConn.close();
- }
- }
- }
- }
- // --------------------------JDBC 2.0-----------------------------
- /**
- * Checks if closed() has been called, and throws an exception if so
- *
- * @throws SQLException
- * if this statement has been closed
- */
- protected void checkClosed() throws SQLException {
- if (this.isClosed) {
- throw SQLError.createSQLException(Messages
- .getString("Statement.49"), //$NON-NLS-1$
- SQLError.SQL_STATE_CONNECTION_NOT_OPEN, getExceptionInterceptor()); //$NON-NLS-1$
- }
- }
- /**
- * Checks if the given SQL query with the given first non-ws char is a DML
- * statement. Throws an exception if it is.
- *
- * @param sql
- * the SQL to check
- * @param firstStatementChar
- * the UC first non-ws char of the statement
- *
- * @throws SQLException
- * if the statement contains DML
- */
- protected void checkForDml(String sql, char firstStatementChar)
- throws SQLException {
- if ((firstStatementChar == 'I') || (firstStatementChar == 'U')
- || (firstStatementChar == 'D') || (firstStatementChar == 'A')
- || (firstStatementChar == 'C')) {
- String noCommentSql = StringUtils.stripComments(sql,
- "'\"", "'\"", true, false, true, true);
- if (StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "INSERT") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "UPDATE") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "DELETE") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "DROP") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "CREATE") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "ALTER")) { //$NON-NLS-1$
- throw SQLError.createSQLException(Messages
- .getString("Statement.57"), //$NON-NLS-1$
- SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
- }
- }
- }
- /**
- * Method checkNullOrEmptyQuery.
- *
- * @param sql
- * the SQL to check
- *
- * @throws SQLException
- * if query is null or empty.
- */
- protected void checkNullOrEmptyQuery(String sql) throws SQLException {
- if (sql == null) {
- throw SQLError.createSQLException(Messages
- .getString("Statement.59"), //$NON-NLS-1$
- SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ //$NON-NLS-2$
- }
- if (sql.length() == 0) {
- throw SQLError.createSQLException(Messages
- .getString("Statement.61"), //$NON-NLS-1$
- SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
- /**
- * JDBC 2.0 Make the set of commands in the current batch empty. This method
- * is optional.
- *
- * @exception SQLException
- * if a database-access error occurs, or the driver does not
- * support batch statements
- */
- public synchronized void clearBatch() throws SQLException {
- if (this.batchedArgs != null) {
- this.batchedArgs.clear();
- }
- }
- /**
- * After this call, getWarnings returns null until a new warning is reported
- * for this Statement.
- *
- * @exception SQLException
- * if a database access error occurs (why?)
- */
- public void clearWarnings() throws SQLException {
- this.warningChain = null;
- }
- /**
- * In many cases, it is desirable to immediately release a Statement's
- * database and JDBC resources instead of waiting for this to happen when it
- * is automatically closed. The close method provides this immediate
- * release.
- *
- * <p>
- * <B>Note:</B> A Statement is automatically closed when it is garbage
- * collected. When a Statement is closed, its current ResultSet, if one
- * exists, is also closed.
- * </p>
- *
- * @exception SQLException
- * if a database access error occurs
- */
- public synchronized void close() throws SQLException {
- realClose(true, true);
- }
- /**
- * Close any open result sets that have been 'held open'
- */
- protected synchronized void closeAllOpenResults() {
- if (this.openResults != null) {
- for (Iterator iter = this.openResults.iterator(); iter.hasNext();) {
- ResultSetInternalMethods element = (ResultSetInternalMethods) iter.next();
- try {
- element.realClose(false);
- } catch (SQLException sqlEx) {
- AssertionFailedException.shouldNotHappen(sqlEx);
- }
- }
- this.openResults.clear();
- }
- }
- public synchronized void removeOpenResultSet(ResultSet rs) {
- if (this.openResults != null) {
- this.openResults.remove(rs);
- }
- }
-
- public synchronized int getOpenResultSetCount() {
- if (this.openResults != null) {
- return this.openResults.size();
- }
-
- return 0;
- }
-
- /**
- * @param sql
- * @return
- */
- private ResultSetInternalMethods createResultSetUsingServerFetch(String sql)
- throws SQLException {
- java.sql.PreparedStatement pStmt = this.connection.prepareStatement(
- sql, this.resultSetType, this.resultSetConcurrency);
- pStmt.setFetchSize(this.fetchSize);
- if (this.maxRows > -1) {
- pStmt.setMaxRows(this.maxRows);
- }
- pStmt.execute();
- //
- // Need to be able to get resultset irrespective if we issued DML or
- // not to make this work.
- //
- ResultSetInternalMethods rs = ((com.mysql.jdbc.StatementImpl) pStmt)
- .getResultSetInternal();
- rs
- .setStatementUsedForFetchingRows((com.mysql.jdbc.PreparedStatement) pStmt);
- this.results = rs;
- return rs;
- }
- /**
- * We only stream result sets when they are forward-only, read-only, and the
- * fetch size has been set to Integer.MIN_VALUE
- *
- * @return true if this result set should be streamed row at-a-time, rather
- * than read all at once.
- */
- protected boolean createStreamingResultSet() {
- return ((this.resultSetType == java.sql.ResultSet.TYPE_FORWARD_ONLY)
- && (this.resultSetConcurrency == java.sql.ResultSet.CONCUR_READ_ONLY) && (this.fetchSize == Integer.MIN_VALUE));
- }
- private int originalResultSetType = 0;
- private int originalFetchSize = 0;
- /* (non-Javadoc)
- * @see com.mysql.jdbc.IStatement#enableStreamingResults()
- */
- public void enableStreamingResults() throws SQLException {
- this.originalResultSetType = this.resultSetType;
- this.originalFetchSize = this.fetchSize;
- setFetchSize(Integer.MIN_VALUE);
- setResultSetType(ResultSet.TYPE_FORWARD_ONLY);
- }
- public void disableStreamingResults() throws SQLException {
- if (this.fetchSize == Integer.MIN_VALUE &&
- this.resultSetType == ResultSet.TYPE_FORWARD_ONLY) {
- setFetchSize(this.originalFetchSize);
- setResultSetType(this.originalResultSetType);
- }
- }
- /**
- * Execute a SQL statement that may return multiple results. We don't have
- * to worry about this since we do not support multiple ResultSets. You can
- * use getResultSet or getUpdateCount to retrieve the result.
- *
- * @param sql
- * any SQL statement
- *
- * @return true if the next result is a ResulSet, false if it is an update
- * count or there are no more results
- *
- * @exception SQLException
- * if a database access error occurs
- */
- public boolean execute(String sql) throws SQLException {
- return execute(sql, false);
- }
-
- private boolean execute(String sql, boolean returnGeneratedKeys) throws SQLException {
- checkClosed();
- MySQLConnection locallyScopedConn = this.connection;
- synchronized (locallyScopedConn.getMutex()) {
- this.retrieveGeneratedKeys = returnGeneratedKeys;
- lastQueryIsOnDupKeyUpdate = false;
- if (returnGeneratedKeys)
- lastQueryIsOnDupKeyUpdate = containsOnDuplicateKeyInString(sql);
-
- resetCancelledState();
- checkNullOrEmptyQuery(sql);
- checkClosed();
- char firstNonWsChar = StringUtils.firstAlphaCharUc(sql, findStartOfStatement(sql));
- boolean isSelect = true;
- if (firstNonWsChar != 'S') {
- isSelect = false;
- if (locallyScopedConn.isReadOnly()) {
- throw SQLError.createSQLException(Messages
- .getString("Statement.27") //$NON-NLS-1$
- + Messages.getString("Statement.28"), //$NON-NLS-1$
- SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
- }
- }
- boolean doStreaming = createStreamingResultSet();
- // Adjust net_write_timeout to a higher value if we're
- // streaming result sets. More often than not, someone runs into
- // an issue where they blow net_write_timeout when using this
- // feature, and if they're willing to hold a result set open
- // for 30 seconds or more, one more round-trip isn't going to hurt
- //
- // This is reset by RowDataDynamic.close().
- if (doStreaming
- && locallyScopedConn.getNetTimeoutForStreamingResults() > 0) {
- executeSimpleNonQuery(locallyScopedConn, "SET net_write_timeout="
- + locallyScopedConn.getNetTimeoutForStreamingResults());
- }
- if (this.doEscapeProcessing) {
- Object escapedSqlResult = EscapeProcessor.escapeSQL(sql,
- locallyScopedConn.serverSupportsConvertFn(), locallyScopedConn);
- if (escapedSqlResult instanceof String) {
- sql = (String) escapedSqlResult;
- } else {
- sql = ((EscapeProcessorResult) escapedSqlResult).escapedSql;
- }
- }
- if (this.results != null) {
- if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) {
- this.results.realClose(false);
- }
- }
- if (sql.charAt(0) == '/') {
- if (sql.startsWith(PING_MARKER)) {
- doPingInstead();
-
- return true;
- }
- }
- CachedResultSetMetaData cachedMetaData = null;
- ResultSetInternalMethods rs = null;
- // If there isn't a limit clause in the SQL
- // then limit the number of rows to return in
- // an efficient manner. Only do this if
- // setMaxRows() hasn't been used on any Statements
- // generated from the current Connection (saves
- // a query, and network traffic).
- this.batchedGeneratedKeys = null;
- if (useServerFetch()) {
- rs = createResultSetUsingServerFetch(sql);
- } else {
- CancelTask timeoutTask = null;
- String oldCatalog = null;
- try {
- if (locallyScopedConn.getEnableQueryTimeouts() &&
- this.timeoutInMillis != 0
- && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
- timeoutTask = new CancelTask(this);
- locallyScopedConn.getCancelTimer().schedule(timeoutTask,
- this.timeoutInMillis);
- }
- if (!locallyScopedConn.getCatalog().equals(
- this.currentCatalog)) {
- oldCatalog = locallyScopedConn.getCatalog();
- locallyScopedConn.setCatalog(this.currentCatalog);
- }
- //
- // Check if we have cached metadata for this query...
- //
- Field[] cachedFields = null;
- if (locallyScopedConn.getCacheResultSetMetadata()) {
- cachedMetaData = locallyScopedConn.getCachedMetaData(sql);
- if (cachedMetaData != null) {
- cachedFields = cachedMetaData.fields;
- }
- }
- //
- // Only apply max_rows to selects
- //
- if (locallyScopedConn.useMaxRows()) {
- int rowLimit = -1;
- if (isSelect) {
- if (StringUtils.indexOfIgnoreCase(sql, "LIMIT") != -1) { //$NON-NLS-1$
- rowLimit = this.maxRows;
- } else {
- if (this.maxRows <= 0) {
- executeSimpleNonQuery(locallyScopedConn,
- "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
- } else {
- executeSimpleNonQuery(locallyScopedConn,
- "SET OPTION SQL_SELECT_LIMIT="
- + this.maxRows);
- }
- }
- } else {
- executeSimpleNonQuery(locallyScopedConn,
- "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
- }
- // Finally, execute the query
- rs = locallyScopedConn.execSQL(this, sql, rowLimit, null,
- this.resultSetType, this.resultSetConcurrency,
- doStreaming,
- this.currentCatalog, cachedFields);
- } else {
- rs = locallyScopedConn.execSQL(this, sql, -1, null,
- this.resultSetType, this.resultSetConcurrency,
- doStreaming,
- this.currentCatalog, cachedFields);
- }
- if (timeoutTask != null) {
- if (timeoutTask.caughtWhileCancelling != null) {
- throw timeoutTask.caughtWhileCancelling;
- }
- timeoutTask.cancel();
- timeoutTask = null;
- }
- synchronized (this.cancelTimeoutMutex) {
- if (this.wasCancelled) {
- SQLException cause = null;
-
- if (this.wasCancelledByTimeout) {
- cause = new MySQLTimeoutException();
- } else {
- cause = new MySQLStatementCancelledException();
- }
-
- resetCancelledState();
-
- throw cause;
- }
- }
- } finally {
- if (timeoutTask != null) {
- timeoutTask.cancel();
- locallyScopedConn.getCancelTimer().purge();
- }
- if (oldCatalog != null) {
- locallyScopedConn.setCatalog(oldCatalog);
- }
- }
- }
- if (rs != null) {
- this.lastInsertId = rs.getUpdateID();
- this.results = rs;
- rs.setFirstCharOfQuery(firstNonWsChar);
- if (rs.reallyResult()) {
- if (cachedMetaData != null) {
- locallyScopedConn.initializeResultsMetadataFromCache(sql, cachedMetaData,
- this.results);
- } else {
- if (this.connection.getCacheResultSetMetadata()) {
- locallyScopedConn.initializeResultsMetadataFromCache(sql,
- null /* will be created */, this.results);
- }
- }
- }
- }
- return ((rs != null) && rs.reallyResult());
- }
- }
- protected synchronized void resetCancelledState() {
- if (this.cancelTimeoutMutex == null) {
- return;
- }
-
- synchronized (this.cancelTimeoutMutex) {
- this.wasCancelled = false;
- this.wasCancelledByTimeout = false;
- }
- }
- /**
- * @see StatementImpl#execute(String, int)
- */
- public boolean execute(String sql, int returnGeneratedKeys)
- throws SQLException {
- if (returnGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS) {
- checkClosed();
- MySQLConnection locallyScopedConn = this.connection;
- synchronized (locallyScopedConn.getMutex()) {
- // If this is a 'REPLACE' query, we need to be able to parse
- // the 'info' message returned from the server to determine
- // the actual number of keys generated.
- boolean readInfoMsgState = this.connection
- .isReadInfoMsgEnabled();
- locallyScopedConn.setReadInfoMsgEnabled(true);
- try {
- return execute(sql, true);
- } finally {
- locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState);
- }
- }
- }
- return execute(sql);
- }
- /**
- * @see StatementImpl#execute(String, int[])
- */
- public boolean execute(String sql, int[] generatedKeyIndices)
- throws SQLException {
- if ((generatedKeyIndices != null) && (generatedKeyIndices.length > 0)) {
- checkClosed();
- MySQLConnection locallyScopedConn = this.connection;
- synchronized (locallyScopedConn.getMutex()) {
- this.retrieveGeneratedKeys = true;
-
- // If this is a 'REPLACE' query, we need to be able to parse
- // the 'info' message returned from the server to determine
- // the actual number of keys generated.
- boolean readInfoMsgState = locallyScopedConn
- .isReadInfoMsgEnabled();
- locallyScopedConn.setReadInfoMsgEnabled(true);
- try {
- return execute(sql, true);
- } finally {
- locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState);
- }
- }
- }
- return execute(sql);
- }
- /**
- * @see StatementImpl#execute(String, String[])
- */
- public boolean execute(String sql, String[] generatedKeyNames)
- throws SQLException {
- if ((generatedKeyNames != null) && (generatedKeyNames.length > 0)) {
- checkClosed();
- MySQLConnection locallyScopedConn = this.connection;
- synchronized (locallyScopedConn.getMutex()) {
- this.retrieveGeneratedKeys = true;
- // If this is a 'REPLACE' query, we need to be able to parse
- // the 'info' message returned from the server to determine
- // the actual number of keys generated.
- boolean readInfoMsgState = this.connection
- .isReadInfoMsgEnabled();
- locallyScopedConn.setReadInfoMsgEnabled(true);
- try {
- return execute(sql, true);
- } finally {
- locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState);
- }
- }
- }
- return execute(sql);
- }
- /**
- * JDBC 2.0 Submit a batch of commands to the database for execution. This
- * method is optional.
- *
- * @return an array of update counts containing one element for each command
- * in the batch. The array is ordered according to the order in
- * which commands were inserted into the batch
- *
- * @exception SQLException
- * if a database-access error occurs, or the driver does not
- * support batch statements
- * @throws java.sql.BatchUpdateException
- * DOCUMENT ME!
- */
- public synchronized int[] executeBatch() throws SQLException {
- checkClosed();
- MySQLConnection locallyScopedConn = this.connection;
- if (locallyScopedConn.isReadOnly()) {
- throw SQLError.createSQLException(Messages
- .getString("Statement.34") //$NON-NLS-1$
- + Messages.getString("Statement.35"), //$NON-NLS-1$
- SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
- }
- if (this.results != null) {
- if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) {
- this.results.realClose(false);
- }
- }
- synchronized (locallyScopedConn.getMutex()) {
- if (this.batchedArgs == null || this.batchedArgs.size() == 0) {
- return new int[0];
- }
-
- // we timeout the entire batch, not individual statements
- int individualStatementTimeout = this.timeoutInMillis;
- this.timeoutInMillis = 0;
-
- CancelTask timeoutTask = null;
-
- try {
- resetCancelledState();
- this.retrieveGeneratedKeys = true; // The JDBC spec doesn't forbid this, but doesn't provide for it either...we do..
- int[] updateCounts = null;
-
- if (this.batchedArgs != null) {
- int nbrCommands = this.batchedArgs.size();
- this.batchedGeneratedKeys = new ArrayList(this.batchedArgs.size());
- boolean multiQueriesEnabled = locallyScopedConn.getAllowMultiQueries();
- if (locallyScopedConn.versionMeetsMinimum(4, 1, 1) &&
- (multiQueriesEnabled ||
- (locallyScopedConn.getRewriteBatchedStatements() &&
- nbrCommands > 4))) {
- return executeBatchUsingMultiQueries(multiQueriesEnabled, nbrCommands, individualStatementTimeout);
- }
- if (locallyScopedConn.getEnableQueryTimeouts() &&
- individualStatementTimeout != 0
- && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
- timeoutTask = new CancelTask(this);
- locallyScopedConn.getCancelTimer().schedule(timeoutTask,
- individualStatementTimeout);
- }
-
- updateCounts = new int[nbrCommands];
- for (int i = 0; i < nbrCommands; i++) {
- updateCounts[i] = -3;
- }
- SQLException sqlEx = null;
- int commandIndex = 0;
- for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) {
- try {
- String sql = (String) this.batchedArgs.get(commandIndex);
- updateCounts[commandIndex] = executeUpdate(sql, true, true);
- // limit one generated key per OnDuplicateKey statement
- getBatchedGeneratedKeys(containsOnDuplicateKeyInString(sql) ? 1 : 0);
- } catch (SQLException ex) {
- updateCounts[commandIndex] = EXECUTE_FAILED;
- if (this.continueBatchOnError &&
- !(ex instanceof MySQLTimeoutException) &&
- !(ex instanceof MySQLStatementCancelledException) &&
- !hasDeadlockOrTimeoutRolledBackTx(ex)) {
- sqlEx = ex;
- } else {
- int[] newUpdateCounts = new int[commandIndex];
-
- if (hasDeadlockOrTimeoutRolledBackTx(ex)) {
- for (int i = 0; i < newUpdateCounts.length; i++) {
- newUpdateCounts[i] = Statement.EXECUTE_FAILED;
- }
- } else {
- System.arraycopy(updateCounts, 0,
- newUpdateCounts, 0, commandIndex);
- }
- throw new java.sql.BatchUpdateException(ex
- .getMessage(), ex.getSQLState(), ex
- .getErrorCode(), newUpdateCounts);
- }
- }
- }
- if (sqlEx != null) {
- throw new java.sql.BatchUpdateException(sqlEx
- .getMessage(), sqlEx.getSQLState(), sqlEx
- .getErrorCode(), updateCounts);
- }
- }
- if (timeoutTask != null) {
- if (timeoutTask.caughtWhileCancelling != null) {
- throw timeoutTask.caughtWhileCancelling;
- }
- timeoutTask.cancel();
-
- locallyScopedConn.getCancelTimer().purge();
- timeoutTask = null;
- }
-
- return (updateCounts != null) ? updateCounts : new int[0];
- } finally {
-
- if (timeoutTask != null) {
- timeoutTask.cancel();
-
- locallyScopedConn.getCancelTimer().purge();
- }
-
- resetCancelledState();
-
- this.timeoutInMillis = individualStatementTimeout;
- clearBatch();
- }
- }
- }
- protected final boolean hasDeadlockOrTimeoutRolledBackTx(SQLException ex) {
- int vendorCode = ex.getErrorCode();
-
- switch (vendorCode) {
- case MysqlErrorNumbers.ER_LOCK_DEADLOCK:
- case MysqlErrorNumbers.ER_LOCK_TABLE_FULL:
- return true;
- case MysqlErrorNumbers.ER_LOCK_WAIT_TIMEOUT:
- try {
- return !this.connection.versionMeetsMinimum(5, 0, 13);
- } catch (SQLException sqlEx) {
- // won't actually be thrown in this case
- return false;
- }
- default:
- return false;
- }
- }
- /**
- * Rewrites batch into a single query to send to the server. This method
- * will constrain each batch to be shorter than max_allowed_packet on the
- * server.
- *
- * @return update counts in the same manner as executeBatch()
- * @throws SQLException
- */
- private int[] executeBatchUsingMultiQueries(boolean multiQueriesEnabled,
- int nbrCommands, int individualStatementTimeout) throws SQLException {
- MySQLConnection locallyScopedConn = this.connection;
- if (!multiQueriesEnabled) {
- locallyScopedConn.getIO().enableMultiQueries();
- }
- java.sql.Statement batchStmt = null;
- CancelTask timeoutTask = null;
-
- try {
- int[] updateCounts = new int[nbrCommands];
- for (int i = 0; i < nbrCommands; i++) {
- updateCounts[i] = -3;
- }
- int commandIndex = 0;
- StringBuffer queryBuf = new StringBuffer();
- batchStmt = locallyScopedConn.createStatement();
- if (locallyScopedConn.getEnableQueryTimeouts() &&
- individualStatementTimeout != 0
- && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
- timeoutTask = new CancelTask((StatementImpl)batchStmt);
- locallyScopedConn.getCancelTimer().schedule(timeoutTask,
- individualStatementTimeout);
- }
-
- int counter = 0;
- int numberOfBytesPerChar = 1;
- String connectionEncoding = locallyScopedConn.getEncoding();
- if (StringUtils.startsWithIgnoreCase(connectionEncoding, "utf")) {
- numberOfBytesPerChar = 3;
- } else if (CharsetMapping.isMultibyteCharset(connectionEncoding)) {
- numberOfBytesPerChar = 2;
- }
- int escapeAdjust = 1;
- batchStmt.setEscapeProcessing(this.doEscapeProcessing);
-
- if (this.doEscapeProcessing) {
-
- escapeAdjust = 2; /* We assume packet _could_ grow by this amount, as we're not
- sure how big statement will end up after
- escape processing */
- }
- SQLException sqlEx = null;
-
- int argumentSetsInBatchSoFar = 0;
-
- for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) {
- String nextQuery = (String) this.batchedArgs.get(commandIndex);
- if (((((queryBuf.length() + nextQuery.length())
- * numberOfBytesPerChar) + 1 /* for semicolon */
- + MysqlIO.HEADER_LENGTH) * escapeAdjust) + 32 > this.connection
- .getMaxAllowedPacket()) {
- try {
- batchStmt.execute(queryBuf.toString(), Statement.RETURN_GENERATED_KEYS);
- } catch (SQLException ex) {
- sqlEx = handleExceptionForBatch(commandIndex,
- argumentSetsInBatchSoFar, updateCounts, ex);
- }
- counter = processMultiCountsAndKeys((StatementImpl)batchStmt, counter,
- updateCounts);
- queryBuf = new StringBuffer();
- argumentSetsInBatchSoFar = 0;
- }
- queryBuf.append(nextQuery);
- queryBuf.append(";");
- argumentSetsInBatchSoFar++;
- }
- if (queryBuf.length() > 0) {
- try {
- batchStmt.execute(queryBuf.toString(), Statement.RETURN_GENERATED_KEYS);
- } catch (SQLException ex) {
- sqlEx = handleExceptionForBatch(commandIndex - 1,
- argumentSetsInBatchSoFar, updateCounts, ex);
- }
- counter = processMultiCountsAndKeys((StatementImpl)batchStmt, counter,
- updateCounts);
- }
- if (timeoutTask != null) {
- if (timeoutTask.caughtWhileCancelling != null) {
- throw timeoutTask.caughtWhileCancelling;
- }
- timeoutTask.cancel();
-
- locallyScopedConn.getCancelTimer().purge();
-
- timeoutTask = null;
- }
-
- if (sqlEx != null) {
- throw new java.sql.BatchUpdateException(sqlEx
- .getMessage(), sqlEx.getSQLState(), sqlEx
- .getErrorCode(), updateCounts);
- }
-
- return (updateCounts != null) ? updateCounts : new int[0];
- } finally {
- if (timeoutTask != null) {
- timeoutTask.cancel();
-
- locallyScopedConn.getCancelTimer().purge();
- }
-
- resetCancelledState();
-
- try {
- if (batchStmt != null) {
- batchStmt.close();
- }
- } finally {
- if (!multiQueriesEnabled) {
- locallyScopedConn.getIO().disableMultiQueries();
- }
- }
- }
- }
-
- protected int processMultiCountsAndKeys(
- StatementImpl batchedStatement,
- int updateCountCounter, int[] updateCounts) throws SQLException {
- updateCounts[updateCountCounter++] = batchedStatement.getUpdateCount();
-
- boolean doGenKeys = this.batchedGeneratedKeys != null;
- byte[][] row = null;
-
- if (doGenKeys) {
- long generatedKey = batchedStatement.getLastInsertID();
-
- row = new byte[1][];
- row[0] = Long.toString(generatedKey).getBytes();
- this.batchedGeneratedKeys.add(new ByteArrayRow(row, getExceptionInterceptor()));
- }
- while (batchedStatement.getMoreResults()
- || batchedStatement.getUpdateCount() != -1) {
- updateCounts[updateCountCounter++] = batchedStatement.getUpdateCount();
-
- if (doGenKeys) {
- long generatedKey = batchedStatement.getLastInsertID();
-
- row = new byte[1][];
- row[0] = Long.toString(generatedKey).getBytes();
- this.batchedGeneratedKeys.add(new ByteArrayRow(row, getExceptionInterceptor()));
- }
- }
-
- return updateCountCounter;
- }
-
- protected SQLException handleExceptionForBatch(int endOfBatchIndex,
- int numValuesPerBatch, int[] updateCounts, SQLException ex)
- throws BatchUpdateException {
- SQLException sqlEx;
-
- for (int j = endOfBatchIndex; j > endOfBatchIndex - numValuesPerBatch; j--) {
- updateCounts[j] = EXECUTE_FAILED;
- }
- if (this.continueBatchOnError &&
- !(ex instanceof MySQLTimeoutException) &&
- !(ex instanceof MySQLStatementCancelledException) &&
- !hasDeadlockOrTimeoutRolledBackTx(ex)) {
- sqlEx = ex;
- } else {
- int[] newUpdateCounts = new int[endOfBatchIndex];
- System.arraycopy(updateCounts, 0,
- newUpdateCounts, 0, endOfBatchIndex);
- throw new java.sql.BatchUpdateException(ex
- .getMessage(), ex.getSQLState(), ex
- .getErrorCode(), newUpdateCounts);
- }
-
- return sqlEx;
- }
-
- /**
- * Execute a SQL statement that retruns a single ResultSet
- *
- * @param sql
- * typically a static SQL SELECT statement
- *
- * @return a ResulSet that contains the data produced by the query
- *
- * @exception SQLException
- * if a database access error occurs
- */
- public java.sql.ResultSet executeQuery(String sql)
- throws SQLException {
- checkClosed();
- MySQLConnection locallyScopedConn = this.connection;
- synchronized (locallyScopedConn.getMutex()) {
- this.retrieveGeneratedKeys = false;
-
- resetCancelledState();
- checkNullOrEmptyQuery(sql);
- boolean doStreaming = createStreamingResultSet();
- // Adjust net_write_timeout to a higher value if we're
- // streaming result sets. More often than not, someone runs into
- // an issue where they blow net_write_timeout when using this
- // feature, and if they're willing to hold a result set open
- // for 30 seconds or more, one more round-trip isn't going to hurt
- //
- // This is reset by RowDataDynamic.close().
- if (doStreaming
- && this.connection.getNetTimeoutForStreamingResults() > 0) {
- executeSimpleNonQuery(locallyScopedConn, "SET net_write_timeout="
- + this.connection.getNetTimeoutForStreamingResults());
- }
- if (this.doEscapeProcessing) {
- Object escapedSqlResult = EscapeProcessor.escapeSQL(sql,
- locallyScopedConn.serverSupportsConvertFn(), this.connection);
- if (escapedSqlResult instanceof String) {
- sql = (String) escapedSqlResult;
- } else {
- sql = ((EscapeProcessorResult) escapedSqlResult).escapedSql;
- }
- }
- char firstStatementChar = StringUtils.firstNonWsCharUc(sql,
- findStartOfStatement(sql));
- if (sql.charAt(0) == '/') {
- if (sql.startsWith(PING_MARKER)) {
- doPingInstead();
-
- return this.results;
- }
- }
-
- checkForDml(sql, firstStatementChar);
- if (this.results != null) {
- if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) {
- this.results.realClose(false);
- }
- }
- CachedResultSetMetaData cachedMetaData = null;
- // If there isn't a limit clause in the SQL
- // then limit the number of rows to return in
- // an efficient manner. Only do this if
- // setMaxRows() hasn't been used on any Statements
- // generated from the current Connection (saves
- // a query, and network traffic).
- if (useServerFetch()) {
- this.results = createResultSetUsingServerFetch(sql);
- return this.results;
- }
- CancelTask timeoutTask = null;
- String oldCatalog = null;
- try {
- if (locallyScopedConn.getEnableQueryTimeouts() &&
- this.timeoutInMillis != 0
- && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
- timeoutTask = new CancelTask(this);
- locallyScopedConn.getCancelTimer().schedule(timeoutTask,
- this.timeoutInMillis);
- }
- if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) {
- oldCatalog = locallyScopedConn.getCatalog();
- locallyScopedConn.setCatalog(this.currentCatalog);
- }
- //
- // Check if we have cached metadata for this query...
- //
- Field[] cachedFields = null;
- if (locallyScopedConn.getCacheResultSetMetadata()) {
- cachedMetaData = locallyScopedConn.getCachedMetaData(sql);
- if (cachedMetaData != null) {
- cachedFields = cachedMetaData.fields;
- }
- }
- if (locallyScopedConn.useMaxRows()) {
- // We need to execute this all together
- // So synchronize on the Connection's mutex (because
- // even queries going through there synchronize
- // on the connection
- if (StringUtils.indexOfIgnoreCase(sql, "LIMIT") != -1) { //$NON-NLS-1$
- this.results = locallyScopedConn.execSQL(this, sql,
- this.maxRows, null, this.resultSetType,
- this.resultSetConcurrency,
- doStreaming,
- this.currentCatalog, cachedFields);
- } else {
- if (this.maxRows <= 0) {
- executeSimpleNonQuery(locallyScopedConn,
- "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
- } else {
- executeSimpleNonQuery(locallyScopedConn,
- "SET OPTION SQL_SELECT_LIMIT=" + this.maxRows);
- }
- this.results = locallyScopedConn.execSQL(this, sql, -1,
- null, this.resultSetType,
- this.resultSetConcurrency,
- doStreaming,
- this.currentCatalog, cachedFields);
- if (oldCatalog != null) {
- locallyScopedConn.setCatalog(oldCatalog);
- }
- }
- } else {
- this.results = locallyScopedConn.execSQL(this, sql, -1, null,
- this.resultSetType, this.resultSetConcurrency,
- doStreaming,
- this.currentCatalog, cachedFields);
- }
- if (timeoutTask != null) {
- if (timeoutTask.caughtWhileCancelling != null) {
- throw timeoutTask.caughtWhileCancelling;
- }
- timeoutTask.cancel();
-
- locallyScopedConn.getCancelTimer().purge();
-
- timeoutTask = null;
- }
- synchronized (this.cancelTimeoutMutex) {
- if (this.wasCancelled) {
- SQLException cause = null;
-
- if (this.wasCancelledByTimeout) {
- cause = new MySQLTimeoutException();
- } else {
- cause = new MySQLStatementCancelledException();
- }
-
- resetCancelledState();
-
- throw cause;
- }
- }
- } finally {
- if (timeoutTask != null) {
- timeoutTask.cancel();
-
- locallyScopedConn.getCancelTimer().purge();
- }
- if (oldCatalog != null) {
- locallyScopedConn.setCatalog(oldCatalog);
- }
- }
- this.lastInsertId = this.results.getUpdateID();
- if (cachedMetaData != null) {
- locallyScopedConn.initializeResultsMetadataFromCache(sql, cachedMetaData,
- this.results);
- } else {
- if (this.connection.getCacheResultSetMetadata()) {
- locallyScopedConn.initializeResultsMetadataFromCache(sql,
- null /* will be created */, this.results);
- }
- }
- return this.results;
- }
- }
- protected void doPingInstead() throws SQLException {
- if (this.pingTarget != null) {
- this.pingTarget.doPing();
- } else {
- this.connection.ping();
- }
- ResultSetInternalMethods fakeSelectOneResultSet = generatePingResultSet();
- this.results = fakeSelectOneResultSet;
- }
- protected ResultSetInternalMethods generatePingResultSet() throws SQLException {
- Field[] fields = { new Field(null, "1", Types.BIGINT, 1) };
- ArrayList rows = new ArrayList();
- byte[] colVal = new byte[] { (byte) '1' };
- rows.add(new ByteArrayRow(new byte[][] { colVal }, getExceptionInterceptor()));
- return (ResultSetInternalMethods) DatabaseMetaData.buildResultSet(fields, rows,
- this.connection);
- }
-
- protected void executeSimpleNonQuery(MySQLConnection c, String nonQuery)
- throws SQLException {
- c.execSQL(this, nonQuery,
- -1, null, ResultSet.TYPE_FORWARD_ONLY,
- ResultSet.CONCUR_READ_ONLY, false, this.currentCatalog,
- null, false).close();
- }
- /**
- * Execute a SQL INSERT, UPDATE or DELETE statement. In addition SQL
- * statements that return nothing such as SQL DDL statements can be executed
- * Any IDs generated for AUTO_INCREMENT fields can be retrieved by casting
- * this Statement to org.gjt.mm.mysql.Statement and calling the
- * getLastInsertID() method.
- *
- * @param sql
- * a SQL statement
- *
- * @return either a row count, or 0 for SQL commands
- *
- * @exception SQLException
- * if a database access error occurs
- */
- public int executeUpdate(String sql) throws SQLException {
- return executeUpdate(sql, false, false);
- }
- protected int executeUpdate(String sql, boolean isBatch, boolean returnGeneratedKeys)
- throws SQLException {
- checkClosed();
- MySQLConnection locallyScopedConn = this.connection;
- char firstStatementChar = StringUtils.firstAlphaCharUc(sql,
- findStartOfStatement(sql));
- ResultSetInternalMethods rs = null;
- synchronized (locallyScopedConn.getMutex()) {
- this.retrieveGeneratedKeys = returnGeneratedKeys;
-
- resetCancelledState();
- checkNullOrEmptyQuery(sql);
- if (this.doEscapeProcessing) {
- Object escapedSqlResult = EscapeProcessor.escapeSQL(sql,
- this.connection.serverSupportsConvertFn(), this.connection);
- if (escapedSqlResult instanceof String) {
- sql = (String) escapedSqlResult;
- } else {
- sql = ((EscapeProcessorResult) escapedSqlResult).escapedSql;
- }
- }
- if (locallyScopedConn.isReadOnly()) {
- throw SQLError.createSQLException(Messages
- .getString("Statement.42") //$NON-NLS-1$
- + Messages.getString("Statement.43"), //$NON-NLS-1$
- SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
- }
- if (StringUtils.startsWithIgnoreCaseAndWs(sql, "select")) { //$NON-NLS-1$
- throw SQLError.createSQLException(Messages
- .getString("Statement.46"), //$NON-NLS-1$
- "01S03", getExceptionInterceptor()); //$NON-NLS-1$
- }
- if (this.results != null) {
- if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) {
- this.results.realClose(false);
- }
- }
- // The checking and changing of catalogs
- // must happen in sequence, so synchronize
- // on the same mutex that _conn is using
- CancelTask timeoutTask = null;
- String oldCatalog = null;
- try {
- if (locallyScopedConn.getEnableQueryTimeouts() &&
- this.timeoutInMillis != 0
- && locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
- timeoutTask = new CancelTask(this);
- locallyScopedConn.getCancelTimer().schedule(timeoutTask,
- this.timeoutInMillis);
- }
- if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) {
- oldCatalog = locallyScopedConn.getCatalog();
- locallyScopedConn.setCatalog(this.currentCatalog);
- }
- //
- // Only apply max_rows to selects
- //
- if (locallyScopedConn.useMaxRows()) {
- executeSimpleNonQuery(locallyScopedConn,
- "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
- }
- rs = locallyScopedConn.execSQL(this, sql, -1, null,
- java.sql.ResultSet.TYPE_FORWARD_ONLY,
- java.sql.ResultSet.CONCUR_READ_ONLY, false,
- this.currentCatalog,
- null /* force read of field info on DML */,
- isBatch);
- if (timeoutTask != null) {
- if (timeoutTask.caughtWhileCancelling != null) {
- throw timeoutTask.caughtWhileCancelling;
- }
- timeoutTask.cancel();
-
- locallyScopedConn.getCancelTimer().purge();
-
- timeoutTask = null;
- }
- synchronized (this.cancelTimeoutMutex) {
- if (this.wasCancelled) {
- SQLException cause = null;
-
- if (this.wasCancelledByTimeout) {
- cause = new MySQLTimeoutException();
- } else {
- cause = new MySQLStatementCancelledException();
- }
-
- resetCancelledState();
-
- throw cause;
- }
- }
- } finally {
- if (timeoutTask != null) {
- timeoutTask.cancel();
-
- locallyScopedConn.getCancelTimer().purge();
- }
- if (oldCatalog != null) {
- locallyScopedConn.setCatalog(oldCatalog);
- }
- }
- }
- this.results = rs;
- rs.setFirstCharOfQuery(firstStatementChar);
- this.updateCount = rs.getUpdateCount();
- int truncatedUpdateCount = 0;
- if (this.updateCount > Integer.MAX_VALUE) {
- truncatedUpdateCount = Integer.MAX_VALUE;
- } else {
- truncatedUpdateCount = (int) this.updateCount;
- }
- this.lastInsertId = rs.getUpdateID();
- return truncatedUpdateCount;
- }
- /**
- * @see StatementImpl#executeUpdate(String, int)
- */
- public int executeUpdate(String sql, int returnGeneratedKeys)
- throws SQLException {
- if (returnGeneratedKe…
Large files files are truncated, but you can click here to view the full file