Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / impl / jdbc / EmbedStatement.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/jdbc/EmbedStatement.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/jdbc/EmbedStatement.java
new file mode 100644 (file)
index 0000000..dd6b451
--- /dev/null
@@ -0,0 +1,1739 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.jdbc.EmbedStatement\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.jdbc;\r
+\r
+import org.apache.derby.iapi.reference.JDBC20Translation;\r
+import org.apache.derby.iapi.reference.JDBC30Translation;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.sql.Activation;\r
+import org.apache.derby.iapi.sql.PreparedStatement;\r
+import org.apache.derby.iapi.sql.ResultSet;\r
+import org.apache.derby.iapi.sql.ParameterValueSet;\r
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.jdbc.EngineStatement;\r
+\r
+import java.sql.SQLException;\r
+import java.sql.SQLWarning;\r
+import java.util.Vector;\r
+\r
+/*\r
+ We would import these, but have name-overlap\r
+import java.sql.Statement;\r
+import java.sql.ResultSet;\r
+*/\r
+\r
+/**\r
+ *\r
+ * EmbedStatement is a local JDBC statement.\r
+ *\r
+   <P><B>Supports</B>\r
+   <UL>\r
+   <LI> JSR169 - no subsetting for java.sql.Statement\r
+   <LI> JDBC 2.0\r
+   <LI> JDBC 3.0 - no new dependencies on new JDBC 3.0 or JDK 1.4 classes,\r
+        new methods can safely be added into implementation.\r
+   </UL>\r
+\r
+ */\r
+public class EmbedStatement extends ConnectionChild\r
+    implements EngineStatement {\r
+\r
+       private final java.sql.Connection applicationConnection;\r
+    \r
+    /**\r
+     * Statement reference the application is using to execute\r
+     * this Statement. Normally set to this, but if this was\r
+     * created by a Connection from an XAConnection then this\r
+     * will be a reference to the BrokeredStatement.\r
+     *\r
+     * Making it protected to allow access from EmbedPreparedStatement40\r
+     * to be used for StatementEvents\r
+     *\r
+     */\r
+    protected EngineStatement applicationStatement;\r
+\r
+       int updateCount = -1;\r
+       java.sql.ResultSet results;\r
+       //for jdbc3.0 feature, where you can get a resultset of rows inserted\r
+       //for auto generated columns after an insert\r
+       private java.sql.ResultSet autoGeneratedKeysResultSet;\r
+       private String cursorName;\r
+\r
+       private final boolean forMetaData;\r
+       final int resultSetType;\r
+       final int resultSetConcurrency;\r
+       private final int resultSetHoldability;\r
+       final LanguageConnectionContext lcc;\r
+\r
+       private SQLWarning warnings;\r
+       String SQLText;\r
+\r
+    private int fetchSize = 1;\r
+    private int fetchDirection = JDBC20Translation.FETCH_FORWARD;\r
+    int MaxFieldSize;\r
+       /**\r
+        * Query timeout in milliseconds. By default, no statements time\r
+        * out. Timeout is set explicitly with setQueryTimeout().\r
+        */\r
+    long timeoutMillis;\r
+\r
+       //the state of this statement, set to false when close() is called\r
+       private boolean active = true;\r
+\r
+    //in case of batch update, save the individual statements in the batch in this vector\r
+       //this is only used by JDBC 2.0\r
+       Vector batchStatements;\r
+       \r
+       // The maximum # of rows to return per result set.\r
+       // (0 means no limit.)\r
+       int maxRows;\r
+\r
+       private ParameterValueSet pvs;\r
+\r
+       // An EmbedStatement is NOT poolable by default. The constructor for\r
+       // PreparedStatement overrides this.\r
+       protected boolean isPoolable = false;\r
+\r
+       //\r
+       // constructor\r
+       //\r
+       public EmbedStatement (EmbedConnection connection, boolean forMetaData,\r
+                                                         int resultSetType, int resultSetConcurrency, int resultSetHoldability)\r
+       {\r
+           super(connection);\r
+               this.forMetaData = forMetaData;\r
+               this.resultSetType = resultSetType;\r
+               this.resultSetConcurrency = resultSetConcurrency;\r
+               this.resultSetHoldability = resultSetHoldability;\r
+\r
+               lcc = getEmbedConnection().getLanguageConnection();\r
+               applicationConnection = getEmbedConnection().getApplicationConnection();\r
+        applicationStatement = this;\r
+       }\r
+\r
+       //\r
+       // java.sql.Statement interface\r
+       // the comments are those from the JDBC interface,\r
+       // so we know what we're supposed to to.\r
+\r
+       /**\r
+     * Execute a SQL statement that returns a single ResultSet.\r
+     *\r
+     * @param sql                                      typically this is a static SQL SELECT statement\r
+        * @return a ResultSet that contains the data produced by the\r
+     * query; never null\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public java.sql.ResultSet executeQuery(String sql)\r
+               throws SQLException\r
+       {\r
+               execute(sql, true, false, JDBC30Translation.NO_GENERATED_KEYS, null, null);\r
+\r
+               if (SanityManager.DEBUG) {\r
+                       if (results == null)\r
+                               SanityManager.THROWASSERT("no results returned on executeQuery()");\r
+               }\r
+\r
+               return results;\r
+       }\r
+\r
+    /**\r
+     * Execute a SQL INSERT, UPDATE or DELETE statement. In addition,\r
+     * SQL statements that return nothing such as SQL DDL statements\r
+     * can be executed.\r
+     *\r
+     * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL\r
+     * statement that returns nothing\r
+     * @return either the row count for INSERT, UPDATE or DELETE; or 0\r
+     * for SQL statements that return nothing\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public int executeUpdate(String sql) throws SQLException\r
+       {\r
+               execute(sql, false, true, JDBC30Translation.NO_GENERATED_KEYS, null, null);\r
+               return updateCount;\r
+       }\r
+\r
+    /**\r
+     * JDBC 3.0\r
+     *\r
+     * Execute the given SQL statement and signals the driver with the given flag\r
+     * about whether the auto-generated keys produced by this Statement object\r
+     * should be made available for retrieval.\r
+     *\r
+     * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL\r
+     * statement that returns nothing\r
+     * @param autoGeneratedKeys - a flag indicating whether auto-generated keys\r
+     * should be made available for retrieval; one of the following constants:\r
+     * Statement.RETURN_GENERATED_KEYS Statement.NO_GENERATED_KEYS\r
+     * @return either the row count for INSERT, UPDATE or DELETE; or 0\r
+     * for SQL statements that return nothing\r
+     * @exception SQLException if a database access error occurs\r
+     */\r
+       public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException\r
+       {\r
+               execute(sql, false, true, autoGeneratedKeys, null, null);\r
+               return updateCount;\r
+       }\r
+\r
+    /**\r
+     * JDBC 3.0\r
+     *\r
+     * Executes the given SQL statement and signals the driver that the\r
+     * auto-generated keys indicated in the given array should be made\r
+     * available for retrieval. The driver will ignore the array if the SQL\r
+     * statement is not an INSERT statement\r
+     *\r
+     * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL\r
+     * statement that returns nothing\r
+     * @param columnIndexes - an array of column indexes indicating the\r
+     * columns that should be returned from the inserted row\r
+     * @return either the row count for INSERT, UPDATE or DELETE; or 0\r
+     * for SQL statements that return nothing\r
+     * @exception SQLException if a database access error occurs\r
+     */\r
+       public int executeUpdate(String sql, int[] columnIndexes) throws SQLException\r
+       {\r
+               execute(sql, false, true,\r
+                       ((columnIndexes == null) || (columnIndexes.length == 0))\r
+                               ? JDBC30Translation.NO_GENERATED_KEYS\r
+                               : JDBC30Translation.RETURN_GENERATED_KEYS,\r
+                       columnIndexes,\r
+                       null);\r
+               return updateCount;\r
+       }\r
+\r
+    /**\r
+     * JDBC 3.0\r
+     *\r
+     * Executes the given SQL statement and signals the driver that the\r
+     * auto-generated keys indicated in the given array should be made\r
+     * available for retrieval. The driver will ignore the array if the SQL\r
+     * statement is not an INSERT statement\r
+     *\r
+     * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL\r
+     * statement that returns nothing\r
+     * @param columnNames - an array of the names of the columns\r
+     * that should be returned from the inserted row\r
+     * @return either the row count for INSERT, UPDATE or DELETE; or 0\r
+     * for SQL statements that return nothing\r
+     * @exception SQLException if a database access error occurs\r
+     */\r
+       public int executeUpdate(String sql, String[] columnNames) throws SQLException\r
+       {\r
+               execute(sql, false, true,\r
+                       ((columnNames == null) || (columnNames.length == 0))\r
+                               ? JDBC30Translation.NO_GENERATED_KEYS\r
+                               : JDBC30Translation.RETURN_GENERATED_KEYS,\r
+                       null,\r
+                       columnNames);\r
+               return updateCount;\r
+       }\r
+\r
+       final void checkIfInMiddleOfBatch() throws SQLException {\r
+               /* If batchStatements is not null then we are in the middle\r
+                * of a batch. That's an invalid state. We need to finish the\r
+                * batch either by clearing the batch or executing the batch.\r
+                * executeUpdate is not allowed inside the batch.\r
+                */\r
+               if (batchStatements != null)\r
+               throw newSQLException(SQLState.MIDDLE_OF_BATCH);\r
+       }\r
+\r
+    /**\r
+     * Tell whether this statment has been closed or not.\r
+     *\r
+     * @return <code>true</code> is closed, <code>false</code> otherwise.\r
+     * @exception SQLException if a database access error occurs.\r
+     */\r
+    public boolean isClosed() throws SQLException {\r
+        // If active, verify state by consulting parent connection.\r
+        if (active) {\r
+            try {\r
+                checkExecStatus();\r
+            } catch (SQLException sqle) {\r
+            }\r
+        }\r
+        return !active;\r
+    }\r
+\r
+    /**\r
+     * In many cases, it is desirable to immediately release a\r
+     * Statements's database and JDBC resources instead of waiting for\r
+     * this to happen when it is automatically closed; the close\r
+     * method provides this immediate release.\r
+     *\r
+     * <P><B>Note:</B> A Statement is automatically closed when it is\r
+     * garbage collected. When a Statement is closed its current\r
+     * ResultSet, if one exists, is also closed.\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public final void close() throws SQLException {\r
+\r
+               /* The close() method is the only method\r
+                * that is allowed to be called on a closed\r
+                * Statement, as per Jon Ellis.\r
+                */\r
+               if (!active)\r
+               {\r
+                       return;\r
+               }\r
+\r
+         synchronized (getConnectionSynchronization()) {\r
+\r
+                 closeActions();\r
+                 \r
+                 //we first set the status\r
+                 active = false;\r
+\r
+                 //first, clear the resutl set\r
+                 clearResultSets();\r
+                 \r
+                 //next, release other resource\r
+                 cursorName = null;\r
+                 warnings = null;\r
+                 SQLText = null;\r
+                 batchStatements = null;\r
+         }\r
+       }\r
+\r
+       // allow sub-classes to execute additional close\r
+       // logic while holding the synchronization.\r
+       void closeActions() throws SQLException {\r
+       }\r
+\r
+    //----------------------------------------------------------------------\r
+\r
+    /**\r
+     * The maxFieldSize limit (in bytes) is the maximum amount of data\r
+     * returned for any column value; it only applies to BINARY,\r
+     * VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and LONGVARCHAR\r
+     * columns.  If the limit is exceeded, the excess data is silently\r
+     * discarded.\r
+     *\r
+     * @return the current max column size limit; zero means unlimited\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public int getMaxFieldSize() throws SQLException {\r
+               checkStatus();\r
+\r
+        return MaxFieldSize;\r
+       }\r
+\r
+    /**\r
+     * The maxFieldSize limit (in bytes) is set to limit the size of\r
+     * data that can be returned for any column value; it only applies\r
+     * to BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and\r
+     * LONGVARCHAR fields.  If the limit is exceeded, the excess data\r
+     * is silently discarded.\r
+     *\r
+     * @param max the new max column size limit; zero means unlimited\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public void setMaxFieldSize(int max) throws SQLException {\r
+               checkStatus();\r
+\r
+               if (max < 0)\r
+               {\r
+                       throw newSQLException(SQLState.INVALID_MAXFIELD_SIZE, new Integer(max));\r
+               }\r
+        this.MaxFieldSize = max;\r
+       }\r
+\r
+    /**\r
+     * The maxRows limit is the maximum number of rows that a\r
+     * ResultSet can contain.  If the limit is exceeded, the excess\r
+     * rows are silently dropped.\r
+     *\r
+     * @return the current max row limit; zero means unlimited\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public int getMaxRows() throws SQLException \r
+       {\r
+               checkStatus();\r
+               return maxRows;\r
+       }\r
+\r
+    /**\r
+     * The maxRows limit is set to limit the number of rows that any\r
+     * ResultSet can contain.  If the limit is exceeded, the excess\r
+     * rows are silently dropped.\r
+     *\r
+     * @param max the new max rows limit; zero means unlimited\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public void setMaxRows(int max) throws SQLException     \r
+       {\r
+               checkStatus();\r
+               if (max < 0)\r
+               {\r
+                       throw newSQLException(SQLState.INVALID_MAX_ROWS_VALUE, new Integer(max));\r
+               }\r
+               this.maxRows = max;\r
+       }\r
+\r
+    /**\r
+     * If escape scanning is on (the default) the driver will do\r
+     * escape substitution before sending the SQL to the database.\r
+     *\r
+     * @param enable true to enable; false to disable\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public void setEscapeProcessing(boolean enable) throws SQLException     {\r
+               checkStatus();\r
+        // Nothing to do in our server , just ignore it.\r
+\r
+       }\r
+\r
+    /**\r
+     * The queryTimeout limit is the number of seconds the driver will\r
+     * wait for a Statement to execute. If the limit is exceeded a\r
+     * SQLException is thrown.\r
+     *\r
+     * @return the current query timeout limit in seconds; zero means unlimited\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public final int getQueryTimeout() throws SQLException {\r
+        checkStatus();\r
+        return (int) (timeoutMillis / 1000);\r
+       }\r
+\r
+    /**\r
+     * The queryTimeout limit is the number of seconds the driver will\r
+     * wait for a Statement to execute. If the limit is exceeded a\r
+     * SQLException is thrown.\r
+     *\r
+     * @param seconds the new query timeout limit in seconds; zero means unlimited\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public final void setQueryTimeout(int seconds) throws SQLException {\r
+               checkStatus();\r
+        if (seconds < 0) {\r
+            throw newSQLException(SQLState.INVALID_QUERYTIMEOUT_VALUE,\r
+                                  new Integer(seconds));\r
+        }\r
+        timeoutMillis = (long) seconds * 1000;\r
+       }\r
+\r
+    /**\r
+     * Cancel can be used by one thread to cancel a statement that\r
+     * is being executed by another thread.\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public void cancel() throws SQLException {\r
+               throw Util.notImplemented("cancel");\r
+       }\r
+\r
+    /**\r
+     * The first warning reported by calls on this Statement is\r
+     * returned.  A Statment's execute methods clear its SQLWarning\r
+     * chain. Subsequent Statement warnings will be chained to this\r
+     * SQLWarning.\r
+     *\r
+     * <p>The warning chain is automatically cleared each time\r
+     * a statement is (re)executed.\r
+     *\r
+     * <P><B>Note:</B> If you are processing a ResultSet then any\r
+     * warnings associated with ResultSet reads will be chained on the\r
+     * ResultSet object.\r
+     *\r
+     * @return the first SQLWarning or null\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public SQLWarning getWarnings() throws SQLException     {\r
+               checkStatus();\r
+               return warnings;\r
+       }\r
+\r
+    /**\r
+     * After this call getWarnings returns null until a new warning is\r
+     * reported for this Statement.\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public void clearWarnings() throws SQLException {\r
+               checkStatus();\r
+               warnings = null;\r
+       }\r
+\r
+    /**\r
+     * setCursorName defines the SQL cursor name that will be used by\r
+     * subsequent Statement execute methods. This name can then be\r
+     * used in SQL positioned update/delete statements to identify the\r
+     * current row in the ResultSet generated by this statement.  If\r
+     * the database doesn't support positioned update/delete, this\r
+     * method is a noop.\r
+     *\r
+     * <P><B>Note:</B> By definition, positioned update/delete\r
+     * execution must be done by a different Statement than the one\r
+     * which generated the ResultSet being used for positioning. Also,\r
+     * cursor names must be unique within a Connection.\r
+     *\r
+     * @param name the new cursor name.\r
+     */\r
+       public void setCursorName(String name) throws SQLException {\r
+               checkStatus();\r
+               cursorName = name;\r
+       }\r
+\r
+    //----------------------- Multiple Results --------------------------\r
+\r
+    /**\r
+     * Execute a SQL statement that may return multiple results.\r
+     * Under some (uncommon) situations a single SQL statement may return\r
+     * multiple result sets and/or update counts.  Normally you can ignore\r
+     * this, unless you're executing a stored procedure that you know may\r
+     * return multiple results, or unless you're dynamically executing an\r
+     * unknown SQL string.  The "execute", "getMoreResults", "getResultSet"\r
+     * and "getUpdateCount" methods let you navigate through multiple results.\r
+     *\r
+     * The "execute" method executes a SQL statement and indicates the\r
+     * form of the first result.  You can then use getResultSet or\r
+     * getUpdateCount to retrieve the result, and getMoreResults to\r
+     * move to any subsequent result(s).\r
+     *\r
+     * @param sql                                      any SQL statement\r
+        *\r
+     * @return true if the first result is a ResultSet; false if it is an integer\r
+     * @see #getResultSet\r
+     * @see #getUpdateCount\r
+     * @see #getMoreResults\r
+        * @exception SQLException thrown on failure\r
+     */\r
+       public boolean execute(String sql)\r
+               throws SQLException\r
+       {\r
+               return execute(sql, false, false, JDBC30Translation.NO_GENERATED_KEYS, null, null);\r
+       }\r
+       \r
+    /**\r
+     * Execute a SQL statement that may return multiple results.\r
+     * Under some (uncommon) situations a single SQL statement may return\r
+     * multiple result sets and/or update counts.  Normally you can ignore\r
+     * this, unless you're executing a stored procedure that you know may\r
+     * return multiple results, or unless you're dynamically executing an\r
+     * unknown SQL string.  The "execute", "getMoreResults", "getResultSet"\r
+     * and "getUpdateCount" methods let you navigate through multiple results.\r
+     *\r
+     * The "execute" method executes a SQL statement and indicates the\r
+     * form of the first result.  You can then use getResultSet or\r
+     * getUpdateCount to retrieve the result, and getMoreResults to\r
+     * move to any subsequent result(s).\r
+     *\r
+     * @param sql                                      any SQL statement\r
+        * @param executeQuery                  caller is executeQuery()\r
+        * @param executeUpdate                 caller is executeUpdate()\r
+     * @param autoGeneratedKeys\r
+     * @param columnIndexes\r
+     * @param columnNames\r
+        *\r
+     * @return true if the first result is a ResultSet; false if it is an integer\r
+     * @see #getResultSet\r
+     * @see #getUpdateCount\r
+     * @see #getMoreResults\r
+        * @exception SQLException thrown on failure\r
+     */\r
+       private boolean execute(String sql, boolean executeQuery, boolean executeUpdate,\r
+               int autoGeneratedKeys, int[] columnIndexes, String[] columnNames) throws SQLException\r
+       {\r
+         synchronized (getConnectionSynchronization()) {\r
+\r
+               checkExecStatus();\r
+               if (sql == null) {\r
+                       throw newSQLException(SQLState.NULL_SQL_TEXT);\r
+               }\r
+               checkIfInMiddleOfBatch();\r
+               clearResultSets(); // release the last statement executed, if any.\r
+\r
+        setupContextStack(); // make sure there's context\r
+\r
+\r
+               // try to remember the SQL statement in case anybody asks for it\r
+               SQLText = sql;          \r
+\r
+               try {\r
+                       Activation activation;\r
+                       try {\r
+                               PreparedStatement preparedStatement = lcc.prepareInternalStatement\r
+                                   (lcc.getDefaultSchema(), sql, resultSetConcurrency==JDBC20Translation.CONCUR_READ_ONLY, false);\r
+                               activation =\r
+                                       preparedStatement.getActivation(lcc, resultSetType == JDBC20Translation.TYPE_SCROLL_INSENSITIVE);\r
+                               checkRequiresCallableStatement(activation);\r
+                        } catch (Throwable t) {\r
+                               throw handleException(t);\r
+                        }\r
+\r
+\r
+                       // this is for a Statement execution\r
+                       activation.setSingleExecution();\r
+\r
+                       //bug 4838 - save the auto-generated key information in activation. keeping this\r
+                       //information in lcc will not work work it can be tampered by a nested trasaction\r
+                       if (autoGeneratedKeys == JDBC30Translation.RETURN_GENERATED_KEYS)\r
+                               activation.setAutoGeneratedKeysResultsetInfo(columnIndexes, columnNames);\r
+                       return executeStatement(activation, executeQuery, executeUpdate);\r
+               } finally {\r
+                   restoreContextStack();\r
+               }\r
+         }\r
+       }\r
+\r
+    /**\r
+     * JDBC 3.0\r
+     *\r
+     * Executes the given SQL statement, which may return multiple\r
+     * results, and signals the driver that any auto-generated keys\r
+     * should be made available for retrieval. The driver will ignore\r
+     * this signal if the SQL statement is not an INSERT statement.\r
+     *\r
+     * @param sql any SQL statement\r
+     * @param autoGeneratedKeys - a constant indicating whether\r
+     * auto-generated keys should be made available for retrieval using\r
+     * the method getGeneratedKeys; one of the following constants:\r
+     * Statement.RETURN_GENERATED_KEYS or Statement.NO_GENERATED_KEYS\r
+     * @return rue if the first result is a ResultSet object; false if\r
+     * it is an update count or there are no results\r
+     * @exception SQLException if a database access error occurs\r
+     */\r
+       public boolean execute(String sql, int autoGeneratedKeys) throws SQLException\r
+       {\r
+               return execute(sql, false, false, autoGeneratedKeys, null, null);\r
+       }\r
+\r
+    /**\r
+     * JDBC 3.0\r
+     *\r
+     * Executes the given SQL statement, which may return multiple\r
+     * results, and signals the driver that the auto-generated keys\r
+     * indicated in the given array should be made available for retrieval.\r
+     * This array contains the indexes of the columns in the target table\r
+     * that contain the auto-generated keys that should be made available.\r
+     * The driver will ignore the array if the given SQL statement is not an\r
+     * INSERT statement.\r
+     *\r
+     * @param sql any SQL statement\r
+     * @param columnIndexes - an array of the indexes of the columns in the\r
+     * inserted row that should be made available for retrieval by a call to\r
+     * the method getGeneratedKeys\r
+     * @return rue if the first result is a ResultSet object; false if\r
+     * it is an update count or there are no results\r
+     * @exception SQLException if a database access error occurs\r
+     */\r
+       public boolean execute(String sql, int[] columnIndexes) throws SQLException\r
+       {\r
+               return execute(sql, false, true,\r
+                       ((columnIndexes == null) || (columnIndexes.length == 0))\r
+                               ? JDBC30Translation.NO_GENERATED_KEYS\r
+                               : JDBC30Translation.RETURN_GENERATED_KEYS,\r
+                       columnIndexes,\r
+                       null);\r
+       }\r
+\r
+    /**\r
+     * JDBC 3.0\r
+     *\r
+     * Executes the given SQL statement, which may return multiple\r
+     * results, and signals the driver that the auto-generated keys\r
+     * indicated in the given array should be made available for retrieval.\r
+     * This array contains the names of the columns in the target table\r
+     * that contain the auto-generated keys that should be made available.\r
+     * The driver will ignore the array if the given SQL statement is not an\r
+     * INSERT statement.\r
+     *\r
+     * @param sql any SQL statement\r
+     * @param columnNames - an array of the names of the columns in the\r
+     * inserted row that should be made available for retrieval by a call to\r
+     * the method getGeneratedKeys\r
+     * @return rue if the first result is a ResultSet object; false if\r
+     * it is an update count or there are no results\r
+     * @exception SQLException if a database access error occurs\r
+     */\r
+       public boolean execute(String sql, String[] columnNames) throws SQLException\r
+       {\r
+               return execute(sql, false, true,\r
+                       ((columnNames == null) || (columnNames.length == 0))\r
+                               ? JDBC30Translation.NO_GENERATED_KEYS\r
+                               : JDBC30Translation.RETURN_GENERATED_KEYS,\r
+                       null,\r
+                       columnNames);\r
+       }\r
+\r
+    /**\r
+     *  getResultSet returns the current result as a ResultSet.  It\r
+     *  should only be called once per result.\r
+     *\r
+     * @return the current result as a ResultSet; null if the result\r
+     * is an update count or there are no more results or the statement\r
+        * was closed.\r
+     * @see #execute\r
+     */\r
+       public final java.sql.ResultSet getResultSet() throws SQLException  {\r
+               checkStatus();\r
+\r
+               return results;\r
+       }\r
+\r
+    /**\r
+     *  getUpdateCount returns the current result as an update count;\r
+     *  if the result is a ResultSet or there are no more results -1\r
+     *  is returned.  It should only be called once per result.\r
+     *\r
+     * <P>The only way to tell for sure that the result is an update\r
+     *  count is to first test to see if it is a ResultSet. If it is\r
+     *  not a ResultSet it is either an update count or there are no\r
+     *  more results.\r
+     *\r
+     * @return the current result as an update count; -1 if it is a\r
+     * ResultSet or there are no more results\r
+     * @see #execute\r
+     */\r
+       public final int getUpdateCount()       throws SQLException  {\r
+               checkStatus();\r
+               return updateCount;\r
+       }\r
+\r
+    /**\r
+     * getMoreResults moves to a Statement's next result.  It returns true if\r
+     * this result is a ResultSet.  getMoreResults also implicitly\r
+     * closes any current ResultSet obtained with getResultSet.\r
+     *\r
+     * There are no more results when (!getMoreResults() &&\r
+     * (getUpdateCount() == -1)\r
+     *\r
+     * @return true if the next result is a ResultSet; false if it is\r
+     * an update count or there are no more results\r
+     * @see #execute\r
+        * @exception SQLException thrown on failure.\r
+     */\r
+       public final boolean getMoreResults() throws SQLException       {\r
+               return getMoreResults(JDBC30Translation.CLOSE_ALL_RESULTS);\r
+       }\r
+\r
+       /////////////////////////////////////////////////////////////////////////\r
+       //\r
+       //      JDBC 2.0 methods that are implemented here because EmbedPreparedStatement\r
+       //  and EmbedCallableStatement in Local20 need access to them, and those\r
+       //      classes extend their peer classes in Local, instead of EmbedStatement\r
+       //      in Local20\r
+       //\r
+       //  We do the same of JDBC 3.0 methods.\r
+       /////////////////////////////////////////////////////////////////////////\r
+\r
+    /**\r
+     * JDBC 2.0\r
+     *\r
+     * Determine the result set type.\r
+     *\r
+     * @exception SQLException Feature not implemented for now.\r
+     */\r
+    public final int getResultSetType()\r
+               throws SQLException \r
+       {\r
+               checkStatus();\r
+               return resultSetType;\r
+       }\r
+\r
+\r
+    /**\r
+     * JDBC 2.0\r
+     *\r
+     * Give a hint as to the direction in which the rows in a result set\r
+     * will be processed. The hint applies only to result sets created\r
+     * using this Statement object.  The default value is \r
+     * ResultSet.FETCH_FORWARD.\r
+     *\r
+     * @param direction the initial direction for processing rows\r
+     * @exception SQLException if a database-access error occurs or direction\r
+     * is not one of ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or\r
+     * ResultSet.FETCH_UNKNOWN\r
+     */\r
+    public void setFetchDirection(int direction) throws SQLException {\r
+               \r
+               checkStatus();\r
+                /* fetch direction is meaningless to us. we just save\r
+                 * it off if it is valid  and return the current value if asked.\r
+                 */\r
+                if (direction == JDBC20Translation.FETCH_FORWARD || \r
+                    direction == JDBC20Translation.FETCH_REVERSE ||\r
+                    direction == JDBC20Translation.FETCH_UNKNOWN )\r
+                {\r
+                    fetchDirection = direction;\r
+                }else\r
+                    throw newSQLException(SQLState.INVALID_FETCH_DIRECTION, \r
+                                   new Integer(direction));\r
+       }\r
+\r
+    /**\r
+     * JDBC 2.0\r
+     *\r
+     * Determine the fetch direction.\r
+     *\r
+     * @return the default fetch direction\r
+     * @exception SQLException if a database-access error occurs\r
+     */\r
+    public int getFetchDirection() throws SQLException {\r
+               checkStatus();\r
+               return fetchDirection;\r
+       }\r
+\r
+\r
+    /**\r
+     * JDBC 2.0\r
+     *\r
+     * Give the JDBC driver a hint as to the number of rows that should\r
+     * be fetched from the database when more rows are needed.  The number \r
+     * of rows specified only affects result sets created using this \r
+     * statement. If the value specified is zero, then the hint is ignored.\r
+     * The default value is zero.\r
+     *\r
+     * @param rows the number of rows to fetch\r
+     * @exception SQLException if a database-access error occurs, or the\r
+     * condition 0 <= rows <= this.getMaxRows() is not satisfied.\r
+     */\r
+    public void setFetchSize(int rows) throws SQLException {\r
+               checkStatus();\r
+        if (rows < 0  || (this.getMaxRows() != 0 && \r
+                             rows > this.getMaxRows()))\r
+        {\r
+               throw newSQLException(SQLState.INVALID_ST_FETCH_SIZE, new Integer(rows));\r
+        }else if ( rows > 0 ) // ignore the call if the value is zero\r
+            fetchSize = rows;\r
+       }\r
+  \r
+    /**\r
+     * JDBC 2.0\r
+     *\r
+     * Determine the default fetch size.\r
+     * @exception SQLException if a database-access error occurs\r
+     *\r
+     */\r
+    public int getFetchSize() throws SQLException {\r
+               checkStatus();\r
+               return fetchSize;\r
+       }\r
+\r
+    /**\r
+     * JDBC 2.0\r
+     *\r
+     * Determine the result set concurrency.\r
+     *\r
+     * @exception SQLException Feature not implemented for now.\r
+     */\r
+    public int getResultSetConcurrency() throws SQLException {\r
+               checkStatus();\r
+               return resultSetConcurrency;\r
+       }\r
+\r
+    /**\r
+     * JDBC 3.0\r
+     *\r
+     * Retrieves the result set holdability for ResultSet objects\r
+     * generated by this Statement object.\r
+     *\r
+     * @return either ResultSet.HOLD_CURSORS_OVER_COMMIT or\r
+     * ResultSet.CLOSE_CURSORS_AT_COMMIT\r
+     * @exception SQLException Feature not implemented for now.\r
+     */\r
+    public final int getResultSetHoldability() throws SQLException {\r
+               checkStatus();\r
+               return resultSetHoldability;\r
+       }\r
+\r
+    /**\r
+     * JDBC 2.0\r
+     *\r
+     * Adds a SQL command to the current batch of commmands for the statement.\r
+     * This method is optional.\r
+     *\r
+     * @param sql typically this is a static SQL INSERT or UPDATE statement\r
+     * @exception SQLException if a database-access error occurs, or the\r
+     * driver does not support batch statements\r
+     */\r
+    public void addBatch( String sql ) throws SQLException {\r
+               checkStatus();\r
+         synchronized (getConnectionSynchronization()) {\r
+                 if (batchStatements == null)\r
+                         batchStatements = new Vector();\r
+        batchStatements.addElement(sql);\r
+               }\r
+       }\r
+\r
+    /**\r
+     * JDBC 2.0\r
+     *\r
+     * Make the set of commands in the current batch empty.\r
+     * This method is optional.\r
+     *\r
+     * @exception SQLException if a database-access error occurs, or the\r
+     * driver does not support batch statements\r
+     */\r
+    public final void clearBatch() throws SQLException {\r
+               checkStatus();\r
+         synchronized (getConnectionSynchronization()) {\r
+        batchStatements = null;\r
+               }\r
+       }\r
+\r
+    /**\r
+     * JDBC 2.0\r
+     * \r
+     * Submit a batch of commands to the database for execution.\r
+     * This method is optional.\r
+        *\r
+        * Moving jdbc2.0 batch related code in this class because\r
+        * callableStatement in jdbc 20 needs this code too and it doesn't derive\r
+        * from prepared statement in jdbc 20 in our implementation. \r
+        * BatchUpdateException is the only new class from jdbc 20 which is being\r
+        * referenced here and in order to avoid any jdk11x problems, using\r
+        * reflection code to make an instance of that class. \r
+     *\r
+     * @return an array of update counts containing one element for each\r
+     * command in the batch.  The array is ordered according\r
+     * to the order in which commands were inserted into the batch\r
+     * @exception SQLException if a database-access error occurs, or the\r
+     * driver does not support batch statements\r
+     */\r
+    public int[] executeBatch() throws SQLException {\r
+               checkExecStatus();\r
+               synchronized (getConnectionSynchronization()) \r
+               {\r
+                        setupContextStack();\r
+                       int i = 0;\r
+                       // As per the jdbc 2.0 specs, close the statement object's current resultset\r
+                       // if one is open.\r
+                       // Are there results?\r
+                       // outside of the lower try/finally since results will\r
+                       // setup and restore themselves.\r
+                       clearResultSets();\r
+\r
+                       Vector stmts = batchStatements;\r
+                       batchStatements = null;\r
+                       int size;\r
+                       if (stmts == null)\r
+                               size = 0;\r
+                       else\r
+                               size = stmts.size();\r
+\r
+                       int[] returnUpdateCountForBatch = new int[size];\r
+\r
+                       SQLException sqle;\r
+                       try {\r
+                               for (; i< size; i++) \r
+                               {\r
+                                       if (executeBatchElement(stmts.elementAt(i)))\r
+                                               throw newSQLException(SQLState.RESULTSET_RETURN_NOT_ALLOWED);\r
+                                       returnUpdateCountForBatch[i] = getUpdateCount();\r
+                               }\r
+                               return returnUpdateCountForBatch;\r
+                       }\r
+                       catch (StandardException se) {\r
+\r
+                               sqle = handleException(se);\r
+                       }\r
+                       catch (SQLException sqle2) \r
+                       {\r
+                               sqle = sqle2;\r
+                       }\r
+                       finally \r
+                       {\r
+                               restoreContextStack();\r
+                       }\r
+\r
+                       int successfulUpdateCount[] = new int[i];\r
+                       for (int j=0; j<i; j++)\r
+                       {\r
+                               successfulUpdateCount[j] = returnUpdateCountForBatch[j];\r
+                       }\r
+\r
+                       SQLException batch =\r
+                       new java.sql.BatchUpdateException(sqle.getMessage(), sqle.getSQLState(),\r
+                                                                       sqle.getErrorCode(), successfulUpdateCount);\r
+\r
+                       batch.setNextException(sqle);\r
+                       batch.initCause(sqle);\r
+                       throw batch;\r
+      }\r
+       }\r
+\r
+       /**\r
+               Execute a single element of the batch. Overridden by EmbedPreparedStatement\r
+       */\r
+       boolean executeBatchElement(Object batchElement) throws SQLException, StandardException {\r
+               return execute((String)batchElement, false, true, JDBC30Translation.NO_GENERATED_KEYS, null, null);\r
+       }\r
+\r
+    /**\r
+     * JDBC 2.0\r
+     *\r
+     * Return the Connection that produced the Statement.\r
+     *\r
+     * @exception SQLException Exception if it cannot find the connection\r
+     * associated to this statement.\r
+     */\r
+    public final java.sql.Connection getConnection()  throws SQLException {\r
+               checkStatus();\r
+\r
+       java.sql.Connection appConn = getEmbedConnection().getApplicationConnection();\r
+               if ((appConn != applicationConnection) || (appConn == null)) {\r
+\r
+                       throw Util.noCurrentConnection();\r
+        }\r
+               return appConn;\r
+    }\r
+\r
+    /**\r
+     * JDBC 3.0\r
+     *\r
+     * Moves to this Statement obect's next result, deals with any current ResultSet\r
+     * object(s) according to the instructions specified by the given flag, and\r
+     * returns true if the next result is a ResultSet object\r
+     *\r
+     * @param current - one of the following Statement constants indicating what\r
+     * should happen to current ResultSet objects obtained using the method\r
+     * getResultSetCLOSE_CURRENT_RESULT, KEEP_CURRENT_RESULT, or CLOSE_ALL_RESULTS\r
+     * @return true if the next result is a ResultSet; false if it is\r
+     * an update count or there are no more results\r
+     * @see #execute\r
+     * @exception SQLException thrown on failure.\r
+     */\r
+       public final boolean getMoreResults(int current) throws SQLException    {\r
+               checkExecStatus();\r
+\r
+               synchronized (getConnectionSynchronization()) {\r
+                       if (dynamicResults == null) {\r
+                               // we only have the one resultset, so this is\r
+                               // simply a close for us.\r
+                               clearResultSets();\r
+                               return false;\r
+                       }\r
+\r
+                       int startingClose;\r
+                       switch (current) {\r
+                       default:\r
+                       case JDBC30Translation.CLOSE_ALL_RESULTS:\r
+                               startingClose = 0;\r
+                               break;\r
+                       case JDBC30Translation.CLOSE_CURRENT_RESULT:\r
+                               // just close the current result set.\r
+                               startingClose = currentDynamicResultSet;\r
+                               break;\r
+                       case JDBC30Translation.KEEP_CURRENT_RESULT:\r
+                               // make the close loop a no-op.\r
+                               startingClose = dynamicResults.length;\r
+                               break;\r
+                       }\r
+\r
+                       // Close loop.\r
+                       SQLException se = null;\r
+                       for (int i = startingClose; i <= currentDynamicResultSet && i < dynamicResults.length; i++) {\r
+                               EmbedResultSet lrs = dynamicResults[i];\r
+                               if (lrs == null)\r
+                                       continue;\r
+\r
+\r
+                               try {\r
+                                       lrs.close();\r
+                               } catch (SQLException sqle) {\r
+                                       if (se == null)\r
+                                               se = sqle;\r
+                                       else\r
+                                               se.setNextException(sqle);\r
+                               } finally {\r
+                                       dynamicResults[i] = null;\r
+                               }\r
+                       }\r
+\r
+                       if (se != null) {\r
+                               // leave positioned on the current result set (?)\r
+                               throw se;\r
+                       }\r
+\r
+                       updateCount = -1;\r
+\r
+                       while (++currentDynamicResultSet < dynamicResults.length) {\r
+\r
+                               EmbedResultSet lrs = dynamicResults[currentDynamicResultSet];\r
+                               if (lrs != null) {\r
+                                       if (lrs.isClosed) {\r
+                                               dynamicResults[currentDynamicResultSet] = null;\r
+                                               continue;\r
+                                       }\r
+\r
+                                       results = lrs;\r
+\r
+                                       return true;\r
+                               }\r
+                       }\r
+\r
+                       results = null;\r
+                       return false;\r
+               }\r
+       }\r
+\r
+    /**\r
+     * JDBC 3.0\r
+     *\r
+     * Retrieves any auto-generated keys created as a result of executing this\r
+     * Statement object. If this Statement is a non-insert statement,\r
+     * a null ResultSet object is returned.\r
+     *\r
+     * @return a ResultSet object containing the auto-generated key(s) generated by\r
+     * the execution of this Statement object\r
+     * @exception SQLException if a database access error occurs\r
+     */\r
+       public final java.sql.ResultSet getGeneratedKeys() throws SQLException  {\r
+               checkStatus();\r
+               if (autoGeneratedKeysResultSet == null)\r
+                       return null;\r
+               else {\r
+                       execute("VALUES IDENTITY_VAL_LOCAL()", true, false, JDBC30Translation.NO_GENERATED_KEYS, null, null);\r
+                       return results;\r
+               }\r
+       }\r
+\r
+       /////////////////////////////////////////////////////////////////////////\r
+       //\r
+       //      Implementation specific methods \r
+       //\r
+       /////////////////////////////////////////////////////////////////////////\r
+\r
+       /**\r
+               Execute the current statement.\r
+           @exception SQLException thrown on failure.\r
+       */\r
+       boolean executeStatement(Activation a,\r
+                     boolean executeQuery, boolean executeUpdate)\r
+                     throws SQLException {\r
+\r
+               // we don't differentiate the update from the resultset case.\r
+               // so, there could be a result set.\r
+\r
+               // note: the statement interface will paste together\r
+               // an activation and make sure the prepared statement\r
+               // is still valid, so it is preferrable, for now,\r
+               // to creating our own activation and stuffing it in\r
+               // the prepared statement.\r
+\r
+               synchronized (getConnectionSynchronization()) {\r
+                        setupContextStack(); // make sure there's context\r
+                       boolean retval;\r
+\r
+                       pvs = a.getParameterValueSet();\r
+\r
+                       try {\r
+                               // The following is from the javadoc for java.sql.Statement\r
+                               // Only one ResultSet per Statement can be open at any point in time.\r
+                               // Therefore, if the reading of one ResultSet is interleaved with the\r
+                               // reading of another, each must have been generated by different Statements.\r
+                               // All statement execute methods implicitly close a\r
+                               // statment's current ResultSet if an open one exists. \r
+                               if (results != null) {\r
+                                       results.close();\r
+                                       results = null;\r
+                               }\r
+\r
+                               clearWarnings();\r
+\r
+                               if (! forMetaData) {\r
+                                       commitIfNeeded(); // commit the last statement if needed\r
+                                       needCommit();\r
+                               } else {\r
+\r
+\r
+                               if (lcc.getActivationCount() > 1) {\r
+                                 // we do not want to commit here as there seems to be other\r
+                                         // statements/resultSets currently opened for this connection.\r
+                                       } else {\r
+                                               commitIfNeeded(); // we can legitimately commit\r
+                                               needCommit();\r
+                                       }\r
+                               }\r
+\r
+                               // if this was a prepared statement, this just\r
+                               // gets it for us, it won't recompile unless it is invalid.\r
+                               PreparedStatement ps = a.getPreparedStatement();\r
+                               ps.rePrepare(lcc);\r
+                               addWarning(ps.getCompileTimeWarnings());\r
+\r
+\r
+                               /*\r
+                               ** WARNING WARNING\r
+                               **\r
+                               ** Any state set in the activation before execution *must* be copied\r
+                               ** to the new activation in GenericActivationHolder.execute() when\r
+                               ** the statement has been recompiled. State such as\r
+                               ** singleExecution, cursorName, holdability, maxRows.\r
+                               */\r
+\r
+                               if (cursorName != null)\r
+                               {\r
+                                       a.setCursorName(cursorName);\r
+                               }\r
+                \r
+                boolean executeHoldable = getExecuteHoldable();\r
\r
+                               a.setResultSetHoldability(executeHoldable);\r
+\r
+                               //reset the activation to clear warnings\r
+                               //and clear existing result sets in case this has been cached\r
+                               a.reset();\r
+                               a.setMaxRows(maxRows);\r
+                ResultSet resultsToWrap = ps.execute(a,\r
+                                                     false,\r
+                                                     timeoutMillis);\r
+                               addWarning(a.getWarnings());\r
+\r
+\r
+                               if (resultsToWrap.returnsRows()) {\r
+\r
+                    // The statement returns rows, so calling it with\r
+                    // executeUpdate() is not allowed.\r
+                    if (executeUpdate) {\r
+                        throw StandardException.newException(\r
+                                SQLState.LANG_INVALID_CALL_TO_EXECUTE_UPDATE);\r
+                    }\r
+\r
+                                       EmbedResultSet lresults = factory.newEmbedResultSet(getEmbedConnection(), resultsToWrap, forMetaData, this, ps.isAtomic());\r
+                                       results = lresults;\r
+\r
+\r
+                                       // Set up the finalization of the ResultSet to\r
+                                       // mark the activation as unused. It will be\r
+                                       // closed sometime later by the connection\r
+                                       // outside of finalization.\r
+                                       if (a.isSingleExecution())\r
+                                               lresults.singleUseActivation = a;\r
+\r
+                                       updateCount = -1;\r
+                                       retval = true;\r
+                               }\r
+                               else {\r
+\r
+                                       // Only applipable for an insert statement, which does not return rows.\r
+                                       //the auto-generated keys resultset will be null if used for non-insert statement\r
+                                       if (a.getAutoGeneratedKeysResultsetMode() && (resultsToWrap.getAutoGeneratedKeysResultset() != null))\r
+                                       {\r
+                                               resultsToWrap.getAutoGeneratedKeysResultset().open();\r
+                                               autoGeneratedKeysResultSet = factory.newEmbedResultSet(getEmbedConnection(),\r
+                                                       resultsToWrap.getAutoGeneratedKeysResultset(), false, this, ps.isAtomic());\r
+                                       }\r
+\r
+                                       updateCount = resultsToWrap.modifiedRowCount();\r
+\r
+                                       results = null; // note that we have none.\r
+\r
+                    int dynamicResultCount = 0;\r
+                                       if (a.getDynamicResults() != null) {\r
+                        dynamicResultCount =\r
+                            processDynamicResults(a.getDynamicResults(),\r
+                                                  a.getMaxDynamicResults());\r
+                                       }\r
+                    \r
+                    resultsToWrap.close(); // Don't need the result set any more\r
+\r
+                    // executeQuery() is not allowed if the statement\r
+                    // doesn't return exactly one ResultSet.\r
+                    if (executeQuery && dynamicResultCount != 1) {\r
+                        throw StandardException.newException(\r
+                                SQLState.LANG_INVALID_CALL_TO_EXECUTE_QUERY);\r
+                    }\r
+\r
+                    // executeUpdate() is not allowed if the statement\r
+                    // returns ResultSets.\r
+                    if (executeUpdate && dynamicResultCount > 0) {\r
+                        throw StandardException.newException(\r
+                                SQLState.LANG_INVALID_CALL_TO_EXECUTE_UPDATE);\r
+                    }\r
+                                       \r
+                    if (dynamicResultCount == 0) {\r
+                                               if (a.isSingleExecution()) {\r
+                                                       a.close();\r
+                                               }\r
+\r
+                                               if (!forMetaData)\r
+                                                       commitIfNeeded();\r
+                                               else {\r
+\r
+                                                       if (lcc.getActivationCount() > 1) {\r
+                                                         // we do not want to commit here as there seems to be other\r
+                                                         // statements/resultSets currently opened for this connection.\r
+                                                       } else {\r
+                                                               commitIfNeeded(); // we can legitimately commit\r
+                                                       }\r
+                                               }\r
+                                       }\r
+\r
+                    retval = (dynamicResultCount > 0);\r
+                               }\r
+               } catch (Throwable t) {\r
+                               if (a.isSingleExecution()) {\r
+                                       try { a.close(); } catch (Throwable tt) {;}\r
+                               }\r
+                       throw handleException(t);\r
+                       } finally {\r
+                           restoreContextStack();\r
+                       }\r
+                       return retval;\r
+               }\r
+       }\r
+\r
+    /**\r
+     * Add a SQLWarning to this Statement object.\r
+     * If the Statement already has a SQLWarning then it\r
+     * is added to the end of the chain.\r
+     * \r
+     * @see #getWarnings()\r
+     */\r
+       final void addWarning(SQLWarning sw)\r
+       {\r
+               if (sw != null) {\r
+                       if (warnings == null)\r
+                               warnings = sw;\r
+                       else\r
+                               warnings.setNextException(sw);\r
+               }\r
+       }\r
+\r
+\r
+       /* package */\r
+       public String getSQLText()\r
+       {\r
+               // no need to synchronize - accessing a reference is atomic\r
+               // synchronized (getConnectionSynchronization()) \r
+               return SQLText;\r
+       }\r
+\r
+       public ParameterValueSet getParameterValueSet()\r
+       {\r
+               return pvs;\r
+       }\r
+\r
+       /**\r
+     * Throw an exception if this Statement has been closed explictly\r
+     * or it has noticed it has been closed implicitly.\r
+     * JDBC specifications require nearly all methods throw a SQLException\r
+     * if the Statement has been closed, thus most methods call this\r
+     * method or checkExecStatus first.\r
+     * \r
+     * @exception SQLException Thrown if the statement is marked as closed.\r
+     * \r
+     * @see #checkExecStatus()\r
+        */\r
+    final void checkStatus() throws SQLException {\r
+               if (!active) {\r
+            // \r
+            // Check the status of the connection first\r
+            //\r
+            java.sql.Connection appConn = getEmbedConnection().getApplicationConnection();\r
+            if (appConn == null || appConn.isClosed()) {\r
+                throw Util.noCurrentConnection();\r
+            }\r
+\r
+            throw newSQLException(SQLState.ALREADY_CLOSED, "Statement");\r
+        }\r
+       }\r
+\r
+       /**\r
+               A heavier weight version of checkStatus() that ensures the application's Connection\r
+               object is still open. This is to stop errors or unexpected behaviour when a [Prepared]Statement\r
+               object is used after the application has been closed. In particular to ensure that\r
+               a Statement obtained from a PooledConnection cannot be used after the application has closed\r
+               its connection (as the underlying Connection is still active).\r
+               To avoid this heavier weight check on every method of [Prepared]Statement it is only used\r
+               on those methods that would end up using the database's connection to read or modify data.\r
+               E.g. execute*(), but not setXXX, etc.\r
+        <BR>\r
+        If this Statement's Connection is closed an exception will\r
+        be thrown and the active field will be set to false,\r
+        completely marking the Statement as closed.\r
+        <BR>\r
+        If the Statement is not currently connected to an active\r
+        transaction, i.e. a suspended global transaction, then\r
+        this method will throw a SQLException but the Statement\r
+        will remain open. The Statement is open but unable to\r
+        process any new requests until its global transaction\r
+        is resumed.\r
+        <BR>\r
+        Upon return from the method, with or without a SQLException\r
+        the field active will correctly represent the open state of\r
+        the Statement.\r
+        \r
+        @exception SQLException Thrown if the statement is marked as closed\r
+        or the Statement's transaction is suspended.\r
+        \r
+        @see #checkStatus()\r
+       */\r
+       final void checkExecStatus() throws SQLException {\r
+               // getConnection() checks if the Statement is closed\r
+               if (!getConnection().isClosed())\r
+                       return;\r
+        \r
+        // Now this connection is closed for all\r
+        // future use.\r
+        active = false;\r
+               \r
+               throw Util.noCurrentConnection();\r
+       }\r
+\r
+       /**\r
+               Close and clear all result sets associated with this statement\r
+               from the last execution.\r
+       */\r
+       void clearResultSets() throws SQLException {\r
+\r
+               SQLException sqle = null;\r
+\r
+               try {\r
+                       // Are there results?\r
+                       // outside of the lower try/finally since results will\r
+                       // setup and restore themselves.\r
+                       if (results != null) {\r
+                               results.close();\r
+                               results = null;\r
+                       }\r
+               } catch (SQLException s1) {\r
+                       sqle = s1;\r
+               }\r
+\r
+               try {\r
+                       if (autoGeneratedKeysResultSet != null) {\r
+                               autoGeneratedKeysResultSet.close();\r
+                               autoGeneratedKeysResultSet = null;\r
+                       }\r
+               } catch (SQLException sauto) {\r
+                       if (sqle == null)\r
+                               sqle = sauto;\r
+                       else\r
+                               sqle.setNextException(sauto);\r
+               }\r
+\r
+               // close all the dynamic result sets.\r
+               if (dynamicResults != null) {\r
+                       for (int i = 0; i < dynamicResults.length; i++) {\r
+                               EmbedResultSet lrs = dynamicResults[i];\r
+                               if (lrs == null)\r
+                                       continue;\r
+\r
+                               try {\r
+                                       lrs.close();\r
+                               } catch (SQLException sdynamic) {\r
+                                       if (sqle == null)\r
+                                               sqle = sdynamic;\r
+                                       else\r
+                                               sqle.setNextException(sdynamic);\r
+                               }\r
+                       }\r
+                       dynamicResults = null;\r
+               }\r
+\r
+               /*\r
+                         We don't reset statement to null because PreparedStatement\r
+                         relies on it being there for subsequent (post-close) execution\r
+                         requests.  There is no close method on database statement objects.\r
+               */\r
+\r
+               updateCount = -1; // reset field\r
+\r
+               if (sqle != null)\r
+                       throw sqle;\r
+        }  \r
+       \r
+       /**\r
+               Check to see if a statement requires to be executed via a callable statement.\r
+       */\r
+       void checkRequiresCallableStatement(Activation activation) throws SQLException {\r
+\r
+               ParameterValueSet pvs = activation.getParameterValueSet();\r
+\r
+               if (pvs == null)\r
+                       return;\r
+\r
+               if (pvs.checkNoDeclaredOutputParameters()) {\r
+                       try {\r
+                               activation.close();\r
+                       } catch (StandardException se) {\r
+                       }\r
+                       throw newSQLException(SQLState.REQUIRES_CALLABLE_STATEMENT, SQLText);\r
+               }\r
+       }\r
+\r
+       /**\r
+               Transfer my batch of Statements to a newly created Statement.\r
+       */\r
+       public void transferBatch(EmbedStatement other) throws SQLException {\r
+               \r
+               synchronized (getConnectionSynchronization()) {\r
+                       other.batchStatements = batchStatements;\r
+                       batchStatements = null;\r
+               }\r
+       }\r
+    \r
+    /**\r
+     * Set the application statement for this Statement.\r
+    */\r
+    public final void setApplicationStatement(EngineStatement s) {\r
+        this.applicationStatement = s;\r
+    }\r
+\r
+       private EmbedResultSet[] dynamicResults;\r
+       private int currentDynamicResultSet;\r
+\r
+    /**\r
+     * Go through a holder of dynamic result sets, remove those that\r
+     * should not be returned, and sort the result sets according to\r
+     * their creation.\r
+     *\r
+     * @param holder a holder of dynamic result sets\r
+     * @param maxDynamicResultSets the maximum number of result sets\r
+     * to be returned\r
+     * @return the actual number of result sets\r
+     * @exception SQLException if an error occurs\r
+     */\r
+    private int processDynamicResults(java.sql.ResultSet[][] holder,\r
+                                      int maxDynamicResultSets)\r
+        throws SQLException\r
+    {\r
+\r
+               EmbedResultSet[] sorted = new EmbedResultSet[holder.length];\r
+\r
+               int actualCount = 0;\r
+               for (int i = 0; i < holder.length; i++) {\r
+\r
+                       java.sql.ResultSet[] param = holder[i];\r
+\r
+                       java.sql.ResultSet rs = param[0];\r
+\r
+            // Clear the JDBC dynamic ResultSet from the language\r
+            // ResultSet for the CALL statement. This stops the\r
+            // CALL statement closing the ResultSet when its language\r
+            // ResultSet is closed, which will happen just after the\r
+            // call to the processDynamicResults() method.\r
+                       param[0] = null;\r
+            \r
+            // ignore non-Derby result sets or results sets from another connection\r
+            // and closed result sets.\r
+            EmbedResultSet lrs = EmbedStatement.processDynamicResult(\r
+                    getEmbedConnection(), rs, this);\r
+            \r
+            if (lrs == null)\r
+            {\r
+                continue;\r
+            }\r
+\r
+                       sorted[actualCount++] = lrs;\r
+               }\r
+\r
+               if (actualCount != 0) {\r
+\r
+                       // results are defined to be ordered according to their creation\r
+                       if (actualCount != 1) {\r
+                               java.util.Arrays.sort(sorted, 0, actualCount);\r
+                       }\r
+\r
+                       dynamicResults = sorted;\r
+\r
+                       if (actualCount > maxDynamicResultSets) {\r
+                               addWarning(StandardException.newWarning(SQLState.LANG_TOO_MANY_DYNAMIC_RESULTS_RETURNED));\r
+\r
+                               for (int i = maxDynamicResultSets; i < actualCount; i++) {\r
+                                       sorted[i].close();\r
+                                       sorted[i] = null;\r
+                               }\r
+\r
+                               actualCount = maxDynamicResultSets;\r
+                       }\r
+\r
+\r
+                       updateCount = -1;\r
+                       results = sorted[0];\r
+                       currentDynamicResultSet = 0;\r
+\r
+                       // 0100C is not returned for procedures written in Java, from the SQL2003 spec.\r
+                       // getWarnings(StandardException.newWarning(SQLState.LANG_DYNAMIC_RESULTS_RETURNED));\r
+               }\r
+\r
+\r
+               return actualCount;\r
+       }\r
+    \r
+    /**\r
+     * Process a ResultSet created in a Java procedure as a dynamic result.\r
+     * To be a valid dynamic result the ResultSet must be:\r
+     * <UL>\r
+     * <LI> From a Derby system\r
+     * <LI> From a nested connection of connection passed in\r
+     * or from the connection itself.\r
+     * <LI> Open\r
+     * </UL>\r
+     * Any invalid ResultSet is ignored.\r
+     * \r
+     * \r
+     * @param conn Connection ResultSet needs to belong to\r
+     * @param resultSet ResultSet to be tested\r
+     * @param callStatement Statement that executed the CALL, null if \r
+     * @return The result set cast down to EmbedResultSet, null if not a valid\r
+     * dynamic result.\r
+     */\r
+    static EmbedResultSet processDynamicResult(EmbedConnection conn,\r
+            java.sql.ResultSet resultSet,\r
+            EmbedStatement callStatement)\r
+    {\r
+        if (resultSet == null)\r
+            return null;\r
+\r
+        // ignore non-Derby result sets or results sets from another connection\r
+        if (!(resultSet instanceof EmbedResultSet))\r
+            return null;\r
+\r
+        EmbedResultSet lrs = (EmbedResultSet) resultSet;\r
+\r
+        if (lrs.getEmbedConnection().rootConnection != conn.rootConnection)\r
+            return null;\r
+\r
+        // ignore closed result sets.\r
+        try {\r
+               //following will check if the JDBC ResultSet or the language\r
+               //ResultSet is closed. If yes, then it will throw an exception.\r
+               //So, the exception indicates that the ResultSet is closed and\r
+               //hence we should ignore it. \r
+               lrs.checkIfClosed("");\r
+        } catch (SQLException ex) {\r
+            return null;               \r
+        }\r
+        \r
+        lrs.setDynamicResultSet(callStatement);\r
+\r
+        return lrs;\r
+    }\r
+\r
+       /**\r
+               Callback on the statement when one of its result sets is closed.\r
+               This allows the statement to control when it completes and hence\r
+               when it commits in auto commit mode.\r
+\r
+        Must have connection synchronization and setupContextStack(), this\r
+        is required for the call to commitIfNeeded().\r
+       */\r
+       void resultSetClosing(EmbedResultSet closingLRS) throws SQLException {\r
+\r
+               // If the Connection is not in auto commit then this statement completion\r
+               // cannot cause a commit.\r
+               if (!getEmbedConnection().autoCommit)\r
+                       return;\r
+\r
+               // If we have dynamic results, see if there is another result set open.\r
+               // If so, then no commit. The last result set to close will close the statement.\r
+               if (dynamicResults != null) {\r
+                       for (int i = 0; i < dynamicResults.length; i++) {\r
+                               EmbedResultSet lrs = dynamicResults[i];\r
+                               if (lrs == null)\r
+                                       continue;\r
+                               if (lrs.isClosed)\r
+                                       continue;\r
+                               if (lrs == closingLRS)\r
+                                       continue;\r
+\r
+                               // at least one still open so no commit now.\r
+                               return;\r
+                       }\r
+               }\r
+\r
+               // new Throwable("COMMIT ON " + SQLText).printStackTrace(System.out);\r
+\r
+        // beetle 5383.  Force a commit in autocommit always.  Before this\r
+        // change if client in autocommit opened a result set, did a commit,\r
+        // then next then close a commit would not be forced on the close.\r
+               commitIfAutoCommit();\r
+       }\r
+    \r
+    /**\r
+     * Get the execute time holdability for the Statement.\r
+     * When in a global transaction holdabilty defaults to false.\r
+     * @throws SQLException Error from getResultSetHoldability.\r
+     */\r
+    private boolean getExecuteHoldable() throws SQLException\r
+    {\r
+        if (resultSetHoldability  == JDBC30Translation.CLOSE_CURSORS_AT_COMMIT)\r
+            return false;\r
+        \r
+        // Simple non-XA case\r
+        if (applicationStatement == this)\r
+            return true;\r
+        \r
+        return applicationStatement.getResultSetHoldability() ==\r
+            JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;\r
+    }\r
+\r
+       /**\r
+        * Returns the value of the EmbedStatement's poolable hint,\r
+        * indicating whether pooling is requested.\r
+        *\r
+        * @return The value of the poolable hint.\r
+        * @throws SQLException if the Statement has been closed.\r
+        */\r
+\r
+       public boolean isPoolable() throws SQLException {\r
+               // Assert the statement is still active (not closed)\r
+               checkStatus();\r
+\r
+               return isPoolable;\r
+       }                \r
+\r
+       /**\r
+        * Requests that an EmbedStatement be pooled or not.\r
+        *\r
+        * @param poolable requests that the EmbedStatement be pooled if true\r
+        * and not be pooled if false.\r
+        * @throws SQLException if the EmbedStatement has been closed.\r
+        */\r
+     \r
+       public void setPoolable(boolean poolable) throws SQLException {\r
+               // Assert the statement is still active (not closed)\r
+               checkStatus();\r
+\r
+               isPoolable = poolable;\r
+       }\r
+\r
+       public boolean isWrapperFor(Class<?> iface) throws SQLException {\r
+               // TODO Auto-generated method stub\r
+               return false;\r
+       }\r
+\r
+       public <T> T unwrap(Class<T> iface) throws SQLException {\r
+               // TODO Auto-generated method stub\r
+               return null;\r
+       }\r
+\r
+       public void closeOnCompletion() throws SQLException {\r
+               // TODO Auto-generated method stub\r
+               \r
+       }\r
+\r
+       public boolean isCloseOnCompletion() throws SQLException {\r
+               // TODO Auto-generated method stub\r
+               return false;\r
+       }\r
+}\r
+\r