/*

   Derby - Class org.apache.derby.impl.jdbc.EmbedStatement

   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to you under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

 */

package org.apache.derby.impl.jdbc;

import org.apache.derby.shared.common.reference.SQLState;

import org.apache.derby.shared.common.sanity.SanityManager;

import org.apache.derby.iapi.sql.Activation;
import org.apache.derby.iapi.sql.PreparedStatement;
import org.apache.derby.iapi.sql.ResultSet;
import org.apache.derby.iapi.sql.ParameterValueSet;
import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
import org.apache.derby.shared.common.error.StandardException;
import org.apache.derby.iapi.jdbc.EngineStatement;

import java.sql.BatchUpdateException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Vector;
import org.apache.derby.iapi.util.InterruptStatus;

/*
 We would import these, but have name-overlap
import java.sql.Statement;
import java.sql.ResultSet;
*/

/**
 * EmbedStatement is a local JDBC statement.
 * It supports JDBC 4.1.
 */
public class EmbedStatement extends ConnectionChild
    implements EngineStatement {

	private final java.sql.Connection applicationConnection;
    
    /**
     * Statement reference the application is using to execute
     * this Statement. Normally set to this, but if this was
     * created by a Connection from an XAConnection then this
     * will be a reference to the BrokeredStatement.
     *
     * Making it protected to allow access from EmbedPreparedStatement40
     * to be used for StatementEvents
     *
     */
    protected EngineStatement applicationStatement;

	long updateCount = -1;
	EmbedResultSet results;
	//for jdbc3.0 feature, where you can get a resultset of rows inserted
	//for auto generated columns after an insert
	private java.sql.ResultSet autoGeneratedKeysResultSet;
	private String cursorName;

	private final boolean forMetaData;
	final int resultSetType;
	final int resultSetConcurrency;
	private final int resultSetHoldability;
	final LanguageConnectionContext lcc;

	private SQLWarning warnings;
	String SQLText;

    private int fetchSize = 1;
    private int fetchDirection = java.sql.ResultSet.FETCH_FORWARD;
    int MaxFieldSize;
	/**
	 * Query timeout in milliseconds. By default, no statements time
	 * out. Timeout is set explicitly with setQueryTimeout().
	 */
    long timeoutMillis;

	//the state of this statement, set to false when close() is called
	private boolean active = true;

    //in case of batch update, save the individual statements in the batch in this vector
 	//this is only used by JDBC 2.0
 	Vector<Object> batchStatements;
	
	// The maximum # of rows to return per result set.
	// (0 means no limit.)
	long maxRows;

	private ParameterValueSet pvs;

	// An EmbedStatement is NOT poolable by default. The constructor for
	// PreparedStatement overrides this.
	protected boolean isPoolable = false;

    private boolean closeOnCompletion = false;
    private boolean closingResultSets = false;
    
	//
	// constructor
	//
	public EmbedStatement (EmbedConnection connection, boolean forMetaData,
							  int resultSetType, int resultSetConcurrency, int resultSetHoldability)
	{
	    super(connection);
		this.forMetaData = forMetaData;
		this.resultSetType = resultSetType;
		this.resultSetConcurrency = resultSetConcurrency;
		this.resultSetHoldability = resultSetHoldability;

		lcc = getLanguageConnectionContext( getEmbedConnection() );
		applicationConnection = getEmbedConnection().getApplicationConnection();
        applicationStatement = this;
	}

	//
	// java.sql.Statement interface
	// the comments are those from the JDBC interface,
	// so we know what we're supposed to to.

	/**
     * Execute a SQL statement that returns a single ResultSet.
     *
     * @param sql					typically this is a static SQL SELECT statement
	 * @return a ResultSet that contains the data produced by the
     * query; never null
	 * @exception SQLException thrown on failure.
     */
	public java.sql.ResultSet executeQuery(String sql)
		throws SQLException
	{
		execute(sql, true, false, Statement.NO_GENERATED_KEYS, null, null);

		if (SanityManager.DEBUG) {
			if (results == null)
				SanityManager.THROWASSERT("no results returned on executeQuery()");
		}

		return results;
	}

    /**
     * Execute a SQL INSERT, UPDATE or DELETE statement. In addition,
     * SQL statements that return nothing such as SQL DDL statements
     * can be executed.
     *
     * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
     * statement that returns nothing
     * @return either the row count for INSERT, UPDATE or DELETE; or 0
     * for SQL statements that return nothing
	 * @exception SQLException thrown on failure.
     */
	public int executeUpdate(String sql) throws SQLException
	{
		return (int) executeLargeUpdate( sql );
	}

    /**
     * JDBC 4.2
     *
     * Execute a SQL INSERT, UPDATE or DELETE statement. For use with
     * statements which may touch more than Integer.MAX_VALUE rows.
     */
	public long executeLargeUpdate(String sql) throws SQLException
	{
		execute(sql, false, true, Statement.NO_GENERATED_KEYS, null, null);
		return updateCount;
	}

    /**
     * JDBC 3.0
     *
     * Execute the given SQL statement and signals the driver with the given flag
     * about whether the auto-generated keys produced by this Statement object
     * should be made available for retrieval.
     *
     * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
     * statement that returns nothing
     * @param autoGeneratedKeys - a flag indicating whether auto-generated keys
     * should be made available for retrieval; one of the following constants:
     * Statement.RETURN_GENERATED_KEYS Statement.NO_GENERATED_KEYS
     * @return either the row count for INSERT, UPDATE or DELETE; or 0
     * for SQL statements that return nothing
     * @exception SQLException if a database access error occurs
     */
	public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException
	{
		return (int) executeLargeUpdate( sql, autoGeneratedKeys );
	}

    /**
     * JDBC 4.2
     *
     * Execute the given SQL statement and signals the driver with the given flag
     * about whether the auto-generated keys produced by this Statement object
     * should be made available for retrieval. For use with
     * statements which may touch more than Integer.MAX_VALUE rows.
     */
	public long executeLargeUpdate( String sql, int autoGeneratedKeys ) throws SQLException
	{
		execute( sql, false, true, autoGeneratedKeys, null, null );
		return updateCount;
	}

    /**
     * JDBC 3.0
     *
     * 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 INSERT statement
     *
     * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
     * statement that returns nothing
     * @param columnIndexes - an array of column indexes indicating the
     * columns that should be returned from the inserted row
     * @return either the row count for INSERT, UPDATE or DELETE; or 0
     * for SQL statements that return nothing
     * @exception SQLException if a database access error occurs
     */
	public int executeUpdate(String sql, int[] columnIndexes) throws SQLException
	{
		return (int) executeLargeUpdate( sql, columnIndexes );
	}

    /**
     * JDBC 4.2
     *
     * 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 INSERT/UPDATE statement. For use with
     * statements which may touch more than Integer.MAX_VALUE rows.
     */
	public long executeLargeUpdate( String sql, int[] columnIndexes ) throws SQLException
	{
		execute(sql, false, true,
			((columnIndexes == null) || (columnIndexes.length == 0))
				? Statement.NO_GENERATED_KEYS
				: Statement.RETURN_GENERATED_KEYS,
			columnIndexes,
			null);
		return updateCount;
	}

    /**
     * JDBC 3.0
     *
     * 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 INSERT statement
     *
     * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
     * statement that returns nothing
     * @param columnNames - an array of the names of the columns
     * that should be returned from the inserted row
     * @return either the row count for INSERT, UPDATE or DELETE; or 0
     * for SQL statements that return nothing
     * @exception SQLException if a database access error occurs
     */
	public int executeUpdate(String sql, String[] columnNames) throws SQLException
	{
		return (int) executeLargeUpdate( sql, columnNames );
	}

    /**
     * JDBC 4.2
     *
     * 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 INSERT/UPDATE statement. For use with
     * statements which may touch more than Integer.MAX_VALUE rows.
     */
	public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException
	{
		execute(sql, false, true,
			((columnNames == null) || (columnNames.length == 0))
				? Statement.NO_GENERATED_KEYS
				: Statement.RETURN_GENERATED_KEYS,
			null,
			columnNames);
		return updateCount;
	}

	final void checkIfInMiddleOfBatch() throws SQLException {
		/* If batchStatements is not null then we are in the middle
		 * of a batch. That's an invalid state. We need to finish the
		 * batch either by clearing the batch or executing the batch.
		 * executeUpdate is not allowed inside the batch.
		 */
		if (batchStatements != null)
  		throw newSQLException(SQLState.MIDDLE_OF_BATCH);
	}

    /**
     * Tell whether this statment has been closed or not.
     *
     * @return <code>true</code> is closed, <code>false</code> otherwise.
     * @exception SQLException if a database access error occurs.
     */
    public boolean isClosed() throws SQLException {
        // If active, verify state by consulting parent connection.
        if (active) {
            try {
                checkExecStatus();
            } catch (SQLException sqle) {
            }
        }
        return !active;
    }

    /**
     * In many cases, it is desirable to immediately release a
     * Statements's database and JDBC resources instead of waiting for
     * this to happen when it is automatically closed; the close
     * method provides this immediate release.
     *
     * <P><B>Note:</B> A Statement is automatically closed when it is
     * garbage collected. When a Statement is closed its current
     * ResultSet, if one exists, is also closed.
	 * @exception SQLException thrown on failure.
     */
	public final void close() throws SQLException {

		/* The close() method is the only method
		 * that is allowed to be called on a closed
		 * Statement, as per Jon Ellis.
		 */
		if (!active)
		{
			return;
		}

	  synchronized (getConnectionSynchronization()) {

		  closeActions();
		  
		  //we first set the status
		  active = false;

		  // first, clear the result sets.
		  clearResultSets();
		  
		  //next, release other resource
		  cursorName = null;
		  warnings = null;
		  SQLText = null;
		  batchStatements = null;
	  }
	}

    /**
     * Mark the statement and its single-use activation as unused. This method
     * should be called from <code>EmbedPreparedStatement</code>'s finalizer as
     * well, even though prepared statements reuse activations, since
     * <code>getGeneratedKeys()</code> uses a single-use activation regardless
     * of statement type.
     * <BR>
     * Dynamic result sets (those in dynamicResults array) need not
     * be handled here as they will be handled by the statement object
     * that created them. In some cases results will point to a
     * ResultSet in dynamicResults but all that will happen is that
     * the activation will get marked as unused twice.
     */
    //
    // This method in java.lang.Object was deprecated as of build 167
    // of JDK 9. See DERBY-6932.
    //
    @SuppressWarnings("deprecation")
    protected void finalize() throws Throwable {
        super.finalize();

        // We mark the activation as not being used and
        // that is it.  We rely on the connection to sweep
        // through the activations to find the ones that
        // aren't in use, and to close them.  We cannot
        // do a activation.close() here because there are
        // synchronized methods under close that cannot
        // be called during finalization.
        if (results != null && results.singleUseActivation != null) {
            results.singleUseActivation.markUnused();
        }
    }

	// allow sub-classes to execute additional close
	// logic while holding the synchronization.
	void closeActions() throws SQLException {
	}

    //----------------------------------------------------------------------

    /**
     * The maxFieldSize limit (in bytes) is the maximum amount of data
     * returned for any column value; it only applies to BINARY,
     * VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and LONGVARCHAR
     * columns.  If the limit is exceeded, the excess data is silently
     * discarded.
     *
     * @return the current max column size limit; zero means unlimited
	 * @exception SQLException thrown on failure.
     */
	public int getMaxFieldSize() throws SQLException {
		checkStatus();

        return MaxFieldSize;
	}

    /**
     * The maxFieldSize limit (in bytes) is set to limit the size of
     * data that can be returned for any column value; it only applies
     * to BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and
     * LONGVARCHAR fields.  If the limit is exceeded, the excess data
     * is silently discarded.
     *
     * @param max the new max column size limit; zero means unlimited
	 * @exception SQLException thrown on failure.
     */
	public void setMaxFieldSize(int max) throws SQLException {
		checkStatus();

		if (max < 0)
		{
			throw newSQLException(SQLState.INVALID_MAXFIELD_SIZE, max);
		}
        this.MaxFieldSize = max;
	}

    /**
     * The maxRows limit is the maximum number of rows that a
     * ResultSet can contain.  If the limit is exceeded, the excess
     * rows are silently dropped.
     *
     * @return the current max row limit; zero means unlimited
	 * @exception SQLException thrown on failure.
     */
	public int getMaxRows() throws SQLException 
	{
        return (int) getLargeMaxRows();
	}

    /**
     * JDBC 4.2
     *
     * The maxRows limit is the maximum number of rows that a
     * ResultSet can contain.  If the limit is exceeded, the excess
     * rows are silently dropped. For use with
     * statements which may touch more than Integer.MAX_VALUE rows.
     *
     * @return the current max row limit; zero means unlimited
	 * @exception SQLException thrown on failure.
     */
	public long getLargeMaxRows() throws SQLException 
	{
		checkStatus();
		return maxRows;
	}

    /**
     * The maxRows limit is set to limit the number of rows that any
     * ResultSet can contain.  If the limit is exceeded, the excess
     * rows are silently dropped.
     *
     * @param max the new max rows limit; zero means unlimited
	 * @exception SQLException thrown on failure.
     */
	public void setMaxRows(int max) throws SQLException	
	{
        setLargeMaxRows( max );
	}

    /**
     * The maxRows limit is set to limit the number of rows that any
     * ResultSet can contain.  If the limit is exceeded, the excess
     * rows are silently dropped.
     *
     * @param max the new max rows limit; zero means unlimited
	 * @exception SQLException thrown on failure.
     */
	public void setLargeMaxRows(long max) throws SQLException	
	{
		checkStatus();
		if (max < 0L)
		{
			throw newSQLException(SQLState.INVALID_MAX_ROWS_VALUE, max);
		}
		this.maxRows = max;
	}

    /**
     * If escape scanning is on (the default) the driver will do
     * escape substitution before sending the SQL to the database.
     *
     * @param enable true to enable; false to disable
	 * @exception SQLException thrown on failure.
     */
	public void setEscapeProcessing(boolean enable) throws SQLException	{
		checkStatus();
        // Nothing to do in our server , just ignore it.

	}

    /**
     * The queryTimeout limit is the number of seconds the driver will
     * wait for a Statement to execute. If the limit is exceeded a
     * SQLException is thrown.
     *
     * @return the current query timeout limit in seconds; zero means unlimited
	 * @exception SQLException thrown on failure.
     */
	public final int getQueryTimeout() throws SQLException {
        checkStatus();
        return (int) (timeoutMillis / 1000);
	}

    /**
     * The queryTimeout limit is the number of seconds the driver will
     * wait for a Statement to execute. If the limit is exceeded a
     * SQLException is thrown.
     *
     * @param seconds the new query timeout limit in seconds; zero means unlimited
	 * @exception SQLException thrown on failure.
     */
	public final void setQueryTimeout(int seconds) throws SQLException {
		checkStatus();
        if (seconds < 0) {
            throw newSQLException(SQLState.INVALID_QUERYTIMEOUT_VALUE, seconds);
        }
        timeoutMillis = (long) seconds * 1000;
	}

    /**
     * Cancel can be used by one thread to cancel a statement that
     * is being executed by another thread.
	 * @exception SQLException thrown on failure.
     */
	public void cancel() throws SQLException {
		throw Util.notImplemented("cancel");
	}

    /**
     * The first warning reported by calls on this Statement is
     * returned.  A Statment's execute methods clear its SQLWarning
     * chain. Subsequent Statement warnings will be chained to this
     * SQLWarning.
     *
     * <p>The warning chain is automatically cleared each time
     * a statement is (re)executed.
     *
     * <P><B>Note:</B> If you are processing a ResultSet then any
     * warnings associated with ResultSet reads will be chained on the
     * ResultSet object.
     *
     * @return the first SQLWarning or null
	 * @exception SQLException thrown on failure.
     */
	public SQLWarning getWarnings() throws SQLException	{
		checkStatus();
		return warnings;
	}

    /**
     * After this call getWarnings returns null until a new warning is
     * reported for this Statement.
	 * @exception SQLException thrown on failure.
     */
	public void clearWarnings() throws SQLException	{
		checkStatus();
		warnings = null;
	}

    /**
     * setCursorName defines the SQL cursor name that will be used by
     * subsequent Statement execute methods. This name can then be
     * used in SQL positioned update/delete statements to identify the
     * current row in the ResultSet generated by this statement.  If
     * the database doesn't support positioned update/delete, this
     * method is a noop.
     *
     * <P><B>Note:</B> By definition, positioned update/delete
     * execution must be done by a different Statement than the one
     * which generated the ResultSet being used for positioning. Also,
     * cursor names must be unique within a Connection.
     *
     * @param name the new cursor name.
     */
	public void setCursorName(String name) throws SQLException {
		checkStatus();
		cursorName = name;
	}

    //----------------------- Multiple Results --------------------------

    /**
     * Execute a SQL statement that may return multiple results.
     * Under some (uncommon) situations a single SQL statement may return
     * multiple result sets and/or update counts.  Normally you can ignore
     * this, unless you're executing a stored procedure that you know may
     * return multiple results, or unless you're dynamically executing an
     * unknown SQL string.  The "execute", "getMoreResults", "getResultSet"
     * and "getUpdateCount" methods let you navigate through multiple results.
     *
     * The "execute" method executes a SQL statement and indicates the
     * form of the first result.  You can then use getResultSet or
     * getUpdateCount to retrieve the result, and getMoreResults to
     * move to any subsequent result(s).
     *
     * @param sql					any SQL statement
	 *
     * @return true if the first result is a ResultSet; false if it is an integer
     * @see #getResultSet
     * @see #getUpdateCount
     * @see #getMoreResults
	 * @exception SQLException thrown on failure
     */
	public boolean execute(String sql)
		throws SQLException
	{
		return execute(sql, false, false, Statement.NO_GENERATED_KEYS, null, null);
	}
	
    /**
     * Execute a SQL statement that may return multiple results.
     * Under some (uncommon) situations a single SQL statement may return
     * multiple result sets and/or update counts.  Normally you can ignore
     * this, unless you're executing a stored procedure that you know may
     * return multiple results, or unless you're dynamically executing an
     * unknown SQL string.  The "execute", "getMoreResults", "getResultSet"
     * and "getUpdateCount" methods let you navigate through multiple results.
     *
     * The "execute" method executes a SQL statement and indicates the
     * form of the first result.  You can then use getResultSet or
     * getUpdateCount to retrieve the result, and getMoreResults to
     * move to any subsequent result(s).
     *
     * @param sql					any SQL statement
	 * @param executeQuery			caller is executeQuery()
	 * @param executeUpdate			caller is executeUpdate()
     * @param autoGeneratedKeys
     * @param columnIndexes
     * @param columnNames
	 *
     * @return true if the first result is a ResultSet; false if it is an integer
     * @see #getResultSet
     * @see #getUpdateCount
     * @see #getMoreResults
	 * @exception SQLException thrown on failure
     */
	private boolean execute(String sql, boolean executeQuery, boolean executeUpdate,
		int autoGeneratedKeys, int[] columnIndexes, String[] columnNames) throws SQLException
	{
	  synchronized (getConnectionSynchronization()) {

		checkExecStatus();
		if (sql == null) {
			throw newSQLException(SQLState.NULL_SQL_TEXT);
		}
		checkIfInMiddleOfBatch();
		clearResultSets(); // release the last statement executed, if any.

        setupContextStack(); // make sure there's context


		// try to remember the SQL statement in case anybody asks for it
		SQLText = sql;		

		try {
			Activation activation;
			try {
				PreparedStatement preparedStatement = lcc.prepareInternalStatement
				    (lcc.getDefaultSchema(), sql, resultSetConcurrency==
                        java.sql.ResultSet.CONCUR_READ_ONLY, false);
				activation =
					preparedStatement.getActivation(lcc, resultSetType ==
                        java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE);
				checkRequiresCallableStatement(activation);
                InterruptStatus.restoreIntrFlagIfSeen(lcc);
			 } catch (Throwable t) {
				throw handleException(t);
			 }


			// this is for a Statement execution
			activation.setSingleExecution();

			//bug 4838 - save the auto-generated key information in activation. keeping this
			//information in lcc will not work work it can be tampered by a nested trasaction
			if (autoGeneratedKeys == Statement.RETURN_GENERATED_KEYS)
            {
				activation.setAutoGeneratedKeysResultsetInfo(columnIndexes, columnNames);
            }
			return executeStatement(activation, executeQuery, executeUpdate);
		} finally {
		    restoreContextStack();
		}
	  }
	}

    /**
     * JDBC 3.0
     *
     * 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 INSERT/UPDATE statement.
     *
     * @param sql any SQL statement
     * @param autoGeneratedKeys - a constant indicating whether
     * auto-generated keys should be made available for retrieval using
     * the method getGeneratedKeys; one of the following constants:
     * Statement.RETURN_GENERATED_KEYS or Statement.NO_GENERATED_KEYS
     * @return rue if the first result is a ResultSet object; false if
     * it is an update count or there are no results
     * @exception SQLException if a database access error occurs
     */
	public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
	{
		return execute(sql, false, false, autoGeneratedKeys, null, null);
	}

    /**
     * JDBC 3.0
     *
     * 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 given SQL statement is not an
     * INSERT/UPDATE statement.
     *
     * @param sql any SQL statement
     * @param columnIndexes - an array of the indexes of the columns in the
     * inserted/updated row that should be made available for retrieval by a
     * call to the method getGeneratedKeys
     * @return rue if the first result is a ResultSet object; false if
     * it is an update count or there are no results
     * @exception SQLException if a database access error occurs
     */
	public boolean execute(String sql, int[] columnIndexes) throws SQLException
	{
		return execute(sql, false, true,
			((columnIndexes == null) || (columnIndexes.length == 0))
				? Statement.NO_GENERATED_KEYS
				: Statement.RETURN_GENERATED_KEYS,
			columnIndexes,
			null);
	}

    /**
     * JDBC 3.0
     *
     * 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 given SQL statement is not an
     * INSERT/UPDATE statement.
     *
     * @param sql any SQL statement
     * @param columnNames - an array of the names of the columns in the
     * inserted/updated row that should be made available for retrieval by a
     * call to the method getGeneratedKeys
     * @return rue if the first result is a ResultSet object; false if
     * it is an update count or there are no results
     * @exception SQLException if a database access error occurs
     */
	public boolean execute(String sql, String[] columnNames) throws SQLException
	{
		return execute(sql, false, true,
			((columnNames == null) || (columnNames.length == 0))
				? Statement.NO_GENERATED_KEYS
				: Statement.RETURN_GENERATED_KEYS,
			null,
			columnNames);
	}

    /**
     *  getResultSet returns the current result as a ResultSet.  It
     *  should only be called once per result.
     *
     * @return the current result as a ResultSet; null if the result
     * is an update count or there are no more results or the statement
	 * was closed.
     * @see #execute
     */
	public final java.sql.ResultSet getResultSet() throws SQLException  {
		checkStatus();

		return results;
	}

    /**
     *  getUpdateCount returns the current result as an update count;
     *  if the result is a ResultSet or there are no more results -1
     *  is returned.  It should only be called once per result.
     *
     * <P>The only way to tell for sure that the result is an update
     *  count is to first test to see if it is a ResultSet. If it is
     *  not a ResultSet it is either an update count or there are no
     *  more results.
     *
     * @return the current result as an update count; -1 if it is a
     * ResultSet or there are no more results
     * @see #execute
     */
	public final int getUpdateCount()	throws SQLException  {
		checkStatus();
		return (int) updateCount;
	}

    /**
     * JDBC 4.2
     *
     *  getLargeUpdateCount returns the current result as an update count;
     *  if the result is a ResultSet or there are no more results -1
     *  is returned.  It should only be called once per result. For use with
     * statements which may touch more than Integer.MAX_VALUE rows.
     */
	public final long getLargeUpdateCount()	throws SQLException  {
		checkStatus();
		return updateCount;
	}

    /**
     * getMoreResults moves to a Statement's next result.  It returns true if
     * this result is a ResultSet.  getMoreResults also implicitly
     * closes any current ResultSet obtained with getResultSet.
     *
     * There are no more results when (!getMoreResults() &amp;&amp;
     * (getUpdateCount() == -1)
     *
     * @return true if the next result is a ResultSet; false if it is
     * an update count or there are no more results
     * @see #execute
	 * @exception SQLException thrown on failure.
     */
	public final boolean getMoreResults() throws SQLException	{
		return getMoreResults(Statement.CLOSE_ALL_RESULTS);
	}

	/////////////////////////////////////////////////////////////////////////
	//
	//	JDBC 2.0 methods that are implemented here because EmbedPreparedStatement
	//  and EmbedCallableStatement in Local20 need access to them, and those
	//	classes extend their peer classes in Local, instead of EmbedStatement
	//	in Local20
	//
	//  We do the same of JDBC 3.0 methods.
	/////////////////////////////////////////////////////////////////////////

    /**
     * JDBC 2.0
     *
     * Determine the result set type.
     *
     * @exception SQLException Feature not implemented for now.
     */
    public final int getResultSetType()
		throws SQLException 
	{
		checkStatus();
		return resultSetType;
	}


    /**
     * JDBC 2.0
     *
     * Give a hint as to the direction in which the rows in a result set
     * will be processed. The hint applies only to result sets created
     * using this Statement object.  The default value is 
     * ResultSet.FETCH_FORWARD.
     *
     * @param direction the initial direction for processing rows
     * @exception SQLException if a database-access error occurs or direction
     * is not one of ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or
     * ResultSet.FETCH_UNKNOWN
     */
    public void setFetchDirection(int direction) throws SQLException {
		
		checkStatus();
                /* fetch direction is meaningless to us. we just save
                 * it off if it is valid  and return the current value if asked.
                 */
                if (direction == java.sql.ResultSet.FETCH_FORWARD || 
                    direction == java.sql.ResultSet.FETCH_REVERSE ||
                    direction == java.sql.ResultSet.FETCH_UNKNOWN )
                {
                    fetchDirection = direction;
                }else
                    throw newSQLException(SQLState.INVALID_FETCH_DIRECTION, direction);
	}

    /**
     * JDBC 2.0
     *
     * Determine the fetch direction.
     *
     * @return the default fetch direction
     * @exception SQLException if a database-access error occurs
     */
    public int getFetchDirection() throws SQLException {
		checkStatus();
		return fetchDirection;
	}


    /**
     * JDBC 2.0
     *
     * Give the JDBC driver a hint as to the number of rows that should
     * be fetched from the database when more rows are needed.  The number 
     * of rows specified only affects result sets created using this 
     * statement. If the value specified is zero, then the hint is ignored.
     * The default value is zero.
     *
     * @param rows the number of rows to fetch
     * @exception SQLException if a database-access error occurs, or the
     * condition 0 &lt;= rows &lt;= this.getMaxRows() is not satisfied.
     */
    public void setFetchSize(int rows) throws SQLException {
		checkStatus();
        if (rows < 0  || (this.getMaxRows() != 0 && 
                             rows > this.getMaxRows()))
        {
	        throw newSQLException(SQLState.INVALID_ST_FETCH_SIZE, rows);
        }else if ( rows > 0 ) // ignore the call if the value is zero
            fetchSize = rows;
	}
  
    /**
     * JDBC 2.0
     *
     * Determine the default fetch size.
     * @exception SQLException if a database-access error occurs
     *
     */
    public int getFetchSize() throws SQLException {
		checkStatus();
		return fetchSize;
	}

    /**
     * JDBC 2.0
     *
     * Determine the result set concurrency.
     *
     * @exception SQLException Feature not implemented for now.
     */
    public int getResultSetConcurrency() throws SQLException {
		checkStatus();
		return resultSetConcurrency;
	}

    /**
     * JDBC 3.0
     *
     * Retrieves the result set holdability for ResultSet objects
     * generated by this Statement object.
     *
     * @return either ResultSet.HOLD_CURSORS_OVER_COMMIT or
     * ResultSet.CLOSE_CURSORS_AT_COMMIT
     * @exception SQLException Feature not implemented for now.
     */
    public final int getResultSetHoldability() throws SQLException {
		checkStatus();
		return resultSetHoldability;
	}

    /**
     * JDBC 2.0
     *
     * Adds a SQL command to the current batch of commmands for the statement.
     * This method is optional.
     *
     * @param sql typically this is a static SQL INSERT or UPDATE statement
     * @exception SQLException if a database-access error occurs, or the
     * driver does not support batch statements
     */
    public void addBatch( String sql ) throws SQLException {
		checkStatus();
  	  synchronized (getConnectionSynchronization()) {
		  if (batchStatements == null)
			  batchStatements = new Vector<Object>();
        batchStatements.add(sql);
  		}
	}

    /**
     * JDBC 2.0
     *
     * Make the set of commands in the current batch empty.
     * This method is optional.
     *
     * @exception SQLException if a database-access error occurs, or the
     * driver does not support batch statements
     */
    public final void clearBatch() throws SQLException {
		checkStatus();
  	  synchronized (getConnectionSynchronization()) {
        batchStatements = null;
  		}
	}

    /**
     * JDBC 2.0
     * 
     * Submit a batch of commands to the database for execution.
     * This method is optional.
	 *
	 * Moving jdbc2.0 batch related code in this class because
	 * callableStatement in jdbc 20 needs this code too and it doesn't derive
	 * from prepared statement in jdbc 20 in our implementation. 
	 * BatchUpdateException is the only new class from jdbc 20 which is being
	 * referenced here and in order to avoid any jdk11x problems, using
	 * reflection code to make an instance of that class. 
     *
     * @return an array of update counts containing one element for each
     * command in the batch.  The array is ordered according
     * to the order in which commands were inserted into the batch
     * @exception SQLException if a database-access error occurs, or the
     * driver does not support batch statements
     */
    public int[] executeBatch() throws SQLException {
        return Util.squashLongs( executeLargeBatch() );
    }
    
    /**
     * JDBC 4.2
     * 
     * Submit a batch of commands to the database for execution.
     * This method is optional. For use with
     * statements which may touch more than Integer.MAX_VALUE rows.
     */
    public long[] executeLargeBatch() throws SQLException {
		checkExecStatus();
		synchronized (getConnectionSynchronization()) 
		{
            setupContextStack();
			int i = 0;
			// As per the jdbc 2.0 specs, close the statement object's current resultset
			// if one is open.
			// Are there results?
			// outside of the lower try/finally since results will
			// setup and restore themselves.
			clearResultSets();

			Vector<Object> stmts = batchStatements;
			batchStatements = null;
			int size;
			if (stmts == null)
				size = 0;
			else
				size = stmts.size();

			long[] returnUpdateCountForBatch = new long[size];

			SQLException sqle;
			try {
				for (; i< size; i++) 
				{
                    // If we saw an interrupt, stop execution of batch now.
                    // throwIf will likely only throw after at least one stm
                    // has been executed, since first time around we probably
                    // didn't do anything to notice interrupts yet.
                    InterruptStatus.throwIf(lcc);
					if (executeBatchElement(stmts.get(i)))
						throw newSQLException(SQLState.RESULTSET_RETURN_NOT_ALLOWED);
					returnUpdateCountForBatch[ i ] = getLargeUpdateCount();
				}

                InterruptStatus.restoreIntrFlagIfSeen(lcc);
				return returnUpdateCountForBatch;
			}
			catch (StandardException se) {

				sqle = handleException(se);
			}
			catch (SQLException sqle2) 
			{
				sqle = sqle2;
			}
			finally 
			{
				restoreContextStack();
			}

            long[] successfulUpdateCount =
                    Arrays.copyOf(returnUpdateCountForBatch, i);

            throw new BatchUpdateException(sqle.getMessage(),
                                           sqle.getSQLState(),
                                           sqle.getErrorCode(),
                                           successfulUpdateCount,
                                           sqle );
        }
	}

	/**
		Execute a single element of the batch. Overridden by EmbedPreparedStatement
	*/
	boolean executeBatchElement(Object batchElement) throws SQLException, StandardException {
		return execute((String)batchElement, false, true, Statement.NO_GENERATED_KEYS, null, null);
	}

    /**
     * JDBC 2.0
     *
     * Return the Connection that produced the Statement.
     *
     * @exception SQLException Exception if it cannot find the connection
     * associated to this statement.
     */
    public final java.sql.Connection getConnection()  throws SQLException {
		checkStatus();

    	java.sql.Connection appConn = getEmbedConnection().getApplicationConnection();
		if ((appConn != applicationConnection) || (appConn == null)) {

			throw Util.noCurrentConnection();
        }
		return appConn;
    }

    /**
     * JDBC 3.0
     *
     * Moves to this Statement obect's next result, deals with any current ResultSet
     * object(s) according to the instructions specified by the given flag, and
     * returns true if the next result is a ResultSet object
     *
     * @param current - one of the following Statement constants indicating what
     * should happen to current ResultSet objects obtained using the method
     * getResultSetCLOSE_CURRENT_RESULT, KEEP_CURRENT_RESULT, or CLOSE_ALL_RESULTS
     * @return true if the next result is a ResultSet; false if it is
     * an update count or there are no more results
     * @see #execute
     * @exception SQLException thrown on failure.
     */
	public final boolean getMoreResults(int current) throws SQLException	{
		checkExecStatus();

		synchronized (getConnectionSynchronization()) {
			if (dynamicResults == null) {
				// we only have the one resultset, so this is
				// simply a close for us.
				clearResultSets();
                closeMeOnCompletion();
				return false;
			}

			int startingClose;
			switch (current) {
			default:
			case Statement.CLOSE_ALL_RESULTS:
				startingClose = 0;
				break;
			case Statement.CLOSE_CURRENT_RESULT:
				// just close the current result set.
				startingClose = currentDynamicResultSet;
				break;
			case Statement.KEEP_CURRENT_RESULT:
				// make the close loop a no-op.
				startingClose = dynamicResults.length;
				break;
			}

			// Close loop.
			SQLException se = null;
			for (int i = startingClose; i <= currentDynamicResultSet && i < dynamicResults.length; i++) {
				EmbedResultSet lrs = dynamicResults[i];
				if (lrs == null)
					continue;


				try {
					lrs.close();
				} catch (SQLException sqle) {
					if (se == null)
						se = sqle;
					else
						se.setNextException(sqle);
				} finally {
					dynamicResults[i] = null;
				}
			}

			if (se != null) {
				// leave positioned on the current result set (?)
				throw se;
			}

			updateCount = -1L;

			while (++currentDynamicResultSet < dynamicResults.length) {

				EmbedResultSet lrs = dynamicResults[currentDynamicResultSet];
				if (lrs != null) {
					if (lrs.isClosed) {
						dynamicResults[currentDynamicResultSet] = null;
						continue;
					}

					results = lrs;

					return true;
				}
			}

			results = null;
			return false;
		}
	}

    /**
     * JDBC 3.0
     *
     * Retrieves any auto-generated keys created as a result of executing this
     * Statement object. If this Statement is a non-insert statement,
     * a null ResultSet object is returned.
     *
     * @return a ResultSet object containing the auto-generated key(s) generated by
     * the execution of this Statement object
     * @exception SQLException if a database access error occurs
     */
	public final java.sql.ResultSet getGeneratedKeys() throws SQLException	{
		checkStatus();
		if (autoGeneratedKeysResultSet == null)
			return null;
		else {
			execute("VALUES IDENTITY_VAL_LOCAL()", true, false, Statement.NO_GENERATED_KEYS, null, null);
			return results;
		}
	}

	/////////////////////////////////////////////////////////////////////////
	//
	//	Implementation specific methods	
	//
	/////////////////////////////////////////////////////////////////////////

	/**
		Execute the current statement.
	    @exception SQLException thrown on failure.
	*/
	boolean executeStatement(Activation a,
                     boolean executeQuery, boolean executeUpdate)
                     throws SQLException {

		// we don't differentiate the update from the resultset case.
		// so, there could be a result set.

		// note: the statement interface will paste together
		// an activation and make sure the prepared statement
		// is still valid, so it is preferrable, for now,
		// to creating our own activation and stuffing it in
		// the prepared statement.

		synchronized (getConnectionSynchronization()) {
            
            if (SanityManager.DEBUG)
            {
                // Ensure that clearResultSets has been called
                // to fulfill [JDBC4: section 15.2.5 ]
                // A ResultSet object is implicitly closed when:
                // The associated Statement object is re-executed
                
                SanityManager.ASSERT(results == null);
                SanityManager.ASSERT(dynamicResults == null);
                SanityManager.ASSERT(autoGeneratedKeysResultSet == null);
           }
            
                        setupContextStack(); // make sure there's context
			boolean retval;

			pvs = a.getParameterValueSet();

			try {

				clearWarnings();

				if (! forMetaData) {
					commitIfNeeded(); // commit the last statement if needed
					needCommit();
				} else {


		        	if (lcc.getActivationCount() > 1) {
		     		  // we do not want to commit here as there seems to be other
					  // statements/resultSets currently opened for this connection.
					} else {
						commitIfNeeded(); // we can legitimately commit
						needCommit();
					}
				}

				// Get the statement. We don't care if it's invalid, because it
				// will be recompiled when we execute it if needed (DERBY-3024).
				PreparedStatement ps = a.getPreparedStatement();

				/*
				** WARNING WARNING
				**
				** Any state set in the activation before execution *must* be copied
				** to the new activation in GenericActivationHolder.execute() when
				** the statement has been recompiled. State such as
				** singleExecution, cursorName, holdability, maxRows.
				*/

				if (cursorName != null)
				{
					a.setCursorName(cursorName);
				}
                
                boolean executeHoldable = getExecuteHoldable();
 
				a.setResultSetHoldability(executeHoldable);

				//reset the activation to clear warnings
				//and clear existing result sets in case this has been cached
				a.reset();
				a.setMaxRows(maxRows);
                ResultSet resultsToWrap =
                        ps.execute(a, forMetaData, timeoutMillis);
                addWarning(ps.getCompileTimeWarnings());
				addWarning(a.getWarnings());


				if (resultsToWrap.returnsRows()) {

                    // The statement returns rows, so calling it with
                    // executeUpdate() is not allowed.
                    if (executeUpdate) {
                        throw StandardException.newException(
                                SQLState.LANG_INVALID_CALL_TO_EXECUTE_UPDATE);
                    }

					EmbedResultSet lresults = factory.newEmbedResultSet(getEmbedConnection(), resultsToWrap, forMetaData, this, ps.isAtomic());
					results = lresults;


					// Set up the finalization of the ResultSet to
					// mark the activation as unused. It will be
					// closed sometime later by the connection
					// outside of finalization.
					if (a.isSingleExecution())
						lresults.singleUseActivation = a;

					updateCount = -1L;
					retval = true;
				}
				else {

					// Only applicable for an insert/update statement, which does not return rows.
					//the auto-generated keys resultset will be null if used for other statement
					if (a.getAutoGeneratedKeysResultsetMode() && (resultsToWrap.getAutoGeneratedKeysResultset() != null))
					{
						resultsToWrap.getAutoGeneratedKeysResultset().open();
						autoGeneratedKeysResultSet = factory.newEmbedResultSet(getEmbedConnection(),
							resultsToWrap.getAutoGeneratedKeysResultset(), false, this, ps.isAtomic());
					}

					updateCount = resultsToWrap.modifiedRowCount();
					results = null; // note that we have none.

                    int dynamicResultCount = 0;
					if (a.getDynamicResults() != null) {
                        dynamicResultCount =
                            processDynamicResults(a.getDynamicResults(),
                                                  a.getMaxDynamicResults());
					}
                    
                    resultsToWrap.close(); // Don't need the result set any more

                    // executeQuery() is not allowed if the statement
                    // doesn't return exactly one ResultSet.
                    if (executeQuery && dynamicResultCount != 1) {
                        throw StandardException.newException(
                                SQLState.LANG_INVALID_CALL_TO_EXECUTE_QUERY);
                    }

                    // executeUpdate() is not allowed if the statement
                    // returns ResultSets.
                    if (executeUpdate && dynamicResultCount > 0) {
                        throw StandardException.newException(
                                SQLState.LANG_INVALID_CALL_TO_EXECUTE_UPDATE);
                    }
					
                    if (dynamicResultCount == 0) {
						if (a.isSingleExecution()) {
							a.close();
						}

						if (!forMetaData)
							commitIfNeeded();
						else {

							if (lcc.getActivationCount() > 1) {
							  // we do not want to commit here as there seems to be other
							  // statements/resultSets currently opened for this connection.
							} else {
								commitIfNeeded(); // we can legitimately commit
							}
						}
					}

                    retval = (dynamicResultCount > 0);
				}

                InterruptStatus.restoreIntrFlagIfSeen(lcc);

            } catch (Throwable t) {
				if (a.isSingleExecution()) {
					try { a.close(); } catch (Throwable tt) {;}
				}
		        throw handleException(t);
			} finally {
			    restoreContextStack();
			}
			return retval;
		}
	}

    /**
     * Add a SQLWarning to this Statement object.
     * If the Statement already has a SQLWarning then it
     * is added to the end of the chain.
     * 
     * @see #getWarnings()
     */
	final void addWarning(SQLWarning sw)
	{
		if (sw != null) {
			if (warnings == null)
				warnings = sw;
			else
				warnings.setNextException(sw);
		}
	}


	/* package */
	public String getSQLText()
	{
		// no need to synchronize - accessing a reference is atomic
		// synchronized (getConnectionSynchronization()) 
		return SQLText;
	}

	public ParameterValueSet getParameterValueSet()
	{
		return pvs;
	}

	/**
     * Throw an exception if this Statement has been closed explictly
     * or it has noticed it has been closed implicitly.
     * JDBC specifications require nearly all methods throw a SQLException
     * if the Statement has been closed, thus most methods call this
     * method or checkExecStatus first.
     * 
     * @exception SQLException Thrown if the statement is marked as closed.
     * 
     * @see #checkExecStatus()
	 */
    final void checkStatus() throws SQLException {
		if (!active) {
            // 
            // Check the status of the connection first
            //
            java.sql.Connection appConn = getEmbedConnection().getApplicationConnection();
            if (appConn == null || appConn.isClosed()) {
                throw Util.noCurrentConnection();
            }

            throw newSQLException(SQLState.ALREADY_CLOSED, "Statement");
        }
	}

	/**
		A heavier weight version of checkStatus() that ensures the application's Connection
		object is still open. This is to stop errors or unexpected behaviour when a [Prepared]Statement
		object is used after the application has been closed. In particular to ensure that
		a Statement obtained from a PooledConnection cannot be used after the application has closed
		its connection (as the underlying Connection is still active).
		To avoid this heavier weight check on every method of [Prepared]Statement it is only used
		on those methods that would end up using the database's connection to read or modify data.
		E.g. execute*(), but not setXXX, etc.
        <BR>
        If this Statement's Connection is closed an exception will
        be thrown and the active field will be set to false,
        completely marking the Statement as closed.
        <BR>
        If the Statement is not currently connected to an active
        transaction, i.e. a suspended global transaction, then
        this method will throw a SQLException but the Statement
        will remain open. The Statement is open but unable to
        process any new requests until its global transaction
        is resumed.
        <BR>
        Upon return from the method, with or without a SQLException
        the field active will correctly represent the open state of
        the Statement.
        
        @exception SQLException Thrown if the statement is marked as closed
        or the Statement's transaction is suspended.
        
        @see #checkStatus()
	*/
	final void checkExecStatus() throws SQLException {
		// getConnection() checks if the Statement is closed
		if (!getConnection().isClosed())
			return;
        
        // Now this connection is closed for all
        // future use.
        active = false;
        	
		throw Util.noCurrentConnection();
	}

	/**
		Close and clear all result sets associated with this statement
		from the last execution.
	*/
	void clearResultSets() throws SQLException
    {
        //
        // Try not to let closeDependentResultSet() close this Statement
        // when we are just cleaning up before the next operation.
        //
        try {
            closingResultSets = true;
            clearResultSetsMinion();
        }
        finally { closingResultSets = false; }

    }
    // don't call this directly. call clearResultSets() instead.
    private void    clearResultSetsMinion() throws SQLException
    {
		SQLException sqle = null;

		try {
			// Are there results?
			// outside of the lower try/finally since results will
			// setup and restore themselves.
			if (results != null) {
				results.close();
				results = null;
			}
		} catch (SQLException s1) {
			sqle = s1;
		}

		try {
			if (autoGeneratedKeysResultSet != null) {
				autoGeneratedKeysResultSet.close();
				autoGeneratedKeysResultSet = null;
			}
		} catch (SQLException sauto) {
			if (sqle == null)
				sqle = sauto;
			else
				sqle.setNextException(sauto);
		}

		// close all the dynamic result sets.
		if (dynamicResults != null) {
			for (int i = 0; i < dynamicResults.length; i++) {
				EmbedResultSet lrs = dynamicResults[i];
				if (lrs == null)
					continue;

				try {
					lrs.close();
				} catch (SQLException sdynamic) {
					if (sqle == null)
						sqle = sdynamic;
					else
						sqle.setNextException(sdynamic);
				}
			}
			dynamicResults = null;
		}

		/*
			  We don't reset statement to null because PreparedStatement
			  relies on it being there for subsequent (post-close) execution
			  requests.  There is no close method on database statement objects.
		*/

		updateCount = -1L; // reset field

		if (sqle != null)
			throw sqle;
	 }  
	
	/**
		Check to see if a statement requires to be executed via a callable statement.
	*/
	void checkRequiresCallableStatement(Activation activation) throws SQLException {

		ParameterValueSet pvs = activation.getParameterValueSet();

		if (pvs == null)
			return;

		if (pvs.checkNoDeclaredOutputParameters()) {
			try {
				activation.close();
			} catch (StandardException se) {
			}
			throw newSQLException(SQLState.REQUIRES_CALLABLE_STATEMENT, SQLText);
		}
	}

	/**
		Transfer my batch of Statements to a newly created Statement.
	*/
	public void transferBatch(EmbedStatement other) throws SQLException {
		
		synchronized (getConnectionSynchronization()) {
			other.batchStatements = batchStatements;
			batchStatements = null;
		}
	}
    
    /**
     * Set the application statement for this Statement.
    */
    public final void setApplicationStatement(EngineStatement s) {
        this.applicationStatement = s;
    }

	private EmbedResultSet[] dynamicResults;
	private int currentDynamicResultSet;

    /**
     * Go through a holder of dynamic result sets, remove those that
     * should not be returned, and sort the result sets according to
     * their creation.
     *
     * @param holder a holder of dynamic result sets
     * @param maxDynamicResultSets the maximum number of result sets
     * to be returned
     * @return the actual number of result sets
     * @exception SQLException if an error occurs
     */
    private int processDynamicResults(java.sql.ResultSet[][] holder,
                                      int maxDynamicResultSets)
        throws SQLException
    {

		EmbedResultSet[] sorted = new EmbedResultSet[holder.length];

		int actualCount = 0;
		for (int i = 0; i < holder.length; i++) {

			java.sql.ResultSet[] param = holder[i];

			java.sql.ResultSet rs = param[0];

            // Clear the JDBC dynamic ResultSet from the language
            // ResultSet for the CALL statement. This stops the
            // CALL statement closing the ResultSet when its language
            // ResultSet is closed, which will happen just after the
            // call to the processDynamicResults() method.
			param[0] = null;
            
            // ignore non-Derby result sets or results sets from another connection
            // and closed result sets.
            EmbedResultSet lrs = EmbedStatement.processDynamicResult(
                    getEmbedConnection(), rs, this);
            
            if (lrs == null)
            {
                continue;
            }

			sorted[actualCount++] = lrs;
		}

		if (actualCount != 0) {

			// results are defined to be ordered according to their creation
			if (actualCount != 1) {
				java.util.Arrays.sort(sorted, 0, actualCount);
			}

			dynamicResults = sorted;

			if (actualCount > maxDynamicResultSets) {
				addWarning(StandardException.newWarning(SQLState.LANG_TOO_MANY_DYNAMIC_RESULTS_RETURNED));

				for (int i = maxDynamicResultSets; i < actualCount; i++) {
					sorted[i].close();
					sorted[i] = null;
				}

				actualCount = maxDynamicResultSets;
			}


			updateCount = -1L;
			results = sorted[0];
			currentDynamicResultSet = 0;

			// 0100C is not returned for procedures written in Java, from the SQL2003 spec.
			// getWarnings(StandardException.newWarning(SQLState.LANG_DYNAMIC_RESULTS_RETURNED));
		}


		return actualCount;
	}
    
    /**
     * Process a ResultSet created in a Java procedure as a dynamic result.
     * To be a valid dynamic result the ResultSet must be:
     * <UL>
     * <LI> From a Derby system
     * <LI> From a nested connection of connection passed in
     * or from the connection itself.
     * <LI> Open
     * </UL>
     * Any invalid ResultSet is ignored.
     * 
     * 
     * @param conn Connection ResultSet needs to belong to
     * @param resultSet ResultSet to be tested
     * @param callStatement Statement that executed the CALL, null if 
     * @return The result set cast down to EmbedResultSet, null if not a valid
     * dynamic result.
     */
    static EmbedResultSet processDynamicResult(EmbedConnection conn,
            java.sql.ResultSet resultSet,
            EmbedStatement callStatement)
    {
        if (resultSet == null)
            return null;

        // ignore non-Derby result sets or results sets from another connection
        if (!(resultSet instanceof EmbedResultSet))
            return null;

        EmbedResultSet lrs = (EmbedResultSet) resultSet;

        if (lrs.getEmbedConnection().rootConnection != conn.rootConnection)
            return null;

        // ignore closed result sets.
        try {
        	//following will check if the JDBC ResultSet or the language
        	//ResultSet is closed. If yes, then it will throw an exception.
        	//So, the exception indicates that the ResultSet is closed and
        	//hence we should ignore it. 
        	lrs.checkIfClosed("");
        } catch (SQLException ex) {
            return null;        	
        }
        
        lrs.setDynamicResultSet(callStatement);

        return lrs;
    }

	/**
		Callback on the statement when one of its result sets is closed.
		This allows the statement to control when it completes and hence
		when it commits in auto commit mode.

        Must have connection synchronization and setupContextStack(), this
        is required for the call to commitIfNeeded().
	*/
	void resultSetClosing(EmbedResultSet closingLRS) throws SQLException {

		// If the Connection is not in auto commit then this statement completion
		// cannot cause a commit.
		if (!getEmbedConnection().autoCommit)
			return;

		// If we have dynamic results, see if there is another result set open.
		// If so, then no commit. The last result set to close will close the statement.
		if (dynamicResults != null) {
			for (int i = 0; i < dynamicResults.length; i++) {
				EmbedResultSet lrs = dynamicResults[i];
				if (lrs == null)
					continue;
				if (lrs.isClosed)
					continue;
				if (lrs == closingLRS)
					continue;

				// at least one still open so no commit now.
				return;
			}
		}

		// new Throwable("COMMIT ON " + SQLText).printStackTrace(System.out);

        // beetle 5383.  Force a commit in autocommit always.  Before this
        // change if client in autocommit opened a result set, did a commit,
        // then next then close a commit would not be forced on the close.
		commitIfAutoCommit();
	}
    
    /**
     * Get the execute time holdability for the Statement.
     * When in a global transaction holdabilty defaults to false.
     * @throws SQLException Error from getResultSetHoldability.
     */
    private boolean getExecuteHoldable() throws SQLException
    {
        if (resultSetHoldability  == java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT)
            return false;
        
        // Simple non-XA case
        if (applicationStatement == this)
            return true;
        
        return applicationStatement.getResultSetHoldability() ==
            java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT;
    }

	/**
	 * Returns the value of the EmbedStatement's poolable hint,
	 * indicating whether pooling is requested.
	 *
	 * @return The value of the poolable hint.
	 * @throws SQLException if the Statement has been closed.
	 */

	public boolean isPoolable() throws SQLException {
		// Assert the statement is still active (not closed)
		checkStatus();

		return isPoolable;
	}                

	/**
	 * Requests that an EmbedStatement be pooled or not.
	 *
	 * @param poolable requests that the EmbedStatement be pooled if true
	 * and not be pooled if false.
	 * @throws SQLException if the EmbedStatement has been closed.
	 */
     
	public void setPoolable(boolean poolable) throws SQLException {
		// Assert the statement is still active (not closed)
		checkStatus();

		isPoolable = poolable;
	}

    /**
     * Returns false unless {@code interfaces} is implemented.
     *
     * @param interfaces a Class defining an interface.
     * @return true if this implements the interface or directly or indirectly
     * wraps an object that does.
     * @throws SQLException if an error occurs while determining
     * whether this is a wrapper for an object with the given interface.
     */
    public final boolean isWrapperFor(Class<?> interfaces) throws SQLException {
        checkStatus();
        return interfaces.isInstance(this);
    }

    /**
     * Returns {@code this} if this class implements the interface.
     *
     * @param interfaces a Class defining an interface
     * @return an object that implements the interface
     * @throws SQLException if no object if found that implements the interface
     */
    public final <T> T unwrap(java.lang.Class<T> interfaces)
            throws SQLException {
        checkStatus();
        try {
            return interfaces.cast(this);
        } catch (ClassCastException cce) {
            throw newSQLException(SQLState.UNABLE_TO_UNWRAP, interfaces);
        }
    }

    ////////////////////////////////////////////////////////////////////
    //
    // INTRODUCED BY JDBC 4.1 IN JAVA 7
    //
    ////////////////////////////////////////////////////////////////////

    public  void    closeOnCompletion() throws SQLException
    {
		// Assert the statement is still active (not closed)
        checkStatus();
        
        closeOnCompletion = true;
    }

    public  boolean isCloseOnCompletion() throws SQLException
    {
		// Assert the statement is still active (not closed)
        checkStatus();
        
        return closeOnCompletion;
    }

    //
    // For tracking all of the ResultSets produced by this Statement so
    // that the Statement can be cleaned up if closeOnCompletion() was invoked.
    //
    void    closeMeOnCompletion()
    {
        // If necessary, close the Statement after all of its dependent
        // ResultSets have closed.
        if ( active && (!closingResultSets) && closeOnCompletion )
        {
            try {
                if ( isOpen( results ) ) { return; }
                if ( autoGeneratedKeysResultSet != null ) { return; }

                if ( dynamicResults != null )
                {
                    int count = dynamicResults.length;
                    for ( int i = 0; i < count; i++ )
                    {
                        if ( isOpen( dynamicResults[ i ] ) ) { return; }
                    }
                }

                // if we got here, then the Statement has no open ResultSets left
                close();
            }
            catch (SQLException se) { Util.logSQLException( se ); }
        }
    }
    private boolean isOpen( EmbedResultSet rs ) throws SQLException
    {
        return ( (rs != null) && (!rs.isClosed()) );
    }
    
}

