/* Copyright (c) 2001-2009, The HSQL Development Group * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the HSQL Development Group nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.hsqldb.jdbc; import java.sql.BatchUpdateException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLWarning; import java.sql.Statement; import org.hsqldb.HsqlException; import org.hsqldb.StatementTypes; import org.hsqldb.navigator.RowSetNavigator; import org.hsqldb.result.Result; /* $Id: JDBCStatement.java 2968 2009-04-10 23:44:16Z fredt $ */ // fredt@users 20020320 - patch 1.7.0 - JDBC 2 support and error trapping // // JDBC 2 methods can now be called from jdk 1.1.x - see javadoc comments // SCROLL_INSENSITIVE and FORWARD_ONLY types for ResultSet are now supported // // boucherb@users 20020509 - added "throws SQLException" to all methods where // it was missing here but specified in the // java.sql.Statement interface, // updated generic documentation to JDK 1.4, and // added JDBC3 methods and docs // boucherb & 20020505 - extensive review and update of docs and behaviour // fredt@users to comply with java.sql specification // fredt@users 20030620 - patch 1.7.2 - rewritten and simplified // boucherb@users 200404xx - javadoc updates toward 1.7.2 final // boucherb@users 20051207 - patch 1.8.0.x initial JDBC 4.0 support work // boucherb@users 20060522 - doc 1.9.0 full synch up to Mustang Build 84 // Revision 1.16 2006/07/12 12:40:59 boucherb // patch 1.9.0 // - full synch up to Mustang b90 /** * <!-- start generic documentation --> * <P>The object used for executing a static SQL statement * and returning the results it produces. * <P> * By default, only one <code>ResultSet</code> object per <code>Statement</code> * object can be open at the same time. Therefore, if the reading of one * <code>ResultSet</code> object is interleaved * with the reading of another, each must have been generated by * different <code>Statement</code> objects. All execution methods in the * <code>Statement</code> interface implicitly close a statment's current * <code>ResultSet</code> object if an open one exists. * <!-- end generic documentation--> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3><p> * From version 1.9.0, the implementation meets the JDBC specification * requirment that any existing ResultSet is closed when execute() or * executeQuery() methods are called. * <p> * * <b>JRE 1.1.x Notes:</b> <p> * * In general, JDBC 2 support requires Java 1.2 and above, and JDBC3 requires * Java 1.4 and above. In HSQLDB, support for methods introduced in different * versions of JDBC depends on the JDK version used for compiling and building * HSQLDB.<p> * * Since 1.7.0, all JDBC 2 methods can be called while executing under the * version 1.1.x * <em>Java Runtime Environment</em><sup><font size="-2">TM</font></sup>. * However, in addition to this technique requiring explicit casts to the * org.hsqldb.jdbc.* classes, some of these method calls require * <code>int</code> values that are defined only in the JDBC 2 or greater * version of the {@link java.sql.ResultSet ResultSet} interface. For this * reason these values are defined in {@link JDBCResultSet JDBCResultSet}.<p> * * In a JRE 1.1.x environment, calling JDBC 2 methods that take or return the * JDBC2-only <code>ResultSet</code> values can be achieved by referring * to them in parameter specifications and return value comparisons, * respectively, as follows: <p> * * <pre class="JavaCodeExample"> * JDBCResultSet.FETCH_FORWARD * JDBCResultSet.TYPE_FORWARD_ONLY * JDBCResultSet.TYPE_SCROLL_INSENSITIVE * JDBCResultSet.CONCUR_READ_ONLY * //etc. * </pre> <p> * * However, please note that code written to use HSQLDB JDBC 2 features under * JDK 1.1.x will not be compatible for use with other JDBC 2 drivers. Please * also note that this feature is offered solely as a convenience to developers * who must work under JDK 1.1.x due to operating constraints, yet wish to * use some of the more advanced features available under the JDBC 2 * specification. <p> * * (fredt@users)<br> * (boucherb@users)<p> * * </div> * <!-- end release-specific documentation --> * * @author Campbell Boucher-Burnett (boucherb@users dot sourceforge.net) * @author Fred Toussi (fredt@users dot sourceforge.net) * @version 1.9.0 * @revised JDK 1.6, HSQLDB 1.9.0 * @see JDBCConnection#createStatement * @see JDBCResultSet */ //#ifdef JAVA6 public class JDBCStatement extends JDBCStatementBase implements Statement, java.sql.Wrapper { //#else /* public class JDBCStatement extends JDBCStatementBase implements Statement { */ //#endif JAVA6 /** * <!-- start generic documentation --> * Executes the given SQL statement, which returns a single * <code>ResultSet</code> object. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * This method should not be used for statements other than SELECT queries.<p> * * From 1.9.0, HSQLDB throws an exception when the statement * is a DDL statement or an UPDATE or DELETE statement. * </div> * <!-- end release-specific documentation --> * * @param sql an SQL statement to be sent to the database, typically a * static SQL <code>SELECT</code> statement * @return a <code>ResultSet</code> object that contains the data produced * by the given query; never <code>null</code> * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> or the given * SQL statement produces anything other than a single * <code>ResultSet</code> object */ public synchronized ResultSet executeQuery( String sql) throws SQLException { fetchResult(sql, StatementTypes.RETURN_RESULT, JDBCStatementBase.NO_GENERATED_KEYS, null, null); return getResultSet(); } /** * <!-- start generic documentation --> * Executes the given SQL statement, which may be an <code>INSERT</code>, * <code>UPDATE</code>, or <code>DELETE</code> statement or an * SQL statement that returns nothing, such as an SQL DDL statement. * <!-- end generic documentation --> * * @param sql (JDBC4 clarification:) an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or * <code>DELETE</code>; or an SQL statement that returns nothing, * such as a DDL statement. * * @return (JDBC4 clarification:) either (1) the row count for SQL Data Manipulation Language (DML) statements * or (2) 0 for SQL statements that return nothing * * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> or the given * SQL statement produces a <code>ResultSet</code> object */ public synchronized int executeUpdate(String sql) throws SQLException { fetchResult(sql, StatementTypes.RETURN_COUNT, JDBCStatementBase.NO_GENERATED_KEYS, null, null); return resultIn.getUpdateCount(); } /** * <!-- start generic documentation --> * Releases this <code>Statement</code> object's database * and JDBC resources immediately instead of waiting for * this to happen when it is automatically closed. * It is generally good practice to release resources as soon as * you are finished with them to avoid tying up database * resources. * <P> * Calling the method <code>close</code> on a <code>Statement</code> * object that is already closed has no effect. * <P> * <B>Note:</B>When a <code>Statement</code> object is * closed, its current <code>ResultSet</code> object, if one exists, is * also closed. * (JDBC4 deleted:) [A <code>Statement</code> object is * automatically closed when it is garbage collected.] * <!-- end generic documentation --> * * @exception SQLException if a database access error occurs */ public synchronized void close() throws SQLException { if (isClosed) { return; } closeResultData(); batchResultOut = null; connection = null; resultIn = null; resultOut = null; isClosed = true; } //---------------------------------------------------------------------- /** * <!-- start generic documentation --> * Retrieves the maximum number of bytes that can be * returned for character and binary column values in a <code>ResultSet</code> * object produced by this <code>Statement</code> object. * This limit applies only to <code>BINARY</code>, <code>VARBINARY</code>, * <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>, * (JDBC4 new:) <code>NCHAR</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code> * and <code>LONGVARCHAR</code> columns. If the limit is exceeded, the * excess data is silently discarded. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Including 1.7.2, HSQLDB always returns zero, meaning there * is no limit. * </div> * <!-- end release-specific documentation --> * * @return the current column size limit for columns storing character and * binary values; zero means there is no limit * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @see #setMaxFieldSize */ public synchronized int getMaxFieldSize() throws SQLException { checkClosed(); return 0; } /** * <!-- start generic documentation --> * (JDBC4 clarification:) Sets the limit for the maximum number of bytes in a <code>ResultSet</code> * Sets the limit for the maximum number of bytes that can be returned for * character and binary column values in a <code>ResultSet</code> * object produced by this <code>Statement</code> object. * * This limit applies * only to <code>BINARY</code>, <code>VARBINARY</code>, * <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>, * (JDBC4 new:) <code>NCHAR</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code> and * <code>LONGVARCHAR</code> fields. If the limit is exceeded, the excess data * is silently discarded. For maximum portability, use values * greater than 256. * <!-- emd generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * To present, calls to this method are simply ignored; HSQLDB always * stores the full number of bytes when dealing with any of the field types * mentioned above. These types all have an absolute maximum element upper * bound determined by the Java array index limit * java.lang.Integer.MAX_VALUE. For XXXBINARY types, this translates to * Integer.MAX_VALUE bytes. For XXXCHAR types, this translates to * 2 * Integer.MAX_VALUE bytes (2 bytes / character). <p> * * In practice, field sizes are limited to values much smaller than the * absolute maximum element upper bound, in particular due to limits imposed * on the maximum available Java heap memory. * </div> * <!-- end release-specific documentation --> * * @param max the new column size limit in bytes; zero means there is no limit * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> * or the condition max >= 0 is not satisfied * @see #getMaxFieldSize */ public void setMaxFieldSize(int max) throws SQLException { checkClosed(); if (max < 0) { throw Util.outOfRangeArgument(); } } /** * <!-- start generic documentation --> * Retrieves the maximum number of rows that a * <code>ResultSet</code> object produced by this * <code>Statement</code> object can contain. If this limit is exceeded, * the excess rows are silently dropped. * <!-- start generic documentation --> * * @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 * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @see #setMaxRows */ public synchronized int getMaxRows() throws SQLException { checkClosed(); return maxRows; } /** * <!-- start generic documentation --> * (JDBC4 clarification:) * Sets the limit for the maximum number of rows that any * <code>ResultSet</code> object generated by this <code>Statement</code> * object can contain to the given number. * If the limit is exceeded, the excess * rows are silently dropped. * <!-- end generic documentation --> * * @param max the new max rows limit; zero means there is no limit * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> * or the condition max >= 0 is not satisfied * @see #getMaxRows */ public synchronized void setMaxRows(int max) throws SQLException { checkClosed(); if (max < 0) { throw Util.outOfRangeArgument(); } maxRows = max; } /** * <!-- start generic documentation --> * 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 * <code>PreparedStatements</code> objects will have no effect. * <!-- end generic documentation --> * * @param enable <code>true</code> to enable escape processing; * <code>false</code> to disable it * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> */ public void setEscapeProcessing(boolean enable) throws SQLException { checkClosed(); isEscapeProcessing = enable; } /** * <!-- start generic documentation --> * Retrieves the number of seconds the driver will * wait for a <code>Statement</code> object to execute. * If the limit is exceeded, a * <code>SQLException</code> is thrown. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * To present, HSQLDB always returns zero, meaning there * is no limit. * </div> * <!-- end release-specific documentation --> * * @return the current query timeout limit in seconds; zero means there is * no limit * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @see #setQueryTimeout */ public synchronized int getQueryTimeout() throws SQLException { checkClosed(); return 0; } /** * <!-- start generic documentation --> * Sets the number of seconds the driver will wait for a * <code>Statement</code> object to execute to the given number of seconds. * If the limit is exceeded, an <code>SQLException</code> is thrown. A JDBC * (JDBC4 clarification:) * driver must apply this limit to the <code>execute</code>, * <code>executeQuery</code> and <code>executeUpdate</code> methods. JDBC driver * implementations may also apply this limit to <code>ResultSet</code> methods * (consult your driver vendor documentation for details). * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Including 1.9.0, calls to this method are ignored; HSQLDB waits an * unlimited amount of time for statement execution * requests to return. * </div> * <!-- end release-specific documentation --> * * @param seconds the new query timeout limit in seconds; zero means * there is no limit * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> * or the condition seconds >= 0 is not satisfied * @see #getQueryTimeout */ public void setQueryTimeout(int seconds) throws SQLException { checkClosed(); if (seconds < 0) { throw Util.outOfRangeArgument(); } } /** * <!-- start generic documentation --> * Cancels this <code>Statement</code> 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. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Including 1.9.0, HSQLDB does <i>not</i> support aborting an SQL * statement; calls to this method are ignored. * </div> * <!-- end release-specific documentation --> * * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method */ public synchronized void cancel() throws SQLException { checkClosed(); } /** * <!-- start generic documentation --> * Retrieves the first warning reported by calls on this <code>Statement</code> object. * Subsequent <code>Statement</code> object warnings will be chained to this * <code>SQLWarning</code> object. * * <p>The warning chain is automatically cleared each time * a statement is (re)executed. This method may not be called on a closed * <code>Statement</code> object; doing so will cause an <code>SQLException</code> * to be thrown. * * <P><B>Note:</B> If you are processing a <code>ResultSet</code> object, any * warnings associated with reads on that <code>ResultSet</code> object * will be chained on it rather than on the <code>Statement</code> * object that produced it. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Including 1.9.0, HSQLDB never produces Statement warnings; * this method always returns null. * </div> * <!-- end release-specific documentation --> * * @return the first <code>SQLWarning</code> object or <code>null</code> * if there are no warnings * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> */ public synchronized SQLWarning getWarnings() throws SQLException { checkClosed(); return null; } /** * <!-- start generic documentation --> * Clears all the warnings reported on this <code>Statement</code> * object. After a call to this method, * the method <code>getWarnings</code> will return * <code>null</code> until a new warning is reported for this * <code>Statement</code> object. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Including HSQLDB 1.9.0, <code>SQLWarning</code> objects are * never produced for Statement Objects; calls to this method are * ignored. * </div> * <!-- end release-specific documentation --> * * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> */ public synchronized void clearWarnings() throws SQLException { checkClosed(); } /** @todo 1.9.0 - implement */ /** * <!-- start generic documentation --> * Sets the SQL cursor name to the given <code>String</code>, which * will be used by subsequent <code>Statement</code> object * <code>execute</code> methods. This name can then be * used in SQL positioned update or delete statements to identify the * current row in the <code>ResultSet</code> 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 <code>SELECT</code> statement * should have the form <code>SELECT FOR UPDATE</code>. If * <code>FOR UPDATE</code> is not present, positioned updates may fail. * * <P><B>Note:</B> By definition, the execution of positioned updates and * deletes must be done by a different <code>Statement</code> object than * the one that generated the <code>ResultSet</code> object being used for * positioning. Also, cursor names must be unique within a connection. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Including 1.9.0, HSQLDB does not support named cursors; * calls to this method are ignored. * </div> * <!-- end release-specific documentation --> * * @param name the new cursor name, which must be unique within * a connection * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method */ public void setCursorName(String name) throws SQLException { checkClosed(); } //----------------------- Multiple Results -------------------------- /** * <!-- start generic documentation --> * Executes the given SQL statement, which may return multiple results. * 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 <code>execute</code> method executes an SQL statement and indicates the * form of the first result. You must then use the methods * <code>getResultSet</code> or <code>getUpdateCount</code> * to retrieve the result, and <code>getMoreResults</code> to * move to any subsequent result(s). * <!-- end generic documentation --> * * @param sql any SQL statement * @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 * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @see #getResultSet * @see #getUpdateCount * @see #getMoreResults */ public synchronized boolean execute(String sql) throws SQLException { fetchResult(sql, StatementTypes.RETURN_ANY, JDBCStatementBase.NO_GENERATED_KEYS, null, null); return resultIn.isData(); } /** * <!-- start generic documentation --> * Retrieves the current result as a <code>ResultSet</code> object. * This method should be called only once per result. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * </div> * <!-- end release-specific documentation --> * * @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 * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @see #execute */ public synchronized ResultSet getResultSet() throws SQLException { return super.getResultSet(); } /** * <!-- start generic documentation --> * Retrieves the current result as an update count; * if the result is a <code>ResultSet</code> object or there are no more results, -1 * is returned. This method should be called only once per result. * <!-- end generic documentation --> * * @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 * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @see #execute */ public synchronized int getUpdateCount() throws SQLException { return super.getUpdateCount(); } /** * <!-- start generic documentation --> * Moves to this <code>Statement</code> object's next result, returns * <code>true</code> if it is a <code>ResultSet</code> object, and * implicitly closes any current <code>ResultSet</code> * object(s) obtained with the method <code>getResultSet</code>. * * <P>There are no more results when the following is true: * <PRE> * // stmt is a Statement object * ((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1)) * </PRE> * <!-- end generic documentation --> * * @return <code>true</code> if the next result is a <code>ResultSet</code> * object; <code>false</code> if it is an update count or there are * no more results * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @see #execute */ public synchronized boolean getMoreResults() throws SQLException { return getMoreResults(JDBCStatementBase.CLOSE_CURRENT_RESULT); } //--------------------------JDBC 2.0----------------------------- /** * <!-- start generic documentation --> * Gives the driver a hint as to the direction in which * rows will be processed in <code>ResultSet</code> * objects created using this <code>Statement</code> object. The * default value is <code>ResultSet.FETCH_FORWARD</code>. * <P> * Note that this method sets the default fetch direction for * result sets generated by this <code>Statement</code> object. * Each result set has its own methods for getting and setting * its own fetch direction. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * HSQLDB accepts all valid parameters. <p> * <!-- end release-specific documentation --> * * @param direction the initial direction for processing rows * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> * or the given direction * is not one of <code>ResultSet.FETCH_FORWARD</code>, * <code>ResultSet.FETCH_REVERSE</code>, or <code>ResultSet.FETCH_UNKNOWN</code> * @since JDK 1.2 (JDK 1.1.x developers: read the overview * for JDBCStatement) * @see #getFetchDirection */ public synchronized void setFetchDirection( int direction) throws SQLException { checkClosed(); checkClosed(); switch (direction) { case JDBCResultSet.FETCH_FORWARD : case JDBCResultSet.FETCH_REVERSE : case JDBCResultSet.FETCH_UNKNOWN : fetchDirection = direction; break; default : throw Util.invalidArgument(); } } /** * <!-- start generic documentation --> * Retrieves the direction for fetching rows from * database tables that is the default for result sets * generated from this <code>Statement</code> object. * If this <code>Statement</code> object has not set * a fetch direction by calling the method <code>setFetchDirection</code>, * the return value is implementation-specific. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * HSQLDB returns the fetch direction. <p> * </div> * <!-- end release-specific documentation --> * * @return the default fetch direction for result sets generated * from this <code>Statement</code> object * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @since JDK 1.2 (JDK 1.1.x developers: read the overview * for JDBCStatement) * @see #setFetchDirection */ public int getFetchDirection() throws SQLException { checkClosed(); return this.fetchDirection; } /** * <!-- start generic documentation --> * (JDBC4 clarification:) * 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 * <code>ResultSet</code> objects genrated by this <code>Statement</code>. * If the value specified is zero, then the hint is ignored. * The default value is zero. * <!-- start generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * HSQLDB uses the specified value as a hint, but may process more or fewer * rows than specified. * </div> * <!-- end release-specific documentation --> * * @param rows the number of rows to fetch * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> or the * (JDBC4 modified:) * condition <code>rows >= 0</code> is not satisfied. * @since JDK 1.2 (JDK 1.1.x developers: read the overview * for JDBCStatement) * @see #getFetchSize */ public synchronized void setFetchSize(int rows) throws SQLException { checkClosed(); if (rows < 0) { throw Util.outOfRangeArgument(); } fetchSize = rows; } /** * <!-- start generic documentation --> * Retrieves the number of result set rows that is the default * fetch size for <code>ResultSet</code> objects * generated from this <code>Statement</code> object. * If this <code>Statement</code> object has not set * a fetch size by calling the method <code>setFetchSize</code>, * the return value is implementation-specific. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <b>HSQLDB-Specific Information</b> <p> * * HSQLDB returns 0 by default, or the fetch size specified by setFetchSize * </div> * <!-- end release-specific documentation --> * * @return the default fetch size for result sets generated * from this <code>Statement</code> object * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @since JDK 1.2 (JDK 1.1.x developers: read the overview * for JDBCStatement) * @see #setFetchSize */ public synchronized int getFetchSize() throws SQLException { checkClosed(); return fetchSize; } /** * <!-- start generic documentation --> * Retrieves the result set concurrency for <code>ResultSet</code> objects * generated by this <code>Statement</code> object. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * HSQLDB supports <code>CONCUR_READ_ONLY</code> and * <code>CONCUR_UPDATABLE</code> concurrency. * </div> * <!-- end release-specific documentation --> * * @return either <code>ResultSet.CONCUR_READ_ONLY</code> or * <code>ResultSet.CONCUR_UPDATABLE</code> * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @since JDK 1.2 (JDK 1.1.x developers: read the overview * for JDBCStatement) */ public synchronized int getResultSetConcurrency() throws SQLException { checkClosed(); return rsConcurrency; } /** * <!-- start generic documentation --> * Retrieves the result set type for <code>ResultSet</code> objects * generated by this <code>Statement</code> object. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * HSQLDB 1.7.0 and later versions support <code>TYPE_FORWARD_ONLY</code> * and <code>TYPE_SCROLL_INSENSITIVE</code>. * </div> * <!-- end release-specific documentation --> * * @return one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code> * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @since JDK 1.2 (JDK 1.1.x developers: read the overview * for JDBCStatement) */ public synchronized int getResultSetType() throws SQLException { checkClosed(); return rsScrollability; } /** * <!-- start generic documentation --> * Adds the given SQL command to the current list of commmands for this * <code>Statement</code> object. The commands in this list can be * executed as a batch by calling the method <code>executeBatch</code>. * <P> * (JDBC4 clarification:)<p> * <B>NOTE:</B> Support of an ability to batch updates is optional. * * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with 1.7.2, this feature is supported. * </div> * <!-- end release-specific documentation --> * * @param sql typically this is a SQL <code>INSERT</code> or * <code>UPDATE</code> statement * (:JDBC4 modified) * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> or the * driver does not support batch updates * @see #executeBatch * @since JDK 1.2 (JDK 1.1.x developers: read the overview * for JDBCStatement) */ public synchronized void addBatch(String sql) throws SQLException { checkClosed(); if (isEscapeProcessing) { sql = connection.nativeSQL(sql); } if (batchResultOut == null) { batchResultOut = Result.newBatchedExecuteRequest(); } batchResultOut.getNavigator().add(new Object[] { sql }); } /** * <!-- start generic documentation --> * Empties this <code>Statement</code> object's current list of * SQL commands. * <P> * (JDBC4 clarification:) <p> * <B>NOTE:</B> Support of an ability to batch updates is optional. * <!-- start generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with HSQLDB 1.7.2, this feature is supported. * </div> * <!-- end release-specific documentation --> * * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> or the * driver does not support batch updates * @see #addBatch * @since JDK 1.2 (JDK 1.1.x developers: read the overview * for JDBCStatement) */ public synchronized void clearBatch() throws SQLException { checkClosed(); if (batchResultOut != null) { batchResultOut.getNavigator().clear(); } } /** * <!-- start generic documentation --> * Submits a batch of commands to the database for execution and * if all commands execute successfully, returns an array of update counts. * The <code>int</code> 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 <code>executeBatch</code> * 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>A value of <code>SUCCESS_NO_INFO</code> -- indicates that the command was * processed successfully but that the number of rows affected is * unknown * <P> * If one of the commands in a batch update fails to execute properly, * this method throws a <code>BatchUpdateException</code>, 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 * <code>BatchUpdateException.getUpdateCounts</code> * will contain as many elements as there are commands in the batch, and * at least one of the elements will be the following: * <P> * <LI>A value of <code>EXECUTE_FAILED</code> -- indicates that the command failed * to execute successfully and occurs only if a driver continues to * process commands after a command fails * </OL> * <P> * (JDBC4 clarification:) <p> * <B>NOTE:</B> Support of an ability to batch updates is optional. * <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 proccess commands in a batch * update after a <code>BatchUpdateException</code> obejct has been thrown. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with HSQLDB 1.7.2, this feature is supported. <p> * * HSQLDB stops execution of commands in a batch when one of the commands * results in an exception. The size of the returned array equals the * number of commands that were executed successfully.<p> * * When the product is built under the JAVA1 target, an exception * is never thrown and it is the responsibility of the client software to * check the size of the returned update count array to determine if any * batch items failed. To build and run under the JAVA2 target, JDK/JRE * 1.3 or higher must be used. * </div> * <!-- end release-specific documentation --> * * @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. * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> or the * driver does not support batch statements. Throws {@link BatchUpdateException} * (a subclass of <code>SQLException</code>) if one of the commands sent to the * database fails to execute properly or attempts to return a result set. * * * @see #addBatch * @see java.sql.DatabaseMetaData#supportsBatchUpdates * @since JDK 1.3 (JDK 1.1.x developers: read the overview for * JDBCStatement) */ public synchronized int[] executeBatch() throws SQLException { checkClosed(); connection.clearWarningsNoCheck(); generatedResult = null; if (batchResultOut == null) { batchResultOut = Result.newBatchedExecuteRequest(); } int batchCount = batchResultOut.getNavigator().getSize(); try { resultIn = connection.sessionProxy.execute(batchResultOut); performPostExecute(); } catch (HsqlException e) { batchResultOut.getNavigator().clear(); throw Util.sqlException(e); } batchResultOut.getNavigator().clear(); if (resultIn.isError()) { throw Util.sqlException(resultIn); } RowSetNavigator navigator = resultIn.getNavigator(); int[] updateCounts = new int[navigator.getSize()]; for (int i = 0; i < updateCounts.length; i++) { Object[] data = navigator.getNext(); updateCounts[i] = ((Integer) data[0]).intValue(); } if (updateCounts.length != batchCount) { if (errorResult == null) { throw new BatchUpdateException(updateCounts); } else { errorResult.getMainString(); throw new BatchUpdateException(errorResult.getMainString(), errorResult.getSubString(), errorResult.getErrorCode(), updateCounts); } } return updateCounts; } /** * <!-- start generic documentation --> * Retrieves the <code>Connection</code> object * that produced this <code>Statement</code> object. * <!-- end generic documentation --> * * @return the connection that produced this statement * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @since JDK 1.2 (JDK 1.1.x developers: read the overview * for JDBCStatement) */ public synchronized Connection getConnection() throws SQLException { checkClosed(); return connection; } //--------------------------JDBC 3.0----------------------------- /** * <!-- start generic documentation --> * Moves to this <code>Statement</code> object's next result, deals with * any current <code>ResultSet</code> object(s) according to the instructions * specified by the given flag, and returns * <code>true</code> if the next result is a <code>ResultSet</code> object. * * <P>There are no more results when the following is true: * <PRE> * // stmt is a Statement object * ((stmt.getMoreResults(current) == false) && (stmt.getUpdateCount() == -1)) * </PRE> * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * HSQLDB moves to the next ResultSet and returns the correct result. <p> * </div> * <!-- end release-specific documentation --> * * @param current one of the following <code>Statement</code> * constants indicating what should happen to current * <code>ResultSet</code> objects obtained using the method * <code>getResultSet</code>: * <code>Statement.CLOSE_CURRENT_RESULT</code>, * <code>Statement.KEEP_CURRENT_RESULT</code>, or * <code>Statement.CLOSE_ALL_RESULTS</code> * @return <code>true</code> if the next result is a <code>ResultSet</code> * object; <code>false</code> if it is an update count or there are no * more results * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> or the argument * supplied is not one of the following: * <code>Statement.CLOSE_CURRENT_RESULT</code>, * <code>Statement.KEEP_CURRENT_RESULT</code>, or * <code>Statement.CLOSE_ALL_RESULTS</code> * @since JDK 1.4, HSQLDB 1.7 * @see #execute */ //#ifdef JAVA4 public synchronized boolean getMoreResults( int current) throws SQLException { return super.getMoreResults(current); } //#endif JAVA4 /** * <!-- start generic documentation --> * Retrieves any auto-generated keys created as a result of executing this * <code>Statement</code> object. If this <code>Statement</code> object did * not generate any keys, an empty <code>ResultSet</code> * object is returned. * <p>(JDBC4 clarification:) * <p><B>Note:</B>If the columns which represent the auto-generated keys were not specified, * the JDBC driver implementation will determine the columns which best represent the auto-generated keys. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Supported in 1.9.0.x <p> * * If column names or indexes provided by the user in the executeUpdate() * method calls are not correct, an empty result is returned. * * </div> * <!-- end release-specific documentation --> * * @return a <code>ResultSet</code> object containing the auto-generated key(s) * generated by the execution of this <code>Statement</code> object * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method * @since JDK 1.4, HSQLDB 1.7 */ //#ifdef JAVA4 public synchronized ResultSet getGeneratedKeys() throws SQLException { return getGeneratedResultSet(); } //#endif JAVA4 /** * <!-- start generic documentation --> * Executes the given SQL statement and signals the driver with the * given flag about whether the * auto-generated keys produced by this <code>Statement</code> object * should be made available for retrieval. The driver will ignore the * flag if the SQL statement * is not an <code>INSERT</code> statement, or an SQL statement able to return * auto-generated keys (the list of such statements is vendor-specific). * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with 1.9.0, HSQLDB supports this feature. * * </div> * <!-- end release-specific documentation --> * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or * <code>DELETE</code>; or an SQL statement that returns nothing, * such as a DDL statement. * (:JDBC4 clarification) * * @param autoGeneratedKeys a flag indicating whether auto-generated keys * should be made available for retrieval; * one of the following constants: * <code>Statement.RETURN_GENERATED_KEYS</code> * <code>Statement.NO_GENERATED_KEYS</code> * @return either (1) the row count for SQL Data Manipulation Language (DML) statements * or (2) 0 for SQL statements that return nothing * (:JDBC4 clarification) * * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code>, the given * SQL statement returns a <code>ResultSet</code> object, or * the given constant is not one of those allowed * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method with a constant of Statement.RETURN_GENERATED_KEYS * @since JDK 1.4, HSQLDB 1.7 */ //#ifdef JAVA4 public synchronized int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { if (autoGeneratedKeys != Statement.RETURN_GENERATED_KEYS && autoGeneratedKeys != Statement.NO_GENERATED_KEYS) { throw Util.invalidArgument("autoGeneratedKeys"); } fetchResult(sql, StatementTypes.RETURN_COUNT, autoGeneratedKeys, null, null); if (resultIn.isError()) { throw Util.sqlException(resultIn); } return resultIn.getUpdateCount(); } //#endif JAVA4 /** * <!-- start generic documentation --> * 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. The driver will ignore the array if the SQL statement * is not an <code>INSERT</code> statement, or an SQL statement able to return * (JDBC 4 clarification) * auto-generated keys (the list of such statements is vendor-specific). * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with 1.9.0, HSQLDB supports this feature with single-row and * multi-row inserts. <p> * CHECKME: possibly change method depending to final GENERATED column support. * * </div> * <!-- end release-specific documentation --> * * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or * <code>DELETE</code>; or an SQL statement that returns nothing, * such as a DDL statement. * (:JDBC4 clarification) * * @param columnIndexes an array of column indexes indicating the columns * that should be returned from the inserted row * @return either (1) the row count for SQL Data Manipulation Language (DML) statements * or (2) 0 for SQL statements that return nothing * (:JDBC 4 clarification) * * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code>, the SQL * statement returns a <code>ResultSet</code> object, or the * second argument supplied to this method is not an <code>int</code> array * whose elements are valid column indexes * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method * @since JDK 1.4, HSQLDB 1.7 */ //#ifdef JAVA4 public synchronized int executeUpdate(String sql, int[] columnIndexes) throws SQLException { if (columnIndexes == null || columnIndexes.length == 0) { throw Util.invalidArgument("columnIndexes"); } fetchResult(sql, StatementTypes.RETURN_COUNT, Statement.RETURN_GENERATED_KEYS, columnIndexes, null); return resultIn.getUpdateCount(); } //#endif JAVA4 /** * <!-- start generic documentation --> * 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. The driver will ignore the array if the SQL statement * (JDBC4 clarification:) * is not an <code>INSERT</code> statement, or an SQL statement able to return * auto-generated keys (the list of such statements is vendor-specific). * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with 1.9.0, HSQLDB supports this feature. * * </div> * <!-- end release-specific documentation --> * * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or * <code>DELETE</code>; or an SQL statement that returns nothing, * such as a DDL statement. * (:JDBC4 clarification) * @param columnNames an array of the names of the columns that should be * returned from the inserted row * @return either the row count for <code>INSERT</code>, <code>UPDATE</code>, * or <code>DELETE</code> statements, or 0 for SQL statements * that return nothing * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code>, the SQL * statement returns a <code>ResultSet</code> object, or the * second argument supplied to this method is not a <code>String</code> array * whose elements are valid column names * * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method * @since JDK 1.4, HSQLDB 1.7 */ //#ifdef JAVA4 public synchronized int executeUpdate(String sql, String[] columnNames) throws SQLException { if (columnNames == null || columnNames.length == 0) { throw Util.invalidArgument("columnIndexes"); } fetchResult(sql, StatementTypes.RETURN_COUNT, Statement.RETURN_GENERATED_KEYS, null, columnNames); return resultIn.getUpdateCount(); } //#endif JAVA4 /** * <!-- start generic documentation --> * 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. The driver will ignore this signal if the SQL statement * is not an <code>INSERT</code> statement, or an SQL statement able to return * (JDBC4 clarification) * auto-generated keys (the list of such statements is vendor-specific). * <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 <code>execute</code> method executes an SQL statement and indicates the * form of the first result. You must then use the methods * <code>getResultSet</code> or <code>getUpdateCount</code> * to retrieve the result, and <code>getMoreResults</code> to * move to any subsequent result(s). * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with 1.9.0, HSQLDB supports this feature. * * </div> * <!-- end release-specific documentation --> * * @param sql any SQL statement * @param autoGeneratedKeys a constant indicating whether auto-generated * keys should be made available for retrieval using the method * <code>getGeneratedKeys</code>; one of the following constants: * <code>Statement.RETURN_GENERATED_KEYS</code> or * <code>Statement.NO_GENERATED_KEYS</code> * @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 * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> or the second * parameter supplied to this method is not * <code>Statement.RETURN_GENERATED_KEYS</code> or * <code>Statement.NO_GENERATED_KEYS</code>. * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method with a constant of Statement.RETURN_GENERATED_KEYS * @see #getResultSet * @see #getUpdateCount * @see #getMoreResults * @see #getGeneratedKeys * @since JDK 1.4, HSQLDB 1.7 */ //#ifdef JAVA4 public synchronized boolean execute( String sql, int autoGeneratedKeys) throws SQLException { if (autoGeneratedKeys != Statement.RETURN_GENERATED_KEYS && autoGeneratedKeys != Statement.NO_GENERATED_KEYS) { throw Util.invalidArgument("autoGeneratedKeys"); } fetchResult(sql, StatementTypes.RETURN_ANY, autoGeneratedKeys, null, null); return resultIn.isData(); } //#endif JAVA4 /** * <!-- start generic documentation --> * 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. 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 * (JDBC4 clarification) * is not an <code>INSERT</code> statement, or an SQL statement able to return * auto-generated keys (the list of such statements is vendor-specific). * <P> * 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 <code>execute</code> method executes an SQL statement and indicates the * form of the first result. You must then use the methods * <code>getResultSet</code> or <code>getUpdateCount</code> * to retrieve the result, and <code>getMoreResults</code> to * move to any subsequent result(s). * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with 1.9.0, HSQLDB supports this feature. * * </div> * <!-- end release-specific documentation --> * * @param sql any SQL statement * @param columnIndexes an array of the indexes of the columns in the * inserted row that should be made available for retrieval by a * call to the method <code>getGeneratedKeys</code> * @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 * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> or the * elements in the <code>int</code> array passed to this method * are not valid column indexes * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method * @see #getResultSet * @see #getUpdateCount * @see #getMoreResults * @since JDK 1.4, HSQLDB 1.7 */ //#ifdef JAVA4 public synchronized boolean execute( String sql, int[] columnIndexes) throws SQLException { if (columnIndexes == null || columnIndexes.length == 0) { throw Util.invalidArgument("columnIndexes"); } fetchResult(sql, StatementTypes.RETURN_ANY, Statement.RETURN_GENERATED_KEYS, columnIndexes, null); return resultIn.isData(); } //#endif JAVA4 /** * <!-- start generic documentation --> * 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. 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 <code>INSERT</code> statement, or an SQL statement able to return * auto-generated keys (the list of such statements is vendor-specific). * <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 <code>execute</code> method executes an SQL statement and indicates the * form of the first result. You must then use the methods * <code>getResultSet</code> or <code>getUpdateCount</code> * to retrieve the result, and <code>getMoreResults</code> to * move to any subsequent result(s). * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with 1.9.0, HSQLDB supports this feature. * * </div> * <!-- end release-specific documentation --> * * @param sql any SQL statement * @param columnNames an array of the names of the columns in the inserted * row that should be made available for retrieval by a call to the * method <code>getGeneratedKeys</code> * @return <code>true</code> if the next result is a <code>ResultSet</code> * object; <code>false</code> if it is an update count or there * are no more results * @exception SQLException if a database access error occurs, * this method is called on a closed <code>Statement</code> or the * elements of the <code>String</code> array passed to this * method are not valid column names * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method * @see #getResultSet * @see #getUpdateCount * @see #getMoreResults * @see #getGeneratedKeys * @since JDK 1.4, HSQLDB 1.7 */ //#ifdef JAVA4 public synchronized boolean execute( String sql, String[] columnNames) throws SQLException { if (columnNames == null || columnNames.length == 0) { throw Util.invalidArgument("columnIndexes"); } fetchResult(sql, StatementTypes.RETURN_ANY, Statement.RETURN_GENERATED_KEYS, null, columnNames); return resultIn.isData(); } //#endif JAVA4 /** * <!-- start generic documentation --> * Retrieves the result set holdability for <code>ResultSet</code> objects * generated by this <code>Statement</code> object. * <!-- end generic documentation --> * * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with 1.7.2, this method returns HOLD_CURSORS_OVER_COMMIT * </div> * <!-- end release-specific documentation --> * * @return either <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code> * @exception SQLException if a database access error occurs or * this method is called on a closed <code>Statement</code> * @since JDK 1.4, HSQLDB 1.7 */ //#ifdef JAVA4 public synchronized int getResultSetHoldability() throws SQLException { return rsHoldability; } //#endif JAVA4 //----------------------------- JDBC 4.0 ----------------------------------- /** * Retrieves whether this <code>Statement</code> object has been closed. A <code>Statement</code> is closed if the * method close has been called on it, or if it is automatically closed. * @return true if this <code>Statement</code> object is closed; false if it is still open * @throws SQLException if a database access error occurs * @since JDK 1.6, HSQLDB 1.9.0 */ public synchronized boolean isClosed() throws SQLException { return isClosed; } // --------------------------- Added: Mustang Build 81 ------------------------- boolean poolable = false; /** * Requests that a <code>Statement</code> be pooled or not pooled. 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. * <p> * 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 <code>Statement</code> is not poolable when created, and * a <code>PreparedStatement</code> and <code>CallableStatement</code> * are poolable when created. * <p> * @param poolable requests that the statement be pooled if true and * that the statement not be pooled if false * <p> * @throws SQLException if this method is called on a closed * <code>Statement</code> * <p> * @since JDK 1.6 Build 81, HSQLDB 1.9.0 */ //#ifdef JAVA6 public synchronized void setPoolable( boolean poolable) throws SQLException { checkClosed(); this.poolable = poolable; } //#endif JAVA6 /** * Returns a value indicating whether the <code>Statement</code> * is poolable or not. * <p> * @return <code>true</code> if the <code>Statement</code> * is poolable; <code>false</code> otherwise * @throws SQLException if this method is called on a closed * <code>Statement</code> * <p> * @since JDK 1.6 Build 81, HSQLDB 1.9.0 * <p> * @see #setPoolable(boolean) setPoolable(boolean) */ //#ifdef JAVA6 public synchronized boolean isPoolable() throws SQLException { checkClosed(); return this.poolable; } //#endif JAVA6 // ------------------- java.sql.Wrapper implementation --------------------- /** * 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. * @return an object that implements the interface. May be a proxy for the actual implementing object. * @throws java.sql.SQLException If no object found that implements the interface * @since JDK 1.6, HSQLDB 1.9.0 */ //#ifdef JAVA6 @SuppressWarnings("unchecked") public <T>T unwrap(Class<T> iface) throws java.sql.SQLException { if (isWrapperFor(iface)) { return (T) this; } throw Util.invalidArgument("iface: " + iface); } //#endif JAVA6 /** * 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 JDK 1.6, HSQLDB 1.9.0 */ //#ifdef JAVA6 public boolean isWrapperFor( java.lang.Class<?> iface) throws java.sql.SQLException { return (iface != null && iface.isAssignableFrom(this.getClass())); } //#endif JAVA6 // -------------------- Internal Implementation ---------------------------- /** * Constructs a new JDBCStatement with the specified connection and result * type. * * @param c the connection on which this statement will execute * @param resultSetConcurrency int * @param resultSetHoldability int */ JDBCStatement(JDBCConnection c, int resultSetScrollability, int resultSetConcurrency, int resultSetHoldability) { resultOut = Result.newExecuteDirectRequest(); connection = c; rsScrollability = resultSetScrollability; rsConcurrency = resultSetConcurrency; rsHoldability = resultSetHoldability; } /** * Internal result producer for JDBCStatement (sqlExecDirect mode). * * <p> * * @param sql a character sequence representing the SQL to be executed * @param statementRetType int * @param generatedKeys int * @param generatedIndexes int[] * @param generatedNames String[] * @throws SQLException when a database access error occurs */ private void fetchResult(String sql, int statementRetType, int generatedKeys, int[] generatedIndexes, String[] generatedNames) throws SQLException { checkClosed(); connection.clearWarningsNoCheck(); closeResultData(); if (isEscapeProcessing) { sql = connection.nativeSQL(sql); } resultOut.setPrepareOrExecuteProperties(sql, maxRows, fetchSize, statementRetType, rsScrollability, rsConcurrency, rsHoldability, generatedKeys, generatedIndexes, generatedNames); try { resultIn = connection.sessionProxy.execute(resultOut); performPostExecute(); } catch (HsqlException e) { throw Util.sqlException(e); } if (resultIn.isError()) { throw Util.sqlException(resultIn); } } public void closeOnCompletion() throws SQLException { throw new SQLException(); } public boolean isCloseOnCompletion() throws SQLException { throw new SQLException(); } }