/*

   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.iapi.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.iapi.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.
     */
    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()) );
    }
    
}

