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:
Source Code for Connector/J 8.0.31 - User Impl
Where to get the Java source code for Connector/J 8.0 User Impl module?
✍: FYIcenter.com
Java source code files for Connector/J 8.0 User Impl module are:
⏎ com/mysql/cj/jdbc/StatementImpl.java
/* * Copyright (c) 2002, 2022, Oracle and/or its affiliates. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License, version 2.0, as published by the * Free Software Foundation. * * This program is also distributed with certain software (including but not * limited to OpenSSL) that is licensed under separate terms, as designated in a * particular file or component or in included license documentation. The * authors of MySQL hereby grant you an additional permission to link the * program and your derivative works with the separately licensed software that * they have included with MySQL. * * Without limiting anything contained in the foregoing, this file, which is * part of MySQL Connector/J, is also subject to the Universal FOSS Exception, * version 1.0, a copy of which can be found at * http://oss.oracle.com/licenses/universal-foss-exception. * * 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, version 2.0, * 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.cj.jdbc; import java.io.IOException; 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.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import com.mysql.cj.CancelQueryTask; import com.mysql.cj.Messages; import com.mysql.cj.MysqlType; import com.mysql.cj.NativeSession; import com.mysql.cj.PingTarget; import com.mysql.cj.Query; import com.mysql.cj.QueryAttributesBindings; import com.mysql.cj.QueryInfo; import com.mysql.cj.QueryReturnType; import com.mysql.cj.Session; import com.mysql.cj.SimpleQuery; import com.mysql.cj.TransactionEventHandler; import com.mysql.cj.conf.HostInfo; import com.mysql.cj.conf.PropertyDefinitions; import com.mysql.cj.conf.PropertyKey; import com.mysql.cj.conf.RuntimeProperty; import com.mysql.cj.exceptions.AssertionFailedException; import com.mysql.cj.exceptions.CJException; import com.mysql.cj.exceptions.CJOperationNotSupportedException; import com.mysql.cj.exceptions.CJTimeoutException; import com.mysql.cj.exceptions.ExceptionFactory; import com.mysql.cj.exceptions.ExceptionInterceptor; import com.mysql.cj.exceptions.MysqlErrorNumbers; import com.mysql.cj.exceptions.OperationCancelledException; import com.mysql.cj.exceptions.StatementIsClosedException; import com.mysql.cj.jdbc.exceptions.MySQLStatementCancelledException; import com.mysql.cj.jdbc.exceptions.MySQLTimeoutException; import com.mysql.cj.jdbc.exceptions.SQLError; import com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping; import com.mysql.cj.jdbc.result.CachedResultSetMetaData; import com.mysql.cj.jdbc.result.ResultSetFactory; import com.mysql.cj.jdbc.result.ResultSetImpl; import com.mysql.cj.jdbc.result.ResultSetInternalMethods; import com.mysql.cj.log.ProfilerEvent; import com.mysql.cj.protocol.Message; import com.mysql.cj.protocol.ProtocolEntityFactory; import com.mysql.cj.protocol.Resultset; import com.mysql.cj.protocol.Resultset.Type; import com.mysql.cj.protocol.a.NativeConstants; import com.mysql.cj.protocol.a.NativeMessageBuilder; import com.mysql.cj.protocol.a.result.ByteArrayRow; import com.mysql.cj.protocol.a.result.ResultsetRowsStatic; import com.mysql.cj.result.DefaultColumnDefinition; import com.mysql.cj.result.Field; import com.mysql.cj.result.Row; import com.mysql.cj.util.StringUtils; import com.mysql.cj.util.Util; /** * A Statement object is used for executing a static SQL statement and obtaining * the results produced by it. * * 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. */ public class StatementImpl implements JdbcStatement { protected static final String PING_MARKER = "/* ping */"; 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 NativeMessageBuilder commandBuilder = null; // TODO use shared builder /** The character encoding to use (if available) */ protected String charEncoding = null; /** The connection that created us */ protected volatile JdbcConnection connection = null; /** Should we process escape codes? */ protected boolean doEscapeProcessing = true; /** 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 = (Integer) PropertyDefinitions.getPropertyDefinition(PropertyKey.maxAllowedPacket).getDefaultValue(); /** * The maximum number of rows to return for this statement (-1 means _all_ * rows) */ public int maxRows = -1; /** Set of currently-open ResultSets */ protected Set<ResultSetInternalMethods> openResults = new HashSet<>(); /** Are we in pedantic mode? */ protected boolean pedantic = false; /** Should we profile? */ protected boolean profileSQL = false; /** The current results */ protected ResultSetInternalMethods results = null; protected ResultSetInternalMethods generatedKeysResults = null; /** The concurrency for this result set (updatable or not) */ protected int resultSetConcurrency = 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<Row> batchedGeneratedKeys = null; protected boolean retrieveGeneratedKeys = false; protected boolean continueBatchOnError = false; protected PingTarget pingTarget = null; protected ExceptionInterceptor exceptionInterceptor; /** Whether or not the last query was of the form ON DUPLICATE KEY UPDATE */ protected boolean lastQueryIsOnDupKeyUpdate = false; /** Are we currently closing results implicitly (internally)? */ private boolean isImplicitlyClosingResults = false; protected RuntimeProperty<Boolean> dontTrackOpenResources; protected RuntimeProperty<Boolean> dumpQueriesOnException; protected boolean logSlowQueries = false; protected RuntimeProperty<Boolean> rewriteBatchedStatements; protected RuntimeProperty<Integer> maxAllowedPacket; protected boolean dontCheckOnDuplicateKeyUpdateInSQL; protected ResultSetFactory resultSetFactory; protected Query query; protected NativeSession session = null; /** * Constructor for a Statement. * * @param c * the Connection instance that creates us * @param db * the database name in use when we were created * * @throws SQLException * if an error occurs. */ public StatementImpl(JdbcConnection c, String db) throws SQLException { if ((c == null) || c.isClosed()) { throw SQLError.createSQLException(Messages.getString("Statement.0"), MysqlErrorNumbers.SQL_STATE_CONNECTION_NOT_OPEN, null); } this.connection = c; this.session = (NativeSession) c.getSession(); this.exceptionInterceptor = c.getExceptionInterceptor(); this.commandBuilder = new NativeMessageBuilder(this.session.getServerSession().supportsQueryAttributes()); try { initQuery(); } catch (CJException e) { throw SQLExceptionsMapping.translateException(e, getExceptionInterceptor()); } this.query.setCurrentDatabase(db); JdbcPropertySet pset = c.getPropertySet(); this.dontTrackOpenResources = pset.getBooleanProperty(PropertyKey.dontTrackOpenResources); this.dumpQueriesOnException = pset.getBooleanProperty(PropertyKey.dumpQueriesOnException); this.continueBatchOnError = pset.getBooleanProperty(PropertyKey.continueBatchOnError).getValue(); this.pedantic = pset.getBooleanProperty(PropertyKey.pedantic).getValue(); this.rewriteBatchedStatements = pset.getBooleanProperty(PropertyKey.rewriteBatchedStatements); this.charEncoding = pset.getStringProperty(PropertyKey.characterEncoding).getValue(); this.profileSQL = pset.getBooleanProperty(PropertyKey.profileSQL).getValue(); this.useUsageAdvisor = pset.getBooleanProperty(PropertyKey.useUsageAdvisor).getValue(); this.logSlowQueries = pset.getBooleanProperty(PropertyKey.logSlowQueries).getValue(); this.maxAllowedPacket = pset.getIntegerProperty(PropertyKey.maxAllowedPacket); this.dontCheckOnDuplicateKeyUpdateInSQL = pset.getBooleanProperty(PropertyKey.dontCheckOnDuplicateKeyUpdateInSQL).getValue(); this.doEscapeProcessing = pset.getBooleanProperty(PropertyKey.enableEscapeProcessing).getValue(); this.maxFieldSize = this.maxAllowedPacket.getValue(); if (!this.dontTrackOpenResources.getValue()) { c.registerStatement(this); } int defaultFetchSize = pset.getIntegerProperty(PropertyKey.defaultFetchSize).getValue(); if (defaultFetchSize != 0) { setFetchSize(defaultFetchSize); } int maxRowsConn = pset.getIntegerProperty(PropertyKey.maxRows).getValue(); if (maxRowsConn != -1) { setMaxRows(maxRowsConn); } this.holdResultsOpenOverClose = pset.getBooleanProperty(PropertyKey.holdResultsOpenOverStatementClose).getValue(); this.resultSetFactory = new ResultSetFactory(this.connection, this); } protected void initQuery() { this.query = new SimpleQuery(this.session); } @Override public void addBatch(String sql) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if (sql != null) { this.query.addBatch(sql); } } } @Override public void addBatch(Object batch) { this.query.addBatch(batch); } @Override public List<Object> getBatchedArgs() { return this.query.getBatchedArgs(); } @Override public void cancel() throws SQLException { if (!this.query.getStatementExecuting().get()) { return; } if (!this.isClosed && this.connection != null) { NativeSession newSession = null; try { HostInfo hostInfo = this.session.getHostInfo(); String database = hostInfo.getDatabase(); String user = hostInfo.getUser(); String password = hostInfo.getPassword(); newSession = new NativeSession(this.session.getHostInfo(), this.session.getPropertySet()); newSession.connect(hostInfo, user, password, database, 30000, new TransactionEventHandler() { @Override public void transactionCompleted() { } @Override public void transactionBegun() { } }); newSession.getProtocol().sendCommand(new NativeMessageBuilder(newSession.getServerSession().supportsQueryAttributes()) .buildComQuery(newSession.getSharedSendPacket(), "KILL QUERY " + this.session.getThreadId()), false, 0); setCancelStatus(CancelStatus.CANCELED_BY_USER); } catch (IOException e) { throw SQLExceptionsMapping.translateException(e, this.exceptionInterceptor); } finally { if (newSession != null) { newSession.forceClose(); } } } } // --------------------------JDBC 2.0----------------------------- /** * Checks if closed() has been called, and throws an exception if so * * @return connection * @throws StatementIsClosedException * if this statement has been closed */ protected JdbcConnection checkClosed() { JdbcConnection c = this.connection; if (c == null) { throw ExceptionFactory.createException(StatementIsClosedException.class, Messages.getString("Statement.AlreadyClosed"), getExceptionInterceptor()); } return c; } /** * Checks if the given SQL query is a result set producing query. * * @param sql * the SQL to check * @return * <code>true</code> if the query produces a result set, <code>false</code> otherwise. */ protected boolean isResultSetProducingQuery(String sql) { QueryReturnType queryReturnType = QueryInfo.getQueryReturnType(sql, this.session.getServerSession().isNoBackslashEscapesSet()); return queryReturnType == QueryReturnType.PRODUCES_RESULT_SET || queryReturnType == QueryReturnType.MAY_PRODUCE_RESULT_SET; } /** * Checks if the given SQL query does not return a result set. * * @param sql * the SQL to check * @return * <code>true</code> if the query does not produce a result set, <code>false</code> otherwise. */ protected boolean isNonResultSetProducingQuery(String sql) { QueryReturnType queryReturnType = QueryInfo.getQueryReturnType(sql, this.session.getServerSession().isNoBackslashEscapesSet()); return queryReturnType == QueryReturnType.DOES_NOT_PRODUCE_RESULT_SET || queryReturnType == QueryReturnType.MAY_PRODUCE_RESULT_SET; } /** * 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"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } if (sql.length() == 0) { throw SQLError.createSQLException(Messages.getString("Statement.61"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } @Override public void clearBatch() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { this.query.clearBatchedArgs(); } } @Override public void clearBatchedArgs() { this.query.clearBatchedArgs(); } @Override public void clearWarnings() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { setClearWarningsCalled(true); this.warningChain = null; // TODO souldn't we also clear warnings from _server_ ? } } /** * 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 */ @Override public void close() throws SQLException { realClose(true, true); } /** * Close any open result sets that have been 'held open' * * @throws SQLException * if an error occurs */ protected void closeAllOpenResults() throws SQLException { JdbcConnection locallyScopedConn = this.connection; if (locallyScopedConn == null) { return; // already closed } synchronized (locallyScopedConn.getConnectionMutex()) { if (this.openResults != null) { for (ResultSetInternalMethods element : this.openResults) { try { element.realClose(false); } catch (SQLException sqlEx) { AssertionFailedException.shouldNotHappen(sqlEx); } } this.openResults.clear(); } } } /** * Close all result sets in this statement. This includes multi-results * * @throws SQLException * if a database access error occurs */ protected void implicitlyCloseAllOpenResults() throws SQLException { this.isImplicitlyClosingResults = true; try { if (!(this.holdResultsOpenOverClose || this.dontTrackOpenResources.getValue())) { if (this.results != null) { this.results.realClose(false); } if (this.generatedKeysResults != null) { this.generatedKeysResults.realClose(false); } closeAllOpenResults(); } } finally { this.isImplicitlyClosingResults = false; } } @Override public void removeOpenResultSet(ResultSetInternalMethods rs) { try { synchronized (checkClosed().getConnectionMutex()) { if (this.openResults != null) { this.openResults.remove(rs); } boolean hasMoreResults = rs.getNextResultset() != null; // clear the current results or GGK results if (this.results == rs && !hasMoreResults) { this.results = null; } if (this.generatedKeysResults == rs) { this.generatedKeysResults = null; } // trigger closeOnCompletion if: // a) the result set removal wasn't triggered internally // b) there are no additional results if (!this.isImplicitlyClosingResults && !hasMoreResults) { checkAndPerformCloseOnCompletionAction(); } } } catch (StatementIsClosedException e) { // we can't break the interface, having this be no-op in case of error is ok } } @Override public int getOpenResultSetCount() { try { synchronized (checkClosed().getConnectionMutex()) { if (this.openResults != null) { return this.openResults.size(); } return 0; } } catch (StatementIsClosedException e) { // we can't break the interface, having this be no-op in case of error is ok return 0; } } /** * Check if all ResultSets generated by this statement are closed. If so, * close this statement. */ private void checkAndPerformCloseOnCompletionAction() { try { synchronized (checkClosed().getConnectionMutex()) { if (isCloseOnCompletion() && !this.dontTrackOpenResources.getValue() && getOpenResultSetCount() == 0 && (this.results == null || !this.results.hasRows() || this.results.isClosed()) && (this.generatedKeysResults == null || !this.generatedKeysResults.hasRows() || this.generatedKeysResults.isClosed())) { realClose(false, false); } } } catch (SQLException e) { } } /** * @param sql * query * @return result set * @throws SQLException * if a database access error occurs or this method is called on a closed Statement */ private ResultSetInternalMethods createResultSetUsingServerFetch(String sql) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { java.sql.PreparedStatement pStmt = this.connection.prepareStatement(sql, this.query.getResultType().getIntValue(), this.resultSetConcurrency); pStmt.setFetchSize(this.query.getResultFetchSize()); if (this.getQueryTimeout() > 0) { pStmt.setQueryTimeout(this.getQueryTimeout()); } if (this.maxRows > -1) { pStmt.setMaxRows(this.maxRows); } statementBegins(); pStmt.execute(); // // Need to be able to get resultset irrespective if we issued DML or not to make this work. // ResultSetInternalMethods rs = ((JdbcStatement) pStmt).getResultSetInternal(); rs.setStatementUsedForFetchingRows((JdbcPreparedStatement) 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.query.getResultType() == Type.FORWARD_ONLY) && (this.resultSetConcurrency == java.sql.ResultSet.CONCUR_READ_ONLY) && (this.query.getResultFetchSize() == Integer.MIN_VALUE)); } private Resultset.Type originalResultSetType = Type.FORWARD_ONLY; private int originalFetchSize = 0; @Override public void enableStreamingResults() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { this.originalResultSetType = this.query.getResultType(); this.originalFetchSize = this.query.getResultFetchSize(); setFetchSize(Integer.MIN_VALUE); setResultSetType(Type.FORWARD_ONLY); } } @Override public void disableStreamingResults() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if (this.query.getResultFetchSize() == Integer.MIN_VALUE && this.query.getResultType() == Type.FORWARD_ONLY) { setFetchSize(this.originalFetchSize); setResultSetType(this.originalResultSetType); } } } /** * 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(). * * @param con * created this statement * @throws SQLException * if a database error occurs */ protected void setupStreamingTimeout(JdbcConnection con) throws SQLException { int netTimeoutForStreamingResults = this.session.getPropertySet().getIntegerProperty(PropertyKey.netTimeoutForStreamingResults).getValue(); if (createStreamingResultSet() && netTimeoutForStreamingResults > 0) { executeSimpleNonQuery(con, "SET net_write_timeout=" + netTimeoutForStreamingResults); } } @Override public CancelQueryTask startQueryTimer(Query stmtToCancel, int timeout) { return this.query.startQueryTimer(stmtToCancel, timeout); } @Override public void stopQueryTimer(CancelQueryTask timeoutTask, boolean rethrowCancelReason, boolean checkCancelTimeout) { this.query.stopQueryTimer(timeoutTask, rethrowCancelReason, checkCancelTimeout); } @Override public boolean execute(String sql) throws SQLException { return executeInternal(sql, false); } private boolean executeInternal(String sql, boolean returnGeneratedKeys) throws SQLException { JdbcConnection locallyScopedConn = checkClosed(); synchronized (locallyScopedConn.getConnectionMutex()) { checkClosed(); checkNullOrEmptyQuery(sql); resetCancelledState(); implicitlyCloseAllOpenResults(); if (sql.charAt(0) == '/') { if (sql.startsWith(PING_MARKER)) { doPingInstead(); return true; } } this.retrieveGeneratedKeys = returnGeneratedKeys; this.lastQueryIsOnDupKeyUpdate = returnGeneratedKeys && QueryInfo.firstCharOfStatementUc(sql, this.session.getServerSession().isNoBackslashEscapesSet()) == 'I' && containsOnDuplicateKeyInString(sql); if (!QueryInfo.isReadOnlySafeQuery(sql, this.session.getServerSession().isNoBackslashEscapesSet()) && locallyScopedConn.isReadOnly()) { throw SQLError.createSQLException(Messages.getString("Statement.27") + Messages.getString("Statement.28"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } try { setupStreamingTimeout(locallyScopedConn); if (this.doEscapeProcessing) { Object escapedSqlResult = EscapeProcessor.escapeSQL(sql, this.session.getServerSession().getSessionTimeZone(), this.session.getServerSession().getCapabilities().serverSupportsFracSecs(), this.session.getServerSession().isServerTruncatesFracSecs(), getExceptionInterceptor()); sql = escapedSqlResult instanceof String ? (String) escapedSqlResult : ((EscapeProcessorResult) escapedSqlResult).escapedSql; } CachedResultSetMetaData cachedMetaData = null; ResultSetInternalMethods rs = null; this.batchedGeneratedKeys = null; if (useServerFetch()) { rs = createResultSetUsingServerFetch(sql); } else { CancelQueryTask timeoutTask = null; String oldDb = null; try { timeoutTask = startQueryTimer(this, getTimeoutInMillis()); if (!locallyScopedConn.getDatabase().equals(getCurrentDatabase())) { oldDb = locallyScopedConn.getDatabase(); locallyScopedConn.setDatabase(getCurrentDatabase()); } // Check if we have cached metadata for this query... if (locallyScopedConn.getPropertySet().getBooleanProperty(PropertyKey.cacheResultSetMetadata).getValue()) { cachedMetaData = locallyScopedConn.getCachedMetaData(sql); } // Only apply max_rows to selects locallyScopedConn.setSessionMaxRows(isResultSetProducingQuery(sql) ? this.maxRows : -1); statementBegins(); rs = ((NativeSession) locallyScopedConn.getSession()).execSQL(this, sql, this.maxRows, null, createStreamingResultSet(), getResultSetFactory(), cachedMetaData, false); if (timeoutTask != null) { stopQueryTimer(timeoutTask, true, true); timeoutTask = null; } } catch (CJTimeoutException | OperationCancelledException e) { throw SQLExceptionsMapping.translateException(e, this.exceptionInterceptor); } finally { stopQueryTimer(timeoutTask, false, false); if (oldDb != null) { locallyScopedConn.setDatabase(oldDb); } } } if (rs != null) { this.lastInsertId = rs.getUpdateID(); this.results = rs; rs.setFirstCharOfQuery(QueryInfo.firstCharOfStatementUc(sql, this.session.getServerSession().isNoBackslashEscapesSet())); if (rs.hasRows()) { if (cachedMetaData != null) { locallyScopedConn.initializeResultsMetadataFromCache(sql, cachedMetaData, this.results); } else if (this.session.getPropertySet().getBooleanProperty(PropertyKey.cacheResultSetMetadata).getValue()) { locallyScopedConn.initializeResultsMetadataFromCache(sql, null /* will be created */, this.results); } } } return ((rs != null) && rs.hasRows()); } finally { this.query.getStatementExecuting().set(false); } } } @Override public void statementBegins() { this.query.statementBegins(); } @Override public void resetCancelledState() { synchronized (checkClosed().getConnectionMutex()) { this.query.resetCancelledState(); } } @Override public boolean execute(String sql, int returnGeneratedKeys) throws SQLException { return executeInternal(sql, returnGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS); } @Override public boolean execute(String sql, int[] generatedKeyIndices) throws SQLException { return executeInternal(sql, generatedKeyIndices != null && generatedKeyIndices.length > 0); } @Override public boolean execute(String sql, String[] generatedKeyNames) throws SQLException { return executeInternal(sql, generatedKeyNames != null && generatedKeyNames.length > 0); } @Override public int[] executeBatch() throws SQLException { return Util.truncateAndConvertToInt(executeBatchInternal()); } protected long[] executeBatchInternal() throws SQLException { JdbcConnection locallyScopedConn = checkClosed(); synchronized (locallyScopedConn.getConnectionMutex()) { if (locallyScopedConn.isReadOnly()) { throw SQLError.createSQLException(Messages.getString("Statement.34") + Messages.getString("Statement.35"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } implicitlyCloseAllOpenResults(); List<Object> batchedArgs = this.query.getBatchedArgs(); if (batchedArgs == null || batchedArgs.size() == 0) { return new long[0]; } // we timeout the entire batch, not individual statements int individualStatementTimeout = getTimeoutInMillis(); setTimeoutInMillis(0); CancelQueryTask timeoutTask = null; try { resetCancelledState(); statementBegins(); try { this.retrieveGeneratedKeys = true; // The JDBC spec doesn't forbid this, but doesn't provide for it either...we do.. long[] updateCounts = null; if (batchedArgs != null) { int nbrCommands = batchedArgs.size(); this.batchedGeneratedKeys = new ArrayList<>(batchedArgs.size()); boolean multiQueriesEnabled = locallyScopedConn.getPropertySet().getBooleanProperty(PropertyKey.allowMultiQueries).getValue(); if (multiQueriesEnabled || this.rewriteBatchedStatements.getValue() && nbrCommands > 4) { return executeBatchUsingMultiQueries(multiQueriesEnabled, nbrCommands, individualStatementTimeout); } timeoutTask = startQueryTimer(this, individualStatementTimeout); updateCounts = new long[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) batchedArgs.get(commandIndex); updateCounts[commandIndex] = executeUpdateInternal(sql, true, true); if (timeoutTask != null) { // we need to check the cancel state on each iteration to generate timeout exception if needed checkCancelTimeout(); } // limit one generated key per OnDuplicateKey statement getBatchedGeneratedKeys(this.results.getFirstCharOfQuery() == 'I' && 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 { long[] newUpdateCounts = new long[commandIndex]; if (hasDeadlockOrTimeoutRolledBackTx(ex)) { for (int i = 0; i < newUpdateCounts.length; i++) { newUpdateCounts[i] = java.sql.Statement.EXECUTE_FAILED; } } else { System.arraycopy(updateCounts, 0, newUpdateCounts, 0, commandIndex); } sqlEx = ex; break; //throw SQLError.createBatchUpdateException(ex, newUpdateCounts, getExceptionInterceptor()); } } } if (sqlEx != null) { throw SQLError.createBatchUpdateException(sqlEx, updateCounts, getExceptionInterceptor()); } } if (timeoutTask != null) { stopQueryTimer(timeoutTask, true, true); timeoutTask = null; } return (updateCounts != null) ? updateCounts : new long[0]; } finally { this.query.getStatementExecuting().set(false); } } finally { stopQueryTimer(timeoutTask, false, false); resetCancelledState(); setTimeoutInMillis(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: 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. * * @param multiQueriesEnabled * is multi-queries syntax allowed? * @param nbrCommands * number of queries in a batch * @param individualStatementTimeout * timeout for a single query in a batch * * @return update counts in the same manner as executeBatch() * @throws SQLException * if a database access error occurs or this method is called on a closed PreparedStatement */ private long[] executeBatchUsingMultiQueries(boolean multiQueriesEnabled, int nbrCommands, int individualStatementTimeout) throws SQLException { JdbcConnection locallyScopedConn = checkClosed(); synchronized (locallyScopedConn.getConnectionMutex()) { if (!multiQueriesEnabled) { this.session.enableMultiQueries(); } java.sql.Statement batchStmt = null; CancelQueryTask timeoutTask = null; try { long[] updateCounts = new long[nbrCommands]; for (int i = 0; i < nbrCommands; i++) { updateCounts[i] = JdbcStatement.EXECUTE_FAILED; } int commandIndex = 0; StringBuilder queryBuf = new StringBuilder(); batchStmt = locallyScopedConn.createStatement(); JdbcStatement jdbcBatchedStmt = (JdbcStatement) batchStmt; getQueryAttributesBindings().runThroughAll(a -> jdbcBatchedStmt.setAttribute(a.getName(), a.getValue())); timeoutTask = startQueryTimer((StatementImpl) batchStmt, individualStatementTimeout); int counter = 0; String connectionEncoding = locallyScopedConn.getPropertySet().getStringProperty(PropertyKey.characterEncoding).getValue(); int numberOfBytesPerChar = StringUtils.startsWithIgnoreCase(connectionEncoding, "utf") ? 3 : (this.session.getServerSession().getCharsetSettings().isMultibyteCharset(connectionEncoding) ? 2 : 1); 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.query.getBatchedArgs().get(commandIndex); if (((((queryBuf.length() + nextQuery.length()) * numberOfBytesPerChar) + 1 /* for semicolon */ + NativeConstants.HEADER_LENGTH) * escapeAdjust) + 32 > this.maxAllowedPacket.getValue()) { try { batchStmt.execute(queryBuf.toString(), java.sql.Statement.RETURN_GENERATED_KEYS); } catch (SQLException ex) { sqlEx = handleExceptionForBatch(commandIndex, argumentSetsInBatchSoFar, updateCounts, ex); } counter = processMultiCountsAndKeys((StatementImpl) batchStmt, counter, updateCounts); queryBuf = new StringBuilder(); argumentSetsInBatchSoFar = 0; } queryBuf.append(nextQuery); queryBuf.append(";"); argumentSetsInBatchSoFar++; } if (queryBuf.length() > 0) { try { batchStmt.execute(queryBuf.toString(), java.sql.Statement.RETURN_GENERATED_KEYS); } catch (SQLException ex) { sqlEx = handleExceptionForBatch(commandIndex - 1, argumentSetsInBatchSoFar, updateCounts, ex); } counter = processMultiCountsAndKeys((StatementImpl) batchStmt, counter, updateCounts); } if (timeoutTask != null) { stopQueryTimer(timeoutTask, true, true); timeoutTask = null; } if (sqlEx != null) { throw SQLError.createBatchUpdateException(sqlEx, updateCounts, getExceptionInterceptor()); } return (updateCounts != null) ? updateCounts : new long[0]; } finally { stopQueryTimer(timeoutTask, false, false); resetCancelledState(); try { if (batchStmt != null) { batchStmt.close(); } } finally { if (!multiQueriesEnabled) { this.session.disableMultiQueries(); } } } } } protected int processMultiCountsAndKeys(StatementImpl batchedStatement, int updateCountCounter, long[] updateCounts) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { updateCounts[updateCountCounter++] = batchedStatement.getLargeUpdateCount(); boolean doGenKeys = this.batchedGeneratedKeys != null; byte[][] row = null; if (doGenKeys) { long generatedKey = batchedStatement.getLastInsertID(); row = new byte[1][]; row[0] = StringUtils.getBytes(Long.toString(generatedKey)); this.batchedGeneratedKeys.add(new ByteArrayRow(row, getExceptionInterceptor())); } while (batchedStatement.getMoreResults() || batchedStatement.getLargeUpdateCount() != -1) { updateCounts[updateCountCounter++] = batchedStatement.getLargeUpdateCount(); if (doGenKeys) { long generatedKey = batchedStatement.getLastInsertID(); row = new byte[1][]; row[0] = StringUtils.getBytes(Long.toString(generatedKey)); this.batchedGeneratedKeys.add(new ByteArrayRow(row, getExceptionInterceptor())); } } return updateCountCounter; } } protected SQLException handleExceptionForBatch(int endOfBatchIndex, int numValuesPerBatch, long[] updateCounts, SQLException ex) throws BatchUpdateException, SQLException { for (int j = endOfBatchIndex; j > endOfBatchIndex - numValuesPerBatch; j--) { updateCounts[j] = EXECUTE_FAILED; } if (this.continueBatchOnError && !(ex instanceof MySQLTimeoutException) && !(ex instanceof MySQLStatementCancelledException) && !hasDeadlockOrTimeoutRolledBackTx(ex)) { return ex; } // else: throw the exception immediately long[] newUpdateCounts = new long[endOfBatchIndex]; System.arraycopy(updateCounts, 0, newUpdateCounts, 0, endOfBatchIndex); throw SQLError.createBatchUpdateException(ex, newUpdateCounts, getExceptionInterceptor()); } @Override public java.sql.ResultSet executeQuery(String sql) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { JdbcConnection locallyScopedConn = this.connection; this.retrieveGeneratedKeys = false; checkNullOrEmptyQuery(sql); resetCancelledState(); implicitlyCloseAllOpenResults(); if (sql.charAt(0) == '/') { if (sql.startsWith(PING_MARKER)) { doPingInstead(); return this.results; } } setupStreamingTimeout(locallyScopedConn); if (this.doEscapeProcessing) { Object escapedSqlResult = EscapeProcessor.escapeSQL(sql, this.session.getServerSession().getSessionTimeZone(), this.session.getServerSession().getCapabilities().serverSupportsFracSecs(), this.session.getServerSession().isServerTruncatesFracSecs(), getExceptionInterceptor()); sql = escapedSqlResult instanceof String ? (String) escapedSqlResult : ((EscapeProcessorResult) escapedSqlResult).escapedSql; } if (!isResultSetProducingQuery(sql)) { throw SQLError.createSQLException(Messages.getString("Statement.57"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } CachedResultSetMetaData cachedMetaData = null; if (useServerFetch()) { this.results = createResultSetUsingServerFetch(sql); return this.results; } CancelQueryTask timeoutTask = null; String oldDb = null; try { timeoutTask = startQueryTimer(this, getTimeoutInMillis()); if (!locallyScopedConn.getDatabase().equals(getCurrentDatabase())) { oldDb = locallyScopedConn.getDatabase(); locallyScopedConn.setDatabase(getCurrentDatabase()); } // // Check if we have cached metadata for this query... // if (locallyScopedConn.getPropertySet().getBooleanProperty(PropertyKey.cacheResultSetMetadata).getValue()) { cachedMetaData = locallyScopedConn.getCachedMetaData(sql); } locallyScopedConn.setSessionMaxRows(this.maxRows); statementBegins(); this.results = ((NativeSession) locallyScopedConn.getSession()).execSQL(this, sql, this.maxRows, null, createStreamingResultSet(), getResultSetFactory(), cachedMetaData, false); if (timeoutTask != null) { stopQueryTimer(timeoutTask, true, true); timeoutTask = null; } } catch (CJTimeoutException | OperationCancelledException e) { throw SQLExceptionsMapping.translateException(e, this.exceptionInterceptor); } finally { this.query.getStatementExecuting().set(false); stopQueryTimer(timeoutTask, false, false); if (oldDb != null) { locallyScopedConn.setDatabase(oldDb); } } this.lastInsertId = this.results.getUpdateID(); if (cachedMetaData != null) { locallyScopedConn.initializeResultsMetadataFromCache(sql, cachedMetaData, this.results); } else { if (this.connection.getPropertySet().getBooleanProperty(PropertyKey.cacheResultSetMetadata).getValue()) { locallyScopedConn.initializeResultsMetadataFromCache(sql, null /* will be created */, this.results); } } return this.results; } } protected void doPingInstead() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if (this.pingTarget != null) { try { this.pingTarget.doPing(); } catch (SQLException e) { throw e; } catch (Exception e) { throw SQLError.createSQLException(e.getMessage(), MysqlErrorNumbers.SQL_STATE_COMMUNICATION_LINK_FAILURE, e, getExceptionInterceptor()); } } else { this.connection.ping(); } ResultSetInternalMethods fakeSelectOneResultSet = generatePingResultSet(); this.results = fakeSelectOneResultSet; } } protected ResultSetInternalMethods generatePingResultSet() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { String encoding = this.session.getServerSession().getCharsetSettings().getMetadataEncoding(); int collationIndex = this.session.getServerSession().getCharsetSettings().getMetadataCollationIndex(); Field[] fields = { new Field(null, "1", collationIndex, encoding, MysqlType.BIGINT, 1) }; ArrayList<Row> rows = new ArrayList<>(); byte[] colVal = new byte[] { (byte) '1' }; rows.add(new ByteArrayRow(new byte[][] { colVal }, getExceptionInterceptor())); return this.resultSetFactory.createFromResultsetRows(ResultSet.CONCUR_READ_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, new ResultsetRowsStatic(rows, new DefaultColumnDefinition(fields))); } } public void executeSimpleNonQuery(JdbcConnection c, String nonQuery) throws SQLException { synchronized (c.getConnectionMutex()) { ((NativeSession) c.getSession()).<ResultSetImpl>execSQL(this, nonQuery, -1, null, false, getResultSetFactory(), null, false).close(); } } @Override public int executeUpdate(String sql) throws SQLException { return Util.truncateAndConvertToInt(executeLargeUpdate(sql)); } protected long executeUpdateInternal(String sql, boolean isBatch, boolean returnGeneratedKeys) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { JdbcConnection locallyScopedConn = this.connection; checkNullOrEmptyQuery(sql); resetCancelledState(); char firstStatementChar = QueryInfo.firstCharOfStatementUc(sql, this.session.getServerSession().isNoBackslashEscapesSet()); if (!isNonResultSetProducingQuery(sql)) { throw SQLError.createSQLException(Messages.getString("Statement.46"), "01S03", getExceptionInterceptor()); } this.retrieveGeneratedKeys = returnGeneratedKeys; this.lastQueryIsOnDupKeyUpdate = returnGeneratedKeys && firstStatementChar == 'I' && containsOnDuplicateKeyInString(sql); ResultSetInternalMethods rs = null; if (this.doEscapeProcessing) { Object escapedSqlResult = EscapeProcessor.escapeSQL(sql, this.session.getServerSession().getSessionTimeZone(), this.session.getServerSession().getCapabilities().serverSupportsFracSecs(), this.session.getServerSession().isServerTruncatesFracSecs(), getExceptionInterceptor()); sql = escapedSqlResult instanceof String ? (String) escapedSqlResult : ((EscapeProcessorResult) escapedSqlResult).escapedSql; } if (locallyScopedConn.isReadOnly(false)) { throw SQLError.createSQLException(Messages.getString("Statement.42") + Messages.getString("Statement.43"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } implicitlyCloseAllOpenResults(); // The checking and changing of databases must happen in sequence, so synchronize on the same mutex that _conn is using CancelQueryTask timeoutTask = null; String oldDb = null; try { timeoutTask = startQueryTimer(this, getTimeoutInMillis()); if (!locallyScopedConn.getDatabase().equals(getCurrentDatabase())) { oldDb = locallyScopedConn.getDatabase(); locallyScopedConn.setDatabase(getCurrentDatabase()); } // // Only apply max_rows to selects // locallyScopedConn.setSessionMaxRows(-1); statementBegins(); // null database: force read of field info on DML rs = ((NativeSession) locallyScopedConn.getSession()).execSQL(this, sql, -1, null, false, getResultSetFactory(), null, isBatch); if (timeoutTask != null) { stopQueryTimer(timeoutTask, true, true); timeoutTask = null; } } catch (CJTimeoutException | OperationCancelledException e) { throw SQLExceptionsMapping.translateException(e, this.exceptionInterceptor); } finally { stopQueryTimer(timeoutTask, false, false); if (oldDb != null) { locallyScopedConn.setDatabase(oldDb); } if (!isBatch) { this.query.getStatementExecuting().set(false); } } this.results = rs; rs.setFirstCharOfQuery(firstStatementChar); this.updateCount = rs.getUpdateCount(); this.lastInsertId = rs.getUpdateID(); return this.updateCount; } } @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { return Util.truncateAndConvertToInt(executeLargeUpdate(sql, autoGeneratedKeys)); } @Override public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { return Util.truncateAndConvertToInt(executeLargeUpdate(sql, columnIndexes)); } @Override public int executeUpdate(String sql, String[] columnNames) throws SQLException { return Util.truncateAndConvertToInt(executeLargeUpdate(sql, columnNames)); } @Override public java.sql.Connection getConnection() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { return this.connection; } } @Override public int getFetchDirection() throws SQLException { return java.sql.ResultSet.FETCH_FORWARD; } @Override public int getFetchSize() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { return this.query.getResultFetchSize(); } } @Override public java.sql.ResultSet getGeneratedKeys() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if (!this.retrieveGeneratedKeys) { throw SQLError.createSQLException(Messages.getString("Statement.GeneratedKeysNotRequested"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } if (this.batchedGeneratedKeys == null) { if (this.lastQueryIsOnDupKeyUpdate) { return this.generatedKeysResults = getGeneratedKeysInternal(1); } return this.generatedKeysResults = getGeneratedKeysInternal(); } String encoding = this.session.getServerSession().getCharsetSettings().getMetadataEncoding(); int collationIndex = this.session.getServerSession().getCharsetSettings().getMetadataCollationIndex(); Field[] fields = new Field[1]; fields[0] = new Field("", "GENERATED_KEY", collationIndex, encoding, MysqlType.BIGINT_UNSIGNED, 20); this.generatedKeysResults = this.resultSetFactory.createFromResultsetRows(ResultSet.CONCUR_READ_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, new ResultsetRowsStatic(this.batchedGeneratedKeys, new DefaultColumnDefinition(fields))); return this.generatedKeysResults; } } /* * Needed because there's no concept of super.super to get to this * implementation from ServerPreparedStatement when dealing with batched * updates. */ protected ResultSetInternalMethods getGeneratedKeysInternal() throws SQLException { long numKeys = getLargeUpdateCount(); return getGeneratedKeysInternal(numKeys); } protected ResultSetInternalMethods getGeneratedKeysInternal(long numKeys) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { String encoding = this.session.getServerSession().getCharsetSettings().getMetadataEncoding(); int collationIndex = this.session.getServerSession().getCharsetSettings().getMetadataCollationIndex(); Field[] fields = new Field[1]; fields[0] = new Field("", "GENERATED_KEY", collationIndex, encoding, MysqlType.BIGINT_UNSIGNED, 20); ArrayList<Row> rowSet = new ArrayList<>(); long beginAt = getLastInsertID(); if (this.results != null) { String serverInfo = this.results.getServerInfo(); // // Only parse server info messages for 'REPLACE' queries // if ((numKeys > 0) && (this.results.getFirstCharOfQuery() == 'R') && (serverInfo != null) && (serverInfo.length() > 0)) { numKeys = getRecordCountFromInfo(serverInfo); } if ((beginAt != 0 /* BIGINT UNSIGNED can wrap the protocol representation */) && (numKeys > 0)) { for (int i = 0; i < numKeys; i++) { byte[][] row = new byte[1][]; if (beginAt > 0) { row[0] = StringUtils.getBytes(Long.toString(beginAt)); } else { byte[] asBytes = new byte[8]; asBytes[7] = (byte) (beginAt & 0xff); asBytes[6] = (byte) (beginAt >>> 8); asBytes[5] = (byte) (beginAt >>> 16); asBytes[4] = (byte) (beginAt >>> 24); asBytes[3] = (byte) (beginAt >>> 32); asBytes[2] = (byte) (beginAt >>> 40); asBytes[1] = (byte) (beginAt >>> 48); asBytes[0] = (byte) (beginAt >>> 56); BigInteger val = new BigInteger(1, asBytes); row[0] = val.toString().getBytes(); } rowSet.add(new ByteArrayRow(row, getExceptionInterceptor())); beginAt += this.connection.getAutoIncrementIncrement(); } } } ResultSetImpl gkRs = this.resultSetFactory.createFromResultsetRows(ResultSet.CONCUR_READ_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, new ResultsetRowsStatic(rowSet, new DefaultColumnDefinition(fields))); return gkRs; } } /** * getLastInsertID returns the value of the auto_incremented key after an * executeQuery() or excute() call. * * <p> * This gets around the un-threadsafe behavior of "select LAST_INSERT_ID()" which is tied to the Connection that created this Statement, and therefore could * have had many INSERTS performed before one gets a chance to call "select LAST_INSERT_ID()". * </p> * * @return the last update ID. */ public long getLastInsertID() { synchronized (checkClosed().getConnectionMutex()) { return this.lastInsertId; } } /** * getLongUpdateCount returns the current result as an update count, if the * result is a ResultSet or there are no more results, -1 is returned. It * should only be called once per result. * * <p> * This method returns longs as MySQL server returns 64-bit values for update counts * </p> * * @return the current update count. */ public long getLongUpdateCount() { synchronized (checkClosed().getConnectionMutex()) { if (this.results == null) { return -1; } if (this.results.hasRows()) { return -1; } return this.updateCount; } } @Override public int getMaxFieldSize() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { return this.maxFieldSize; } } @Override public int getMaxRows() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if (this.maxRows <= 0) { return 0; } return this.maxRows; } } @Override public boolean getMoreResults() throws SQLException { return getMoreResults(CLOSE_CURRENT_RESULT); } @Override public boolean getMoreResults(int current) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if (this.results == null) { return false; } boolean streamingMode = createStreamingResultSet(); if (streamingMode) { if (this.results.hasRows()) { while (this.results.next()) { // need to drain remaining rows to get to server status which tells us whether more results actually exist or not } } } ResultSetInternalMethods nextResultSet = (ResultSetInternalMethods) this.results.getNextResultset(); switch (current) { case java.sql.Statement.CLOSE_CURRENT_RESULT: if (this.results != null) { if (!(streamingMode || this.dontTrackOpenResources.getValue())) { this.results.realClose(false); } this.results.clearNextResultset(); } break; case java.sql.Statement.CLOSE_ALL_RESULTS: if (this.results != null) { if (!(streamingMode || this.dontTrackOpenResources.getValue())) { this.results.realClose(false); } this.results.clearNextResultset(); } closeAllOpenResults(); break; case java.sql.Statement.KEEP_CURRENT_RESULT: if (!this.dontTrackOpenResources.getValue()) { this.openResults.add(this.results); } this.results.clearNextResultset(); // nobody besides us should // ever need this value... break; default: throw SQLError.createSQLException(Messages.getString("Statement.19"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } this.results = nextResultSet; if (this.results == null) { this.updateCount = -1; this.lastInsertId = -1; } else if (this.results.hasRows()) { this.updateCount = -1; this.lastInsertId = -1; } else { this.updateCount = this.results.getUpdateCount(); this.lastInsertId = this.results.getUpdateID(); } boolean moreResults = (this.results != null) && this.results.hasRows(); if (!moreResults) { checkAndPerformCloseOnCompletionAction(); } return moreResults; } } @Override public int getQueryTimeout() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { return getTimeoutInMillis() / 1000; } } /** * Parses actual record count from 'info' message * * @param serverInfo * server info message * @return records count */ private long getRecordCountFromInfo(String serverInfo) { StringBuilder recordsBuf = new StringBuilder(); long recordsCount = 0; long duplicatesCount = 0; char c = (char) 0; int length = serverInfo.length(); int i = 0; for (; i < length; i++) { c = serverInfo.charAt(i); if (Character.isDigit(c)) { break; } } recordsBuf.append(c); i++; for (; i < length; i++) { c = serverInfo.charAt(i); if (!Character.isDigit(c)) { break; } recordsBuf.append(c); } recordsCount = Long.parseLong(recordsBuf.toString()); StringBuilder duplicatesBuf = new StringBuilder(); for (; i < length; i++) { c = serverInfo.charAt(i); if (Character.isDigit(c)) { break; } } duplicatesBuf.append(c); i++; for (; i < length; i++) { c = serverInfo.charAt(i); if (!Character.isDigit(c)) { break; } duplicatesBuf.append(c); } duplicatesCount = Long.parseLong(duplicatesBuf.toString()); return recordsCount - duplicatesCount; } @Override public java.sql.ResultSet getResultSet() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { return ((this.results != null) && this.results.hasRows()) ? (java.sql.ResultSet) this.results : null; } } @Override public int getResultSetConcurrency() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { return this.resultSetConcurrency; } } @Override public int getResultSetHoldability() throws SQLException { return java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT; } @Override public ResultSetInternalMethods getResultSetInternal() { try { synchronized (checkClosed().getConnectionMutex()) { return this.results; } } catch (StatementIsClosedException e) { return this.results; // you end up with the same thing as before, you'll get exception when actually trying to use it } } @Override public int getResultSetType() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { return this.query.getResultType().getIntValue(); } } @Override public int getUpdateCount() throws SQLException { return Util.truncateAndConvertToInt(getLargeUpdateCount()); } @Override public java.sql.SQLWarning getWarnings() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if (isClearWarningsCalled()) { return null; } SQLWarning pendingWarningsFromServer = this.session.getProtocol().convertShowWarningsToSQLWarnings(false); if (this.warningChain != null) { this.warningChain.setNextWarning(pendingWarningsFromServer); } else { this.warningChain = pendingWarningsFromServer; } return this.warningChain; } } /** * Closes this statement, and frees resources. * * @param calledExplicitly * was this called from close()? * @param closeOpenResults * should open result sets be closed? * * @throws SQLException * if an error occurs */ protected void realClose(boolean calledExplicitly, boolean closeOpenResults) throws SQLException { JdbcConnection locallyScopedConn = this.connection; if (locallyScopedConn == null || this.isClosed) { return; // already closed } // do it ASAP to reduce the chance of calling this method concurrently from ConnectionImpl.closeAllOpenStatements() if (!this.dontTrackOpenResources.getValue()) { locallyScopedConn.unregisterStatement(this); } if (this.useUsageAdvisor) { if (!calledExplicitly) { this.session.getProfilerEventHandler().processEvent(ProfilerEvent.TYPE_USAGE, this.session, this, null, 0, new Throwable(), Messages.getString("Statement.63")); } } if (closeOpenResults) { closeOpenResults = !(this.holdResultsOpenOverClose || this.dontTrackOpenResources.getValue()); } if (closeOpenResults) { if (this.results != null) { try { this.results.close(); } catch (Exception ex) { } } if (this.generatedKeysResults != null) { try { this.generatedKeysResults.close(); } catch (Exception ex) { } } closeAllOpenResults(); } clearAttributes(); this.isClosed = true; closeQuery(); this.results = null; this.generatedKeysResults = null; this.connection = null; this.session = null; this.warningChain = null; this.openResults = null; this.batchedGeneratedKeys = null; this.pingTarget = null; this.resultSetFactory = null; } @Override public void setCursorName(String name) throws SQLException { // No-op } @Override public void setEscapeProcessing(boolean enable) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { this.doEscapeProcessing = enable; } } @Override public void setFetchDirection(int direction) throws SQLException { switch (direction) { case java.sql.ResultSet.FETCH_FORWARD: case java.sql.ResultSet.FETCH_REVERSE: case java.sql.ResultSet.FETCH_UNKNOWN: break; default: throw SQLError.createSQLException(Messages.getString("Statement.5"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } @Override public void setFetchSize(int rows) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if (((rows < 0) && (rows != Integer.MIN_VALUE)) || ((this.maxRows > 0) && (rows > this.getMaxRows()))) { throw SQLError.createSQLException(Messages.getString("Statement.7"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } this.query.setResultFetchSize(rows); } } @Override public void setHoldResultsOpenOverClose(boolean holdResultsOpenOverClose) { try { synchronized (checkClosed().getConnectionMutex()) { this.holdResultsOpenOverClose = holdResultsOpenOverClose; } } catch (StatementIsClosedException e) { // FIXME: can't break interface at this point } } @Override public void setMaxFieldSize(int max) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if (max < 0) { throw SQLError.createSQLException(Messages.getString("Statement.11"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } int maxBuf = this.maxAllowedPacket.getValue(); if (max > maxBuf) { throw SQLError.createSQLException(Messages.getString("Statement.13", new Object[] { Long.valueOf(maxBuf) }), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } this.maxFieldSize = max; } } @Override public void setMaxRows(int max) throws SQLException { setLargeMaxRows(max); } @Override public void setQueryTimeout(int seconds) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if (seconds < 0) { throw SQLError.createSQLException(Messages.getString("Statement.21"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } setTimeoutInMillis(seconds * 1000); } } /** * Sets the concurrency for result sets generated by this statement * * @param concurrencyFlag * concurrency flag * @throws SQLException * if a database access error occurs or this method is called on a closed PreparedStatement */ void setResultSetConcurrency(int concurrencyFlag) throws SQLException { try { synchronized (checkClosed().getConnectionMutex()) { this.resultSetConcurrency = concurrencyFlag; // updating resultset factory because concurrency is cached there this.resultSetFactory = new ResultSetFactory(this.connection, this); } } catch (StatementIsClosedException e) { // FIXME: Can't break interface atm, we'll get the exception later when you try and do something useful with a closed statement... } } /** * Sets the result set type for result sets generated by this statement * * @param typeFlag * {@link com.mysql.cj.protocol.Resultset.Type} * @throws SQLException * if a database access error occurs or this method is called on a closed PreparedStatement */ void setResultSetType(Resultset.Type typeFlag) throws SQLException { try { synchronized (checkClosed().getConnectionMutex()) { this.query.setResultType(typeFlag); // updating resultset factory because type is cached there this.resultSetFactory = new ResultSetFactory(this.connection, this); } } catch (StatementIsClosedException e) { // FIXME: Can't break interface atm, we'll get the exception later when you try and do something useful with a closed statement... } } void setResultSetType(int typeFlag) throws SQLException { this.query.setResultType(Type.fromValue(typeFlag, Type.FORWARD_ONLY)); } protected void getBatchedGeneratedKeys(java.sql.Statement batchedStatement) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if (this.retrieveGeneratedKeys) { java.sql.ResultSet rs = null; try { rs = batchedStatement.getGeneratedKeys(); while (rs.next()) { this.batchedGeneratedKeys.add(new ByteArrayRow(new byte[][] { rs.getBytes(1) }, getExceptionInterceptor())); } } finally { if (rs != null) { rs.close(); } } } } } protected void getBatchedGeneratedKeys(int maxKeys) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if (this.retrieveGeneratedKeys) { java.sql.ResultSet rs = null; try { rs = maxKeys == 0 ? getGeneratedKeysInternal() : getGeneratedKeysInternal(maxKeys); while (rs.next()) { this.batchedGeneratedKeys.add(new ByteArrayRow(new byte[][] { rs.getBytes(1) }, getExceptionInterceptor())); } } finally { this.isImplicitlyClosingResults = true; try { if (rs != null) { rs.close(); } } finally { this.isImplicitlyClosingResults = false; } } } } } private boolean useServerFetch() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { return this.session.getPropertySet().getBooleanProperty(PropertyKey.useCursorFetch).getValue() && this.query.getResultFetchSize() > 0 && this.query.getResultType() == Type.FORWARD_ONLY; } } @Override public boolean isClosed() throws SQLException { JdbcConnection locallyScopedConn = this.connection; if (locallyScopedConn == null) { return true; } synchronized (locallyScopedConn.getConnectionMutex()) { return this.isClosed; } } private boolean isPoolable = false; @Override public boolean isPoolable() throws SQLException { checkClosed(); return this.isPoolable; } @Override public void setPoolable(boolean poolable) throws SQLException { checkClosed(); this.isPoolable = poolable; } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { checkClosed(); // This works for classes that aren't actually wrapping anything return iface.isInstance(this); } @Override public <T> T unwrap(Class<T> iface) throws SQLException { try { // This works for classes that aren't actually wrapping anything return iface.cast(this); } catch (ClassCastException cce) { throw SQLError.createSQLException(Messages.getString("Common.UnableToUnwrap", new Object[] { iface.toString() }), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } } @Override public InputStream getLocalInfileInputStream() { return this.session.getLocalInfileInputStream(); } @Override public void setLocalInfileInputStream(InputStream stream) { this.session.setLocalInfileInputStream(stream); } @Override public void setPingTarget(PingTarget pingTarget) { this.pingTarget = pingTarget; } @Override public ExceptionInterceptor getExceptionInterceptor() { return this.exceptionInterceptor; } protected boolean containsOnDuplicateKeyInString(String sql) { return (!this.dontCheckOnDuplicateKeyUpdateInSQL || this.rewriteBatchedStatements.getValue()) && QueryInfo.containsOnDuplicateKeyUpdateClause(sql, this.session.getServerSession().isNoBackslashEscapesSet()); } private boolean closeOnCompletion = false; @Override public void closeOnCompletion() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { this.closeOnCompletion = true; } } @Override public boolean isCloseOnCompletion() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { return this.closeOnCompletion; } } @Override public long[] executeLargeBatch() throws SQLException { return executeBatchInternal(); } @Override public long executeLargeUpdate(String sql) throws SQLException { return executeUpdateInternal(sql, false, false); } @Override public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException { return executeUpdateInternal(sql, false, autoGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS); } @Override public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException { return executeUpdateInternal(sql, false, columnIndexes != null && columnIndexes.length > 0); } @Override public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException { return executeUpdateInternal(sql, false, columnNames != null && columnNames.length > 0); } @Override public long getLargeMaxRows() throws SQLException { // Max rows is limited by MySQLDefs.MAX_ROWS anyway... return getMaxRows(); } @Override public long getLargeUpdateCount() throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if (this.results == null) { return -1; } if (this.results.hasRows()) { return -1; } return this.results.getUpdateCount(); } } @Override public void setLargeMaxRows(long max) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { if ((max > MAX_ROWS) || (max < 0)) { throw SQLError.createSQLException(Messages.getString("Statement.15") + max + " > " + MAX_ROWS + ".", MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } if (max == 0) { max = -1; } this.maxRows = (int) max; } } @Override public String getCurrentDatabase() { return this.query.getCurrentDatabase(); } public long getServerStatementId() { throw ExceptionFactory.createException(CJOperationNotSupportedException.class, Messages.getString("Statement.65")); } @Override @SuppressWarnings("unchecked") public <T extends Resultset, M extends Message> ProtocolEntityFactory<T, M> getResultSetFactory() { return (ProtocolEntityFactory<T, M>) this.resultSetFactory; } @Override public int getId() { return this.query.getId(); } @Override public void setCancelStatus(CancelStatus cs) { this.query.setCancelStatus(cs); } @Override public void checkCancelTimeout() { this.query.checkCancelTimeout(); } @Override public Session getSession() { return this.session; } @Override public Object getCancelTimeoutMutex() { return this.query.getCancelTimeoutMutex(); } @Override public void closeQuery() { if (this.query != null) { this.query.closeQuery(); } } @Override public int getResultFetchSize() { return this.query.getResultFetchSize(); } @Override public void setResultFetchSize(int fetchSize) { this.query.setResultFetchSize(fetchSize); } @Override public Resultset.Type getResultType() { return this.query.getResultType(); } @Override public void setResultType(Resultset.Type resultSetType) { this.query.setResultType(resultSetType); } @Override public int getTimeoutInMillis() { return this.query.getTimeoutInMillis(); } @Override public void setTimeoutInMillis(int timeoutInMillis) { this.query.setTimeoutInMillis(timeoutInMillis); } @Override public long getExecuteTime() { return this.query.getExecuteTime(); } @Override public void setExecuteTime(long executeTime) { this.query.setExecuteTime(executeTime); } @Override public AtomicBoolean getStatementExecuting() { return this.query.getStatementExecuting(); } @Override public void setCurrentDatabase(String currentDb) { this.query.setCurrentDatabase(currentDb); } @Override public boolean isClearWarningsCalled() { return this.query.isClearWarningsCalled(); } @Override public void setClearWarningsCalled(boolean clearWarningsCalled) { this.query.setClearWarningsCalled(clearWarningsCalled); } @Override public Query getQuery() { return this.query; } @Override public QueryAttributesBindings getQueryAttributesBindings() { return this.query.getQueryAttributesBindings(); } @Override public void setAttribute(String name, Object value) { getQueryAttributesBindings().setAttribute(name, value); } @Override public void clearAttributes() { QueryAttributesBindings qab = getQueryAttributesBindings(); if (qab != null) { qab.clearAttributes(); } } }
⏎ com/mysql/cj/jdbc/StatementImpl.java
Or download all of them as a single archive file:
File name: mysql-connector-java-user-impl-8.0.31.zip File size: 429580 bytes Release date: 2022-09-03 Download
⇒ Downloading mysql-connector-java-5.1.40.zip
⇐ Source Code for Connector/J 8.0.31 - User API
2023-05-09, 7594👍, 0💬
Popular Posts:
Apache Avalon began in 1999 as the Java Apache Server Framework and in late 2002 separated from the ...
JDK 11 jdk.internal.opt.jmod is the JMOD file for JDK 11 Internal Opt module. JDK 11 Internal Opt mo...
Jaxen, Release 1.1.1, is an open source XPath library written in Java. It is adaptable to many diffe...
What Is poi-scratchpad-3.5.jar? poi-scratchpad-3.5.jar is one of the JAR files for Apache POI 3.5, w...
commons-net-1.4.1.jar is the JAR file for Apache Commons Net 1.4.1, which implements the client side...