📄 statementimpl.java
字号:
* <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 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(); } } /** * @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(); ConnectionImpl locallyScopedConn = this.connection; synchronized (locallyScopedConn.getMutex()) { this.retrieveGeneratedKeys = returnGeneratedKeys; 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); //$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 && this.connection.getNetTimeoutForStreamingResults() > 0) { executeSimpleNonQuery(locallyScopedConn, "SET net_write_timeout=" + this.connection.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); ConnectionImpl.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(); } 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(); ConnectionImpl 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(); ConnectionImpl 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(); ConnectionImpl 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(); ConnectionImpl 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); //$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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -