Java tutorial
/* * Copyright 2013 Gregory Graham. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package nz.co.gregs.dbvolution.databases; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; import nz.co.gregs.dbvolution.DBDatabase; import nz.co.gregs.dbvolution.databases.definitions.DBDefinition; import nz.co.gregs.dbvolution.exceptions.UnableToCreateDatabaseConnectionException; import nz.co.gregs.dbvolution.exceptions.UnableToFindJDBCDriver; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Encapsulates the JDBC Connection and Statement classes. * * <p> * You should not need to create a DBStatement as they are managed by the * DBDatabase internally. * * <p> * DBStatement simplifies the JDBC interface by managing the connection and * statement simultaneously. When the statement is closed so is the connection * ensuring minimalist usage of the database. * * <p> * Mostly this is a thin wrapper around DBDatabase, Connection, and Statement * objects * * @author Gregory Graham */ public class DBStatement implements Statement { static final private Log log = LogFactory.getLog(DBStatement.class); private Statement internalStatement; private boolean batchHasEntries; final DBDatabase database; private Connection connection; private boolean isClosed = false; /** * Creates a statement object for the given DBDatabase and Connection. * * @param db the target database * @param connection the connection to the database * @throws SQLException datbase exceptions */ public DBStatement(DBDatabase db, Connection connection) throws SQLException { this.database = db; this.connection = connection; this.internalStatement = connection.createStatement(); } /** * Executes the given SQL statement, which returns a single ResultSet object. * * @param string SQL * @return a ResultSet * @throws SQLException database exceptions */ @Override public ResultSet executeQuery(String string) throws SQLException { final String logSQL = "EXECUTING QUERY: " + string; database.printSQLIfRequested(logSQL); log.debug(logSQL); ResultSet executeQuery = null; try { executeQuery = getInternalStatement().executeQuery(string); } catch (SQLException exp) { try { executeQuery = addFeatureAndAttemptQueryAgain(exp, string); } catch (Exception ex) { throw new RuntimeException(ex); } } return executeQuery; } private ResultSet addFeatureAndAttemptQueryAgain(Exception exp, String string) throws Exception { ResultSet executeQuery; final String ln = System.getProperty("line.separator"); // System.out.println("Adding Feature for: " + exp.getMessage() + ln + exp.toString()); // for (StackTraceElement el : exp.getStackTrace()) { // System.out.println(""+el); // } try { database.addFeatureToFixException(exp); } catch (Exception ex) { Exception ex1 = exp; while (!ex1.getMessage().equals(ex.getMessage())) { database.addFeatureToFixException(ex); } throw new SQLException(ex); } try { executeQuery = getInternalStatement().executeQuery(string); return executeQuery; } catch (SQLException exp2) { if (exp.getMessage().equals(exp2.getMessage())) { throw exp; } else { executeQuery = addFeatureAndAttemptQueryAgain(exp2, string); return executeQuery; } } } /** * Executes the given SQL statement, which may be an INSERT, UPDATE, or DELETE * statement or an SQL statement that returns nothing, such as an SQL DDL * statement. * * @param string string * @return either (1) the row count for SQL Data Manipulation Language (DML) * statements or (2) 0 for SQL statements that return nothing 1 Database * exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int executeUpdate(String string) throws SQLException { return getInternalStatement().executeUpdate(string); } /** * Closes the Statement and the Connection. * * <p> * Also informs the DBDatabase that there is one less connection to the * database. * * 1 Database exceptions may be thrown * * @throws java.sql.SQLException java.sql.SQLException */ @Override public void close() throws SQLException { isClosed = true; try { database.unusedConnection(getConnection()); getInternalStatement().close(); } catch (Exception e) { // Someone please tell me how you are supposed to cope // with an exception during the close method???????? log.warn("Exception occurred during close(): " + e.getMessage(), e); // throw e; e.printStackTrace(System.err); } } /** * Retrieves the maximum number of bytes that can be returned for character * and binary column values in a ResultSet object produced by this Statement * object. This limit applies only to BINARY, VARBINARY, LONGVARBINARY, CHAR, * VARCHAR, NCHAR, NVARCHAR, LONGNVARCHAR and LONGVARCHAR columns. If the * limit is exceeded, the excess data is silently discarded. * * @return the current column size limit for columns storing character and * binary values; zero means there is no limit. 1 Database exceptions may be * thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int getMaxFieldSize() throws SQLException { return getInternalStatement().getMaxFieldSize(); } /** * Sets the limit for the maximum number of bytes that can be returned for * character and binary column values in a ResultSet object produced by this * Statement object. This limit applies only to BINARY, VARBINARY, * LONGVARBINARY, CHAR, VARCHAR, NCHAR, NVARCHAR, LONGNVARCHAR and LONGVARCHAR * fields. If the limit is exceeded, the excess data is silently discarded. * For maximum portability, use values greater than 256. * * * 1 Database exceptions may be thrown * * @param i i * @throws java.sql.SQLException java.sql.SQLException */ @Override public void setMaxFieldSize(int i) throws SQLException { getInternalStatement().setMaxFieldSize(i); } /** * Retrieves the maximum number of rows that a ResultSet object produced by * this Statement object can contain. If this limit is exceeded, the excess * rows are silently dropped. * * @return the current maximum number of rows for a <code>ResultSet</code> * object produced by this <code>Statement</code> object; zero means there is * no limit 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int getMaxRows() throws SQLException { return getInternalStatement().getMaxRows(); } /** * Sets the limit for the maximum number of rows that any ResultSet object * generated by this Statement object can contain to the given number. If the * limit is exceeded, the excess rows are silently dropped. * * * 1 Database exceptions may be thrown * * @param i i * @throws java.sql.SQLException java.sql.SQLException */ @Override public void setMaxRows(int i) throws SQLException { getInternalStatement().setMaxRows(i); } /** * Sets escape processing on or off. If escape scanning is on (the default), * the driver will do escape substitution before sending the SQL statement to * the database. Note: Since prepared statements have usually been parsed * prior to making this call, disabling escape processing for * PreparedStatements objects will have no effect. * * * 1 Database exceptions may be thrown * * @param bln bln * @throws java.sql.SQLException java.sql.SQLException */ @Override public void setEscapeProcessing(boolean bln) throws SQLException { getInternalStatement().setEscapeProcessing(bln); } /** * Retrieves the number of seconds the driver will wait for a Statement object * to execute. If the limit is exceeded, a SQLException is thrown. * * @return the current query timeout limit in seconds; zero means there is no * limit 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int getQueryTimeout() throws SQLException { return getInternalStatement().getQueryTimeout(); } /** * Sets the number of seconds the driver will wait for a Statement object to * execute to the given number of seconds. By default there is no limit on the * amount of time allowed for a running statement to complete. If the limit is * exceeded, an SQLTimeoutException is thrown. A JDBC driver must apply this * limit to the execute, executeQuery and executeUpdate methods. * * * 1 Database exceptions may be thrown * * @param i i * @throws java.sql.SQLException java.sql.SQLException */ @Override public void setQueryTimeout(int i) throws SQLException { getInternalStatement().setQueryTimeout(i); } /** * 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. * * 1 Database exceptions may be thrown * * @throws java.sql.SQLException java.sql.SQLException */ @Override public synchronized void cancel() throws SQLException { getInternalStatement().cancel(); if (database.getDefinition().willCloseConnectionOnStatementCancel()) { replaceBrokenConnection(); } } /** * Discards the current connection, replaces it, and creates a new statement. * * <p> * Call this after canceling or closing a statement for a database that close * the connection with the statement. Use {@link DBDefinition#willCloseConnectionOnStatementCancel() * } to detect this situation. * * @throws SQLException exceptions from connecting to the database and * creating a Statement. * @throws UnableToCreateDatabaseConnectionException may be thrown if there is * an issue with connecting. * @throws UnableToFindJDBCDriver may be thrown if the JDBCDriver is not on * the class path. DBvolution includes several JDBCDrivers already but * Oracle and MS SQLserver, in particular, need to be added to the path if you * wish to work with those databases. */ protected synchronized void replaceBrokenConnection() throws SQLException, UnableToCreateDatabaseConnectionException, UnableToFindJDBCDriver { database.discardConnection(connection); connection = database.getConnection(); internalStatement = connection.createStatement(); } /** * Retrieves the first warning reported by calls on this Statement object. * Subsequent Statement object warnings will be chained to this SQLWarning * object. * * <p> * The warning chain is automatically cleared each time a statement is * (re)executed. This method may not be called on a closed Statement object; * doing so will cause an SQLException to be thrown. * * @return the first <code>SQLWarning</code> object or <code>null</code> if * there are no warnings 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public SQLWarning getWarnings() throws SQLException { return getInternalStatement().getWarnings(); } /** * Clears all the warnings reported on this Statement object. After a call to * this method, the method getWarnings will return null until a new warning is * reported for this Statement object. * * 1 Database exceptions may be thrown * * @throws java.sql.SQLException java.sql.SQLException */ @Override public void clearWarnings() throws SQLException { getInternalStatement().clearWarnings(); } /** * Sets the SQL cursor name to the given String, which will be used by * subsequent Statement object execute methods. * * <P> * This name can then be used in SQL positioned update or delete statements to * identify the current row in the ResultSet object generated by this * statement. If the database does not support positioned update/delete, this * method is a noop. To insure that a cursor has the proper isolation level to * support updates, the cursor's SELECT statement should have the form SELECT * FOR UPDATE. If FOR UPDATE is not present, positioned updates may fail. * * * 1 Database exceptions may be thrown * * @param string string * @throws java.sql.SQLException java.sql.SQLException */ @Override public void setCursorName(String string) throws SQLException { getInternalStatement().setCursorName(string); } /** * Executes the given SQL statement, which may return multiple results. * * <p> * In some (uncommon) situations, a single SQL statement may return multiple * result sets and/or update counts. Normally you can ignore this unless you * are (1) executing a stored procedure that you know may return multiple * results or (2) you are dynamically executing an unknown SQL string. * * <p> * The execute method executes an SQL statement and indicates the form of the * first result. You must then use the methods getResultSet or getUpdateCount * to retrieve the result, and getMoreResults to move to any subsequent * result(s). * * @param string string * @return <code>TRUE</code> if the first result is a <code>ResultSet</code> * object; <code>FALSE</code> if it is an update count or there are no results * 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public boolean execute(String string) throws SQLException { final String logSQL = "EXECUTING: " + string; database.printSQLIfRequested(logSQL); log.debug(logSQL); final boolean execute; try { execute = getInternalStatement().execute(string); } catch (Exception exp) { return addFeatureAndAttemptExecuteAgain(exp, string); } return execute; } private boolean addFeatureAndAttemptExecuteAgain(Exception exp, String string) throws SQLException { boolean executeQuery; final String ln = System.getProperty("line.separator"); // System.out.println("Adding Feature for: " + exp.getMessage() + ln + exp.toString()); try { database.addFeatureToFixException(exp); } catch (Exception ex) { throw new SQLException(ex); } try { executeQuery = getInternalStatement().execute(string); return executeQuery; } catch (Exception exp2) { if (!exp.getMessage().equals(exp2.getMessage())) { executeQuery = addFeatureAndAttemptExecuteAgain(exp2, string); return executeQuery; } else { throw new SQLException(exp); } } } /** * Retrieves the current result as a ResultSet object. * * <p> * This method should be called only once per result. * * @return the current result as a <code>ResultSet</code> object or * <code>null</code> if the result is an update count or there are no more * results 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public ResultSet getResultSet() throws SQLException { return getInternalStatement().getResultSet(); } /** * Retrieves the current result as an update count; if the result is a * ResultSet object or there are no more results, -1 is returned. * <p> * This method should be called only once per result. * * @return the current result as an update count; -1 if the current result is * a <code>ResultSet</code> object or there are no more results. 1 Database * exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int getUpdateCount() throws SQLException { return getInternalStatement().getUpdateCount(); } /** * Moves to this Statement object's next result, returns true if it is a * ResultSet object, and implicitly closes any current ResultSet object(s) * obtained with the method getResultSet. * <p> * There are no more results when the following is true: * <p> * <code> * // stmt is a Statement object ((stmt.getMoreResults() == false) && * (stmt.getUpdateCount() == -1)) * </code> * * @return true if the next result is a ResultSet object; false if it is an * update count or there are no more results 1 Database exceptions may be * thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public boolean getMoreResults() throws SQLException { return getInternalStatement().getMoreResults(); } /** * Gives the driver a hint as to the direction in which rows will be processed * in ResultSet objects created using this Statement object. * <P> * The default value is ResultSet.FETCH_FORWARD. * * * 1 Database exceptions may be thrown * * @param i i * @throws java.sql.SQLException java.sql.SQLException */ @Override public void setFetchDirection(int i) throws SQLException { getInternalStatement().setFetchDirection(i); } /** * Retrieves the direction for fetching rows from database tables that is the * default for result sets generated from this Statement object. * <P> * If this Statement object has not set a fetch direction by calling the * method setFetchDirection, the return value is implementation-specific. * * @return the default fetch direction for result sets generated from this * Statement object 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int getFetchDirection() throws SQLException { return getInternalStatement().getFetchDirection(); } /** * Gives the JDBC driver a hint as to the number of rows that should be * fetched from the database when more rows are needed for ResultSet objects * generated by this Statement. * <P> * If the value specified is zero, then the hint is ignored. The default value * is zero. * * * 1 Database exceptions may be thrown * * @param i i * @throws java.sql.SQLException java.sql.SQLException */ @Override public void setFetchSize(int i) throws SQLException { getInternalStatement().setFetchSize(i); } /** * Retrieves the number of result set rows that is the default fetch size for * ResultSet objects generated from this Statement object. * <P> * If this Statement object has not set a fetch size by calling the method * setFetchSize, the return value is implementation-specific. * * @return the default fetch size for result sets generated from this * Statement object * * 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int getFetchSize() throws SQLException { return getInternalStatement().getFetchSize(); } /** * Retrieves the result set concurrency for ResultSet objects generated by * this Statement object. * * @return either ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE 1 * Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int getResultSetConcurrency() throws SQLException { return getInternalStatement().getResultSetConcurrency(); } /** * Retrieves the result set type for ResultSet objects generated by this * Statement object. * * @return one of ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE 1 * Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int getResultSetType() throws SQLException { return getInternalStatement().getResultSetType(); } /** * Adds the given SQL command to the current list of commands for this * Statement object. The commands in this list can be executed as a batch by * calling the method executeBatch. * * * 1 Database exceptions may be thrown * * @param string string * @throws java.sql.SQLException java.sql.SQLException */ @Override public void addBatch(String string) throws SQLException { getInternalStatement().addBatch(string); setBatchHasEntries(true); } /** * Empties this Statement object's current list of SQL commands. * * 1 Database exceptions may be thrown * * @throws java.sql.SQLException java.sql.SQLException */ @Override public void clearBatch() throws SQLException { getInternalStatement().clearBatch(); setBatchHasEntries(false); } /** * Submits a batch of commands to the database for execution and if all * commands execute successfully, returns an array of update counts. * <P> * The int elements of the array that is returned are ordered to correspond to * the commands in the batch, which are ordered according to the order in * which they were added to the batch. The elements in the array returned by * the method executeBatch may be one of the following: <ol><li>A number * greater than or equal to zero -- indicates that the command was processed * successfully and is an update count giving the number of rows in the * database that were affected by the command's execution </li><li>A value of * SUCCESS_NO_INFO -- indicates that the command was processed successfully * but that the number of rows affected is unknown </li><li>A value of * EXECUTE_FAILED -- indicates that the command failed to execute successfully * and occurs only if a driver continues to process commands after a command * fails</li></ol><p> * If one of the commands in a batch update fails to execute properly, this * method throws a BatchUpdateException, and a JDBC driver may or may not * continue to process the remaining commands in the batch. However, the * driver's behavior must be consistent with a particular DBMS, either always * continuing to process commands or never continuing to process commands. If * the driver continues processing after a failure, the array returned by the * method BatchUpdateException.getUpdateCounts will contain as many elements * as there are commands in the batch, and at least one of the elements will * be a value of EXECUTE_FAILED. * <p> * The possible implementations and return values have been modified in the * Java 2 SDK, Standard Edition, version 1.3 to accommodate the option of * continuing to process commands in a batch update after a * BatchUpdateException object has been thrown. * * @return an array of update counts containing one element for each command * in the batch. The elements of the array are ordered according to the order * in which commands were added to the batch. 1 Database exceptions may be * thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int[] executeBatch() throws SQLException { return getInternalStatement().executeBatch(); } /** * Retrieves the Connection object that produced this Statement object. * * @return the connection that produced this statement 1 Database exceptions * may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public Connection getConnection() throws SQLException { return connection; } /** * Moves to this Statement object's next result, deals with any current * ResultSet object(s) according to the instructions specified by the given * flag, and returns true if the next result is a ResultSet object. * <p> * There are no more results when the following is true:</p> * <code> * * (statement.getMoreResults(current) == false) * && (statement.getUpdateCount() == -1)) * </code> * * @param i i * @return true if the next result is a ResultSet object; false if it is an * update count or there are no more results. 1 Database exceptions may be * thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public boolean getMoreResults(int i) throws SQLException { return getInternalStatement().getMoreResults(); } /** * Retrieves any auto-generated keys created as a result of executing this * Statement object. * <p> * If this Statement object did not generate any keys, an empty ResultSet * object is returned. * * @return a ResultSet object containing the auto-generated key(s) generated * by the execution of this Statement object 1 Database exceptions may be * thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public ResultSet getGeneratedKeys() throws SQLException { return getInternalStatement().getGeneratedKeys(); } /** * Executes the given SQL statement and signals the driver with the given flag * about whether the auto-generated keys produced by this Statement object * should be made available for retrieval. * <P> * The driver will ignore the flag if the SQL statement is not an INSERT * statement, or an SQL statement able to return auto-generated keys (the list * of such statements is vendor-specific). * * @param string string * @param i i * @return either (1) the row count for SQL Data Manipulation Language (DML) * statements or (2) 0 for SQL statements that return nothing 1 Database * exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int executeUpdate(String string, int i) throws SQLException { return getInternalStatement().executeUpdate(string, i); } /** * Executes the given SQL statement and signals the driver that the * auto-generated keys indicated in the given array should be made available * for retrieval. * <P> * This array contains the indexes of the columns in the target table that * contain the auto-generated keys that should be made available. The driver * will ignore the array if the SQL statement is not an INSERT statement, or * an SQL statement able to return auto-generated keys (the list of such * statements is vendor-specific). * * @param string string * @param ints ints * @return either (1) the row count for SQL Data Manipulation Language (DML) * statements or (2) 0 for SQL statements that return nothing 1 Database * exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int executeUpdate(String string, int[] ints) throws SQLException { return getInternalStatement().executeUpdate(string, ints); } /** * Executes the given SQL statement and signals the driver that the * auto-generated keys indicated in the given array should be made available * for retrieval. * <p> * This array contains the names of the columns in the target table that * contain the auto-generated keys that should be made available. The driver * will ignore the array if the SQL statement is not an INSERT statement, or * an SQL statement able to return auto-generated keys (the list of such * statements is vendor-specific). * * @param string string * @param strings strings * @return either the row count for INSERT, UPDATE, or DELETE statements, or 0 * for SQL statements that return nothing 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int executeUpdate(String string, String[] strings) throws SQLException { final String logSQL = "EXECUTING UPDATE: " + string; database.printSQLIfRequested(logSQL); log.debug(logSQL); return getInternalStatement().executeUpdate(string, strings); } /** * Executes the given SQL statement, which may return multiple results, and * signals the driver that any auto-generated keys should be made available * for retrieval. * <P> * The driver will ignore this signal if the SQL statement is not an INSERT * statement, or an SQL statement able to return auto-generated keys (the list * of such statements is vendor-specific). In some (uncommon) situations, a * single SQL statement may return multiple result sets and/or update counts. * Normally you can ignore this unless you are (1) executing a stored * procedure that you know may return multiple results or (2) you are * dynamically executing an unknown SQL string. * <P> * The execute method executes an SQL statement and indicates the form of the * first result. You must then use the methods getResultSet or getUpdateCount * to retrieve the result, and getMoreResults to move to any subsequent * result(s). * * @param string string * @param i i * @return true if the first result is a ResultSet object; false if it is an * update count or there are no results. 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public boolean execute(String string, int i) throws SQLException { final String logSQL = "EXECUTING: " + string; database.printSQLIfRequested(logSQL); log.debug(logSQL); return getInternalStatement().execute(string, i); } /** * Executes the given SQL statement, which may return multiple results, and * signals the driver that the auto-generated keys indicated in the given * array should be made available for retrieval. * <P> * This array contains the indexes of the columns in the target table that * contain the auto-generated keys that should be made available. The driver * will ignore the array if the SQL statement is not an INSERT statement, or * an SQL statement able to return auto-generated keys (the list of such * statements is vendor-specific). Under some (uncommon) situations, a single * SQL statement may return multiple result sets and/or update counts. * Normally you can ignore this unless you are (1) executing a stored * procedure that you know may return multiple results or (2) you are * dynamically executing an unknown SQL string. * <P> * The execute method executes an SQL statement and indicates the form of the * first result. You must then use the methods getResultSet or getUpdateCount * to retrieve the result, and getMoreResults to move to any subsequent * result(s). * * @param string string * @param ints ints * @return true if the first result is a ResultSet object; false if it is an * update count or there are no results 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public boolean execute(String string, int[] ints) throws SQLException { final String logSQL = "EXECUTING: " + string; database.printSQLIfRequested(logSQL); log.debug(logSQL); return getInternalStatement().execute(string, ints); } /** * Executes the given SQL statement, which may return multiple results, and * signals the driver that the auto-generated keys indicated in the given * array should be made available for retrieval. * <P> * This array contains the names of the columns in the target table that * contain the auto-generated keys that should be made available. The driver * will ignore the array if the SQL statement is not an INSERT statement, or * an SQL statement able to return auto-generated keys (the list of such * statements is vendor-specific). In some (uncommon) situations, a single SQL * statement may return multiple result sets and/or update counts. Normally * you can ignore this unless you are (1) executing a stored procedure that * you know may return multiple results or (2) you are dynamically executing * an unknown SQL string. * <P> * The execute method executes an SQL statement and indicates the form of the * first result. You must then use the methods getResultSet or getUpdateCount * to retrieve the result, and getMoreResults to move to any subsequent * result(s). * * @param string string * @param strings strings * @return true if the next result is a ResultSet object; false if it is an * update count or there are no more results 1 Database exceptions may be * thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public boolean execute(String string, String[] strings) throws SQLException { final String logSQL = "EXECUTING: " + string; database.printSQLIfRequested(logSQL); log.debug(logSQL); return getInternalStatement().execute(string, strings); } /** * Retrieves the result set holdability for ResultSet objects generated by * this Statement object. * * @return either ResultSet.HOLD_CURSORS_OVER_COMMIT or * ResultSet.CLOSE_CURSORS_AT_COMMIT 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public int getResultSetHoldability() throws SQLException { return getInternalStatement().getResultSetHoldability(); } /** * Retrieves whether this Statement object has been closed. A Statement is * closed if the method close has been called on it, or if it is automatically * closed. * * @return true if this Statement object is closed; false if it is still open * 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public boolean isClosed() throws SQLException { if (database.getDefinition().supportsStatementIsClosed()) { return getInternalStatement().isClosed(); } else { return isClosed; } } /** * Requests that a Statement be pooled or not pooled. * <P> * The value specified is a hint to the statement pool implementation * indicating whether the applicaiton wants the statement to be pooled. It is * up to the statement pool manager as to whether the hint is used. The * poolable value of a statement is applicable to both internal statement * caches implemented by the driver and external statement caches implemented * by application servers and other applications. * <P> * By default, a Statement is not poolable when created, and a * PreparedStatement and CallableStatement are poolable when created. * * * 1 Database exceptions may be thrown * * @param bln bln * @throws java.sql.SQLException java.sql.SQLException */ @Override public void setPoolable(boolean bln) throws SQLException { getInternalStatement().setPoolable(bln); } /** * Returns a value indicating whether the Statement is poolable or not. * * @return true if the Statement is poolable; false otherwise * * 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public boolean isPoolable() throws SQLException { return getInternalStatement().isPoolable(); } /** * Returns an object that implements the given interface to allow access to * non-standard methods, or standard methods not exposed by the proxy. * * If the receiver implements the interface then the result is the receiver or * a proxy for the receiver. If the receiver is a wrapper and the wrapped * object implements the interface then the result is the wrapped object or a * proxy for the wrapped object. Otherwise return the the result of calling * <code>unwrap</code> recursively on the wrapped object or a proxy for that * result. If the receiver is not a wrapper and does not implement the * interface, then an <code>SQLException</code> is thrown. * * @param iface A Class defining an interface that the result must implement. * @param <T> the required interface. * @return an object that implements the interface. May be a proxy for the * actual implementing object. 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ @Override public <T> T unwrap(Class<T> iface) throws SQLException { return getInternalStatement().unwrap(iface); } /** * Returns true if this either implements the interface argument or is * directly or indirectly a wrapper for an object that does. Returns false * otherwise. If this implements the interface then return true, else if this * is a wrapper then return the result of recursively calling * <code>isWrapperFor</code> on the wrapped object. If this does not implement * the interface and is not a wrapper, return false. This method should be * implemented as a low-cost operation compared to <code>unwrap</code> so that * callers can use this method to avoid expensive <code>unwrap</code> calls * that may fail. If this method returns true then calling <code>unwrap</code> * with the same argument should succeed. * * @param iface a Class defining an interface. * @return true if this implements the interface or directly or indirectly * wraps an object that does. * @throws java.sql.SQLException if an error occurs while determining whether * this is a wrapper for an object with the given interface. * @since 1.6 */ @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return getInternalStatement().isWrapperFor(iface); } private void setBatchHasEntries(boolean b) { batchHasEntries = b; } /** * Indicates that a batch has been added. * * @return TRUE if the batch has un-executed entries, otherwise FALSE. */ public boolean getBatchHasEntries() { return batchHasEntries; } /** * Unsupported. * * 1 Database exceptions may be thrown * * @throws java.sql.SQLException java.sql.SQLException */ public void closeOnCompletion() throws SQLException { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } /** * Unsupported. * * @return unsupported 1 Database exceptions may be thrown * @throws java.sql.SQLException java.sql.SQLException */ public boolean isCloseOnCompletion() throws SQLException { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } /** * @return the internalStatement */ protected Statement getInternalStatement() { return internalStatement; } /** * @param realStatement the internalStatement to set */ protected void setInternalStatement(Statement realStatement) { this.internalStatement = realStatement; } }