/*

   Derby - Class org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext

   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.sql.conn;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import org.apache.derby.catalog.UUID;
import org.apache.derby.iapi.db.Database;
import org.apache.derby.iapi.db.TriggerExecutionContext;
import org.apache.derby.iapi.error.ExceptionSeverity;
import org.apache.derby.iapi.error.StandardException;
import org.apache.derby.iapi.reference.ContextId;
import org.apache.derby.iapi.reference.Limits;
import org.apache.derby.iapi.reference.Property;
import org.apache.derby.iapi.reference.SQLState;
import org.apache.derby.iapi.services.cache.CacheManager;
import org.apache.derby.iapi.services.cache.Cacheable;
import org.apache.derby.iapi.services.context.Context;
import org.apache.derby.iapi.services.context.ContextImpl;
import org.apache.derby.iapi.services.context.ContextManager;
import org.apache.derby.iapi.services.io.FormatableBitSet;
import org.apache.derby.iapi.services.loader.GeneratedClass;
import org.apache.derby.iapi.services.monitor.Monitor;
import org.apache.derby.iapi.services.property.PropertyUtil;
import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
import org.apache.derby.iapi.sql.Activation;
import org.apache.derby.iapi.sql.LanguageFactory;
import org.apache.derby.iapi.sql.ParameterValueSet;
import org.apache.derby.iapi.sql.PreparedStatement;
import org.apache.derby.iapi.sql.ResultSet;
import org.apache.derby.iapi.sql.compile.ASTVisitor;
import org.apache.derby.iapi.sql.compile.CompilerContext;
import org.apache.derby.iapi.sql.compile.OptTrace;
import org.apache.derby.iapi.sql.compile.OptimizerFactory;
import org.apache.derby.iapi.sql.compile.TypeCompilerFactory;
import org.apache.derby.iapi.sql.conn.Authorizer;
import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
import org.apache.derby.iapi.sql.conn.LanguageConnectionFactory;
import org.apache.derby.iapi.sql.conn.SQLSessionContext;
import org.apache.derby.iapi.sql.conn.StatementContext;
import org.apache.derby.iapi.sql.depend.DependencyManager;
import org.apache.derby.iapi.sql.depend.Provider;
import org.apache.derby.iapi.sql.dictionary.CheckConstraintDescriptor;
import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptorList;
import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;
import org.apache.derby.iapi.sql.dictionary.DataDictionary;
import org.apache.derby.iapi.sql.dictionary.RoleGrantDescriptor;
import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
import org.apache.derby.iapi.sql.execute.ConstantAction;
import org.apache.derby.iapi.sql.execute.CursorActivation;
import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
import org.apache.derby.iapi.sql.execute.ExecutionStmtValidator;
import org.apache.derby.iapi.sql.execute.RunTimeStatistics;
import org.apache.derby.iapi.store.access.TransactionController;
import org.apache.derby.iapi.store.access.XATransactionController;
import org.apache.derby.iapi.transaction.TransactionControl;
import org.apache.derby.iapi.types.DataValueFactory;
import org.apache.derby.iapi.util.IdUtil;
import org.apache.derby.iapi.util.InterruptStatus;
import org.apache.derby.impl.sql.GenericPreparedStatement;
import org.apache.derby.impl.sql.GenericStatement;
import org.apache.derby.impl.sql.compile.CompilerContextImpl;
import org.apache.derby.impl.sql.execute.AutoincrementCounter;
import org.apache.derby.impl.sql.execute.DeferredConstraintsMemory.ValidationInfo;
import org.apache.derby.shared.common.sanity.SanityManager;
/**
 * LanguageConnectionContext keeps the pool of prepared statements,
 * activations, and cursors in use by the current connection.
 * <p>
 * The generic impl does not provide statement caching.
 *
 *
 */
public class GenericLanguageConnectionContext
    extends ContextImpl 
    implements LanguageConnectionContext
{

    // make sure these are not zeros
    private final static int NON_XA = 0;
    private final static int XA_ONE_PHASE = 1;
    private final static int XA_TWO_PHASE = 2;

    /*
        fields
     */

    private final ArrayList<Activation> acts;
    private volatile boolean unusedActs=false;
    /** The maximum size of acts since the last time it was trimmed. Used to
     * determine whether acts should be trimmed to reclaim space. */
    private int maxActsSize;
    protected int bindCount;
    private boolean ddWriteMode;
    private boolean runTimeStatisticsSetting ;
    private boolean statisticsTiming;

    /**
     * If xplainOnlyMode is set (via SYSCS_SET_XPLAIN_MODE), then the
     * connection does not actually execute statements, but only
     * compiles them, and emits the query plan information into the
     * XPLAIN tables.
     */
    private boolean xplainOnlyMode = false;
    
    /** the current xplain schema. Is usually NULL. Can be set via
     * SYSCS_SET_XPLAIN_SCHEMA, in which case it species the schema into
     * which XPLAIN information should be stored in user tables.
     */
    private String xplain_schema = null;
    /**
     * For each XPLAIN table, this map stores a SQL INSERT statement which
     * can be prepared and used to insert rows into the table during the
     * capturing of statistics data into the user XPLAIN tables.
     */
    private Map<Object,Object> xplain_statements = new HashMap<Object,Object>();
    
    //all the temporary tables declared for this connection
    private ArrayList<TempTableInfo> allDeclaredGlobalTempTables;

    //The currentSavepointLevel is used to provide the rollback behavior of 
    //temporary tables.  At any point, this variable has the total number of 
    //savepoints defined for the transaction.
    private int currentSavepointLevel = 0;

    protected long  nextCursorId;

    protected int   nextSavepointId;

    private RunTimeStatistics runTimeStatisticsObject;
    private StringBuffer sb;

    private Database db;

    private final int instanceNumber;
    private String drdaID;
    private String dbname;

    private Object lastQueryTree; // for debugging
    
    /**
    The transaction to use within this language connection context.  It may
    be more appropriate to have it in a separate context (LanguageTransactionContext?).
    REVISIT (nat): I shoehorned the transaction context that
    the language uses into this class.  The main purpose is so
    that the various language code can find out what its
    transaction is.
    **/
    private final TransactionController tran;

    /**
     * If non-null indicates that a read-only nested 
     * user transaction is in progress.
     */
    private TransactionController readOnlyNestedTransaction;
    
    /**
     * queryNestingDepth is a counter used to keep track of how many calls 
     * have been made to begin read-only nested transactions. Only the first call 
     * actually starts a Nested User Transaction with the store. Subsequent
     * calls simply increment this counter. commitNestedTransaction only
     * decrements the counter and when it drops to 0 actually commits the 
     * nested user transaction.
     */
    private int queryNestingDepth;

    protected DataValueFactory dataFactory;
    protected LanguageFactory langFactory;
    protected TypeCompilerFactory tcf;
    protected OptimizerFactory of;
    protected LanguageConnectionFactory connFactory;
    
    /* 
     * A statement context is "pushed" and "popped" at the beginning and
     * end of every statement so that only that statement is cleaned up
     * on a Statement Exception.  As a performance optimization, we only push
     * the outermost statement context once, and never pop it.  Also, we
     * save off a 2nd StatementContext for speeding server side method
     * invocation, though we still push and pop it as needed.  All other
     * statement contexts will allocated and pushed and popped on demand.
     */
    private final StatementContext[] statementContexts = new StatementContext[2];
    private int     statementDepth;
    protected int     outermostTrigger = -1;

    protected Authorizer authorizer;
    protected String userName = null; //The name the user connects with.
                                      //May still be quoted.
    /**
     * The top SQL session context stack frame (SQL 2003, section
     * 4.37.3), is kept in topLevelSSC. For nested session contexts,
     * the SQL session context is held by the activation of the
     * calling statement, cf. pushNestedSessionContext and it is
     * accessible through the current statement context
     * (compile-time), or via the current activation (execution-time).
     * @see GenericLanguageConnectionContext#getTopLevelSQLSessionContext
     */
    private SQLSessionContext topLevelSSC;

    /**
     * Used to hold the computed value of the initial default schema,
     * cf logic in initDefaultSchemaDescriptor.
     */
    private SchemaDescriptor cachedInitialDefaultSchemaDescr = null;

    // RESOLVE - How do we want to set the default.
    private int defaultIsolationLevel = TransactionControl.READ_COMMITTED_ISOLATION_LEVEL;
    protected int isolationLevel = defaultIsolationLevel;

    private boolean isolationLevelExplicitlySet = false;
    // Isolation level can be changed using JDBC api Connection.setTransactionIsolation
    // or it can be changed using SQL "set current isolation = NEWLEVEL".
    // 
    // In XA transactions, BrokeredConnection keeps isolation state information.
    // When isolation is changed in XA transaction using JDBC, that state gets
    // correctly set in BrokeredConnection.setTransactionIsolation method. But
    // when SQL is used to set the isolation level, the code path is different
    // and it does not go through BrokeredConnection's setTransactionIsolation
    // method and hence the state is not maintained correctly when coming through
    // SQL. To get around this, I am adding following flag which will get set
    // everytime the isolation level is set using JDBC or SQL. This flag will be
    // checked at global transaction start and end time. If the flag is set to true
    // then BrokeredConnection's isolation level state will be brought upto date
    // with Real Connection's isolation level and this flag will be set to false
    // after that.
    private boolean isolationLevelSetUsingSQLorJDBC = false;

    // isolation level to when preparing statements.
    // if unspecified, the statement won't be prepared with a specific 
    // scan isolationlevel
    protected int prepareIsolationLevel = TransactionControl.UNSPECIFIED_ISOLATION_LEVEL;

    // Whether or not to write executing statement info to db2j.log
    private boolean logStatementText;
    private boolean logQueryPlan;
    private HeaderPrintWriter istream;

    // this used to be computed in OptimizerFactoryContextImpl; i.e everytime a
    // connection was made. To keep the semantics same I'm putting it out here
    // instead of in the OptimizerFactory which is only initialized when the
    // database is booted.
    private int lockEscalationThreshold; 

    private ArrayList<ExecutionStmtValidator> stmtValidators;
    private ArrayList<TriggerExecutionContext> triggerExecutionContexts;
    private ArrayList <TableDescriptor> triggerTables;

    // OptimizerTrace
    private OptTrace    optimizerTracer;

    //// Support for AUTOINCREMENT

    /**
     * To support lastAutoincrementValue: This is a hashtable which maps
     * schemaName,tableName,columnName to a Long value.
     */
    private HashMap<String,Long> autoincrementHT;
    /**
     * whether to allow updates or not. 
     */
    private boolean autoincrementUpdate;
    private long identityVal;   //support IDENTITY_VAL_LOCAL function
    private boolean identityNotNull;    //frugal programmer

    // cache of ai being handled in memory (bulk insert + alter table).
    private HashMap<String,AutoincrementCounter> autoincrementCacheHashtable;

    // User-written inspector to print out query tree
    private ASTVisitor astWalker;

    /**
     * Interrupt status flag of this session's thread, in the form of an
     * exception created where an interrupt was (last) detected during operation,
     * null if no interrupt has been seen.
     */
    private StandardException interruptedException;

    /**
     * Connection local state for cached {@code TableDescriptor}s used
     * for keeping track of referenced columns for a table during DDL
     * operations.
     */
    private WeakHashMap<TableDescriptor,FormatableBitSet> referencedColumnMap;

    /**
     * The set of disk backed hash tables containing any index rows
     * saved for deferred constraints in this transaction, keyed by the
     * conglomerate id. Checked at commit time, then discarded.
     */
    private HashMap<UUID, ValidationInfo> deferredHashTables;

    /*
       constructor
    */
    public GenericLanguageConnectionContext
    (
     ContextManager cm,
     TransactionController tranCtrl,

     LanguageFactory lf,
     LanguageConnectionFactory lcf,
     Database db,
     String userName,
     int instanceNumber,
     String drdaID,
     String dbname)
         throws StandardException
    {
        super(cm, org.apache.derby.iapi.reference.ContextId.LANG_CONNECTION);
        acts = new ArrayList<Activation>();
        tran = tranCtrl;

        dataFactory = lcf.getDataValueFactory();
        tcf = lcf.getTypeCompilerFactory();
        of = lcf.getOptimizerFactory();
        langFactory =  lf;
        connFactory =  lcf;
        this.db = db;
        this.userName = userName;
        this.instanceNumber = instanceNumber;
        this.drdaID = drdaID;
        this.dbname = dbname;

        /* Find out whether or not to log info on executing statements to error log
         */
        String logStatementProperty = PropertyUtil.getServiceProperty(getTransactionCompile(),
                    "derby.language.logStatementText");
        logStatementText = Boolean.valueOf(logStatementProperty).booleanValue();

        String logQueryPlanProperty = PropertyUtil.getServiceProperty(getTransactionCompile(),
                    "derby.language.logQueryPlan");
        logQueryPlan = Boolean.valueOf(logQueryPlanProperty).booleanValue();

        setRunTimeStatisticsMode(logQueryPlan);

        lockEscalationThreshold = 
            PropertyUtil.getServiceInt(tranCtrl,
                                       Property.LOCKS_ESCALATION_THRESHOLD,
                                       Property.MIN_LOCKS_ESCALATION_THRESHOLD,
                                       Integer.MAX_VALUE,
                                       Property.DEFAULT_LOCKS_ESCALATION_THRESHOLD);                                                             
        stmtValidators = new ArrayList<ExecutionStmtValidator>();
        triggerExecutionContexts = new ArrayList<TriggerExecutionContext>();
        triggerTables = new ArrayList<TableDescriptor>();
    }

    /**
     * In contrast to current user id, which may change (inside a routine
     * executing with definer's rights), the sessionUser is constant in a
     * session.
     */
    private String sessionUser = null;

    public void initialize() throws StandardException
    {
        interruptedException = null;
        sessionUser = IdUtil.getUserAuthorizationId(userName);
        //
        //Creating the authorizer authorizes the connection.
        authorizer = new GenericAuthorizer(this);

        /*
        ** Set the authorization id.  User shouldn't
        ** be null or else we are going to blow up trying
        ** to create a schema for this user.
        */
        if (SanityManager.DEBUG)
        {
            if (getSessionUserId() == null)
            {
                SanityManager.THROWASSERT("User name is null," +
                    " check the connection manager to make sure it is set" +
                    " reasonably");
            }
        }

        setDefaultSchema(initDefaultSchemaDescriptor());
        referencedColumnMap = new WeakHashMap<TableDescriptor,FormatableBitSet>();
    }

    /**
     * Compute the initial default schema and set
     * cachedInitialDefaultSchemaDescr accordingly.
     *
     * @return computed initial default schema value for this session
     * @throws StandardException
     */
    protected SchemaDescriptor initDefaultSchemaDescriptor()
        throws StandardException {
        /*
        ** - If the database supports schemas and a schema with the
        ** same name as the user's name exists (has been created using
        ** create schema already) the database will set the users
        ** default schema to the the schema with the same name as the
        ** user.
        ** - Else Set the default schema to APP.
        */
        if (cachedInitialDefaultSchemaDescr == null) {
            DataDictionary dd = getDataDictionary();

            SchemaDescriptor sd =
                dd.getSchemaDescriptor(
                    getSessionUserId(), getTransactionCompile(), false);

            if (sd == null) {
                sd = new SchemaDescriptor(
                    dd,
                    getSessionUserId(),
                    getSessionUserId(),
                    (UUID) null,
                    false);
            }

            cachedInitialDefaultSchemaDescr = sd;
        }
        return cachedInitialDefaultSchemaDescr;
    }

    /**
     * Get the computed value for the initial default schema.
     * @return the schema descriptor of the computed initial default schema
     */
    private SchemaDescriptor getInitialDefaultSchemaDescriptor() {
        return cachedInitialDefaultSchemaDescr;
    }
    

    //
    // LanguageConnectionContext interface
    //
    /**
     * @see LanguageConnectionContext#getLogStatementText
     */
    public boolean getLogStatementText()
    {
        return logStatementText;
    }

    /**
     * @see LanguageConnectionContext#setLogStatementText
     */
    public void setLogStatementText(boolean logStatementText)
    {
        this.logStatementText = logStatementText;
    }

    /**
     * @see LanguageConnectionContext#getLogQueryPlan
     */
    public boolean getLogQueryPlan()
    {
        return logQueryPlan;
    }

    /**
     * @see LanguageConnectionContext#usesSqlAuthorization
     */
    public boolean usesSqlAuthorization()
    {
        return getDataDictionary().usesSqlAuthorization();
    }

    /**
     * get the lock escalation threshold.
     */
    public int getLockEscalationThreshold()
    {
        return lockEscalationThreshold;
    }

    /**
     * Add the activation to those known about by this connection.
     */
    public void addActivation(Activation a) 
        throws StandardException {
        acts.add(a);

        if (acts.size() > maxActsSize) {
            maxActsSize = acts.size();
        }
    }

    public void closeUnusedActivations()
            throws StandardException
    {
        // DERBY-418. Activations which are marked unused,
        // are closed here. Activations Vector is iterated 
        // to identify and close unused activations, only if 
        // unusedActs flag is set to true and if the total 
        // size exceeds 20.
        if( (unusedActs) && (acts.size() > 20) ) {
            unusedActs = false;

            for (int i = acts.size() - 1; i >= 0; i--) {

                // it maybe the case that a Activation's reset() ends up
                // closing one or more activation leaving our index beyond
                // the end of the array
                if (i >= acts.size())
                    continue;

                Activation a1 = acts.get(i);
                if (!a1.isInUse()) {
                    a1.close();
                }
            }
        }

        if (SanityManager.DEBUG) {

            if (SanityManager.DEBUG_ON("memoryLeakTrace")) {

                if (acts.size() > 20)
                    System.out.println("memoryLeakTrace:GenericLanguageContext:activations " + acts.size());
            }
        }
    }

    /**
     * Make a note that some activations are marked unused
     */
    public void notifyUnusedActivation() {
        unusedActs = true;
    }

    /**
     * @see LanguageConnectionContext#checkIfAnyDeclaredGlobalTempTablesForThisConnection
     */
    public boolean checkIfAnyDeclaredGlobalTempTablesForThisConnection() {
        return (allDeclaredGlobalTempTables == null ? false : true);
    }

    /**
     * @see LanguageConnectionContext#addDeclaredGlobalTempTable
     */
    public void addDeclaredGlobalTempTable(TableDescriptor td)
        throws StandardException 
    {

        if (findDeclaredGlobalTempTable(td.getName()) != null) 
        {
            //if table already declared, throw an exception
            throw StandardException.newException(
                SQLState.LANG_OBJECT_ALREADY_EXISTS_IN_OBJECT,
                "Declared global temporary table",
                td.getName(),
                "Schema",
                SchemaDescriptor.STD_DECLARED_GLOBAL_TEMPORARY_TABLES_SCHEMA_NAME);
        }

        //save all the information about temp table in this special class
        TempTableInfo tempTableInfo = 
            new TempTableInfo(td, currentSavepointLevel);

        // Rather than exist in a catalog, a simple array is kept of the 
        // tables currently active in the transaction.

        if (allDeclaredGlobalTempTables == null)
            allDeclaredGlobalTempTables = new ArrayList<TempTableInfo>();

        allDeclaredGlobalTempTables.add(tempTableInfo);
    }

    /**
     * @see LanguageConnectionContext#dropDeclaredGlobalTempTable
     */
    public boolean dropDeclaredGlobalTempTable(String tableName) 
    {
        TempTableInfo tempTableInfo = findDeclaredGlobalTempTable(tableName);

        if (tempTableInfo != null)
        {
            if (SanityManager.DEBUG)
            {
                if (tempTableInfo.getDeclaredInSavepointLevel() > 
                        currentSavepointLevel)
                {
                    SanityManager.THROWASSERT(
                        "declared in savepoint level (" + 
                            tempTableInfo.getDeclaredInSavepointLevel() + 
                        ") can not be higher than current savepoint level (" +
                            currentSavepointLevel +
                        ").");
                }
            }

            // check if the table was declared in the current unit of work.
            if (tempTableInfo.getDeclaredInSavepointLevel() == 
                    currentSavepointLevel)
            {
                // since the table was declared in this unit of work, the drop 
                // table method should remove it from the valid list of temp 
                // table for this unit of work
                allDeclaredGlobalTempTables.remove(
                        allDeclaredGlobalTempTables.indexOf(tempTableInfo));

                if (allDeclaredGlobalTempTables.isEmpty()) {
                    allDeclaredGlobalTempTables = null;
                }
            }
            else
            {
                // since the table was not declared in this unit of work, the
                // drop table method will just mark the table as dropped
                // in the current unit of work. This information will be used 
                // at rollback time.

                tempTableInfo.setDroppedInSavepointLevel(currentSavepointLevel);
            }

            return true;
        } 
        else
        {
            return false;
        }
    }

    /**
     * After a release of a savepoint, we need to go through our temp tables 
     * list. If there are tables with their declare or drop or modified in 
     * savepoint levels set to savepoint levels higher than the current 
     * savepoint level, then we should change them to the current savepoint
     * level
     */
    private void tempTablesReleaseSavepointLevels() 
    {
        // unlike rollback, here we check for dropped in / declared in / 
        // modified in savepoint levels > current savepoint level only.
        // This is because the temp tables with their savepoint levels same as 
        // currentSavepointLevel have correct value assigned to them and
        // do not need to be changed and hence no need to check for >=

        for (int i = 0; i < allDeclaredGlobalTempTables.size(); i++) 
        {
            TempTableInfo tempTableInfo = 
                allDeclaredGlobalTempTables.get(i);

            if (tempTableInfo.getDroppedInSavepointLevel() > 
                    currentSavepointLevel)
            {
                tempTableInfo.setDroppedInSavepointLevel(currentSavepointLevel);
            }

            if (tempTableInfo.getDeclaredInSavepointLevel() > 
                    currentSavepointLevel)
            {
                tempTableInfo.setDeclaredInSavepointLevel(
                    currentSavepointLevel);
            }

            if (tempTableInfo.getModifiedInSavepointLevel() > 
                    currentSavepointLevel)
            {
                tempTableInfo.setModifiedInSavepointLevel(
                    currentSavepointLevel);
            }
        }
    }

    /**
     * Do the necessary work at commit time for temporary tables
     * <p>
     * 1)If a temporary table was marked as dropped in this transaction, then 
     *   remove it from the list of temp tables for this connection
     * 2)If a temporary table was not dropped in this transaction, then mark 
     *   it's declared savepoint level and modified savepoint level as -1
     * 3)After savepoint fix up, then handle all ON COMMIT DELETE ROWS with
     *   no open held cursor temp tables.
     * <p>
     *
     * @param in_xa_transaction if true, then transaction is an XA transaction,
     *                          and special nested transaction may be necessary
     *                          to cleanup internal containers supporting the
     *                          temp tables at commit time.
     *
     * @exception  StandardException  Standard exception policy.
     **/
    private void tempTablesAndCommit(boolean in_xa_transaction) 
        throws StandardException
    {
        // loop through all declared global temporary tables and determine
        // what to do at commit time based on if they were dropped during
        // the current savepoint level.
        for (int i = allDeclaredGlobalTempTables.size()-1; i >= 0; i--) 
        {
            TempTableInfo tempTableInfo = 
                allDeclaredGlobalTempTables.get(i);

            if (tempTableInfo.getDroppedInSavepointLevel() != -1)
            {
                // this means table was dropped in this unit of work and hence 
                // should be removed from valid list of temp tables

                allDeclaredGlobalTempTables.remove(i);
            } 
            else 
            {
                //this table was not dropped in this unit of work, hence set 
                //its declaredInSavepointLevel as -1 and also mark it as not 
                //modified 

                tempTableInfo.setDeclaredInSavepointLevel(-1);
                tempTableInfo.setModifiedInSavepointLevel(-1);
            }
        }

        // at commit time, for all the temp tables declared with 
        // ON COMMIT DELETE ROWS, make sure there are no held cursor open
        // on them.
        // If there are no held cursors open on ON COMMIT DELETE ROWS, 
        // drop those temp tables and redeclare them to get rid of all the 
        // data in them

        // in XA use nested user updatable transaction.  Delay creating
        // the transaction until loop below finds one it needs to 
        // process.
        
        for (int i=0; i<allDeclaredGlobalTempTables.size(); i++)
        {
            TableDescriptor td = 
                allDeclaredGlobalTempTables.
                                      get(i).getTableDescriptor();
            if (td.isOnCommitDeleteRows() == false) 
            {
                // do nothing for temp table with ON COMMIT PRESERVE ROWS
                continue;
            }
            else if (checkIfAnyActivationHasHoldCursor(td.getName()) == 
                        false)
            {
                // temp tables with ON COMMIT DELETE ROWS and 
                // no open held cursors
                getDataDictionary().getDependencyManager().invalidateFor(
                    td, DependencyManager.DROP_TABLE, this);

                if (!in_xa_transaction)
                {
                    // delay physical cleanup to after the commit for XA
                    // transactions.   In XA the transaction is likely in
                    // prepare state at this point and physical changes to
                    // store are not allowed until after the commit.
                    // Do the work here for non-XA so that fast path does
                    // have to do the 2 commits that the XA path will.
                    cleanupTempTableOnCommitOrRollback(td, true);
                }
            }
        }
    }

    private void tempTablesXApostCommit() 
        throws StandardException
    {
        TransactionController tc = getTransactionExecute();

        // at commit time for an XA transaction drop all temporary tables.
        // A transaction context may not be maintained from one
        // XAResource.xa_commit to the next in the case of XA with
        // network server and thus there is no way to get at the temp
        // tables again.  To provide consistent behavior in embedded vs
        // network server, consistently remove temp tables at XA commit
        // transaction boundary.
        for (int i=0; i < allDeclaredGlobalTempTables.size(); i++)
        {
            // remove all temp tables from this context.
            TableDescriptor td = 
                allDeclaredGlobalTempTables.get(i).getTableDescriptor();

            //remove the conglomerate created for this temp table
            tc.dropConglomerate(td.getHeapConglomerateId()); 

            //remove it from the list of temp tables
            allDeclaredGlobalTempTables.remove(i); 
        }

        tc.commit();
    }

    /**
        Reset the connection before it is returned (indirectly) by
        a PooledConnection object. See EmbeddedConnection.
     */
    public void resetFromPool()
         throws StandardException
    {
        interruptedException = null;

        // Reset IDENTITY_VAL_LOCAL
        identityNotNull = false;

        // drop all temp tables.
        dropAllDeclaredGlobalTempTables();

        // Reset the current schema (see DERBY-3690).
        setDefaultSchema(null);

        // Reset the current role
        getCurrentSQLSessionContext().setRole(null);

        // Reset the current user
        getCurrentSQLSessionContext().setUser(getSessionUserId());

        referencedColumnMap = new WeakHashMap<TableDescriptor,FormatableBitSet>();
    }

    // debug methods
    public  void    setLastQueryTree( Object queryTree ) { lastQueryTree = queryTree; }
    public  Object    getLastQueryTree() { return lastQueryTree; }

    /**
     * Drop all the declared global temporary tables associated with this 
     * connection. This gets called when a getConnection() is done on a 
     * PooledConnection. This will ensure all the temporary tables declared on
     * earlier connection handle associated with this physical database 
     * connection are dropped before a new connection handle is issued on that 
     * same physical database connection.
     */
    private void dropAllDeclaredGlobalTempTables() throws StandardException 
    {
        if (allDeclaredGlobalTempTables == null)
            return;
    
        DependencyManager dm = getDataDictionary().getDependencyManager();
        StandardException topLevelStandardException = null;

        // collect all the exceptions we might receive while dropping the 
        // temporary tables and throw them as one chained exception at the end.
        for (int i = 0; i < allDeclaredGlobalTempTables.size(); i++) 
        {
            try 
            {
                TempTableInfo tempTableInfo = 
                    allDeclaredGlobalTempTables.get(i);

                TableDescriptor td = tempTableInfo.getTableDescriptor();

                // the following 2 lines of code has been copied from 
                // DropTableConstantAction. If there are any changes made there
                // in future, we should check if they need to be made here too.
                dm.invalidateFor(td, DependencyManager.DROP_TABLE, this);
                tran.dropConglomerate(td.getHeapConglomerateId());

            } 
            catch (StandardException e) 
            {
                if (topLevelStandardException == null) 
                {
                    // always keep the first exception unchanged
                    topLevelStandardException = e;
                } 
                else 
                {
                    try 
                    {
                        // Try to create a chain of exceptions. If successful,
                        // the current exception is the top-level exception,
                        // and the previous exception the cause of it.
                        e.initCause(topLevelStandardException);
                        topLevelStandardException = e;
                    } 
                    catch (IllegalStateException ise) 
                    {
                        // initCause() has already been called on e. We don't
                        // expect this to happen, but if it happens, just skip
                        // the current exception from the chain. This is safe
                        // since we always keep the first exception.
                    }
                }
            }
        }
    
        allDeclaredGlobalTempTables = null;
        try 
        {
            internalCommit(true);
        } 
        catch (StandardException e) 
        {
            // do the same chaining as above
            if (topLevelStandardException == null) 
            {
                topLevelStandardException = e;
            } 
            else 
            {
                try 
                {
                    e.initCause(topLevelStandardException);
                    topLevelStandardException = e;
                } 
                catch (IllegalStateException ise) 
                { 
                    /* ignore */ 
                }
            }
        }

        if (topLevelStandardException != null) 
            throw topLevelStandardException;
    }

    /**
     * do the necessary work at rollback time for temporary tables
     * 1)If a temp table was declared in the UOW, then drop it and remove it 
     *   from list of temporary tables.
     * 2)If a temp table was declared and dropped in the UOW, then remove it 
     *   from list of temporary tables.
     * 3)If an existing temp table was dropped in the UOW, then recreate it 
     *   with no data.
     * 4)If an existing temp table was modified in the UOW, then get rid of 
     *   all the rows from the table.
     */
    private void tempTablesAndRollback()
        throws StandardException 
    {
        for (int i = allDeclaredGlobalTempTables.size()-1; i >= 0; i--) 
        {
            TempTableInfo tempTableInfo = 
                allDeclaredGlobalTempTables.get(i);

            if (tempTableInfo.getDeclaredInSavepointLevel() >= 
                    currentSavepointLevel)
            {
                if (tempTableInfo.getDroppedInSavepointLevel() == -1)
                {
                    // the table was declared but not dropped in the unit of 
                    // work getting rolled back and hence we will remove it 
                    // from valid list of temporary tables and drop the 
                    // conglomerate associated with it

                    TableDescriptor td = tempTableInfo.getTableDescriptor();
                    invalidateCleanupDroppedTable( td );

                    //remove the conglomerate created for this temp table
                    tran.dropConglomerate(td.getHeapConglomerateId()); 

                    //remove it from the list of temp tables
                    allDeclaredGlobalTempTables.remove(i); 

                } 
                else if (tempTableInfo.getDroppedInSavepointLevel() >= 
                            currentSavepointLevel)
                {
                    // the table was declared and dropped in the unit of work 
                    // getting rolled back
                    allDeclaredGlobalTempTables.remove(i);
                }
            } 
            else if (tempTableInfo.getDroppedInSavepointLevel() >= 
                        currentSavepointLevel) 
            {
                // this means the table was declared in an earlier savepoint 
                // unit / transaction and then dropped in current UOW 

                // restore the old definition of temp table because drop is 
                // being rolledback
                TableDescriptor td = tempTableInfo.getTableDescriptor();
                td = cleanupTempTableOnCommitOrRollback(td, false);

                // In order to store the old conglomerate information for the 
                // temp table, we need to replace the existing table descriptor
                // with the old table descriptor which has the old conglomerate 
                // information
                tempTableInfo.setTableDescriptor(td);
                tempTableInfo.setDroppedInSavepointLevel(-1);

                // following will mark the table as not modified. This is 
                // because the table data has been deleted as part of the 
                // current rollback
                tempTableInfo.setModifiedInSavepointLevel(-1);
                allDeclaredGlobalTempTables.set(i, tempTableInfo);
                
            } 
            else if (tempTableInfo.getModifiedInSavepointLevel() >= 
                    currentSavepointLevel) 
            {
                // this means the table was declared in an earlier savepoint 
                // unit / transaction and modified in current UOW

                // following will mark the table as not modified. This is 
                // because the table data will be deleted as part of the 
                // current rollback
                tempTableInfo.setModifiedInSavepointLevel(-1);
                TableDescriptor td = tempTableInfo.getTableDescriptor();

                invalidateCleanupDroppedTable( td );
            } 
            // there is no else here because there is no special processing 
            // required for temp tables declares in earlier work of 
            // unit/transaction and not modified
        }
    
        if (allDeclaredGlobalTempTables.isEmpty())
        {
            allDeclaredGlobalTempTables = null;
        }
    }

    /** Invalidate a dropped temp table */
    private void    invalidateCleanupDroppedTable( TableDescriptor td )
        throws StandardException
    {
        getDataDictionary().getDependencyManager().invalidateFor( td, DependencyManager.DROP_TABLE, this );
        cleanupTempTableOnCommitOrRollback( td, true );
    }

    /**
     * This is called at the commit time for temporary tables with 
     * ON COMMIT DELETE ROWS
     *
     * If a temp table with ON COMMIT DELETE ROWS doesn't have any held cursor 
     * open on them, we delete the data from them by dropping the conglomerate 
     * and recreating the conglomerate. In order to store the new conglomerate
     * information for the temp table, we need to replace the existing table 
     * descriptor with the new table descriptor which has the new conglomerate
     * information
     *
     * @param tableName Temporary table name whose table descriptor is 
     *                  getting changed
     * @param td        New table descriptor for the temporary table
     */
    private void replaceDeclaredGlobalTempTable(
    String          tableName, 
    TableDescriptor td) 
    {
        TempTableInfo tempTableInfo = findDeclaredGlobalTempTable(tableName);
        
        tempTableInfo.setDroppedInSavepointLevel(-1);
        tempTableInfo.setDeclaredInSavepointLevel(-1);
        tempTableInfo.setTableDescriptor(td);

        allDeclaredGlobalTempTables.set(
            allDeclaredGlobalTempTables.indexOf(tempTableInfo), tempTableInfo);
    }

    /**
     * @see LanguageConnectionContext#getTableDescriptorForDeclaredGlobalTempTable
     */
    public TableDescriptor getTableDescriptorForDeclaredGlobalTempTable(String tableName) {
    TempTableInfo tempTableInfo = findDeclaredGlobalTempTable(tableName);
        if (tempTableInfo == null)
            return null;
        else
            return tempTableInfo.getTableDescriptor();
    }

    /**
     * Find the declared global temporary table in the list of temporary tables known by this connection.
     * @param tableName look for this table name in the saved list
     * @return data structure defining the temporary table if found. Else, return null 
     *
     */
    private TempTableInfo findDeclaredGlobalTempTable(String tableName) {
        if (allDeclaredGlobalTempTables == null)
            return null;

        for (int i = 0; i < allDeclaredGlobalTempTables.size(); i++) {
            if ((allDeclaredGlobalTempTables.get(i)).matches(tableName))
                return allDeclaredGlobalTempTables.get(i);
        }
        return null;
    }

    /**
     * @see LanguageConnectionContext#markTempTableAsModifiedInUnitOfWork
     */
    public void markTempTableAsModifiedInUnitOfWork(String tableName) {
    TempTableInfo tempTableInfo = findDeclaredGlobalTempTable(tableName);
    tempTableInfo.setModifiedInSavepointLevel(currentSavepointLevel);
    }

        /**
     * @see LanguageConnectionContext#prepareInternalStatement
     */
        public PreparedStatement prepareInternalStatement(SchemaDescriptor compilationSchema, String sqlText, boolean isForReadOnly, boolean forMetaData) 
        throws StandardException 
        {
            if (forMetaData) {
                //DERBY-2946
                //Make sure that metadata queries always run with SYS as 
                //compilation schema. This will make sure that the collation
                //type of character string constants will be UCS_BASIC which
                //is also the collation of character string columns belonging
                //to system tables. 
                compilationSchema = getDataDictionary().getSystemSchemaDescriptor(); 
            }
        return connFactory.getStatement(compilationSchema, sqlText, isForReadOnly).prepare(this, forMetaData);
        }

        /**
         * @see LanguageConnectionContext#prepareInternalStatement
         */
        public PreparedStatement prepareInternalStatement(String sqlText) 
        throws StandardException 
        {
            return connFactory.
                getStatement(getDefaultSchema(), sqlText, true).prepare(this);
        }      

    /**
     * Remove the activation to those known about by this connection.
     *
     */
    public void removeActivation(Activation a) 
    {
        if (SanityManager.DEBUG) {
            SanityManager.ASSERT(a.isClosed(), "Activation is not closed");
        }

        acts.remove(a);

        if (maxActsSize > 20 && (maxActsSize > 2 * acts.size())) {
            acts.trimToSize();
            maxActsSize = acts.size();
        }
    }

    /**
     * Return the number of activations known for this connection.
     * Note that some of these activations may not be in use
     * (when a prepared statement is finalized, its activations
     * are marked as unused and later closed and removed on
     * the next commit/rollback).
     */
    public int getActivationCount() {
        return acts.size();
    }

    /**
     * See if a given cursor is available for use.
     * if so return its activation. Returns null if not found.
     * For use in execution.
     *
     * @return the activation for the given cursor, null
     *  if none was found.
     */
    public CursorActivation lookupCursorActivation(String cursorName) {

        int size = acts.size();
        if (size > 0)
        {
            int cursorHash = cursorName.hashCode();

            for (int i = 0; i < size; i++) {
                 Activation a = acts.get(i);

                 if (!a.isInUse())
                 {
                    continue;
                 }



                String executingCursorName = a.getCursorName();

                // If the executing cursor has no name, or if the hash code of
                // its name is different from the one we're looking for, it
                // can't possibly match. Since java.lang.String caches the
                // hash code (at least in the most common implementations),
                // checking the hash code is cheaper than comparing the names
                // with java.lang.String.equals(), especially if there are many
                // open statements associated with the connection. See
                // DERBY-3882. Note that we can only use the hash codes to
                // determine that the names don't match. Even if the hash codes
                // are equal, we still need to call equals() to verify that the
                // two names actually are equal.
                if (executingCursorName == null ||
                        executingCursorName.hashCode() != cursorHash) {
                    continue;
                }

                 if (cursorName.equals(executingCursorName)) {

                    ResultSet rs = a.getResultSet();
                    if (rs == null)
                        continue;

                     // if the result set is closed, the the cursor doesn't exist
                     if (rs.isClosed()) {                   
                        continue;
                     }

                    return (CursorActivation)a;
                 }
            }
        }
        return null;
    }

    /**
    *  This method will remove a statement from the  statement cache.
    *  It should only be called if there is an exception preparing
    *  the statement. The caller must have set the flag
    *  {@code preparedStmt.compilingStatement} in the {@code GenericStatement}
    *  before calling this method in order to prevent race conditions when
    *  calling {@link CacheManager#remove(Cacheable)}.
    *
    *  @param statement Statement to remove
    *  @exception StandardException thrown if lookup goes wrong.
    */  
    public void removeStatement(GenericStatement statement)
        throws StandardException {
        
        CacheManager statementCache =
            getLanguageConnectionFactory().getStatementCache();

        if (statementCache == null)
            return;
 
        Cacheable cachedItem = statementCache.findCached(statement);
        // No need to do anything if the statement is already removed
        if (cachedItem != null) {
            CachedStatement cs = (CachedStatement) cachedItem;
            if (statement.getPreparedStatement() != cs.getPreparedStatement()) {
                // DERBY-3786: Someone else has removed the statement from
                // the cache, probably because of the same error that brought
                // us here. In addition, someone else has recreated the
                // statement. Since the recreated statement is not the same
                // object as the one we are working on, we don't have the
                // proper guarding (through the synchronized flag
                // GenericStatement.preparedStmt.compilingStatement) to ensure
                // that we're the only ones calling CacheManager.remove() on
                // this statement. Therefore, just release the statement here
                // so that we don't get in the way for the other thread that
                // is trying to compile the same query.
                statementCache.release(cachedItem);
            } else {
                // The statement object that we were trying to compile is still
                // in the cache. Since the compilation failed, remove it.
                statementCache.remove(cachedItem);
            }
        }
    }

    /**
     * See if a given statement has already been compiled for this user, and
     * if so use its prepared statement. Returns null if not found.
     *
     * @exception StandardException thrown if lookup goes wrong.
     * @return the prepared statement for the given string, null
     *  if none was found.
     */
    public PreparedStatement lookupStatement(GenericStatement statement)
        throws StandardException {

        CacheManager statementCache =
            getLanguageConnectionFactory().getStatementCache();
            
        if (statementCache == null)
            return null;

        // statement caching disable when in DDL mode
        if (dataDictionaryInWriteMode()) {
            return null;
        }

        Cacheable cachedItem = statementCache.find(statement);

        CachedStatement cs = (CachedStatement) cachedItem;


        GenericPreparedStatement ps = cs.getPreparedStatement();

        synchronized (ps) {
            if (ps.upToDate()) {
                GeneratedClass ac = ps.getActivationClass();

                // Check to see if the statement was prepared before some change
                // in the class loading set. If this is the case then force it to be invalid
                int currentClasses =
                        getLanguageConnectionFactory().getClassFactory().getClassLoaderVersion();

                if (ac.getClassLoaderVersion() != currentClasses) {
                    ps.makeInvalid(DependencyManager.INTERNAL_RECOMPILE_REQUEST, this);
                }

                // note that the PreparedStatement is not kept in the cache. This is because
                // having items kept in the cache that ultimately are held onto by
                // user code is impossible to manage. E.g. an open ResultSet would hold onto
                // a PreparedStatement (through its activation) and the user can allow
                // this object to be garbage collected. Pushing a context stack is impossible
                // in garbage collection as it may deadlock with the open connection and
                // the context manager assumes a singel current thread per context stack
            }
        }

        statementCache.release(cachedItem);
        return ps;
    }

    /**
        Get a connection unique system generated name for a cursor.
    */
    public String getUniqueCursorName() 
    {
        return getNameString("SQLCUR", nextCursorId++);
    }

    /**
        Get a connection unique system generated name for an unnamed savepoint.
    */
    public String getUniqueSavepointName()
    {
        return getNameString("SAVEPT", nextSavepointId++);
    }

    /**
        Get a connection unique system generated id for an unnamed savepoint.
    */
    public int getUniqueSavepointID()
    {
        return nextSavepointId-1;
    }

    /**
     * Build a String for a statement name.
     *
     * @param prefix    The prefix for the statement name.
     * @param number    The number to append for uniqueness
     *
     * @return  A unique String for a statement name.
     */
    private String getNameString(String prefix, long number)
    {
        if (sb != null)
        {
            sb.setLength(0);
        }
        else
        {
            sb = new StringBuffer();
        }
        sb.append(prefix).append(number);

        return sb.toString();
    }

    /**
     * Do a commit as appropriate for an internally generated
     * commit (e.g. as needed by sync, or autocommit).
     *
     * @param   commitStore true if we should commit the Store transaction
     *
     * @exception StandardException thrown on failure
     */
    public void internalCommit(boolean commitStore) throws StandardException
    {
        doCommit(commitStore, true, NON_XA, false);
    }

    /**
     * Do a commmit as is appropriate for a user requested
     * commit (e.g. a java.sql.Connection.commit() or a language
     * 'COMMIT' statement.  Does some extra checking to make
     * sure that users aren't doing anything bad.
     *
     * @exception StandardException thrown on failure
     */
    public void userCommit() throws StandardException
    {
        doCommit(true, true, NON_XA, true);
    }


    /**
        Commit the language transaction by doing a commitNoSync()
        on the store's TransactionController.

        <p>
        Do *NOT* tell the data dictionary that the transaction is
        finished. The reason is that this would allow other transactions
        to see comitted DDL that could be undone in the event of a
        system crash.

        @param  commitflag  the flags to pass to commitNoSync in the store's
                            TransactionController

        @exception StandardException thrown on failure
     */
    public final void internalCommitNoSync(int commitflag) 
        throws StandardException
    {
        doCommit(true, false, commitflag, false);
    }


    /**
        Same as userCommit except commit a distributed transaction.   
        This commit always commit store and sync the commit.

        @param onePhase if true, allow it to commit without first going thru a
        prepared state.

        @exception StandardException    thrown if something goes wrong
     */
    public final void xaCommit(boolean onePhase) throws StandardException
    {
        // further overload internalCommit to make it understand 2 phase commit
        doCommit(true /* commit store */,
                                  true /* sync */,
                                  onePhase ? XA_ONE_PHASE : XA_TWO_PHASE,
                                  true);
    }


    /**
     * This is where the work on internalCommit(), userCOmmit() and 
     * internalCommitNoSync() actually takes place.
     * <p>
     * When a commit happens, the language connection context
     * will close all open activations/cursors and commit the
     * Store transaction.
     * <p>
     * REVISIT: we talked about having a LanguageTransactionContext,
     * but since store transaction management is currently in flux
     * and our context might want to delegate to that context,
     * for now all commit/rollback actions are handled directly by
     * the language connection context.
     * REVISIT: this may need additional alterations when
     * RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINT show up.
     * <P>
     * Since the access manager's own context takes care of its own
     * resources on commit, and the transaction stays open, there is
     * nothing that this context has to do with the transaction controller.
     * <p>
     * Also, tell the data dictionary that the transaction is finished,
     * if necessary (that is, if the data dictionary was put into
     * DDL mode in this transaction.
     *
     *
     * @param   commitStore true if we should commit the Store transaction
     * @param   sync        true means do a synchronized commit,
     *                      false means do an unsynchronized commit
     * @param   commitflag  if this is an unsynchronized commit, the flags to
     *                      pass to commitNoSync in the store's
     *                      TransactionController.  If this is a synchronized
     *                      commit, this flag is overloaded for xacommit.
     * @param   requestedByUser    False iff the commit is for internal use and
     *                      we should ignore the check to prevent commits
     *                      in an atomic statement.
     *
     * @exception StandardException     Thrown on error
     */

    protected void doCommit(boolean commitStore,
                                               boolean sync,
                                               int commitflag,
                                               boolean requestedByUser)
         throws StandardException
    {
        StatementContext statementContext = getStatementContext();

        if (requestedByUser  &&
            (statementContext != null) &&
            statementContext.inUse() &&
            statementContext.isAtomic())
        {
            throw StandardException.newException(
                    SQLState.LANG_NO_COMMIT_IN_NESTED_CONNECTION);
        }

        checkIntegrity();

        // Log commit to error log, if appropriate
        if (logStatementText)
        {
            if (istream == null)
            {
                istream = Monitor.getStream();
            }
            String xactId = tran.getTransactionIdString();
            istream.printlnWithHeader(
                LanguageConnectionContext.xidStr + 
                xactId + 
                "), " +
                LanguageConnectionContext.lccStr +
                instanceNumber +
                "), " + LanguageConnectionContext.dbnameStr +
                dbname +
                "), " +
                LanguageConnectionContext.drdaStr +
                drdaID +
                "), Committing");
        }

        endTransactionActivationHandling(false);

        // Do clean up work required for temporary tables at commit time.  
        if (allDeclaredGlobalTempTables != null)
        {
            tempTablesAndCommit(commitflag != NON_XA);
        }

        //reset the current savepoint level for the connection to 0 at the end 
        //of commit work for temp tables
        currentSavepointLevel = 0; 

        // Do *NOT* tell the DataDictionary to start using its cache again
        // if this is an unsynchronized commit. The reason is that it
        // would allow other transactions to see this transaction's DDL,
        // which could be rolled back in case of a system crash.
        if (sync)
        {
            finishDDTransaction();
        }
        
        // Check that any nested transaction has been destoyed
        // before a commit.
        if (SanityManager.DEBUG)
        {
            if (readOnlyNestedTransaction != null)
            {
                SanityManager.THROWASSERT("Nested transaction active!");
            }
        }

        // now commit the Store transaction
        TransactionController tc = getTransactionExecute();
        if ( tc != null && commitStore ) 
        { 
            if (sync)
            {
                if (commitflag == NON_XA)
                {
                    // regular commit
                    tc.commit();
                }
                else
                {
                    // This may be a xa_commit, check overloaded commitflag.

                    if (SanityManager.DEBUG)
                        SanityManager.ASSERT(commitflag == XA_ONE_PHASE ||
                                             commitflag == XA_TWO_PHASE,
                                               "invalid commit flag");

                    ((XATransactionController)tc).xa_commit(
                            commitflag == XA_ONE_PHASE);

                }
            }
            else
            {
                tc.commitNoSync(commitflag);
            }

            // reset the savepoints to the new
            // location, since any outer nesting
            // levels expect there to be a savepoint
            resetSavepoints();

            // Do post commit XA temp table cleanup if necessary.
            if ((allDeclaredGlobalTempTables != null) &&
                (commitflag != NON_XA))
            {
                tempTablesXApostCommit();
            }
        }
    }

    /**
     * If dropAndRedeclare is true, that means we have come here for temp 
     * tables with on commit delete rows and no held curosr open on them. We 
     * will drop the existing conglomerate and redeclare a new conglomerate
     * similar to old conglomerate. This is a more efficient way of deleting 
     * all rows from the table.
     *
     * If dropAndRedeclare is false, that means we have come here for the 
     * rollback cleanup work. We are trying to restore old definition of the 
     * temp table (because the drop on it is being rolled back).
     */
    private TableDescriptor cleanupTempTableOnCommitOrRollback(
    TableDescriptor         td, 
    boolean                 dropAndRedeclare)
         throws StandardException
    {
        TransactionController tc = getTransactionExecute();

        //create new conglomerate with same properties as the old conglomerate 
        //and same row template as the old conglomerate
        long conglomId = 
            tc.createConglomerate(
                "heap", // we're requesting a heap conglomerate
                td.getEmptyExecRow().getRowArray(), // row template
                null, //column sort order - not required for heap
                td.getColumnCollationIds(),  // same ids as old conglomerate
                null, // properties
                (TransactionController.IS_TEMPORARY | 
                 TransactionController.IS_KEPT));

        long cid = td.getHeapConglomerateId();

        //remove the old conglomerate descriptor from the table descriptor
        ConglomerateDescriptor cgd = td.getConglomerateDescriptor(cid);
        td.getConglomerateDescriptorList().dropConglomerateDescriptorByUUID(
            cgd.getUUID());

        //add the new conglomerate descriptor to the table descriptor
        cgd = getDataDictionary().getDataDescriptorGenerator().newConglomerateDescriptor(conglomId, null, false, null, false, null, td.getUUID(),
        td.getSchemaDescriptor().getUUID());
        ConglomerateDescriptorList conglomList = 
            td.getConglomerateDescriptorList();
        conglomList.add(cgd);

        //reset the heap conglomerate number in table descriptor to -1 so it 
        //will be refetched next time with the new value
        td.resetHeapConglomNumber();

        if (dropAndRedeclare)
        {
            //remove the old conglomerate from the system
            tc.dropConglomerate(cid); 

            replaceDeclaredGlobalTempTable(td.getName(), td);
        }

        return(td);
    }

    /**
      Do a rollback as appropriate for an internally generated
      rollback (e.g. as needed by sync, or autocommit).
     
      When a rollback happens, we 
      close all open activations and invalidate their
      prepared statements.  We then tell the cache to
      age out everything else, which effectively invalidates
      them.  Thus, all prepared statements will be
      compiled anew on their 1st execution after
      a rollback.
      <p>
      The invalidated statements can revalidate themselves without
      a full recompile if they verify their dependencies' providers still
      exist unchanged. REVISIT when invalidation types are created.
      <p>
      REVISIT: this may need additional alterations when
      RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINT show up.
      <p>
      Also, tell the data dictionary that the transaction is finished,
      if necessary (that is, if the data dictionary was put into
      DDL mode in this transaction.

      @exception StandardException thrown on failure
     */

    public void internalRollback() throws StandardException 
    {
        doRollback(false /* non-xa */, false);
    }

    /**
     * Do a rollback as is appropriate for a user requested
     * rollback (e.g. a java.sql.Connection.rollback() or a language
     * 'ROLLBACk' statement.  Does some extra checking to make
     * sure that users aren't doing anything bad.
     *
     * @exception StandardException thrown on failure
     */
    public void userRollback() throws StandardException
    {
        doRollback(false /* non-xa */, true);
    }

    /**
        Same as userRollback() except rolls back a distrubuted transaction.

        @exception StandardException    thrown if something goes wrong
     */
    public void xaRollback() throws StandardException
    {
        doRollback(true /* xa */, true);
    }

    /**
     * When a rollback happens, the language connection context
     * will close all open activations and invalidate
     * their prepared statements. Then the language will abort the
     * Store transaction.
     * <p>
     * The invalidated statements can revalidate themselves without
     * a full recompile if they verify their dependencies' providers still
     * exist unchanged. REVISIT when invalidation types are created.
     * <p>
     * REVISIT: this may need additional alterations when
     * RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINT show up.
     * <p>
     * Also, tell the data dictionary that the transaction is finished,
     * if necessary (that is, if the data dictionary was put into
     * DDL mode in this transaction.
     *
     * @param xa    true if this is an xa rollback
     * @param requestedByUser   true if requested by user
     *
     * @exception StandardException thrown on failure
     */
    private void doRollback(boolean xa, boolean requestedByUser) throws StandardException
    {
        StatementContext statementContext = getStatementContext();
        if (requestedByUser &&
            (statementContext != null) &&
            statementContext.inUse() &&
            statementContext.isAtomic())
        {
            throw StandardException.newException(SQLState.LANG_NO_ROLLBACK_IN_NESTED_CONNECTION);
        }

        clearDeferreds();

        // Log rollback to error log, if appropriate
        if (logStatementText)
        {
            if (istream == null)
            {
                istream = Monitor.getStream();
            }
            String xactId = tran.getTransactionIdString();
            istream.printlnWithHeader(LanguageConnectionContext.xidStr +
                                      xactId + 
                                      "), " +
                                      LanguageConnectionContext.lccStr +
                                      instanceNumber +
                                      "), " + LanguageConnectionContext.dbnameStr +
                                          dbname +
                                          "), " +
                                          LanguageConnectionContext.drdaStr +
                                          drdaID +
                                      "), Rolling back");
        }

        endTransactionActivationHandling(true);

        currentSavepointLevel = 0; //reset the current savepoint level for the connection to 0 at the beginning of rollback work for temp tables
        if (allDeclaredGlobalTempTables != null)
            tempTablesAndRollback();

        finishDDTransaction();
        
        // If a nested transaction is active then
        // ensure it is destroyed before working
        // with the user transaction.
        if (readOnlyNestedTransaction != null)
        {
            readOnlyNestedTransaction.destroy();
            readOnlyNestedTransaction = null;
            queryNestingDepth = 0;
        }

        // now rollback the Store transaction
        TransactionController tc = getTransactionExecute();
        if (tc != null) 
        {   
            if (xa)
                ((XATransactionController)tc).xa_rollback();
            else
                tc.abort(); 
            
            // reset the savepoints to the new
            // location, since any outer nesting
            // levels expet there to be a savepoint
            resetSavepoints();
        }
    }

    /**
     * Reset all statement savepoints. Traverses the StatementContext
     * stack from bottom to top, calling resetSavePoint()
     * on each element.
     *
     * @exception StandardException thrown if something goes wrong
     */
    private void resetSavepoints() throws StandardException 
    {
        final ContextManager cm = getContextManager();
        final List<Context>
                stmts = cm.getContextStack(ContextId.LANG_STATEMENT);

        for (Context c : stmts) {
            ((StatementContext)c).resetSavePoint();
        }
    }

    /**
     * Let the context deal with a rollback to savepoint
     *
     * @param   savepointName   Name of the savepoint that needs to be rolled back
     * @param   refreshStyle    boolean indicating whether or not the controller should close
     * open conglomerates and scans. Also used to determine if language should close
     * open activations.
     * @param   kindOfSavepoint  A NULL value means it is an internal savepoint (ie not a user defined savepoint)
     * Non NULL value means it is a user defined savepoint which can be a SQL savepoint or a JDBC savepoint
     *   A String value for kindOfSavepoint would mean it is SQL savepoint
     *   A JDBC Savepoint object value for kindOfSavepoint would mean it is JDBC savepoint
     *
     * @exception StandardException thrown if something goes wrong
     */
    public void internalRollbackToSavepoint( String savepointName, boolean refreshStyle, Object kindOfSavepoint )
        throws StandardException
    {
        // now rollback the Store transaction to the savepoint
        TransactionController tc = getTransactionExecute();
        if (tc != null)
        {
            boolean     closeConglomerates;

            if ( refreshStyle ) 
            {
                closeConglomerates = true;
                // bug 5145 - don't forget to close the activations while rolling
                // back to a savepoint
                endTransactionActivationHandling(true);
            }
            else { closeConglomerates = false; }

            currentSavepointLevel = tc.rollbackToSavePoint( savepointName, closeConglomerates, kindOfSavepoint );
        }

        if (tc != null && refreshStyle && allDeclaredGlobalTempTables != null)
            tempTablesAndRollback();
    }

    /**
      Let the context deal with a release of a savepoint

      @param    savepointName   Name of the savepoint that needs to be released
      @param    kindOfSavepoint  A NULL value means it is an internal savepoint (ie not a user defined savepoint)
      Non NULL value means it is a user defined savepoint which can be a SQL savepoint or a JDBC savepoint
      A String value for kindOfSavepoint would mean it is SQL savepoint
      A JDBC Savepoint object value for kindOfSavepoint would mean it is JDBC savepoint

      @exception StandardException thrown if something goes wrong
     */
    public  void    releaseSavePoint( String savepointName, Object kindOfSavepoint )  throws StandardException
    {
        TransactionController tc = getTransactionExecute();
        if (tc != null)
        {
            currentSavepointLevel = tc.releaseSavePoint( savepointName, kindOfSavepoint );
            //after a release of a savepoint, we need to go through our temp tables list.
            if (allDeclaredGlobalTempTables != null)
                tempTablesReleaseSavepointLevels();
        }
    }

    /**
      Sets a savepoint. Causes the Store to set a savepoint.

      @param    savepointName   name of savepoint
      @param    kindOfSavepoint  A NULL value means it is an internal savepoint (ie not a user defined savepoint)
      Non NULL value means it is a user defined savepoint which can be a SQL savepoint or a JDBC savepoint
      A String value for kindOfSavepoint would mean it is SQL savepoint
      A JDBC Savepoint object value for kindOfSavepoint would mean it is JDBC savepoint

        @exception StandardException thrown if something goes wrong
      */
    public  void    languageSetSavePoint( String savepointName, Object kindOfSavepoint )  throws StandardException
    {
        TransactionController tc = getTransactionExecute();
        if (tc != null)
        {
            currentSavepointLevel = tc.setSavePoint( savepointName, kindOfSavepoint );
        }
    }

    /**
     * Start a Nested User Transaction (NUT) with the store. If a NUT is 
     * already active simply increment a counter, queryNestingDepth, to keep
     * track of how many times we have tried to start a NUT.
     */
    public void beginNestedTransaction(boolean readOnly) throws StandardException
    {
        // DERBY-2490 incremental rework, currently this is only called
        // with read-only true. Future changes will have this
        // method support read-write nested transactions as well
        // instead of callers using the startNestedUserTransaction
        // directly on tran.
        if (SanityManager.DEBUG)
        {
            // if called for update transactions, compile would start using
            // non-readonly xacts for compile.  For now, throw an error if
            // someone tries to use this call to make non readonly transaction.
            SanityManager.ASSERT(
                readOnly, 
                "Routine not yet coded to support non-readonly transactions.");
        }

        if (readOnlyNestedTransaction == null)
            readOnlyNestedTransaction = 
                tran.startNestedUserTransaction(readOnly, true);

        queryNestingDepth++;
    }

    public void commitNestedTransaction()
        throws StandardException
    {
        if (--queryNestingDepth == 0)
        {
            readOnlyNestedTransaction.commit();
            readOnlyNestedTransaction.destroy();
            readOnlyNestedTransaction = null;
        }
    }

    /**
     * Get the transaction controller to use at compile time with this language
     * connection context. If a NUT is active then return NUT else return parent
     * transaction.
     */
    public final TransactionController getTransactionCompile()
    {
        return (readOnlyNestedTransaction != null) ? readOnlyNestedTransaction : tran;
    }

    public TransactionController getTransactionExecute()
    {
        return tran;
    }

 /** Get the data value factory to use with this language connection
        context.
     */
    public DataValueFactory getDataValueFactory() {
        return dataFactory;
    }
    
    /**
        Get the language factory to use with this language connection
        context.
     */
    public LanguageFactory getLanguageFactory() {
        return langFactory;
    }
        
    public OptimizerFactory getOptimizerFactory() {
        return of;
    }

    /**
        Get the language connection factory to use with this language connection
        context.
     */
    public LanguageConnectionFactory getLanguageConnectionFactory() {
        return connFactory;
    }

    /**
     * check if there are any activations that reference this temporary table
     * @param tableName look for any activations referencing this table name
     * @return boolean  false if found no activations
     */
    private boolean checkIfAnyActivationHasHoldCursor(String tableName)
            throws StandardException
    {
        for (int i = acts.size() - 1; i >= 0; i--) {
            Activation a = acts.get(i);
            if (a.checkIfThisActivationHasHoldCursor(tableName))
                return true;
    }
    return false;
    }


    /**
     * Verify that there are no activations with open held result sets.
     *
     * @return boolean  Found no open (held) resultsets.
     *
     * @exception StandardException thrown on failure
     */
    /* This gets used in case of hold cursors. If there are any hold cursors open
     * then user can't change the isolation level without closing them. At the
     * execution time, set transaction isolation level calls this method before
     * changing the isolation level.
     */
    public boolean verifyAllHeldResultSetsAreClosed()
            throws StandardException
    {
        boolean seenOpenResultSets = false;

        /* For every activation */
        for (int i = acts.size() - 1; i >= 0; i--) {

            Activation a = acts.get(i);

            if (SanityManager.DEBUG)
            {
                SanityManager.ASSERT(a instanceof CursorActivation, "a is not a CursorActivation");
            }

            if (!a.isInUse())
            {
                continue;
            }

            if (!a.getResultSetHoldability())
            {
                continue;
            }

            ResultSet rs = ((CursorActivation) a).getResultSet();

            /* is there an open result set? */
            if ((rs != null) && !rs.isClosed() && rs.returnsRows())
            {
                seenOpenResultSets = true;
                break;
            }
        }

        if (!seenOpenResultSets)
            return(true);

        // There may be open ResultSet's that are yet to be garbage collected
        // let's try and force these out rather than throw an error
        System.gc();
        System.runFinalization();


        /* For every activation */
        for (int i = acts.size() - 1; i >= 0; i--) {
                
            Activation a = acts.get(i);

            if (SanityManager.DEBUG)
            {
                SanityManager.ASSERT(a instanceof CursorActivation, "a is not a CursorActivation");
            }

            if (!a.isInUse())
            {
                continue;
            }

            if (!a.getResultSetHoldability())
            {
                continue;
            }

            ResultSet rs = ((CursorActivation) a).getResultSet();

            /* is there an open held result set? */
            if ((rs != null) && !rs.isClosed() && rs.returnsRows())
            {
                return(false);
            }
        }
        return(true);
    }

    /**
     * Verify that there are no activations with open result sets
     * on the specified prepared statement.
     *
     * @param pStmt     The prepared Statement
     * @param provider  The object precipitating a possible invalidation
     * @param action    The action causing the possible invalidation
     *
     * @return Nothing.
     *
     * @exception StandardException thrown on failure
     */
    public boolean verifyNoOpenResultSets(PreparedStatement pStmt, Provider provider,
                                       int action)
            throws StandardException
    {
        /*
        ** It is not a problem to create an index when there is an open
        ** result set, since it doesn't invalidate the access path that was
        ** chosen for the result set.
        */
        boolean seenOpenResultSets = false;

        /* For every activation */

        // synchronize on acts as other threads may be closing activations
        // in this list, thus invalidating the Enumeration
        for (int i = acts.size() - 1; i >= 0; i--) {
                
            Activation a = acts.get(i);

            if (!a.isInUse())
            {
                continue;
            }
            
            /* for this prepared statement */
            if (pStmt == a.getPreparedStatement()) {
                ResultSet rs = a.getResultSet();

                /* is there an open result set? */
                if (rs != null && ! rs.isClosed())
                {
                    if (!rs.returnsRows())
                        continue;
                    seenOpenResultSets = true;
                    break;
                }
                
            }
        }

        if (!seenOpenResultSets)
            return false;

        // There may be open ResultSet's that are yet to be garbage collected
        // let's try and force these out rather than throw an error
        System.gc();
        System.runFinalization();


        /* For every activation */
        // synchronize on acts as other threads may be closing activations
        // in this list, thus invalidating the Enumeration
        for (int i = acts.size() - 1; i >= 0; i--) {
                
            Activation a = acts.get(i);

            if (!a.isInUse())
            {
                continue;
            }

            /* for this prepared statement */
            if (pStmt == a.getPreparedStatement()) {
                ResultSet rs = a.getResultSet();

                /* is there an open result set? */
                if (rs != null && ! rs.isClosed())
                {
                    if ((provider != null) && rs.returnsRows()) {
                    DependencyManager dmgr = getDataDictionary().getDependencyManager();

                    throw StandardException.newException(SQLState.LANG_CANT_INVALIDATE_OPEN_RESULT_SET, 
                                    dmgr.getActionString(action), 
                                    provider.getObjectName());

                    }
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Get the session user
     *
     * @return String the authorization id of the session user.
     */
    public String getSessionUserId()
    {
        return sessionUser;
    }

    /**
     * @see LanguageConnectionContext#getDefaultSchema
     */
    public SchemaDescriptor getDefaultSchema() 
    { 
        return getCurrentSQLSessionContext().getDefaultSchema();
    }

    /**
     * @see LanguageConnectionContext#getDefaultSchema(Activation a)
     */
    public SchemaDescriptor getDefaultSchema(Activation a) {
        return getCurrentSQLSessionContext(a).getDefaultSchema();
    }

    /**
     * @see LanguageConnectionContext#getCurrentSchemaName()
     */
    public String getCurrentSchemaName()
    {
        // getCurrentSchemaName with no arg is used even
        // at run-time but only in places(*) where the statement context
        // can be relied on, AFAICT.
        //
        // (*) SpaceTable#getConglomInfo,
        //     SystemProcedures#{INSTALL|REPLACE|REMOVE}_JAR

        SchemaDescriptor s = getDefaultSchema();
        if( null == s)
            return null;
        return s.getSchemaName();
    }


    /**
     * @see LanguageConnectionContext#getCurrentSchemaName(Activation a)
     */
    public String getCurrentSchemaName(Activation a)
    {
        SchemaDescriptor s = getDefaultSchema(a);
        if( null == s)
            return null;
        return s.getSchemaName();
    }


    /**
     * @see LanguageConnectionContext#isInitialDefaultSchema
     */
    public boolean isInitialDefaultSchema(String schemaName) {
        return cachedInitialDefaultSchemaDescr.getSchemaName().
            equals(schemaName);
    }


    /**
     * @see LanguageConnectionContext#setDefaultSchema(SchemaDescriptor sd)
     */
    public void setDefaultSchema(SchemaDescriptor sd)
        throws StandardException
    {   
        if (sd == null) {   
            sd = getInitialDefaultSchemaDescriptor();
        }

        getCurrentSQLSessionContext().setDefaultSchema(sd);
    }

    /**
     * @see LanguageConnectionContext#setDefaultSchema(Activation a,
     * SchemaDescriptor sd)
     */
    public void setDefaultSchema(Activation a, SchemaDescriptor sd)
        throws StandardException
    {
        if (sd == null) {
            sd = getInitialDefaultSchemaDescriptor();
        }

        getCurrentSQLSessionContext(a).setDefaultSchema(sd);
    }


    /**
     * @see LanguageConnectionContext#resetSchemaUsages(Activation activation,
     *      String schemaName)
     */
    public void resetSchemaUsages(Activation activation, String schemaName)
            throws StandardException {

        Activation parent = activation.getParentActivation();
        SchemaDescriptor defaultSchema = getInitialDefaultSchemaDescriptor();

        // walk SQL session context chain
        while (parent != null) {
            SQLSessionContext ssc = parent.getSQLSessionContextForChildren();
            SchemaDescriptor s = ssc.getDefaultSchema();

            if (SanityManager.DEBUG) {
                SanityManager.ASSERT(s != null, "s should not be empty here");
            }

            if (schemaName.equals(s.getSchemaName())) {
                ssc.setDefaultSchema(defaultSchema);
            }
            parent = parent.getParentActivation();
        }

        // finally top level
        SQLSessionContext top = getTopLevelSQLSessionContext();
        SchemaDescriptor sd = top.getDefaultSchema();

        if (SanityManager.DEBUG) {
            SanityManager.ASSERT(sd != null, "sd should not be empty here");
        }

        if (schemaName.equals(sd.getSchemaName())) {
            top.setDefaultSchema(defaultSchema);
        }
    }

    /**
     * Get the identity column value most recently generated.
     *
     * @return the generated identity column value
     */
    public Long getIdentityValue()
    {
        return identityNotNull ? Long.valueOf(identityVal) : null;
    }

    /**
     * Set the field of most recently generated identity column value.
     *
     * @param val the generated identity column value
     */
    public void setIdentityValue(long val)
    {
        identityVal = val;
        identityNotNull = true;
    }

    /**
     * Push a CompilerContext on the context stack with
     * the current default schema as the default schema
     * which we compile against.
     *
     * @return the compiler context
     */
    public  final CompilerContext pushCompilerContext()
    {
        return pushCompilerContext((SchemaDescriptor)null);
    }

    /**
     * Push a CompilerContext on the context stack with
     * the passed in schema sd as the default schema
     * we compile against.
     *
     * @param sd the default schema 
     *
     * @return the compiler context
     *
     * For the parameter sd, there are 3 possible values(of interest) that can 
     * get passed into this method:
     * 
     * a) A null SchemaDescriptor which indicates to the system to use the 
     *    CURRENT SCHEMA as the compilation schema.
     *    
     * b) A SchemaDescriptor with its UUID == null, this indicates that either 
     *    the schema has not been physically created yet or that the LCC's 
     *    getDefaultSchema() is not yet up-to-date with its actual UUID. 
     *    The system will use the CURRENT SCHEMA as the compilation schema. 
     *    
     * c) A SchemaDescriptor with its UUID != null, this means that the schema 
     *    has been physically created.  The system will use this schema as the 
     *    compilation schema (e.g.: for trigger or view recompilation cases, 
     *    etc.). 
     *    
     * The compiler context's compilation schema will be set accordingly based 
     * on the given input above.   
     */
    public  CompilerContext pushCompilerContext(SchemaDescriptor sd)
    {
        CompilerContext cc;
        boolean         firstCompilerContext = false;

        //  DEBUG   END

        cc = (CompilerContext) (getContextManager().getContext(CompilerContext.CONTEXT_ID));

        /*
        ** If there is no compiler context, this is the first one on the
        ** stack, so don't pop it when we're done (saves time).
        */
        if (cc == null) { firstCompilerContext = true; }

        if (cc == null || cc.getInUse())
        {
            cc = new CompilerContextImpl(getContextManager(), this, tcf);
            if (firstCompilerContext) { cc.firstOnStack(); }
        }
        else
        {
            /* Reset the next column,table, subquery and ResultSet numbers at 
            * the beginning of each statement 
            */
            cc.resetContext();
        }

        cc.setInUse(true);

        StatementContext sc = getStatementContext();
        if (sc.getSystemCode())
            cc.setReliability(CompilerContext.INTERNAL_SQL_LEGAL);

        /*
         * Set the compilation schema when its UUID is available.
         * i.e.:  Schema may not have been physically created yet, so
         *        its UUID will be null.
         * 
         * o For trigger SPS recompilation, the system must use its
         *   compilation schema to recompile the statement. 
         * 
         * o For view recompilation, we set the compilation schema
         *   for this compiler context if its UUID is available.
         *   Otherwise, the compilation schema will be determined
         *   at execution time of view creation.
         */
        if (sd != null && sd.getUUID() != null)
        {
            cc.setCompilationSchema(sd);
        }
        
        return  cc;
    }


    /**
     * Pop a CompilerContext off the context stack.
     *
     * @param cc  The compiler context.
     */
    public void popCompilerContext(CompilerContext cc)
    {
        cc.setCurrentDependent(null);

        cc.setInUse(false);

        /*
        ** Only pop the compiler context if it's not the first one
        ** on the stack.
        */
        if (! cc.isFirstOnStack()) 
        { 
            cc.popMe(); 
        }
        else
        {
            cc.setCompilationSchema((SchemaDescriptor)null);
        }
    }

    /**
     * Push a StatementContext on the context stack.
     *
     * Inherit SQL session state a priori (statementContext will get
     * its own SQL session state if this statement executes a call,
     * cf. pushNestedSessionContext.

     * @param isAtomic whether this statement is atomic or not
     * @param isForReadOnly whether this statement is for a read only resultset
     * @param stmtText the text of the statement.  Needed for any language
     *  statement (currently, for any statement that can cause a trigger
     *  to fire).  Please set this unless you are some funky jdbc setXXX
     *  method or something.
     * @param pvs parameter value set, if it has one
     * @param rollbackParentContext True if 1) the statement context is
     *  NOT a top-level context, AND 2) in the event of a statement-level
     *  exception, the parent context needs to be rolled back, too.
     * @param timeoutMillis timeout value for this statement, in milliseconds.
     *  The value 0 means that no timeout is set.
     *
     * @return StatementContext  The statement context.
     *
     */
    public StatementContext pushStatementContext (boolean isAtomic, boolean isForReadOnly, 
                              String stmtText, ParameterValueSet pvs, 
                              boolean rollbackParentContext, 
                              long timeoutMillis)
    {
        int                 parentStatementDepth = statementDepth;
        boolean             inTrigger = false;
        boolean             parentIsAtomic = false;

        // by default, assume we are going to use the outermost statement context
        StatementContext    statementContext = statementContexts[0];

        /*
        ** If we haven't allocated any statement contexts yet, allocate
        ** the outermost stmt context now and push it.
        */

        if (statementContext == null)
        {
            statementContext = statementContexts[0] = new GenericStatementContext(this);
            statementContext.
                setSQLSessionContext(getTopLevelSQLSessionContext());
        }
        else if (statementDepth > 0)
        {
            StatementContext    parentStatementContext;
            /*
            ** We also cache a 2nd statement context, though we still
            ** push and pop it. Note, new contexts are automatically pushed.
            */
            if (statementDepth == 1)
            {
                statementContext = statementContexts[1];

                if (statementContext == null)
                    statementContext = statementContexts[1] = new GenericStatementContext(this);
                else
                    statementContext.pushMe();

                parentStatementContext = statementContexts[0];
            }
            else
            {
                parentStatementContext = getStatementContext();
                statementContext = new GenericStatementContext(this);
            }

            statementContext.setSQLSessionContext(
                parentStatementContext.getSQLSessionContext());

            inTrigger = parentStatementContext.inTrigger() || (outermostTrigger == parentStatementDepth);
            parentIsAtomic = parentStatementContext.isAtomic();
            statementContext.setSQLAllowed(parentStatementContext.getSQLAllowed(), false);
            if (parentStatementContext.getSystemCode())
                statementContext.setSystemCode();
        } else {
            statementContext.
                setSQLSessionContext(getTopLevelSQLSessionContext());
        }

        incrementStatementDepth();

        statementContext.setInUse(inTrigger, isAtomic || parentIsAtomic, isForReadOnly, stmtText, pvs, timeoutMillis);
        if (rollbackParentContext)
            statementContext.setParentRollback();
        return statementContext;
    }

    /**
     * Pop a StatementContext of the context stack.
     *
     * @param statementContext  The statement context.
     * @param error             The error, if any  (Only relevant for DEBUG)
     */
    public void popStatementContext(StatementContext statementContext,
                                    Throwable error) 
    {
        if ( statementContext != null ) 
        { 
            /*
            ** If someone beat us to the punch, then it is ok,
            ** just silently ignore it.  We probably got here
            ** because we had a try catch block around a push/pop
            ** statement context, and we already got the context
            ** on a cleanupOnError.
            */
            if (!statementContext.inUse())
            {
                return;
            }
            statementContext.clearInUse(); 
        }

        decrementStatementDepth();
        if (statementDepth == -1)
        {
            /*
             * Only ignore the pop request for an already
             * empty stack when dealing with a session exception.
             */
            if (SanityManager.DEBUG)
            {
                int severity = (error instanceof StandardException) ?
                                    ((StandardException)error).getSeverity() :
                                0;
                SanityManager.ASSERT(error != null,
                    "Must have error to try popStatementContext with 0 depth");
                SanityManager.ASSERT(
                    (severity == ExceptionSeverity.SESSION_SEVERITY),
                    "Must have session severity error to try popStatementContext with 0 depth");
                SanityManager.ASSERT(statementContext == statementContexts[0],
                    "statementContext is expected to equal statementContexts[0]");
            }
            resetStatementDepth(); // pretend we did nothing.
        }
        else if (statementDepth == 0)
        {
            if (SanityManager.DEBUG)
            {
                /* Okay to pop last context on a session exception.
                 * (We call clean up on error when exiting connection.)
                 */
                int severity = (error instanceof StandardException) ?
                                    ((StandardException)error).getSeverity() :
                                0;
                if ((error == null) || 
                    (severity != ExceptionSeverity.SESSION_SEVERITY))
                {
                    SanityManager.ASSERT(statementContext == statementContexts[0],
                        "statementContext is expected to equal statementContexts[0]");
                }
            }
        }
        else
        {
            if (SanityManager.DEBUG)
            {
                SanityManager.ASSERT(statementContext != statementContexts[0],
                    "statementContext is not expected to equal statementContexts[0]");
                if (statementDepth <= 0)
                    SanityManager.THROWASSERT(
                        "statement depth expected to be >0, was "+statementDepth);
                
                if (getContextManager().getContext(statementContext.getIdName()) != statementContext)
                {
                    SanityManager.THROWASSERT("trying to pop statement context from middle of stack");
                }
            }

            statementContext.popMe();       
        }

    }

    /**
     * Push a new execution statement validator.  An execution statement 
     * validator is an object that validates the current statement to
     * ensure that it is permitted given the current execution context.
     * An example of a validator a trigger ExecutionStmtValidator that
     * doesn't allow ddl on the trigger target table.
     * <p>
     * Multiple ExecutionStmtValidators may be active at any given time.
     * This mirrors the way there can be multiple connection nestings
     * at a single time.  The validation is performed by calling each
     * validator's validateStatement() method.  This yields the union
     * of all validations.
     *
     * @param validator the validator to add
     */
    public void pushExecutionStmtValidator(ExecutionStmtValidator validator)
    {
        stmtValidators.add(validator);
    }

    /**
     * Remove the validator.  Does an object identity (validator == validator)
     * comparison.  Asserts that the validator is found.
     *
     * @param validator the validator to remove
     *
     * @exception StandardException on error
     */
    public void popExecutionStmtValidator(ExecutionStmtValidator validator)
        throws StandardException
    {
        boolean foundElement = stmtValidators.remove(validator);
        if (SanityManager.DEBUG)
        {
            if (!foundElement)
            {
                SanityManager.THROWASSERT("statement validator "+validator+" not found");
            }
        }
    }

    /**
     * Push a new trigger execution context.
     * <p>
     * Multiple TriggerExecutionContexts may be active at any given time.
     *
     * @param tec the trigger execution context
     *
     * @exception StandardException on trigger recursion error
     */
    public void pushTriggerExecutionContext(TriggerExecutionContext tec) throws StandardException
    {
        if (outermostTrigger == -1) 
        {
            outermostTrigger = statementDepth; 
        }

        /* Maximum 16 nesting levels allowed */
        if (triggerExecutionContexts.size() >= Limits.DB2_MAX_TRIGGER_RECURSION)
        {
            throw StandardException.newException(SQLState.LANG_TRIGGER_RECURSION_EXCEEDED);
        }

        triggerExecutionContexts.add(tec);
    }

    /**
     * Remove the tec.  Does an object identity (tec == tec)
     * comparison.  Asserts that the tec is found.
     *
     * @param tec the tec to remove
     *
     * @exception StandardException on error
     */
    public void popTriggerExecutionContext(TriggerExecutionContext tec)
        throws StandardException
    {
        if (outermostTrigger == statementDepth)
        {
            outermostTrigger = -1; 
        }

        boolean foundElement = triggerExecutionContexts.remove(tec);
        if (SanityManager.DEBUG)
        {
            if (!foundElement)
            {
                SanityManager.THROWASSERT("trigger execution context "+tec+" not found");
            }
        }
    }

    /**
     * Get the topmost tec.  
     *
     * @return the tec
     */
    public TriggerExecutionContext getTriggerExecutionContext()
    {
        return triggerExecutionContexts.isEmpty() ?
                null :
                triggerExecutionContexts.get( triggerExecutionContexts.size() - 1 );   
    }

    /**
     * Validate a statement.  Does so by stepping through all the validators
     * and executing them.  If a validator throws and exception, then the
     * checking is stopped and the exception is passed up.
     *
     * @param constantAction the constantAction that is about to be executed (and
     *  should be validated
     *
     * @exception StandardException on validation failure
     */
    public void validateStmtExecution(ConstantAction constantAction)
        throws StandardException
    {
        if (SanityManager.DEBUG)
        {
            SanityManager.ASSERT(constantAction!=null, "constantAction is null");
        }

        if (stmtValidators.size() > 0)
        {
            for (Iterator<ExecutionStmtValidator> it = stmtValidators.iterator(); it.hasNext(); )
            {
                it.next()
                    .validateStatement(constantAction);
            }
        }
    }
    
    /**
     * Set the trigger table descriptor.  Used to compile
     * statements that may special trigger pseudo tables.
     *
     * @param td the table that the trigger is 
     * defined upon
     *
     */
    public void pushTriggerTable(TableDescriptor td)
    {
        triggerTables.add(td);
    }

    /**
     * Remove the trigger table descriptor.
     *
     * @param td the table to remove from the stack.
     */
    public void popTriggerTable(TableDescriptor td)
    {
        boolean foundElement = triggerTables.remove(td);
        if (SanityManager.DEBUG)
        {
            if (!foundElement)
            {
                SanityManager.THROWASSERT("trigger table not found: "+td);
            }
        }
    }

    /**
     * Get the topmost trigger table descriptor
     *
     * @return the table descriptor, or null if we
     * aren't in the middle of compiling a create
     * trigger.
     */
    public TableDescriptor getTriggerTable()
    {
        return triggerTables.isEmpty() ?
            (TableDescriptor)null :
            triggerTables.get(triggerTables.size() - 1);
    }
    /**
     * @see LanguageConnectionContext#getDatabase
     */
    public Database
    getDatabase()
    {
        return db;
    }

    /** @see LanguageConnectionContext#incrementBindCount */
    public int incrementBindCount()
    {
        bindCount++;
        return bindCount;
    }

    
    /** @see LanguageConnectionContext#decrementBindCount */
    public int decrementBindCount()
    {
        bindCount--;

        if (SanityManager.DEBUG)
        {
            if (bindCount < 0)
                SanityManager.THROWASSERT(
                    "Level of nested binding == " + bindCount);
        }

        return bindCount;
    }

    /** @see LanguageConnectionContext#getBindCount */
    public int getBindCount()
    {
        return bindCount;
    }

    /** @see LanguageConnectionContext#setDataDictionaryWriteMode */
    public final void setDataDictionaryWriteMode()
    {
        ddWriteMode = true;
    }

    /** @see LanguageConnectionContext#dataDictionaryInWriteMode */
    public final boolean dataDictionaryInWriteMode()
    {
        return ddWriteMode;
    }

    /** @see LanguageConnectionContext#setRunTimeStatisticsMode */
    public final void setRunTimeStatisticsMode(boolean onOrOff)
    {
        runTimeStatisticsSetting = onOrOff;
    }

    /** @see LanguageConnectionContext#getRunTimeStatisticsMode */
    public boolean getRunTimeStatisticsMode()
    {
        return runTimeStatisticsSetting;
    }

    /** @see LanguageConnectionContext#setStatisticsTiming */
    public void setStatisticsTiming(boolean onOrOff)
    {
        statisticsTiming = onOrOff;
    }

    /** @see LanguageConnectionContext#getStatisticsTiming */
    public boolean getStatisticsTiming()
    {
        return statisticsTiming;
    }

    /** @see LanguageConnectionContext#setRunTimeStatisticsObject */
    public void setRunTimeStatisticsObject(RunTimeStatistics runTimeStatisticsObject)
    {
        this.runTimeStatisticsObject = runTimeStatisticsObject;
    }

    /** @see LanguageConnectionContext#getRunTimeStatisticsObject */
    public RunTimeStatistics getRunTimeStatisticsObject()
    {
        return runTimeStatisticsObject;
    }


    /**
      * Reports how many statement levels deep we are.
      *
      * @return a statement level >= OUTERMOST_STATEMENT
      */
    public  int     getStatementDepth()
    { return statementDepth; }

    /**
     * @see LanguageConnectionContext#isIsolationLevelSetUsingSQLorJDBC
     */
    public boolean isIsolationLevelSetUsingSQLorJDBC()
    {
        return isolationLevelSetUsingSQLorJDBC;
    }

    /**
     * @see LanguageConnectionContext#resetIsolationLevelFlagUsedForSQLandJDBC
     */
    public void resetIsolationLevelFlagUsedForSQLandJDBC()
    {
        isolationLevelSetUsingSQLorJDBC = false;
    }

    /**
     * @see LanguageConnectionContext#setIsolationLevel
     */
    public void setIsolationLevel(int isolationLevel) throws StandardException
    {
        StatementContext stmtCtxt = getStatementContext();
        if (stmtCtxt!= null && stmtCtxt.inTrigger())
            throw StandardException.newException(SQLState.LANG_NO_XACT_IN_TRIGGER, getTriggerExecutionContext().toString());

        // find if there are any held cursors from previous isolation level.
        // if yes, then throw an exception that isolation change not allowed until
        // the held cursors are closed.
        // I had to move this check outside of transaction idle check because if a
        // transactions creates held cursors and commits the transaction, then
        // there still would be held cursors but the transaction state would be idle.
        // In order to check the above mentioned case, the held cursor check
        // shouldn't rely on transaction state.
        if (this.isolationLevel != isolationLevel)
        {
            if (!verifyAllHeldResultSetsAreClosed())
            {
                throw StandardException.newException(SQLState.LANG_CANT_CHANGE_ISOLATION_HOLD_CURSOR);
            }
        }

        /* Commit and set to new isolation level.
         * NOTE: We commit first in case there's some kind
         * of error, like can't commit within a server side jdbc call.
         */
        TransactionController tc = getTransactionExecute();
        if (!tc.isIdle())
        {
            // If this transaction is in progress, commit it.
            // However, do not allow commit to happen if this is a global
            // transaction.
            if (tc.isGlobal())
                throw StandardException.newException(SQLState.LANG_NO_SET_TRAN_ISO_IN_GLOBAL_CONNECTION);

            userCommit();
        }
        this.isolationLevel = isolationLevel;
        this.isolationLevelExplicitlySet = true;
        this.isolationLevelSetUsingSQLorJDBC = true;
    }

    /**
     * @see LanguageConnectionContext#getCurrentIsolationLevel
     */
    public int getCurrentIsolationLevel()
    {
        return (isolationLevel == TransactionControl.UNSPECIFIED_ISOLATION_LEVEL) ? defaultIsolationLevel : isolationLevel;
    }

    /**
     * @see LanguageConnectionContext#getCurrentIsolationLevel
     */
    public String getCurrentIsolationLevelStr()
    {
        if( isolationLevel >= 0 && isolationLevel < TransactionControl.isolationMapCount() )
        {
            return TransactionControl.isolationTextNames( isolationLevel )[0];
        }
        return TransactionControl.isolationTextNames( TransactionControl.UNSPECIFIED_ISOLATION_LEVEL )[0];
    }

    /**
     * @see LanguageConnectionContext#setPrepareIsolationLevel
     */
    public void setPrepareIsolationLevel(int level) 
    {
            prepareIsolationLevel = level;
    }

    /**
     * @see LanguageConnectionContext#getPrepareIsolationLevel
     */
    public int getPrepareIsolationLevel()
    {
        if (!isolationLevelExplicitlySet)
            return prepareIsolationLevel;
        else
            return TransactionControl.UNSPECIFIED_ISOLATION_LEVEL;
    }

    /**
     * @see LanguageConnectionContext#getStatementContext
     */
    public StatementContext getStatementContext()
    {   
        return (StatementContext) getContextManager().getContext(org.apache.derby.iapi.reference.ContextId.LANG_STATEMENT);
    }

    /**
     * @see LanguageConnectionContext#setOptimizerTracer
     */
    public void setOptimizerTracer( OptTrace tracer )
    {
        optimizerTracer = tracer;
    }

    /**
     * @see LanguageConnectionContext#getOptimizerTracer
     */
	public OptTrace getOptimizerTracer() { return optimizerTracer; }
    
    /**
     * @see LanguageConnectionContext#optimizerTracingIsOn
     */
    public boolean optimizerTracingIsOn()
    {
        return (optimizerTracer != null);
    }

    /**
      * Reports whether there is any outstanding work in the transaction.
      *
      * @return true if there is outstanding work in the transaction
      *             false otherwise
      */
    public  boolean isTransactionPristine()
    {
        return getTransactionExecute().isPristine();
    }


    //
    // Context interface
    //
    /**
        If worse than a transaction error, everything goes; we
        rely on other contexts to kill the context manager
        for this session.
        <p>
        If a transaction error, act like we saw a rollback.
        <p>
        If more severe or a java error, the outer cleanup
        will shutdown the connection, so we don't have to clean up.
        <p>
        REMIND: connection should throw out all contexts and start
        over when the connection is closed... perhaps by throwing
        out the context manager?
        <p>
        REVISIT: If statement error, should we do anything?
        <P>
        Since the access manager's own context takes care of its own
        resources on errors, there is nothing that this context has
        to do with the transaction controller.

        @exception StandardException thrown on error. REVISIT: don't want
        cleanupOnError's to throw exceptions.
     */
    public void cleanupOnError(Throwable error) throws StandardException {

        /*
        ** If it isn't a StandardException, then assume
        ** session severity. It is probably an unexpected
        ** java error somewhere in the language.
        ** Store layer treats JVM error as session severity, 
        ** hence to be consistent and to avoid getting rawstore
        ** protocol violation errors, we treat java errors here
        ** to be of session severity.
        */  

        int severity = (error instanceof StandardException) ?
            ((StandardException) error).getSeverity() :
            ExceptionSeverity.SESSION_SEVERITY;
 
        if (statementContexts[0] != null)
        {
            statementContexts[0].clearInUse();
            
            // Force the StatementContext that's normally
            // left on the stack for optimization to be popped
            // when the session is closed. Ensures full cleanup
            // and no hanging refrences in the ContextManager.
            if (severity >= ExceptionSeverity.SESSION_SEVERITY)
                statementContexts[0].popMe();
        }
        if (statementContexts[1] != null)
        {
            statementContexts[1].clearInUse();                
        }

        // closing the activations closes all the open cursors.
        // the activations are, for all intents and purposes, the
        // cursors.
        if (severity >= ExceptionSeverity.SESSION_SEVERITY) 
        {
            for (int i = acts.size() - 1; i >= 0; i--) {
                // it maybe the case that a reset()/close() ends up closing
                // one or more activation leaving our index beyond
                // the end of the array
                if (i >= acts.size())
                    continue;
                Activation a = acts.get(i);
                a.reset();
                a.close();
            }
                       
            popMe();

            InterruptStatus.saveInfoFromLcc(this);
        }

        /*
        ** We have some global state that we need
        ** to clean up no matter what.  Be sure
        ** to do so.
        */
        else if (severity >= ExceptionSeverity.TRANSACTION_SEVERITY) 
        {
            internalRollback();
        }
    }

    /**
     * @see org.apache.derby.iapi.services.context.Context#isLastHandler
     */
    @Override
    public boolean isLastHandler(int severity)
    {
        return false;
    }

    //
    // class implementation
    //

    /**
        If we are called as part of rollback code path, then we will reset all 
        the activations that have resultset returning rows associated with 
        them. DERBY-3304 Resultsets that do not return rows should be left 
        alone when the rollback is through the JDBC Connection object. If the 
        rollback is caused by an exception, then at that time, all kinds of
        resultsets should be closed. 
        
        If we are called as part of commit code path, then we will do one of 
        the following if the activation has resultset assoicated with it. Also,
        we will clear the conglomerate used while scanning for update/delete
        1)Close result sets that return rows and are not held across commit.
        2)Clear the current row of the resultsets that return rows and are
        held across commit.
        3)Leave the result sets untouched if they do not return rows
        
        Additionally, clean up (close()) activations that have been
        marked as unused during statement finalization.

        @exception StandardException thrown on failure
     */
    private void endTransactionActivationHandling(boolean forRollback) throws StandardException {

        // don't use an enumeration as the activation may remove
        // itself from the list, thus invalidating the Enumeration
        for (int i = acts.size() - 1; i >= 0; i--) {

            // it maybe the case that a reset() ends up closing
            // one or more activation leaving our index beyond
            // the end of the array
            if (i >= acts.size())
                continue;

            Activation a = acts.get(i);
            /*
            ** Look for stale activations.  Activations are
            ** marked as unused during statement finalization.
            ** Here, we sweep and remove this inactive ones.
            */  
            if (!a.isInUse())
            {
                a.close();
                continue;
            }

            //Determine if the activation has a resultset and if that resultset
            //returns rows. For such an activation, we need to take special
            //actions during commit and rollback as explained in the comments
            //below.
            ResultSet activationResultSet = a.getResultSet();
            boolean resultsetReturnsRows =
                    activationResultSet != null &&
                    activationResultSet.returnsRows();

            if (forRollback) { 
                if (resultsetReturnsRows)
                    //Since we are dealing with rollback, we need to reset 
                    //the activation no matter what the holdability might 
                    //be provided that resultset returns rows. An example
                    //where we do not want to close a resultset that does
                    //not return rows would be a java procedure which has
                    //user invoked rollback inside of it. That rollback
                    //should not reset the activation associated with
                    //the call to java procedure because that activation
                    //is still being used.
                    a.reset();
                // Only invalidate statements if we performed DDL.
                if (dataDictionaryInWriteMode()) {
                    ExecPreparedStatement ps = a.getPreparedStatement();
                    if (ps != null) {
                        ps.makeInvalid(DependencyManager.ROLLBACK, this);
                    }
                }
            } else {
                //We are dealing with commit here. 
                if (resultsetReturnsRows){
                    if (a.getResultSetHoldability() == false)
                        //Close result sets that return rows and are not held 
                        //across commit. This is to implement closing JDBC 
                        //result sets that are CLOSE_CURSOR_ON_COMMIT at commit 
                        //time. 
                        activationResultSet.close();
                    else 
                        //Clear the current row of the result sets that return
                        //rows and are held across commit. This is to implement
                        //keeping JDBC result sets open that are 
                        //HOLD_CURSORS_OVER_COMMIT at commit time and marking
                        //the resultset to be not on a valid row position. The 
                        //user will need to reposition within the resultset 
                        //before doing any row operations.
                        activationResultSet.clearCurrentRow();                          
                }
                a.clearHeapConglomerateController();
            }
        }
    }

    /**
        Finish the data dictionary transaction, if any.

        @exception StandardException    Thrown on error
     */
    private void finishDDTransaction() throws StandardException {

        /* Was the data dictionary put into write mode? */
        if (ddWriteMode) {
            DataDictionary dd = getDataDictionary();

            /* Tell the data dictionary that the transaction is finished */
            dd.transactionFinished();

            /* The data dictionary isn't in write mode any more */
            ddWriteMode = false;
        }
    }

    ////////////////////////////////////////////////////////////////////
    //
    //  MINIONS
    //
    ////////////////////////////////////////////////////////////////////

    /**
      * Increments the statement depth.
      */
    private void    incrementStatementDepth() { statementDepth++; }

    /**
      * Decrements the statement depth
      */
    private void    decrementStatementDepth()
    {
        statementDepth--;
    }

    /**
      * Resets the statementDepth.
      */
    protected   void    resetStatementDepth()
    {
        statementDepth = 0;
    }

    public DataDictionary getDataDictionary()
    {
        return getDatabase().getDataDictionary();
    }

    /**
      @see LanguageConnectionContext#setReadOnly
      @exception StandardException The operation is disallowed.
      */
    public void setReadOnly(boolean on) throws StandardException
    {
        if (!tran.isPristine())
            throw StandardException.newException(SQLState.AUTH_SET_CONNECTION_READ_ONLY_IN_ACTIVE_XACT);
        authorizer.setReadOnlyConnection(on,true);
    }

    /**
      @see LanguageConnectionContext#isReadOnly
      */
    public boolean isReadOnly()
    {
        return authorizer.isReadOnlyConnection();
    }

    /**
      @see LanguageConnectionContext#getAuthorizer
     */
    public Authorizer getAuthorizer()
    {
        return authorizer;
    }

    /**
     * lastAutoincrementValue searches for the last autoincrement value inserted
     * into a column specified by the user. The search for the "last" value
     * supports nesting levels caused by triggers (Only triggers cause nesting,
     * not server side JDBC). 
     * If lastAutoincrementValue is called from within a trigger, the search
     * space for ai-values are those values that are inserted by this trigger as
     * well as previous triggers; 
     * i.e if a SQL statement fires trigger T1, which in turn does something
     * that fires trigger t2, and if lastAutoincrementValue is called from
     * within t2, then autoincrement values genereated by t1 are visible to
     * it. By the same logic, if it is called from within t1, then it does not
     * see values inserted by t2.
     *
     * @see LanguageConnectionContext#lastAutoincrementValue
     */
    public Long lastAutoincrementValue(String schemaName, String tableName,
                                       String columnName)
    {
        String aiKey = AutoincrementCounter.makeIdentity(schemaName, tableName, columnName);
        
        int size = triggerExecutionContexts.size();
        //      System.out.println(" searching for " + aiKey);
        for (int i = size - 1; i >= 0; i--)
        {
            // first loop through triggers.
            TriggerExecutionContext itec = triggerExecutionContexts.get(i);
            Long value = itec.getAutoincrementValue(aiKey);
            if (value == null)
                continue;

            return value;
        }
        if (autoincrementHT == null)
            return null;
        return autoincrementHT.get(aiKey);
    }   

    /**
     * @see LanguageConnectionContext#setAutoincrementUpdate
     */
    public void setAutoincrementUpdate(boolean flag)
    {
        autoincrementUpdate = flag;
    }
    
    /**
     * @see LanguageConnectionContext#getAutoincrementUpdate
     */
    public boolean getAutoincrementUpdate()
    {
        return autoincrementUpdate;
    }
    
    /**
     * @see LanguageConnectionContext#autoincrementCreateCounter
     */
    public void autoincrementCreateCounter(String s, String t, String c,
                                           Long initialValue, long increment,
                                           int position)
    {
        String key = AutoincrementCounter.makeIdentity(s,t,c);
        
        if (autoincrementCacheHashtable == null)
        {
            autoincrementCacheHashtable = new HashMap<String,AutoincrementCounter>();
        }

        AutoincrementCounter aic = 
            autoincrementCacheHashtable.get(key);
        if (aic != null)
        {
            if (SanityManager.DEBUG)            
            {
                SanityManager.THROWASSERT(
                              "Autoincrement Counter already exists:" + key);
            }
            return;
        }
        
        aic = new AutoincrementCounter(initialValue, 
                                       increment, 0, s, t, c, position);
        autoincrementCacheHashtable.put(key, aic);
    }

    /**
     * returns the <b>next</b> value to be inserted into an autoincrement col.
     * This is used internally by the system to generate autoincrement values
     * which are going to be inserted into a autoincrement column. This is
     * used when as autoincrement column is added to a table by an alter 
     * table statemenet and during bulk insert.
     *
     * @param schemaName
     * @param tableName
     * @param columnName identify the column uniquely in the system.
     */
    public long nextAutoincrementValue(String schemaName, String tableName,
                                       String columnName)
            throws StandardException                           
    {
        String key = AutoincrementCounter.makeIdentity(schemaName,tableName,
                                                       columnName);
        
        AutoincrementCounter aic = 
            autoincrementCacheHashtable.get(key);

        if (aic == null)
        {
            if (SanityManager.DEBUG)            
            {
                SanityManager.THROWASSERT("counter doesn't exist:" + key);
            }
            return 0;
        }
        else
        {
            return aic.update();
        }
    }
    
    /**
     * Flush the cache of autoincrement values being kept by the lcc.
     * This will result in the autoincrement values being written to the
     * SYSCOLUMNS table as well as the mapping used by lastAutoincrementValue
     * 
     * @exception StandardException thrown on error.
     * @see LanguageConnectionContext#lastAutoincrementValue
     * @see GenericLanguageConnectionContext#lastAutoincrementValue
     */
    public void autoincrementFlushCache(UUID tableUUID)
        throws StandardException
    {
        if (autoincrementCacheHashtable == null)
            return;

        if (autoincrementHT == null)
            autoincrementHT = new HashMap<String,Long>();

        DataDictionary dd = getDataDictionary();
        for (Iterator<String> it = autoincrementCacheHashtable.keySet().iterator();
             it.hasNext(); )
        {
            String key = it.next();
            AutoincrementCounter aic = 
                autoincrementCacheHashtable.get(key);
            Long value = aic.getCurrentValue();
            aic.flushToDisk(getTransactionExecute(), dd, tableUUID);
            if (value != null)
            {
                autoincrementHT.put(key, value);
            }
        }
        autoincrementCacheHashtable.clear();
    }

    /**
     * Copies an existing autoincrement mapping
     * into autoincrementHT, the cache of autoincrement values 
     * kept in the languageconnectioncontext.
     */
    public void copyHashtableToAIHT(Map<String,Long> from)
    {
        if (from.isEmpty())
            return;
        if (autoincrementHT == null)
            autoincrementHT = new HashMap<String,Long>();
        
        autoincrementHT.putAll(from);
    }
    
    /**
     * @see LanguageConnectionContext#getInstanceNumber
     */
    public int getInstanceNumber()
    {
        return instanceNumber;
    }

    /**
     * @see LanguageConnectionContext#getDrdaID
     */
    public String getDrdaID()
    {
        return drdaID;
    }

    /**
     * @see LanguageConnectionContext#setDrdaID
     */
    public void setDrdaID(String drdaID)
    {
        this.drdaID = drdaID;
    }

    /**
     * @see LanguageConnectionContext#getDbname
     */
    public String getDbname()
    {
        return dbname;
    }

    /**
     * @see LanguageConnectionContext#getLastActivation
     */
    public Activation getLastActivation()
    {
        return acts.get(acts.size() - 1);
    }

    @Override
    public StringBuffer appendErrorInfo() {

        TransactionController tc = getTransactionExecute();
        if (tc == null)
            return null;

        StringBuffer sb = new StringBuffer(200);

        sb.append(LanguageConnectionContext.xidStr);
        sb.append(tc.getTransactionIdString());
        sb.append("), ");

        sb.append(LanguageConnectionContext.lccStr);
        sb.append(Integer.toString(getInstanceNumber()));
        sb.append("), ");

        sb.append(LanguageConnectionContext.dbnameStr);
        sb.append(getDbname());
        sb.append("), ");

        sb.append(LanguageConnectionContext.drdaStr);
        sb.append(getDrdaID());
        sb.append("), ");

        return sb;
    }


    /**
     * @see LanguageConnectionContext#setCurrentRole(Activation a, String role)
     */
    public void setCurrentRole(Activation a, String role) {
        getCurrentSQLSessionContext(a).setRole(role);
    }


    /**
     * @see LanguageConnectionContext#getCurrentRoleId(Activation a)
     */
    public String getCurrentRoleId(Activation a) {
        return getCurrentSQLSessionContext(a).getRole();
    }


    /**
     * @see LanguageConnectionContext#getCurrentUserId(Activation a)
     */
    public String getCurrentUserId(Activation a) {
        return getCurrentSQLSessionContext(a).getCurrentUser();
    }


    /**
     * @see LanguageConnectionContext#getCurrentRoleIdDelimited(Activation a)
     */
    public String getCurrentRoleIdDelimited(Activation a)
            throws StandardException {

        String role = getCurrentSQLSessionContext(a).getRole();

        if (role != null) {
            beginNestedTransaction(true);

            try {
                if (!roleIsSettable(a, role)) {
                    // invalid role, so lazily reset it.
                    setCurrentRole(a, null);
                    role = null;
                }
            } finally {
                commitNestedTransaction();
            }
        }

        if (role != null) {
            role = IdUtil.normalToDelimited(role);
        }

        return role;
    }


    /**
     * @see LanguageConnectionContext#roleIsSettable(Activation a, String role)
     */
    public boolean roleIsSettable(Activation a, String role)
            throws StandardException {

        DataDictionary dd = getDataDictionary();
        String dbo = dd.getAuthorizationDatabaseOwner();

        RoleGrantDescriptor grantDesc;
        String currentUser = getCurrentUserId(a);

        if (currentUser.equals(dbo)) {
            grantDesc = dd.getRoleDefinitionDescriptor(role);
        } else {
            grantDesc = dd.getRoleGrantDescriptor
                (role, currentUser, dbo);

            if (grantDesc == null) {
                // or if not, via PUBLIC?
                grantDesc = dd.getRoleGrantDescriptor
                    (role, Authorizer.PUBLIC_AUTHORIZATION_ID,dbo);
            }
        }
        return grantDesc != null;
    }

    /**
     * Return the current SQL session context of the activation
     *
     * @param activation the activation
     */
    public SQLSessionContext getCurrentSQLSessionContext(
        Activation activation) {

        SQLSessionContext curr;

        Activation parent = activation.getParentActivation();

        if (parent == null ) {
            // top level
            curr = getTopLevelSQLSessionContext();
        } else {
            // inside a nested connection (stored procedure/function), or when
            // executing a substatement the SQL session context is maintained
            // in the activation of the parent
            curr = parent.getSQLSessionContextForChildren();
        }

        return curr;
    }


    /**
     * Return the current SQL session context based on statement context
     */
    private SQLSessionContext getCurrentSQLSessionContext() {
        StatementContext ctx = getStatementContext();
        SQLSessionContext curr;

        if (ctx == null || !ctx.inUse()) {
            curr = getTopLevelSQLSessionContext();
        } else {
            // We are inside a nested connection in a procedure of
            // function.
            curr = ctx.getSQLSessionContext();

            if (SanityManager.DEBUG) {
                SanityManager.ASSERT(
                    curr != null,
                    "SQL session context should never be empty here");
            }
        }

        return curr;
    }


    /**
     * {@inheritDoc}
     */
    public void pushNestedSessionContext(
        Activation a,
        boolean definersRights,
        String definer) throws StandardException {

        setupSessionContextMinion(a, true, definersRights, definer);
    }

    private void setupSessionContextMinion(
        Activation a,
        boolean push,
        boolean definersRights,
        String definer) throws StandardException {

        if (SanityManager.DEBUG) {
            if (definersRights) {
                SanityManager.ASSERT(push);
            }
        }

        SQLSessionContext sc = a.setupSQLSessionContextForChildren(push);

        if (definersRights) {
            sc.setUser(definer);
        } else {
            // A priori: invoker's rights: Current user
            sc.setUser(getCurrentUserId(a));
        }


        if (definersRights) {
            // No role a priori. Cf. SQL 2008, section 10.4 <routine
            // invocation>, GR 5 j) i) 1) B) "If the external security
            // characteristic of R is DEFINER, then the top cell of the
            // authorization stack of RSC is set to contain only the routine
            // authorization identifier of R.

            sc.setRole(null);
        } else {
            // Semantics for roles dictate (SQL 4.34.1.1 and 4.27.3.) that the
            // role is initially inherited from the current session context
            // when we run with INVOKER security characteristic.
            sc.setRole(getCurrentRoleId(a));
        }


        if (definersRights) {
            SchemaDescriptor sd = getDataDictionary().getSchemaDescriptor(
                definer,
                getTransactionExecute(),
                false);

            if (sd == null) {
                sd = new SchemaDescriptor(
                    getDataDictionary(), definer, definer, (UUID) null, false);
            }

            sc.setDefaultSchema(sd);
        } else {
            // Inherit current default schema. The initial value of the
            // default schema is implementation defined. In Derby we
            // inherit it when we invoke stored procedures and functions.
            sc.setDefaultSchema(getDefaultSchema(a));
        }

        final SQLSessionContext ssc = getCurrentSQLSessionContext(a);
        sc.setDeferredAll(ssc.getDeferredAll());
        sc.setConstraintModes(ssc.getConstraintModes());

        StatementContext stmctx = getStatementContext();

        // Since the statement is an invocation (iff push=true), it will now be
        // associated with the pushed SQLSessionContext (and no longer just
        // share that of its caller (or top).  The statement contexts of nested
        // connection statements will inherit statement context so the SQL
        // session context is available through it when nested statements are
        // compiled (and executed, for the most part).  However, for dynamic
        // result sets, the relevant statement context (originating result set)
        // is no longer available for execution time references to the SQL
        // session context, so we rely on the activation of the caller for
        // accessing it, cf. e.g. overload variants of
        // getDefaultSchema/setDefaultSchema.  If such nested connections
        // themselves turn out to be invocations, they in turn get a new
        // SQLSessionContext associated with them etc.
        stmctx.setSQLSessionContext(sc);
    }

    /**
     * @param a {@inheritDoc}
     * @throws StandardException {@inheritDoc}
     */
    public void popNestedSessionContext(Activation a) throws StandardException {
        SQLSessionContext nested = a.getSQLSessionContextForChildren();
        SQLSessionContext caller = getCurrentSQLSessionContext(a);

        compareConstraintModes(nested, caller);
    }

    private void compareConstraintModes(
            SQLSessionContext nested,
            SQLSessionContext caller) throws StandardException {

        if (deferredHashTables == null) {
            // Nothing to do
            return;
        }

        // Check all constraints that were deferred inside the routine
        // but whose constraint mode is immediate on the outside. If
        // any of these violate the constraints, roll back.
        for (ValidationInfo info : deferredHashTables.values()) {
            info.possiblyValidateOnReturn(this, nested, caller);
        }
    }

    public boolean isEffectivelyDeferred(SQLSessionContext sc, UUID constraintId)
            throws StandardException {

        final Boolean deferred = sc.isDeferred(constraintId);
        final boolean effectivelyDeferred;
        final DataDictionary dd = getDataDictionary();

        if (deferred != null) {
            effectivelyDeferred = deferred.booleanValue();
        } else {
            // no explicit setting applicable, use initial constraint mode
            final ConstraintDescriptor conDesc =
                    dd.getConstraintDescriptor(constraintId);
            effectivelyDeferred = conDesc.initiallyDeferred();
        }

        return effectivelyDeferred;
    }


    /**
     * @see LanguageConnectionContext#setupSubStatementSessionContext(Activation a)
     */
    public void setupSubStatementSessionContext(Activation a)
            throws StandardException {

        setupSessionContextMinion(a, false, false, null);
    }


    /**
     * @see GenericLanguageConnectionContext#topLevelSSC
     */
    public SQLSessionContext getTopLevelSQLSessionContext() {
        if (topLevelSSC == null) {
            topLevelSSC = new SQLSessionContextImpl(
                getInitialDefaultSchemaDescriptor(),
                getSessionUserId());
        }
        return topLevelSSC;
    }


    /**
     * @see LanguageConnectionContext#createSQLSessionContext
     */
    public SQLSessionContext createSQLSessionContext() {
        return new SQLSessionContextImpl(
            getInitialDefaultSchemaDescriptor(),
            getSessionUserId()); /* a priori */
    }

    /**
     * This holds a map of AST nodes that have already been printed during a
     * compiler phase, so as to be able to avoid printing a node more than once.
     * @see org.apache.derby.impl.sql.compile.QueryTreeNode#treePrint(int)
     */
    Map<Object,Object> printedObjectsMap = null;

    /**
     * @see org.apache.derby.iapi.sql.conn.LanguageConnectionContext#getPrintedObjectsMap
     */
    public Map<Object,Object> getPrintedObjectsMap() {
        if (printedObjectsMap == null) {
            printedObjectsMap = new IdentityHashMap<Object,Object>();
        }
        return printedObjectsMap;
    }

    /** @see LanguageConnectionContext#getXplainOnlyMode() */
    public boolean getXplainOnlyMode() {
        return xplainOnlyMode;
    }
    
    /** @see LanguageConnectionContext#setXplainOnlyMode(boolean) */
    public void setXplainOnlyMode(boolean onOrOff) {
        xplainOnlyMode = onOrOff;
    }
    
    /** @see LanguageConnectionContext#getXplainSchema() */
    public String getXplainSchema() {
        return xplain_schema;
    }
    
    /** @see LanguageConnectionContext#setXplainSchema(String) */
    public void setXplainSchema(String s) {
        xplain_schema = s;
    }
    public void setXplainStatement(Object key, Object stmt)
    {
        xplain_statements.put(key, stmt);
    }
    public Object getXplainStatement(Object key)
    {
        return xplain_statements.get(key);
    }
    
    public void setASTVisitor( ASTVisitor visitor )
    {
        astWalker = visitor;
    }
    public ASTVisitor getASTVisitor( )
    {
        return astWalker;
    }

    public void setInterruptedException(StandardException e) {
        interruptedException = e;
    }

    public StandardException getInterruptedException() {
        return interruptedException;
    }

    public FormatableBitSet getReferencedColumnMap(TableDescriptor td) {
        return referencedColumnMap.get(td);
    }

    public void setReferencedColumnMap(TableDescriptor td,
                                       FormatableBitSet map) {
        referencedColumnMap.put(td, map);
    }

    /**
     * Set the constraint mode to deferred for the specified constraint.
     *
     * @param a             activation
     * @param cd            the constraint descriptor
     * @param deferred      the constraint mode
     * @throws StandardException standard error policy
     */
    public void setConstraintDeferred(
            final Activation a,
            ConstraintDescriptor cd,
            final boolean deferred) throws StandardException {

        if (!deferred) {
            // Moving to immediate, check what's done in this transaction first
            validateDeferredConstraint(cd);
        }

        getCurrentSQLSessionContext(a).setDeferred(cd.getUUID(), deferred);
    }

    public void checkIntegrity() throws StandardException {
        validateDeferredConstraints(true);
        clearDeferreds();
    }

    /**
     * Clear deferred information for this transaction.
     */
    private void clearDeferreds() {
        deferredHashTables = null;
        getCurrentSQLSessionContext().resetConstraintModes();
    }

    public void setDeferredAll(final Activation a, final boolean deferred)
            throws StandardException {
        if (!deferred) {
            validateDeferredConstraints(false);

            // No violations, bug can't forget since we might roll back to a
            // savepoint that migh re-introduce the violations
            // DERBY-6670
            // deferredHashTables = null;
        }
        getCurrentSQLSessionContext(a).setDeferredAll(
            Boolean.valueOf(deferred));
    }

    public HashMap<UUID, ValidationInfo> getDeferredHashTables() {
        if (deferredHashTables == null) {
            deferredHashTables = new HashMap<UUID, ValidationInfo>();
        }
        return deferredHashTables;
    }

    /**
     * Validate all deferred constraints.
     */
    private void validateDeferredConstraints(final boolean rollbackOnError)
            throws StandardException {

        if (deferredHashTables == null) {
            // Nothing to do
            return;
        }

        for (ValidationInfo info : deferredHashTables.values()) {
            info.validateConstraint(this, null, rollbackOnError);
        }
    }

    /**
     * Validate a deferred constraint.
     *
     * @param cd the descriptor of the constraint to validate
     */
    private void validateDeferredConstraint(ConstraintDescriptor cd)
            throws StandardException {

        if (deferredHashTables == null) {
            // Nothing to do.
            return;
        }

        // For CHECK constraints, the key is the table id. All other
        // constraints use the constraint id as key.
        UUID key = cd.hasBackingIndex() ? cd.getUUID() : cd.getTableId();

        ValidationInfo vi = deferredHashTables.get(key);

        if (vi == null) {
            // Nothing to do
            return;
        }

        vi.validateConstraint(this, cd.getUUID(), false);

        // No violations, bug can't forget since we might roll back to a
        // savepoint that migh re-introduce the violations
        // DERBY-6670-
        //
        // deferredHashTables.remove(key);
    }
}
