📄 statementimpl.java
字号:
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); } } 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 })); return (ResultSetInternalMethods) DatabaseMetaData.buildResultSet(fields, rows, this.connection); } protected void executeSimpleNonQuery(ConnectionImpl 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(); ConnectionImpl 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); //$NON-NLS-1$ } if (StringUtils.startsWithIgnoreCaseAndWs(sql, "select")) { //$NON-NLS-1$ throw SQLError.createSQLException(Messages .getString("Statement.46"), //$NON-NLS-1$ "01S03"); //$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); ConnectionImpl.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(); 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); } } } 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 (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 = locallyScopedConn .isReadInfoMsgEnabled(); locallyScopedConn.setReadInfoMsgEnabled(true); try { return executeUpdate(sql, false, true); } finally { locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); } } } return executeUpdate(sql); } /** * @see StatementImpl#executeUpdate(String, int[]) */ public int executeUpdate(String sql, int[] generatedKeyIndices) throws SQLException { if ((generatedKeyIndices != null) && (generatedKeyIndices.length > 0)) { 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 = locallyScopedConn .isReadInfoMsgEnabled(); locallyScopedConn.setReadInfoMsgEnabled(true); try { return executeUpdate(sql, false, true); } finally { locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); } } } return executeUpdate(sql); } /** * @see StatementImpl#executeUpdate(String, String[]) */ public int executeUpdate(String sql, String[] generatedKeyNames) throws SQLException { if ((generatedKeyNames != null) && (generatedKeyNames.length > 0)) { 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 executeUpdate(sql, false, true); } finally { locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState); } } } return executeUpdate(sql); } /** * Optimization to only use one calendar per-session, or calculate it for * each call, depending on user configuration */ protected Calendar getCalendarInstanceForSessionOrNew() { if (this.connection != null) { return this.connection.getCalendarInstanceForSessionOrNew(); } else { // punt, no connection around return new GregorianCalendar(); } } /** * JDBC 2.0 Return the Connection that produced the Statement. * * @return the Connection that produced the Statement * * @throws SQLException * if an error occurs */ public java.sql.Connection getConnection() throws SQLException { return this.connection; } /** * JDBC 2.0 Determine the fetch direction. * * @return the default fetch direction * * @exception SQLException * if a database-access error occurs */ public int getFetchDirection() throws SQLException { return java.sql.ResultSet.FETCH_FORWARD; } /** * JDBC 2.0 Determine the default fetch size. * * @return the number of rows to fetch at a time * * @throws SQLException * if an error occurs */ public int getFetchSize() throws SQLException { return this.fetchSize; } /** * DOCUMENT ME! * * @return DOCUMENT ME! * * @throws SQLException * DOCUMENT ME! */ public synchronized java.sql.ResultSet getGeneratedKeys() throws SQLException { if (!this.retrieveGeneratedKeys) { throw SQLError.createSQLException(Messages.getString("Statement.GeneratedKeysNotRequested"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } if (this.batchedGeneratedKeys == null) { return getGeneratedKeysInternal(); } Field[] fields = new Field[1]; fields[0] = new Field("", "GENERATED_KEY", Types.BIGINT, 17); //$NON-NLS-1$ //$NON-NLS-2$ fields[0].setConnection(this.connection); return com.mysql.jdbc.ResultSetImpl.getInstance(this.currentCatalog, fields, new RowDataStatic(this.batchedGeneratedKeys), this.connection, this, false); } /* * Needed because there's no concept of super.super to get to this * implementation from ServerPreparedStatement when dealing with batched * updates. */ protected java.sql.ResultSet getGeneratedKeysInternal() throws SQLException { Field[] fields = new Field[1]; fields[0] = new Field("", "GENERATED_KEY", Types.BIGINT, 17); //$NON-NLS-1$ //$NON-NLS-2$ fields[0].setConnection(this.connection); fields[0].setUseOldNameMetadata(true); ArrayList rowSet = new ArrayList(); long beginAt = getLastInsertID(); int numKeys = getUpdateCount(); 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) && (numKeys > 0)) { for (int i = 0; i < numKeys; i++) { byte[][] row = new byte[1][]; row[0] = Long.toString(beginAt).getBytes(); rowSet.add(new ByteArrayRow(row)); beginAt += this.connection.getAutoIncrementIncrement(); } } } com.mysql.jdbc.ResultSetImpl gkRs = com.mysql.jdbc.ResultSetImpl.getInstance(this.currentCatalog, fields, new RowDataStatic(rowSet), this.connection, this, false); this.openResults.add(gkRs); return gkRs; } /** * Returns the id used when profiling * * @return the id used when profiling. */ protected int getId() { return this.statementId; } /** * 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> *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -