You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by rh...@apache.org on 2022/08/21 18:20:01 UTC

svn commit: r1903614 [5/6] - in /db/derby/code/branches/10.15: ./ java/org.apache.derby.engine/org/apache/derby/impl/sql/compile/ java/org.apache.derby.engine/org/apache/derby/impl/sql/execute/ java/org.apache.derby.tests/org/apache/derbyTesting/functi...

Modified: db/derby/code/branches/10.15/java/org.apache.derby.engine/org/apache/derby/impl/sql/execute/InsertResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.15/java/org.apache.derby.engine/org/apache/derby/impl/sql/execute/InsertResultSet.java?rev=1903614&r1=1903613&r2=1903614&view=diff
==============================================================================
--- db/derby/code/branches/10.15/java/org.apache.derby.engine/org/apache/derby/impl/sql/execute/InsertResultSet.java (original)
+++ db/derby/code/branches/10.15/java/org.apache.derby.engine/org/apache/derby/impl/sql/execute/InsertResultSet.java Sun Aug 21 18:20:01 2022
@@ -87,155 +87,153 @@ import org.apache.derby.shared.common.sa
  */
 class InsertResultSet extends DMLWriteGeneratedColumnsResultSet implements TargetResultSet
 {
-	// RESOLVE. Embarrassingly large public state. If we could move the 
-	// Replication code into the same package, then these variables 
-	// could be protected. 
-	// passed in at construction time
+    // RESOLVE. Embarrassingly large public state. If we could move the 
+    // Replication code into the same package, then these variables 
+    // could be protected. 
+    // passed in at construction time
                                                  
-	NoPutResultSet			savedSource;
-	InsertConstantAction	constants;
+    NoPutResultSet			savedSource;
+    InsertConstantAction	constants;
     private GeneratedMethod         generationClauses;
-	private GeneratedMethod			checkGM;
-	private long					heapConglom;
+    private GeneratedMethod			checkGM;
+    private long					heapConglom;
 
-	// divined at run time
+    // divined at run time
 
-	private RowChanger 				rowChanger;
+    private RowChanger 				rowChanger;
 
-	private	TransactionController 	tc;
-	private	ExecRow					row;
+    private	TransactionController 	tc;
+    private	ExecRow					row;
 	
-	boolean					userSpecifiedBulkInsert;
-	boolean					bulkInsertPerformed;
+    boolean					userSpecifiedBulkInsert;
+    boolean					bulkInsertPerformed;
 
-	// bulkInsert
-	protected boolean				bulkInsert;
-	private boolean					bulkInsertReplace;
-	private boolean					firstRow = true;
-	private	boolean[]				needToDropSort;
-
-	/*
-	** This hashtable is used to convert an index conglomerate
-	** from it's old conglom number to the new one.  It is
-	** bulk insert specific.
-	*/
-	private Hashtable<Long,Long>				indexConversionTable;
-
-	// indexedCols is 1-based
-	private FormatableBitSet					indexedCols;
-	private ConglomerateController	bulkHeapCC;
+    // bulkInsert
+    protected boolean				bulkInsert;
+    private boolean					bulkInsertReplace;
+    private boolean					firstRow = true;
+    private	boolean[]				needToDropSort;
 
-	protected DataDictionary			dd;
-	protected TableDescriptor			td;
+    /*
+    ** This hashtable is used to convert an index conglomerate
+    ** from it's old conglom number to the new one.  It is
+    ** bulk insert specific.
+    */
+    private Hashtable<Long,Long>				indexConversionTable;
+
+    // indexedCols is 1-based
+    private FormatableBitSet					indexedCols;
+    private ConglomerateController	bulkHeapCC;
+
+    protected DataDictionary			dd;
+    protected TableDescriptor			td;
 		
-	private ExecIndexRow[]			indexRows;
+    private ExecIndexRow[]			indexRows;
     private final int               fullTemplateId;
     private final String            schemaName;
     private final String            tableName;
-	private	long[]					sortIds;
-	private RowLocationRetRowSource[]
-                                    rowSources;
-	private	ScanController			bulkHeapSC;
-	private ColumnOrdering[][]		ordering;
-	private int[][]		            collation;
-	private SortController[]		sorters;
-	private	TemporaryRowHolderImpl	rowHolder;
-	private RowLocation				rl;
-
-	private	boolean					hasBeforeRowTrigger;
-	private	BulkTableScanResultSet	tableScan;
-
-	private int						numOpens;
-	private boolean					firstExecute;
-
-	// cached across open()s
-	private	FKInfo[]				fkInfoArray;
-	private	TriggerInfo				triggerInfo;
-	private RISetChecker 			fkChecker;
-	private TriggerEventActivator	triggerActivator;
+    private	long[]					sortIds;
+    private RowLocationRetRowSource[]
+    rowSources;
+    private	ScanController			bulkHeapSC;
+    private ColumnOrdering[][]		ordering;
+    private int[][]		            collation;
+    private SortController[]		sorters;
+    private	TemporaryRowHolderImpl	rowHolder;
+    private RowLocation				rl;
+
+    private	boolean					hasBeforeRowTrigger;
+    private	BulkTableScanResultSet	tableScan;
+
+    private int						numOpens;
+    private boolean					firstExecute;
+
+    // cached across open()s
+    private	FKInfo[]				fkInfoArray;
+    private	TriggerInfo				triggerInfo;
+    private RISetChecker 			fkChecker;
+    private TriggerEventActivator	triggerActivator;
     private BulkInsertCounter[]                 bulkInsertCounters;
     private BackingStoreHashtable   deferredChecks; // cached ref.
     private List<UUID>              violatingCheckConstraints;
 	
-	// TargetResultSet interface
+    // TargetResultSet interface
 
-	/**
-	 * @see TargetResultSet#changedRow
-	 *
-	 * @exception StandardException thrown if cursor finish ed.
-	 */
-	public void changedRow(ExecRow execRow, RowLocation rowLocation)
-		throws StandardException
-	{
-		if (SanityManager.DEBUG)
-		{
-			SanityManager.ASSERT(bulkInsert,
-				"bulkInsert exected to be true");
-		}
-
-		/* Set up sorters, etc. if 1st row and there are indexes */
-		if (constants.irgs.length > 0)
-		{
-           RowLocation rlClone = (RowLocation) rowLocation.cloneValue(false);
-
-			// Objectify any the streaming columns that are indexed.
-			for (int i = 0; i < execRow.getRowArray().length; i++)
-			{
-				if (! constants.indexedCols[i])
-				{
-					continue;
-				}
-
-				if (execRow.getRowArray()[i] instanceof StreamStorable)
-					((DataValueDescriptor)execRow.getRowArray()[i]).getObject();
-			}
-
-			// Every index row will share the same row location, etc.
-			if (firstRow)
-			{
-				firstRow = false;
-				indexRows = new ExecIndexRow[constants.irgs.length];
-				setUpAllSorts(execRow.getNewNullRow(), rlClone);
-			}
-
-			// Put the row into the indexes
-			for (int index = 0; index < constants.irgs.length; index++)
-			{
-				// Get a new object Array for the index
-				indexRows[index].getNewObjectArray();
-				// Associate the index row with the source row
-				constants.irgs[index].getIndexRow(execRow, 
-											   rlClone, 
-											   indexRows[index],
-											   (FormatableBitSet) null);
-
-				// Insert the index row into the matching sorter
-				sorters[index].insert(indexRows[index].getRowArray());
-			}
-		}
-	}
+    /**
+     * @see TargetResultSet#changedRow
+     *
+     * @exception StandardException thrown if cursor finish ed.
+     */
+    public void changedRow(ExecRow execRow, RowLocation rowLocation)
+        throws StandardException {
+        if (SanityManager.DEBUG)
+        {
+            SanityManager.ASSERT(bulkInsert,
+                                 "bulkInsert exected to be true");
+        }
 
-	/**
-	 * Preprocess the source row.  Apply any check constraints here.
-	 * Do an inplace cloning of all key columns.  For triggers, if
-	 * we have a before row trigger, we fire it here if we can.
-	 * This is useful for bulk insert where the store stands between
-	 * the source and us.
-	 *
-	 * @param execRow	The source row.
-	 *
-	 * @return The preprocessed source row.
-	 * @exception StandardException thrown on error
-	 */
-	public ExecRow preprocessSourceRow(ExecRow execRow)
-		throws StandardException
-	{
+        /* Set up sorters, etc. if 1st row and there are indexes */
+        if (constants.irgs.length > 0)
+        {
+            RowLocation rlClone = (RowLocation) rowLocation.cloneValue(false);
+
+            // Objectify any the streaming columns that are indexed.
+            for (int i = 0; i < execRow.getRowArray().length; i++)
+            {
+                if (! constants.indexedCols[i])
+                {
+                    continue;
+                }
+
+                if (execRow.getRowArray()[i] instanceof StreamStorable)
+                    ((DataValueDescriptor)execRow.getRowArray()[i]).getObject();
+            }
+
+            // Every index row will share the same row location, etc.
+            if (firstRow)
+            {
+                firstRow = false;
+                indexRows = new ExecIndexRow[constants.irgs.length];
+                setUpAllSorts(execRow.getNewNullRow(), rlClone);
+            }
+
+            // Put the row into the indexes
+            for (int index = 0; index < constants.irgs.length; index++)
+            {
+                // Get a new object Array for the index
+                indexRows[index].getNewObjectArray();
+                // Associate the index row with the source row
+                constants.irgs[index].getIndexRow(execRow, 
+                                                  rlClone, 
+                                                  indexRows[index],
+                                                  (FormatableBitSet) null);
+
+                // Insert the index row into the matching sorter
+                sorters[index].insert(indexRows[index].getRowArray());
+            }
+        }
+    }
+
+    /**
+     * Preprocess the source row.  Apply any check constraints here.
+     * Do an inplace cloning of all key columns.  For triggers, if
+     * we have a before row trigger, we fire it here if we can.
+     * This is useful for bulk insert where the store stands between
+     * the source and us.
+     *
+     * @param execRow	The source row.
+     *
+     * @return The preprocessed source row.
+     * @exception StandardException thrown on error
+     */
+    public ExecRow preprocessSourceRow(ExecRow execRow)
+        throws StandardException {
         if (triggerInfo != null) {
             // We do not use bulk insert if we have triggers
             if (SanityManager.DEBUG) {
                 SanityManager.NOTREACHED();
             }
-		}
+        }
 
         if ( generationClauses != null )
         {
@@ -247,40 +245,40 @@ class InsertResultSet extends DMLWriteGe
             if (!allOk) {
                 if (SanityManager.DEBUG) {
                     SanityManager.ASSERT(
-                            violatingCheckConstraints != null &&
-                            violatingCheckConstraints.size() > 0) ;
+                        violatingCheckConstraints != null &&
+                        violatingCheckConstraints.size() > 0) ;
                 }
 
                 // We will do a callback to remember this by
                 // offendingRowLocation called from HeapController#load
             }
-		}
-		// RESOLVE - optimize the cloning
-		if (constants.irgs.length > 0)
-		{
-			/* Do in-place cloning of all of the key columns */
-			return execRow.getClone(indexedCols);
-		}
-		else
-		{
-			return execRow;
-		}
-	}
+        }
+        // RESOLVE - optimize the cloning
+        if (constants.irgs.length > 0)
+        {
+            /* Do in-place cloning of all of the key columns */
+            return execRow.getClone(indexedCols);
+        }
+        else
+        {
+            return execRow;
+        }
+    }
 
 
     public void offendingRowLocation(RowLocation rl, long constainerId)
-            throws StandardException {
+        throws StandardException {
         if (violatingCheckConstraints != null) {
             deferredChecks =
-                    DeferredConstraintsMemory.rememberCheckViolations(
-                            lcc,
-                            constants.targetUUID,
-                            schemaName,
-                            tableName,
-                            deferredChecks,
-                            violatingCheckConstraints,
-                            rl,
-                            new CheckInfo[1] /* dummy */);
+                DeferredConstraintsMemory.rememberCheckViolations(
+                    lcc,
+                    constants.targetUUID,
+                    schemaName,
+                    tableName,
+                    deferredChecks,
+                    violatingCheckConstraints,
+                    rl,
+                    new CheckInfo[1] /* dummy */);
             violatingCheckConstraints.clear();
         }
     }
@@ -301,137 +299,135 @@ class InsertResultSet extends DMLWriteGe
             // immediate, a check error will throw rather than return a false
             // value.
             SQLBoolean allOk =
-                    (SQLBoolean)checkGM.invoke(activation);
+                (SQLBoolean)checkGM.invoke(activation);
             result = allOk.isNull() || allOk.getBoolean();
-		}
+        }
 
         return result;
-	}
+    }
 
     /*
      * class interface
      *
      */
     /**
-	 *
-	 * @exception StandardException		Thrown on error
+     *
+     * @exception StandardException		Thrown on error
      */
     InsertResultSet(NoPutResultSet source, 
-						   GeneratedMethod generationClauses,
-						   GeneratedMethod checkGM,
-                           int fullTemplate,
-                           String schemaName,
-                           String tableName,
-						   Activation activation)
-		throws StandardException
-    {
-		super(activation);
-		sourceResultSet = source;
-		constants = (InsertConstantAction) constantAction;
+                    GeneratedMethod generationClauses,
+                    GeneratedMethod checkGM,
+                    int fullTemplate,
+                    String schemaName,
+                    String tableName,
+                    Activation activation)
+        throws StandardException {
+        super(activation);
+        sourceResultSet = source;
+        constants = (InsertConstantAction) constantAction;
         this.generationClauses = generationClauses;
-		this.checkGM = checkGM;
+        this.checkGM = checkGM;
         this.fullTemplateId = fullTemplate;
         this.schemaName = schemaName;
         this.tableName = tableName;
-		heapConglom = constants.conglomId;
+        heapConglom = constants.conglomId;
         identitySequenceUUIDString = constants.identitySequenceUUIDString;
 
         tc = activation.getTransactionController();
-		fkInfoArray = constants.getFKInfo();
-		triggerInfo = constants.getTriggerInfo();
+        fkInfoArray = constants.getFKInfo();
+        triggerInfo = constants.getTriggerInfo();
 		
-		hasBeforeRowTrigger = (triggerInfo != null) ?
-				triggerInfo.hasTrigger(true, true) :
-				false;
+        hasBeforeRowTrigger = (triggerInfo != null) ?
+            triggerInfo.hasTrigger(true, true) :
+            false;
 
         resultDescription = sourceResultSet.getResultDescription();
         
-		// Is this a bulkInsert or regular insert?
-		String insertMode = constants.getProperty("insertMode");
+        // Is this a bulkInsert or regular insert?
+        String insertMode = constants.getProperty("insertMode");
 
-		initializeAIcache(constants.getAutoincRowLocation());
+        initializeAIcache(constants.getAutoincRowLocation());
 
-		if (insertMode != null)
-		{
-			if (StringUtil.SQLEqualsIgnoreCase(insertMode,"BULKINSERT"))
-			{
-				userSpecifiedBulkInsert = true;
-			}
-			else if (StringUtil.SQLEqualsIgnoreCase(insertMode,"REPLACE"))
-			{
-				userSpecifiedBulkInsert = true;
-				bulkInsertReplace = true;
-				bulkInsert = true;
-
-				/*
-				** For now, we don't allow bulk insert replace when 
-				** there is a trigger. 
-				*/
-				if (triggerInfo != null)
-				{
+        if (insertMode != null)
+        {
+            if (StringUtil.SQLEqualsIgnoreCase(insertMode,"BULKINSERT"))
+            {
+                userSpecifiedBulkInsert = true;
+            }
+            else if (StringUtil.SQLEqualsIgnoreCase(insertMode,"REPLACE"))
+            {
+                userSpecifiedBulkInsert = true;
+                bulkInsertReplace = true;
+                bulkInsert = true;
+
+                /*
+                ** For now, we don't allow bulk insert replace when 
+                ** there is a trigger. 
+                */
+                if (triggerInfo != null)
+                {
                     TriggerDescriptor trD = triggerInfo.getTriggerArray()[0];
                     throw StandardException.newException(
                         SQLState.LANG_NO_BULK_INSERT_REPLACE_WITH_TRIGGER_DURING_EXECUTION,
                         constants.getTableName(),
                         trD.getName());
-				}
-			}
-		}
-	}
+                }
+            }
+        }
+    }
 	
-	/**
-		@exception StandardException Standard Derby error policy
-	*/
-	public void open() throws StandardException
-	{
-		setup();
-		// Remember if this is the 1st execution
-		firstExecute = (rowChanger == null);
-
-		autoincrementGenerated = false;
-
-		dd = lcc.getDataDictionary();
-
-		verifyAutoGeneratedRScolumnsList(constants.targetUUID);
-
-		rowCount = 0L;
-
-		if (numOpens++ == 0)
-		{
-			sourceResultSet.openCore();
-		}
-		else
-		{
-			sourceResultSet.reopenCore();
-		}
-
-		/* If the user specified bulkInsert (or replace) then we need 
-		 * to get an exclusive table lock on the table.  If it is a
-		 * regular bulk insert then we need to check to see if the
-		 * table is empty.  (If not empty, then we end up doing a row
-		 * at a time insert.)
-		 */
-		if (userSpecifiedBulkInsert)
-		{
-			if (! bulkInsertReplace)
-			{
-				bulkInsert = verifyBulkInsert();
-			}
-			else
-			{
-				getExclusiveTableLock();
-			}
-		}
-
-		if (bulkInsert)
-		{
-			// Notify the source that we are the target
-			sourceResultSet.setTargetResultSet(this);
+    /**
+       @exception StandardException Standard Derby error policy
+    */
+    public void open() throws StandardException {
+        setup();
+        // Remember if this is the 1st execution
+        firstExecute = (rowChanger == null);
+
+        autoincrementGenerated = false;
+
+        dd = lcc.getDataDictionary();
+
+        verifyAutoGeneratedRScolumnsList(constants.targetUUID);
+
+        rowCount = 0L;
+
+        if (numOpens++ == 0)
+        {
+            sourceResultSet.openCore();
+        }
+        else
+        {
+            sourceResultSet.reopenCore();
+        }
+
+        /* If the user specified bulkInsert (or replace) then we need 
+         * to get an exclusive table lock on the table.  If it is a
+         * regular bulk insert then we need to check to see if the
+         * table is empty.  (If not empty, then we end up doing a row
+         * at a time insert.)
+         */
+        if (userSpecifiedBulkInsert)
+        {
+            if (! bulkInsertReplace)
+            {
+                bulkInsert = verifyBulkInsert();
+            }
+            else
+            {
+                getExclusiveTableLock();
+            }
+        }
+
+        if (bulkInsert)
+        {
+            // Notify the source that we are the target
+            sourceResultSet.setTargetResultSet(this);
 
             ExecRow fullTemplate =
                 ((ExecRowBuilder) activation.getPreparedStatement().
-                    getSavedObject(fullTemplateId)).build(
-                        activation.getExecutionFactory());
+                 getSavedObject(fullTemplateId)).build(
+                     activation.getExecutionFactory());
 
             bulkInsertCore(lcc, fullTemplate, heapConglom);
 
@@ -440,108 +436,106 @@ class InsertResultSet extends DMLWriteGe
                     // If we have triggers, we do not use bulkInsert
                     SanityManager.NOTREACHED();
                 }
-			}
+            }
 			
             bulkValidateForeignKeys(tc, lcc.getContextManager(), fullTemplate);
 	
-			bulkInsertPerformed = true;
-		}
-		else
-		{
-	        row = getNextRowCore(sourceResultSet);
-			normalInsertCore(lcc, firstExecute);
-		}
-
-		/* Cache query plan text for source, before it gets blown away */
-		if (lcc.getRunTimeStatisticsMode())
-		{
-			/* savedSource nulled after run time statistics generation */
-			savedSource = sourceResultSet;
-		}
+            bulkInsertPerformed = true;
+        }
+        else
+        {
+            row = getNextRowCore(sourceResultSet);
+            normalInsertCore(lcc, firstExecute);
+        }
 
-		cleanUp();
+        /* Cache query plan text for source, before it gets blown away */
+        if (lcc.getRunTimeStatisticsMode())
+        {
+            /* savedSource nulled after run time statistics generation */
+            savedSource = sourceResultSet;
+        }
 
-		saveAIcacheInformation(constants.getSchemaName(), 
-			constants.getTableName(), constants.getColumnNames());
+        cleanUp();
 
-		endTime = getCurrentTimeMillis();
-	}
+        saveAIcacheInformation(constants.getSchemaName(), 
+                               constants.getTableName(), constants.getColumnNames());
 
-	/**
-	 * Clean up resources and call close on data members.
-	 */
-	public void close() throws StandardException {
-		close( constants.underMerge() );
-		if (autoGeneratedKeysRowsHolder != null) {
-			autoGeneratedKeysRowsHolder.close();
-		}
-	}
+        endTime = getCurrentTimeMillis();
+    }
 
-	/**
-	 * If user didn't provide columns list for auto-generated columns, then only include
-	 * columns with auto-generated values in the resultset. Those columns would be ones
-	 * with default value defined.
-	 */
-	private int[] generatedColumnPositionsArray()
-		throws StandardException
-	{
+    /**
+     * Clean up resources and call close on data members.
+     */
+    public void close() throws StandardException {
+        close( constants.underMerge() );
+        if (autoGeneratedKeysRowsHolder != null) {
+            autoGeneratedKeysRowsHolder.close();
+        }
+    }
+
+    /**
+     * If user didn't provide columns list for auto-generated columns, then only include
+     * columns with auto-generated values in the resultset. Those columns would be ones
+     * with default value defined.
+     */
+    private int[] generatedColumnPositionsArray()
+        throws StandardException {
         TableDescriptor tabDesb = dd.getTableDescriptor(constants.targetUUID);
-		ColumnDescriptor cd;
+        ColumnDescriptor cd;
         int size = tabDesb.getMaxColumnID();
 
-		int[] generatedColumnPositionsArray = new int[size];
+        int[] generatedColumnPositionsArray = new int[size];
         Arrays.fill(generatedColumnPositionsArray, -1);
-		int generatedColumnNumbers = 0;
+        int generatedColumnNumbers = 0;
 
-		for (int i=0; i<size; i++) {
+        for (int i=0; i<size; i++) {
             cd = tabDesb.getColumnDescriptor(i+1);
-			if (cd.isAutoincrement()) { //if the column has auto-increment value
-				generatedColumnNumbers++;
-				generatedColumnPositionsArray[i] = i+1;
-			} else if (cd.getDefaultValue() != null || cd.getDefaultInfo() != null) {//default value
-				generatedColumnNumbers++;
-				generatedColumnPositionsArray[i] = i+1;
-			}
-		}
-		int[] returnGeneratedColumnPositionsArray = new int[generatedColumnNumbers];
-
-		for (int i=0, j=0; i<size; i++) {
-			if (generatedColumnPositionsArray[i] != -1)
-				returnGeneratedColumnPositionsArray[j++] = generatedColumnPositionsArray[i];
-		}
+            if (cd.isAutoincrement()) { //if the column has auto-increment value
+                generatedColumnNumbers++;
+                generatedColumnPositionsArray[i] = i+1;
+            } else if (cd.getDefaultValue() != null || cd.getDefaultInfo() != null) {//default value
+                generatedColumnNumbers++;
+                generatedColumnPositionsArray[i] = i+1;
+            }
+        }
+        int[] returnGeneratedColumnPositionsArray = new int[generatedColumnNumbers];
 
-		return returnGeneratedColumnPositionsArray;
-	}
+        for (int i=0, j=0; i<size; i++) {
+            if (generatedColumnPositionsArray[i] != -1)
+                returnGeneratedColumnPositionsArray[j++] = generatedColumnPositionsArray[i];
+        }
 
-	/**
-	 * getSetAutoincrementValue will get the autoincrement value of the 
-	 * columnPosition specified for the target table. If increment is 
-	 * non-zero we will also update the autoincrement value. 
-	 *
-	 * @param columnPosition	position of the column in the table (1-based)
-	 * @param increment			amount of increment. 
-	 *
-	 * @exception StandardException if anything goes wrong.
-	 */
-	public NumberDataValue
-		getSetAutoincrementValue(int columnPosition, long increment)
-		throws StandardException
-	{
-		int index = columnPosition - 1;	// all our indices are 0 based.
+        return returnGeneratedColumnPositionsArray;
+    }
 
-		/* As in DB2, only for single row insert: insert into t1(c1) values (..) do
-		 * we return the correct most recently generated identity column value.  For
-		 * multiple row insert, or insert with sub-select, the return value is non-
-		 * deterministic, and is the previous return value of the IDENTITY_VAL_LOCAL
-		 * function, before the insert statement.  Also, DB2 can have at most 1 identity
-		 * column per table.  The return value won't be affected either if Derby
-		 * table has more than one identity columns.
-		 */
-		setIdentity = (! autoincrementGenerated) && isSourceRowResultSet();
-		autoincrementGenerated = true;
+    /**
+     * getSetAutoincrementValue will get the autoincrement value of the 
+     * columnPosition specified for the target table. If increment is 
+     * non-zero we will also update the autoincrement value. 
+     *
+     * @param columnPosition	position of the column in the table (1-based)
+     * @param increment			amount of increment. 
+     *
+     * @exception StandardException if anything goes wrong.
+     */
+    public NumberDataValue
+    getSetAutoincrementValue(int columnPosition, long increment)
+        throws StandardException {
+        int index = columnPosition - 1;	// all our indices are 0 based.
+
+        /* As in DB2, only for single row insert: insert into t1(c1) values (..) do
+         * we return the correct most recently generated identity column value.  For
+         * multiple row insert, or insert with sub-select, the return value is non-
+         * deterministic, and is the previous return value of the IDENTITY_VAL_LOCAL
+         * function, before the insert statement.  Also, DB2 can have at most 1 identity
+         * column per table.  The return value won't be affected either if Derby
+         * table has more than one identity columns.
+         */
+        setIdentity = (! autoincrementGenerated) && isSourceRowResultSet();
+        autoincrementGenerated = true;
 
-  		if (bulkInsert)
-  		{
+        if (bulkInsert)
+        {
             if ( identitySequenceUUIDString == null )
             {
                 getOldStyleBulkInsertValue( index, increment );
@@ -554,10 +548,10 @@ class InsertResultSet extends DMLWriteGe
                 }
                 bulkInsertCounters[ index ].getCurrentValueAndAdvance( (NumberDataValue) aiCache[ index ] );
             }
-		}	
-		else
-		{
-			NumberDataValue newValue;
+        }	
+        else
+        {
+            NumberDataValue newValue;
 
             //
             // If there is a sequence generator uuid, then the database is at level
@@ -574,308 +568,304 @@ class InsertResultSet extends DMLWriteGe
                     ( identitySequenceUUIDString, aiCache[ index ].getTypeFormatId() );
             }
             
-			aiCache[index] = newValue;
-			if (setIdentity)
+            aiCache[index] = newValue;
+            if (setIdentity)
             {
-				identityVal = newValue.getLong();
+                identityVal = newValue.getLong();
             }
-		}
+        }
 
-		return (NumberDataValue) aiCache[index];
-	}
+        return (NumberDataValue) aiCache[index];
+    }
 
-     /**
-      * Identity generation logic for bulk-insert used in pre-10.11 databases.
-      *
-      * @param index   0-based index into aiCache
-      */
-     private void    getOldStyleBulkInsertValue( int index, long increment )
-         throws StandardException
-     {
-         NumberDataValue dvd;
-         int columnPosition = index + 1;
-         ColumnDescriptor cd = td.getColumnDescriptor(columnPosition);
-         long ret;
+    /**
+     * Identity generation logic for bulk-insert used in pre-10.11 databases.
+     *
+     * @param index   0-based index into aiCache
+     */
+    private void    getOldStyleBulkInsertValue( int index, long increment )
+        throws StandardException {
+        NumberDataValue dvd;
+        int columnPosition = index + 1;
+        ColumnDescriptor cd = td.getColumnDescriptor(columnPosition);
+        long ret;
  
-         // for bulk insert we have the table descriptor
-         //			System.out.println("in bulk insert");
-         if (aiCache[index].isNull())
-         {
-             long startValue;
+        // for bulk insert we have the table descriptor
+        //			System.out.println("in bulk insert");
+        if (aiCache[index].isNull())
+        {
+            long startValue;
  
-             if (bulkInsertReplace)
-             {
-                 startValue = cd.getAutoincStart();
-             }
-             else
-             {
-                 dvd = dd.getSetAutoincrementValue(
-                                                   constants.autoincRowLocation[index],
-                                                   tc, false, (NumberDataValue) aiCache[index], true);
-                 startValue = dvd.getLong();
-             }
-             lcc.autoincrementCreateCounter(td.getSchemaName(),
-                                            td.getName(),
-                                            cd.getColumnName(),
-                                            Long.valueOf(startValue),
-                                            increment,
-                                            columnPosition);
+            if (bulkInsertReplace)
+            {
+                startValue = cd.getAutoincStart();
+            }
+            else
+            {
+                dvd = dd.getSetAutoincrementValue(
+                    constants.autoincRowLocation[index],
+                    tc, false, (NumberDataValue) aiCache[index], true);
+                startValue = dvd.getLong();
+            }
+            lcc.autoincrementCreateCounter(td.getSchemaName(),
+                                           td.getName(),
+                                           cd.getColumnName(),
+                                           Long.valueOf(startValue),
+                                           increment,
+                                           columnPosition);
  			
-         }  		
-         ret = lcc.nextAutoincrementValue(td.getSchemaName(),
-                                          td.getName(),
-                                          cd.getColumnName());
-         aiCache[columnPosition - 1].setValue(ret);
-     }
+        }  		
+        ret = lcc.nextAutoincrementValue(td.getSchemaName(),
+                                         td.getName(),
+                                         cd.getColumnName());
+        aiCache[columnPosition - 1].setValue(ret);
+    }
  
-     /**
-      * Identity generation logic used in pre-10.11 databases.
-      *
-      * @param index   0-based index into aiCache
-      */
-     private NumberDataValue getOldStyleIdentityValue( int index )
-         throws StandardException
-     {
-         NumberDataValue newValue;
-         TransactionController nestedTC = null;
-         TransactionController tcToUse;
+    /**
+     * Identity generation logic used in pre-10.11 databases.
+     *
+     * @param index   0-based index into aiCache
+     */
+    private NumberDataValue getOldStyleIdentityValue( int index )
+        throws StandardException {
+        NumberDataValue newValue;
+        TransactionController nestedTC = null;
+        TransactionController tcToUse;
  
-         try
-         {
-             // DERBY-5780, defaulting log syncing to false, which improves
-             // performance of identity value generation.  If system 
-             // crashes may reuse an identity value because commit did not
-             // sync, but only if no subsequent user transaction has 
-             // committed or aborted and thus no row can exist that used
-             // the previous value.  Without this identity values pay
-             // a synchronous I/O to the log file for each new value no
-             // matter how many are inserted in a single transaction.
-             nestedTC = tc.startNestedUserTransaction(false, false);
-             tcToUse = nestedTC;
-         }
-         catch (StandardException se)
-         {
-             // If I cannot start a Nested User Transaction use the parent
-             // transaction to do all the work.
-             tcToUse = tc;
-         }
+        try
+        {
+            // DERBY-5780, defaulting log syncing to false, which improves
+            // performance of identity value generation.  If system 
+            // crashes may reuse an identity value because commit did not
+            // sync, but only if no subsequent user transaction has 
+            // committed or aborted and thus no row can exist that used
+            // the previous value.  Without this identity values pay
+            // a synchronous I/O to the log file for each new value no
+            // matter how many are inserted in a single transaction.
+            nestedTC = tc.startNestedUserTransaction(false, false);
+            tcToUse = nestedTC;
+        }
+        catch (StandardException se)
+        {
+            // If I cannot start a Nested User Transaction use the parent
+            // transaction to do all the work.
+            tcToUse = tc;
+        }
  
-         try 
-         {
-             /* If tcToUse == tc, then we are using parent xaction-- this
-                can happen if for some reason we couldn't start a nested
-                transaction
-             */
-             newValue = dd.getSetAutoincrementValue(
-                                                    constants.autoincRowLocation[index],
-                                                    tcToUse, true, (NumberDataValue) aiCache[index], (tcToUse == tc));
-         }
-         catch (StandardException se)
-         {
-             if (tcToUse == tc)
-             {
-                 /* we've using the parent xaction and we've timed out; just
-                    throw an error and exit.
-                 */
-                 throw se;
-             }
+        try 
+        {
+            /* If tcToUse == tc, then we are using parent xaction-- this
+               can happen if for some reason we couldn't start a nested
+               transaction
+            */
+            newValue = dd.getSetAutoincrementValue(
+                constants.autoincRowLocation[index],
+                tcToUse, true, (NumberDataValue) aiCache[index], (tcToUse == tc));
+        }
+        catch (StandardException se)
+        {
+            if (tcToUse == tc)
+            {
+                /* we've using the parent xaction and we've timed out; just
+                   throw an error and exit.
+                */
+                throw se;
+            }
  
-             if ( se.getMessageId().equals(SQLState.LOCK_TIMEOUT) || se.isSelfDeadlock() )
-             {
-                 // if we couldn't do this with a nested xaction, retry with
-                 // parent-- we need to wait this time!
-                 newValue = dd.getSetAutoincrementValue(
-                                                        constants.autoincRowLocation[index],
-                                                        tc, true, (NumberDataValue) aiCache[index], true);
-             }
-             else if (se.getMessageId().equals(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE))
-             {
-                 // if we got an overflow error, throw a more meaningful
-                 // error message
-                 throw StandardException.newException(
-                                                      SQLState.LANG_AI_OVERFLOW,
-                                                      se,
-                                                      constants.getTableName(),
-                                                      constants.getColumnName(index));
-             }
-             else throw se;
-         }
-         finally 
-         {
-             // no matter what, commit the nested transaction; if something
-             // bad happened in the child xaction lets not abort the parent
-             // here.
+            if ( se.getMessageId().equals(SQLState.LOCK_TIMEOUT) || se.isSelfDeadlock() )
+            {
+                // if we couldn't do this with a nested xaction, retry with
+                // parent-- we need to wait this time!
+                newValue = dd.getSetAutoincrementValue(
+                    constants.autoincRowLocation[index],
+                    tc, true, (NumberDataValue) aiCache[index], true);
+            }
+            else if (se.getMessageId().equals(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE))
+            {
+                // if we got an overflow error, throw a more meaningful
+                // error message
+                throw StandardException.newException(
+                    SQLState.LANG_AI_OVERFLOW,
+                    se,
+                    constants.getTableName(),
+                    constants.getColumnName(index));
+            }
+            else throw se;
+        }
+        finally 
+        {
+            // no matter what, commit the nested transaction; if something
+            // bad happened in the child xaction lets not abort the parent
+            // here.
                  
-             if (nestedTC != null)
-             {
-                 // DERBY-5493 - prior to fix all nested user update 
-                 // transactions did a nosync commit when commit() was 
-                 // called, this default has been changed to do synced 
-                 // commit.  Changed this commit to be commitNoSync to
-                 // not introduce performce degredation for autoincrement
-                 // keys.  As before, if server crashes the changes 
-                 // made in the nested transaction may be lost.  If any
-                 // subsequent user transaction is commited, including any
-                 // inserts that would depend on the autoincrement value
-                 // change then the nested tranaction is guaranteed on
-                 // system crash.
-                 nestedTC.commitNoSync(TransactionController.RELEASE_LOCKS);
-                 nestedTC.destroy();
-             }
-         }
+            if (nestedTC != null)
+            {
+                // DERBY-5493 - prior to fix all nested user update 
+                // transactions did a nosync commit when commit() was 
+                // called, this default has been changed to do synced 
+                // commit.  Changed this commit to be commitNoSync to
+                // not introduce performce degredation for autoincrement
+                // keys.  As before, if server crashes the changes 
+                // made in the nested transaction may be lost.  If any
+                // subsequent user transaction is commited, including any
+                // inserts that would depend on the autoincrement value
+                // change then the nested tranaction is guaranteed on
+                // system crash.
+                nestedTC.commitNoSync(TransactionController.RELEASE_LOCKS);
+                nestedTC.destroy();
+            }
+        }
  
-         return newValue;
-     }
+        return newValue;
+    }
      
-	// Is sourceResultSet a RowResultSet (values clause)?
-	private boolean isSourceRowResultSet ()
+    // Is sourceResultSet a RowResultSet (values clause)?
+    private boolean isSourceRowResultSet ()
 	{
-		boolean isRow = false;
-		if (sourceResultSet instanceof NormalizeResultSet)
-			isRow = (((NormalizeResultSet) sourceResultSet).source instanceof RowResultSet);
-		return isRow;
+            boolean isRow = false;
+            if (sourceResultSet instanceof NormalizeResultSet)
+                isRow = (((NormalizeResultSet) sourceResultSet).source instanceof RowResultSet);
+            return isRow;
 	}
 
     // checks if source result set is a RowResultSet type.
-    private boolean isSingleRowResultSet()
-    {
+    private boolean isSingleRowResultSet() {
         boolean isRow = false;
         
         if (sourceResultSet instanceof RowResultSet)
-        	isRow = true;
+            isRow = true;
         else if (sourceResultSet instanceof NormalizeResultSet)
             isRow = (((NormalizeResultSet) sourceResultSet).source instanceof RowResultSet);
         
         return isRow;
     }
 	
-	// Do the work for a "normal" insert
-	private void normalInsertCore(LanguageConnectionContext lcc, boolean firstExecute)
-		throws StandardException
-	{
-		boolean setUserIdentity = constants.hasAutoincrement() && isSingleRowResultSet();
+    // Do the work for a "normal" insert
+    private void normalInsertCore(LanguageConnectionContext lcc, boolean firstExecute)
+        throws StandardException {
+        boolean setUserIdentity = constants.hasAutoincrement() && isSingleRowResultSet();
         ExecRow deferredRowBuffer;
         long user_autoinc=0;
                         
-		/* Get or re-use the row changer.
-		 */
-		if (firstExecute)
-		{
-			rowChanger = lcc.getLanguageConnectionFactory().getExecutionFactory()
-						     .getRowChanger(
-									 heapConglom,
-									 constants.heapSCOCI,
-									 heapDCOCI,
-									 constants.irgs,
-									 constants.indexCIDS,
-									 constants.indexSCOCIs,
-									 indexDCOCIs,
-									 0, // number of columns in partial row meaningless for insert
-									 tc,
-									 null, //Changed column ids
-									 constants.getStreamStorableHeapColIds(),
-									 activation
-							       );
-			rowChanger.setIndexNames(constants.indexNames);
-		}
-
-		/* decode lock mode for the execution isolation level */
-		int lockMode = decodeLockMode(constants.lockMode);
-
-		rowChanger.open(lockMode);
-
-		/* The source does not know whether or not we are doing a
-		 * deferred mode insert.  If we are, then we must clear the
-		 * index scan info from the activation so that the row changer
-		 * does not re-use that information (which won't be valid for
-		 * a deferred mode insert).
-		 */
-		if (constants.deferred)
-		{
-			activation.clearIndexScanInfo();
-		}
-
-		if (fkInfoArray != null)
-		{
-			if (fkChecker == null)
-			{
+        /* Get or re-use the row changer.
+         */
+        if (firstExecute)
+        {
+            rowChanger = lcc.getLanguageConnectionFactory().getExecutionFactory()
+                .getRowChanger(
+                    heapConglom,
+                    constants.heapSCOCI,
+                    heapDCOCI,
+                    constants.irgs,
+                    constants.indexCIDS,
+                    constants.indexSCOCIs,
+                    indexDCOCIs,
+                    0, // number of columns in partial row meaningless for insert
+                    tc,
+                    null, //Changed column ids
+                    constants.getStreamStorableHeapColIds(),
+                    activation
+                    );
+            rowChanger.setIndexNames(constants.indexNames);
+        }
+
+        /* decode lock mode for the execution isolation level */
+        int lockMode = decodeLockMode(constants.lockMode);
+
+        rowChanger.open(lockMode);
+
+        /* The source does not know whether or not we are doing a
+         * deferred mode insert.  If we are, then we must clear the
+         * index scan info from the activation so that the row changer
+         * does not re-use that information (which won't be valid for
+         * a deferred mode insert).
+         */
+        if (constants.deferred)
+        {
+            activation.clearIndexScanInfo();
+        }
+
+        if (fkInfoArray != null)
+        {
+            if (fkChecker == null)
+            {
                 fkChecker = new RISetChecker(lcc, tc, fkInfoArray);
-			}
-			else
-			{
-				fkChecker.reopen();
-			}
-		}
-
-		if (firstExecute && constants.deferred)
-		{
-			Properties properties = new Properties();
-
-			// Get the properties on the old heap
-			rowChanger.getHeapConglomerateController().getInternalTablePropertySet(properties);
-
-			/*
-			** If deferred we save a copy of the entire row.
-			*/
-			rowHolder = new TemporaryRowHolderImpl(activation, properties,
-												   resultDescription);
-			rowChanger.setRowHolder(rowHolder);
-		}
+            }
+            else
+            {
+                fkChecker.reopen();
+            }
+        }
 
-		firstExecuteSpecialHandlingAutoGen(firstExecute, rowChanger, constants.targetUUID);
+        if (firstExecute && constants.deferred)
+        {
+            Properties properties = new Properties();
+
+            // Get the properties on the old heap
+            rowChanger.getHeapConglomerateController().getInternalTablePropertySet(properties);
+
+            /*
+            ** If deferred we save a copy of the entire row.
+            */
+            rowHolder = new TemporaryRowHolderImpl(activation, properties,
+                                                   resultDescription);
+            rowChanger.setRowHolder(rowHolder);
+        }
 
-		while ( row != null )
-		{
+        firstExecuteSpecialHandlingAutoGen(firstExecute, rowChanger, constants.targetUUID);
+
+        while ( row != null )
+        {
             // Collect auto-generated keys if requested.
             // DERBY-5823: No need to collect them if there are no
             // auto-generated key columns.
             if (activation.getAutoGeneratedKeysResultsetMode() &&
-                    autoGeneratedKeysColumnIndexes.length > 0) {
+                autoGeneratedKeysColumnIndexes.length > 0) {
                 autoGeneratedKeysRowsHolder.insert(
-                        getCompactRow(row, autoGeneratedKeysColumnIndexes));
+                    getCompactRow(row, autoGeneratedKeysColumnIndexes));
             }
 
             // fill in columns that are computed from expressions on other columns
             evaluateGenerationClauses( generationClauses, activation, sourceResultSet, row, false );
                     
-			/*
-			** If we're doing a deferred insert, insert into the temporary
-			** conglomerate.  Otherwise, insert directly into the permanent
-			** conglomerates using the rowChanger.
-			*/
-			if (constants.deferred)
-			{
-					rowHolder.insert(row);
-			}
-			else
-			{
+            /*
+            ** If we're doing a deferred insert, insert into the temporary
+            ** conglomerate.  Otherwise, insert directly into the permanent
+            ** conglomerates using the rowChanger.
+            */
+            if (constants.deferred)
+            {
+                rowHolder.insert(row);
+            }
+            else
+            {
                 // Immediate mode violations will throw, so we only ever
                 // see false here with deferred constraint mode for one or more
                 // of the constraints being checked.
                 boolean allOk = evaluateCheckConstraints();
 
-				if (fkChecker != null)
-				{
+                if (fkChecker != null)
+                {
                     fkChecker.doFKCheck(activation, row);
-				}
+                }
+
+                // Objectify any streaming columns that are indexed.
+                if (constants.irgs.length > 0)
+                {
+                    DataValueDescriptor[] rowArray = row.getRowArray();
+                    for (int i = 0; i < rowArray.length; i++)
+                    {
+                        //System.out.println("checking " + i);
+                        if (! constants.indexedCols[i])
+                        {
+                            continue;
+                        }
 
-				// Objectify any streaming columns that are indexed.
-				if (constants.irgs.length > 0)
-				{
-					DataValueDescriptor[] rowArray = row.getRowArray();
-					for (int i = 0; i < rowArray.length; i++)
-					{
-						//System.out.println("checking " + i);
-						if (! constants.indexedCols[i])
-						{
-							continue;
-						}
-
-
-						if (rowArray[i] instanceof StreamStorable)
-							rowArray[i].getObject();
-					}
-				}
+
+                        if (rowArray[i] instanceof StreamStorable)
+                            rowArray[i].getObject();
+                    }
+                }
 
                 if (allOk) {
                     rowChanger.insertRow(row, false);
@@ -892,110 +882,110 @@ class InsertResultSet extends DMLWriteGe
                             offendingRow,
                             new CheckInfo[1] /* dummy */);
                 }
-			}
+            }
 
             rowCount++;
             
             if(setUserIdentity )
             {
-                        dd = lcc.getDataDictionary();
-                        td = dd.getTableDescriptor(constants.targetUUID);
+                dd = lcc.getDataDictionary();
+                td = dd.getTableDescriptor(constants.targetUUID);
                        
-                        int maxColumns = td.getMaxColumnID();
-                        int col;
+                int maxColumns = td.getMaxColumnID();
+                int col;
                         
-                        for(col=1;col<=maxColumns;col++)
-                        {
-                            ColumnDescriptor cd = td.getColumnDescriptor(col);
-                            if(cd.isAutoincrement())
-                            {
-                                break;
-                            }
-                        }
+                for(col=1;col<=maxColumns;col++)
+                {
+                    ColumnDescriptor cd = td.getColumnDescriptor(col);
+                    if(cd.isAutoincrement())
+                    {
+                        break;
+                    }
+                }
                         
-                        if(col <= maxColumns)
-                        {
-                            DataValueDescriptor dvd = row.cloneColumn(col);
-                            user_autoinc = dvd.getLong();
-                        }
-             } 
+                if(col <= maxColumns)
+                {
+                    DataValueDescriptor dvd = row.cloneColumn(col);
+                    user_autoinc = dvd.getLong();
+                }
+            } 
 
-			// No need to do a next on a single row source
-             if (constants.singleRowSource)
-	     {
-			row = null;
-	     }
-	     else
-	     {
+            // No need to do a next on a single row source
+            if (constants.singleRowSource)
+            {
+                row = null;
+            }
+            else
+            {
 		row = getNextRowCore(sourceResultSet);
-	     }
+            }
         }
 
-		/*
-		** If it's a deferred insert, scan the temporary conglomerate and
-		** insert the rows into the permanent conglomerates using rowChanger.
-		*/
-		if (constants.deferred)
-		{
-			if (triggerInfo != null)
-			{
-				Vector<AutoincrementCounter> v = null;
-				if (aiCache != null)
-				{
-					v = new Vector<AutoincrementCounter>();
-					for (int i = 0; i < aiCache.length; i++)
-					{
-						String s, t, c;
-						if (aiCache[i] == null)
-							continue;
+        /*
+        ** If it's a deferred insert, scan the temporary conglomerate and
+        ** insert the rows into the permanent conglomerates using rowChanger.
+        */
+        if (constants.deferred)
+        {
+            if (triggerInfo != null)
+            {
+                Vector<AutoincrementCounter> v = null;
+                if (aiCache != null)
+                {
+                    v = new Vector<AutoincrementCounter>();
+                    for (int i = 0; i < aiCache.length; i++)
+                    {
+                        String s, t, c;
+                        if (aiCache[i] == null)
+                            continue;
 					
-						Long initialValue = 
-							lcc.lastAutoincrementValue(
-											(s = constants.getSchemaName()),
-											(t = constants.getTableName()),
-											(c = constants.getColumnName(i)));
-
-
-						AutoincrementCounter aic = 
-							new AutoincrementCounter(
-											 initialValue,
-											 constants.getAutoincIncrement(i),
-											 aiCache[i].getLong(),
-											 s, t, c, i + 1);
-						v.addElement(aic);
-					}
-				}
-
-				if (triggerActivator == null)
-				{
-					triggerActivator = new TriggerEventActivator(lcc, 
-										constants.targetUUID,
-										triggerInfo,
-										TriggerExecutionContext.INSERT_EVENT,
-										activation, 
-										v);
-				}
-				else
-				{
-					triggerActivator.reopen();
-				}
-
-				// fire BEFORE trigger, do this before checking constraints
-				triggerActivator.notifyEvent(TriggerEvents.BEFORE_INSERT, 
-												(CursorResultSet)null,
-												rowHolder.getResultSet(), 
-												(int[])null);
-			}
-
-			CursorResultSet rs = rowHolder.getResultSet();
-			try
-			{
-				rs.open();
-				while ((deferredRowBuffer = rs.getNextRow()) != null)
-				{
-					// we have to set the source row so the check constraint
-					// sees the correct row.
-					sourceResultSet.setCurrentRow(deferredRowBuffer);
+                        Long initialValue = 
+                            lcc.lastAutoincrementValue(
+                                (s = constants.getSchemaName()),
+                                (t = constants.getTableName()),
+                                (c = constants.getColumnName(i)));
+
+
+                        AutoincrementCounter aic = 
+                            new AutoincrementCounter(
+                                initialValue,
+                                constants.getAutoincIncrement(i),
+                                aiCache[i].getLong(),
+                                s, t, c, i + 1);
+                        v.addElement(aic);
+                    }
+                }
+
+                if (triggerActivator == null)
+                {
+                    triggerActivator = new TriggerEventActivator(lcc, 
+                                                                 constants.targetUUID,
+                                                                 triggerInfo,
+                                                                 TriggerExecutionContext.INSERT_EVENT,
+                                                                 activation, 
+                                                                 v);
+                }
+                else
+                {
+                    triggerActivator.reopen();
+                }
+
+                // fire BEFORE trigger, do this before checking constraints
+                triggerActivator.notifyEvent(TriggerEvents.BEFORE_INSERT, 
+                                             (CursorResultSet)null,
+                                             rowHolder.getResultSet(), 
+                                             (int[])null);
+            }
+
+            CursorResultSet rs = rowHolder.getResultSet();
+            try
+            {
+                rs.open();
+                while ((deferredRowBuffer = rs.getNextRow()) != null)
+                {
+                    // we have to set the source row so the check constraint
+                    // sees the correct row.
+                    sourceResultSet.setCurrentRow(deferredRowBuffer);
                     boolean allOk = evaluateCheckConstraints();
 
                     if (allOk) {
@@ -1014,71 +1004,70 @@ class InsertResultSet extends DMLWriteGe
                                 offendingRow,
                                 new CheckInfo[1]);
                     }
-				}
-			} finally
-			{
-				sourceResultSet.clearCurrentRow();
-				rs.close();
-			}
+                }
+            } finally
+            {
+                sourceResultSet.clearCurrentRow();
+                rs.close();
+            }
 			
-			if (fkChecker != null)
-			{
-				/*
-				** Second scan to make sure all the foreign key
-				** constraints are ok.  We have to do this after
-				** we have completed the inserts in case of self
-				** referencing constraints.
-				*/
-				rs = rowHolder.getResultSet();
-				try
-				{
-					rs.open();
-					while ((deferredRowBuffer = rs.getNextRow()) != null)
-					{
-                        fkChecker.doFKCheck(activation, deferredRowBuffer);
-					}
-				} finally
-				{
-					rs.close();
-				}
-			}
-
-			// fire AFTER trigger
-			if (triggerActivator != null)
-			{
-				triggerActivator.notifyEvent(TriggerEvents.AFTER_INSERT, 
-										(CursorResultSet)null,
-										rowHolder.getResultSet(), 
-										(int[])null);
-			}
-		}
-
-		if (rowHolder != null)
-		{
-			rowHolder.close();
-			// rowHolder kept across opens
-		}
-		if (fkChecker != null)
-		{
-			fkChecker.close();
-			fkChecker = null;
-		}
-		if (setIdentity)
-			lcc.setIdentityValue(identityVal);
+            if (fkChecker != null)
+            {
                 /*
-                 * find the value of the identity column from the user inserted value
-                 * and do a lcc.setIdentityValue(<user_value>);
-                 */
-                else if(setUserIdentity )
-                {
-                        lcc.setIdentityValue(user_autoinc);
-                } 
- }
+                ** Second scan to make sure all the foreign key
+                ** constraints are ok.  We have to do this after
+                ** we have completed the inserts in case of self
+                ** referencing constraints.
+                */
+                rs = rowHolder.getResultSet();
+                try
+                {
+                    rs.open();
+                    while ((deferredRowBuffer = rs.getNextRow()) != null)
+                    {
+                        fkChecker.doFKCheck(activation, deferredRowBuffer);
+                    }
+                } finally
+                {
+                    rs.close();
+                }
+            }
+
+            // fire AFTER trigger
+            if (triggerActivator != null)
+            {
+                triggerActivator.notifyEvent(TriggerEvents.AFTER_INSERT, 
+                                             (CursorResultSet)null,
+                                             rowHolder.getResultSet(), 
+                                             (int[])null);
+            }
+        }
+
+        if (rowHolder != null)
+        {
+            rowHolder.close();
+            // rowHolder kept across opens
+        }
+        if (fkChecker != null)
+        {
+            fkChecker.close();
+            fkChecker = null;
+        }
+        if (setIdentity)
+            lcc.setIdentityValue(identityVal);
+        /*
+         * find the value of the identity column from the user inserted value
+         * and do a lcc.setIdentityValue(<user_value>);
+         */
+        else if(setUserIdentity )
+        {
+            lcc.setIdentityValue(user_autoinc);
+        } 
+    }
 
     @Override
-	protected ExecRow getNextRowCore( NoPutResultSet source )
-		throws StandardException
-	{
+    protected ExecRow getNextRowCore( NoPutResultSet source )
+        throws StandardException {
         ExecRow nextRow = super.getNextRowCore( source );
 
         if ( (nextRow != null) && constants.underMerge() ) {
@@ -1086,16 +1075,15 @@ class InsertResultSet extends DMLWriteGe
         }
 
         return nextRow;
-	}
+    }
 
     /**
      * <p>
      * Special handling if this is an INSERT action of a MERGE statement.
      * </p>
      */
-	private ExecRow processMergeRow( NoPutResultSet sourceRS, ExecRow row )
-		throws StandardException
-	{
+    private ExecRow processMergeRow( NoPutResultSet sourceRS, ExecRow row )
+        throws StandardException {
         //
         // The normal processing of autogenerated columns happens in
         // the evaluation of the driving ResultSet. That processing assumes
@@ -1116,9 +1104,12 @@ class InsertResultSet extends DMLWriteGe
             // If the identity column was declared BY DEFAULT, then it could be
             // overridden by the WHEN NOT MATCHED clause. In that case, the
             // row will contain a non-null value which we do not want to clobber.
+            // Commented code preserves previous attempts to solve this situation--
+            // in case this issue needs to be revisited.
             //
             //boolean needToGenerateValue = ( dvd == null ) || ( dvd.isNullOp().getBoolean() );
-            boolean needToGenerateValue = ( dvd == null );
+            //boolean needToGenerateValue = ( dvd == null );
+            boolean needToGenerateValue = ( dvd == null ) || constants.autoincrementColumnSetToDEFAULT();
 
             if ( needToGenerateValue )
             {
@@ -1129,79 +1120,78 @@ class InsertResultSet extends DMLWriteGe
         }
 
         return normalizeRow( sourceRS, row );
-	}
+    }
 
-	// Do the work for a bulk insert
+    // Do the work for a bulk insert
     private void bulkInsertCore(LanguageConnectionContext lcc,
                                 ExecRow fullTemplate,
-								long oldHeapConglom)
-		throws StandardException
-	{
-		bulkHeapCC = tc.openCompiledConglomerate(
-                                false,
-                                TransactionController.OPENMODE_FORUPDATE,
-                                TransactionController.MODE_TABLE,
-                                TransactionController.ISOLATION_SERIALIZABLE,
-								constants.heapSCOCI,
-								heapDCOCI);
+                                long oldHeapConglom)
+        throws StandardException {
+        bulkHeapCC = tc.openCompiledConglomerate(
+            false,
+            TransactionController.OPENMODE_FORUPDATE,
+            TransactionController.MODE_TABLE,
+            TransactionController.ISOLATION_SERIALIZABLE,
+            constants.heapSCOCI,
+            heapDCOCI);
 
-		long newHeapConglom;
+        long newHeapConglom;
 
-		Properties properties = new Properties();
+        Properties properties = new Properties();
 
-		// Get the properties on the old heap
-		bulkHeapCC.getInternalTablePropertySet(properties);
+        // Get the properties on the old heap
+        bulkHeapCC.getInternalTablePropertySet(properties);
 
         if (triggerInfo != null) {
             // no triggers in bulk insert mode
             if (SanityManager.DEBUG) {
                 SanityManager.NOTREACHED();
             }
-		}
+        }
+
+        /*
+        ** If we have a before row trigger, then we
+        ** are going to use a row holder pass to our
+        ** trigger.
+        */
+        if (hasBeforeRowTrigger && rowHolder != null)
+        {
+            rowHolder =
+                new TemporaryRowHolderImpl(activation, properties,
+                                           resultDescription);
+        }
 
-		/*
-		** If we have a before row trigger, then we
-		** are going to use a row holder pass to our
-		** trigger.
-		*/
-		if (hasBeforeRowTrigger && rowHolder != null)
-		{
-			rowHolder =
-				new TemporaryRowHolderImpl(activation, properties,
-										   resultDescription);
-		}
-
-		// Add any new properties or change the values of any existing properties
-		Properties targetProperties = constants.getTargetProperties();
-		Enumeration key = targetProperties.keys();
-		while (key.hasMoreElements())
-		{
-			String keyValue = (String) key.nextElement();
-			properties.put(keyValue, targetProperties.getProperty(keyValue));
-		}
-
-		// Are there indexes to be updated?
-		if (constants.irgs.length > 0)
-		{
-			// Tell source whether or not we need the RIDs back
-			sourceResultSet.setNeedsRowLocation(true);
-		}
+        // Add any new properties or change the values of any existing properties
+        Properties targetProperties = constants.getTargetProperties();
+        Enumeration key = targetProperties.keys();
+        while (key.hasMoreElements())
+        {
+            String keyValue = (String) key.nextElement();
+            properties.put(keyValue, targetProperties.getProperty(keyValue));
+        }
+
+        // Are there indexes to be updated?
+        if (constants.irgs.length > 0)
+        {
+            // Tell source whether or not we need the RIDs back
+            sourceResultSet.setNeedsRowLocation(true);
+        }
 
         if (constants.hasDeferrableChecks) {
             sourceResultSet.setHasDeferrableChecks();
         }
 
 
-		dd = lcc.getDataDictionary();
-		td = dd.getTableDescriptor(constants.targetUUID);
+        dd = lcc.getDataDictionary();
+        td = dd.getTableDescriptor(constants.targetUUID);
 
-		/* Do the bulk insert - only okay to reuse the
-		 * same conglomerate if bulkInsert.
-		 */
-		long[] loadedRowCount = new long[1];
-		if (bulkInsertReplace)
-		{
-			newHeapConglom = 
+        /* Do the bulk insert - only okay to reuse the
+         * same conglomerate if bulkInsert.
+         */
+        long[] loadedRowCount = new long[1];
+        if (bulkInsertReplace)
+        {
+            newHeapConglom = 
                 tc.createAndLoadConglomerate(
                     "heap",
                     fullTemplate.getRowArray(),
@@ -1211,10 +1201,10 @@ class InsertResultSet extends DMLWriteGe
                     TransactionController.IS_DEFAULT,
                     sourceResultSet,
                     loadedRowCount);
-		}
-		else
-		{
-			newHeapConglom = 
+        }
+        else
+        {
+            newHeapConglom = 
                 tc.recreateAndLoadConglomerate(
                     "heap",
                     false,
@@ -1226,32 +1216,32 @@ class InsertResultSet extends DMLWriteGe
                     oldHeapConglom,
                     sourceResultSet,
                     loadedRowCount);
-		}
+        }
 
-		/* Nothing else to do if we get back the same conglomerate number.
-		 * (In 2.0 this means that 0 rows were inserted.)
-		 */
-		if (newHeapConglom == oldHeapConglom)
-		{
+        /* Nothing else to do if we get back the same conglomerate number.
+         * (In 2.0 this means that 0 rows were inserted.)
+         */
+        if (newHeapConglom == oldHeapConglom)
+        {
             return;
-		}
+        }
 
-		// Find out how many rows were inserted
-		rowCount = loadedRowCount[0];
+        // Find out how many rows were inserted
+        rowCount = loadedRowCount[0];
 
-		// Set the "estimated" row count
-		setEstimatedRowCount(newHeapConglom);
+        // Set the "estimated" row count
+        setEstimatedRowCount(newHeapConglom);
 
-		/*
-		** Inform the data dictionary that we are about to write to it.
-		** There are several calls to data dictionary "get" methods here
-		** that might be done in "read" mode in the data dictionary, but
-		** it seemed safer to do this whole operation in "write" mode.
-		**
-		** We tell the data dictionary we're done writing at the end of
-		** the transaction.
-		*/
-		dd.startWriting(lcc);
+        /*
+        ** Inform the data dictionary that we are about to write to it.
+        ** There are several calls to data dictionary "get" methods here
+        ** that might be done in "read" mode in the data dictionary, but
+        ** it seemed safer to do this whole operation in "write" mode.
+        **
+        ** We tell the data dictionary we're done writing at the end of
+        ** the transaction.
+        */
+        dd.startWriting(lcc);
 
         //
         // If we were doing bulkInsert, then we need to flush the last
@@ -1272,388 +1262,384 @@ class InsertResultSet extends DMLWriteGe
             }
         }
 
-		// invalidate any prepared statements that
-		// depended on this table (including this one)
-		DependencyManager dm = dd.getDependencyManager();
+        // invalidate any prepared statements that
+        // depended on this table (including this one)
+        DependencyManager dm = dd.getDependencyManager();
 
-		dm.invalidateFor(td, DependencyManager.BULK_INSERT, lcc);
+        dm.invalidateFor(td, DependencyManager.BULK_INSERT, lcc);
 
 		
-		// Update all indexes
-		if (constants.irgs.length > 0)
-		{
+        // Update all indexes
+        if (constants.irgs.length > 0)
+        {
 //            MEN VI HAR MANGE SORTS, EN PR INDEX: alle blir droppet, hvordan
 //                    assossiere alle med nye indekser som tildeles inni her???
 //                            FIXME!!
-			updateAllIndexes(newHeapConglom, constants, td, dd, fullTemplate);
-		}
+            updateAllIndexes(newHeapConglom, constants, td, dd, fullTemplate);
+        }
 
-		// Drop the old conglomerate
-		bulkHeapCC.close();
-		bulkHeapCC = null;
-
-		/* Update the DataDictionary
-		 * RESOLVE - this will change in 1.4 because we will get
-		 * back the same conglomerate number
-		 */
-		// Get the ConglomerateDescriptor for the heap
-		ConglomerateDescriptor cd = td.getConglomerateDescriptor(oldHeapConglom);
-
-		// Update sys.sysconglomerates with new conglomerate #
-		dd.updateConglomerateDescriptor(cd, newHeapConglom, tc);
-		tc.dropConglomerate(oldHeapConglom);
-		// END RESOLVE
-	}
+        // Drop the old conglomerate
+        bulkHeapCC.close();
+        bulkHeapCC = null;
+
+        /* Update the DataDictionary
+         * RESOLVE - this will change in 1.4 because we will get
+         * back the same conglomerate number
+         */
+        // Get the ConglomerateDescriptor for the heap
+        ConglomerateDescriptor cd = td.getConglomerateDescriptor(oldHeapConglom);
+
+        // Update sys.sysconglomerates with new conglomerate #
+        dd.updateConglomerateDescriptor(cd, newHeapConglom, tc);
+        tc.dropConglomerate(oldHeapConglom);
+        // END RESOLVE
+    }
 
-	/**
-	** Bulk Referential Integrity Checker
-	*/
+    /**
+     ** Bulk Referential Integrity Checker
+     */
     private void bulkValidateForeignKeys(
-            TransactionController tc, ContextManager cm, ExecRow fullTemplate)
-		throws StandardException
-	{
-		/*
-		** If there are no foreign keys, then nothing to worry 
-		** about.
-		** With bulk insert replace, we still need to verify 
-		** all non-self referencing foreign keys when
-		** there are no rows inserted into the table.
-		*/
-		if ((indexRows == null && !bulkInsertReplace) || 
-			fkInfoArray == null)
-		{
-			return;
-		}
+        TransactionController tc, ContextManager cm, ExecRow fullTemplate)
+        throws StandardException {
+        /*
+        ** If there are no foreign keys, then nothing to worry 
+        ** about.
+        ** With bulk insert replace, we still need to verify 
+        ** all non-self referencing foreign keys when
+        ** there are no rows inserted into the table.
+        */
+        if ((indexRows == null && !bulkInsertReplace) || 
+            fkInfoArray == null)
+        {
+            return;
+        }
 
         for (FKInfo fkInfo : fkInfoArray)
-		{
+        {
 
-			/* With regular bulk insert, we only need to check the
-			 * foreign keys in the table we inserted into.  We need
-			 * to get the new conglomerate #s for the foreign keys.
-			 *
-			 * With bulk insert replace, we need to check both the
-			 * foreign keys in the table as well as any foreign keys
-			 * on other tables referencing the table we inserted into.
-			 * If the foreign key is self-referencing then we need to
-			 * get the new conglomerate #, otherwise the conglomerate
-			 * # is the same as the compile time conglomerate #.
-			 * If the foreign key is self-referencing then we need to
-			 * get the new conglomerate # for the primary key as it
-			 * has changed.  However, if the foreign key is not self-referencing
-			 * then we only need to get the new conglomerate # for
-			 * the primary key if the primary key is on the table being 
-			 * inserted into.
-			 */
-			if (bulkInsertReplace)
-			{
-				for (int index = 0; index < fkInfo.fkConglomNumbers.length; index++)
-				{
-					/* No need to check foreign key if it is self referencing
-					 * and there were no rows inserted on the replace, as both
-					 * indexes will be empty.
-					 */
-					if (fkInfo.fkIsSelfReferencing[index] && indexRows == null)
-					{
-						continue;
-					}
-
-					long pkConglom;
-					long fkConglom;
-
-					if (fkInfo.fkIsSelfReferencing[index])
-					{
-						/* Self-referencing foreign key.  Both conglomerate
-						 * #s have changed.
-						 */
-						pkConglom = (indexConversionTable.get(
-                            Long.valueOf(fkInfo.refConglomNumber))).longValue();
-						fkConglom = (indexConversionTable.get(
-                            Long.valueOf(fkInfo.fkConglomNumbers[index]))).
+            /* With regular bulk insert, we only need to check the
+             * foreign keys in the table we inserted into.  We need
+             * to get the new conglomerate #s for the foreign keys.
+             *
+             * With bulk insert replace, we need to check both the
+             * foreign keys in the table as well as any foreign keys
+             * on other tables referencing the table we inserted into.
+             * If the foreign key is self-referencing then we need to
+             * get the new conglomerate #, otherwise the conglomerate
+             * # is the same as the compile time conglomerate #.
+             * If the foreign key is self-referencing then we need to
+             * get the new conglomerate # for the primary key as it
+             * has changed.  However, if the foreign key is not self-referencing
+             * then we only need to get the new conglomerate # for
+             * the primary key if the primary key is on the table being 
+             * inserted into.
+             */
+            if (bulkInsertReplace)
+            {
+                for (int index = 0; index < fkInfo.fkConglomNumbers.length; index++)
+                {
+                    /* No need to check foreign key if it is self referencing
+                     * and there were no rows inserted on the replace, as both
+                     * indexes will be empty.
+                     */
+                    if (fkInfo.fkIsSelfReferencing[index] && indexRows == null)
+                    {
+                        continue;
+                    }
+
+                    long pkConglom;
+                    long fkConglom;
+
+                    if (fkInfo.fkIsSelfReferencing[index])
+                    {
+                        /* Self-referencing foreign key.  Both conglomerate
+                         * #s have changed.
+                         */
+                        pkConglom = (indexConversionTable.get(
+                                         Long.valueOf(fkInfo.refConglomNumber))).longValue();
+                        fkConglom = (indexConversionTable.get(
+                                         Long.valueOf(fkInfo.fkConglomNumbers[index]))).
                             longValue();
-					}
-					else
-					{
-						/* Non-self referencing foreign key.  At this point we
-						 * don't know if the primary key or the foreign key is
-						 * on this table.  So, for each one, we look to see
-						 * if the old conglomerate # is in the conversion table.
-						 * If so, then we get the new conglomerate #, otherwise
-						 * we use the compile time conglomerate #.  This
-						 * is very simple, though not very elegant.
-						 */
-						Long pkConglomLong = indexConversionTable.get(
+                    }
+                    else
+                    {
+                        /* Non-self referencing foreign key.  At this point we
+                         * don't know if the primary key or the foreign key is
+                         * on this table.  So, for each one, we look to see
+                         * if the old conglomerate # is in the conversion table.
+                         * If so, then we get the new conglomerate #, otherwise
+                         * we use the compile time conglomerate #.  This
+                         * is very simple, though not very elegant.
+                         */
+                        Long pkConglomLong = indexConversionTable.get(
                             Long.valueOf(fkInfo.refConglomNumber));
-						Long fkConglomLong = indexConversionTable.get(
+                        Long fkConglomLong = indexConversionTable.get(
                             Long.valueOf(fkInfo.fkConglomNumbers[index]));
 
-						if (pkConglomLong == null)
-						{
-							pkConglom = fkInfo.refConglomNumber;
-						}
-						else
-						{
-							pkConglom = pkConglomLong.longValue();
-						}
-						if (fkConglomLong == null)
-						{
-							fkConglom = fkInfo.fkConglomNumbers[index];
-						}
-						else
-						{
-							fkConglom = fkConglomLong.longValue();
-						}
-					}
-					bulkValidateForeignKeysCore(
-                            tc, cm, fkInfo, fkConglom, pkConglom,
-							fkInfo.fkConstraintNames[index], fullTemplate);
-				}
-			}
-			else
-			{
-				/*
-				** We have a FKInfo for each foreign key we are
-				** checking.  Note that there are no primary key
-				** checks on insert, so we can always reference
-				** element[0] in the current FKInfo structure.
-				*/ 
-				if (SanityManager.DEBUG)
-				{
-					SanityManager.ASSERT(fkInfo.type == FKInfo.FOREIGN_KEY, 
-						"error, expected to only check foreign keys on insert");
-				}
-				Long fkConglom = indexConversionTable.get(fkInfo.fkConglomNumbers[0]);
-				bulkValidateForeignKeysCore(
-                        tc, cm, fkInfo, fkConglom.longValue(),
-						fkInfo.refConglomNumber, fkInfo.fkConstraintNames[0],
-                        fullTemplate);
-			}
-		}
-	}
+                        if (pkConglomLong == null)
+                        {
+                            pkConglom = fkInfo.refConglomNumber;
+                        }
+                        else
+                        {
+                            pkConglom = pkConglomLong.longValue();
+                        }
+                        if (fkConglomLong == null)
+                        {
+                            fkConglom = fkInfo.fkConglomNumbers[index];
+                        }
+                        else
+                        {
+                            fkConglom = fkConglomLong.longValue();
+                        }
+                    }
+                    bulkValidateForeignKeysCore(
+                        tc, cm, fkInfo, fkConglom, pkConglom,
+                        fkInfo.fkConstraintNames[index], fullTemplate);
+                }
+            }
+            else
+            {
+                /*
+                ** We have a FKInfo for each foreign key we are
+                ** checking.  Note that there are no primary key
+                ** checks on insert, so we can always reference
+                ** element[0] in the current FKInfo structure.
+                */ 
+                if (SanityManager.DEBUG)
+                {
+                    SanityManager.ASSERT(fkInfo.type == FKInfo.FOREIGN_KEY, 
+                                         "error, expected to only check foreign keys on insert");
+                }
+                Long fkConglom = indexConversionTable.get(fkInfo.fkConglomNumbers[0]);
+                bulkValidateForeignKeysCore(
+                    tc, cm, fkInfo, fkConglom.longValue(),
+                    fkInfo.refConglomNumber, fkInfo.fkConstraintNames[0],
+                    fullTemplate);
+            }
+        }
+    }
 
-	private void bulkValidateForeignKeysCore(
-						TransactionController tc, ContextManager cm, 
-						FKInfo fkInfo, long fkConglom, long pkConglom,
-                        String fkConstraintName, ExecRow fullTemplate)
-		throws StandardException
-	{
-		ExecRow 		            template;
-		GroupFetchScanController 	refScan = null;
-		GroupFetchScanController 	fkScan  = null;
-
-		try
-		{
-
-				template = makeIndexTemplate(fkInfo, fullTemplate, cm);
-
-				/*
-				** The indexes have been dropped and recreated, so
-				** we need to get the new index conglomerate number.
-				*/
-				fkScan = 
-                    tc.openGroupFetchScan(
-                        fkConglom,
-                        false,                       // hold 
-                        0, 							 // read only
-                        // doesn't matter, already locked
-                        TransactionController.MODE_TABLE,
-                        // doesn't matter, already locked
-                        TransactionController.ISOLATION_READ_COMMITTED,
-                        (FormatableBitSet)null, 				 // retrieve all fields
-                        (DataValueDescriptor[])null, // startKeyValue
-                        ScanController.GE,           // startSearchOp
-                        null,                        // qualifier
-                        (DataValueDescriptor[])null, // stopKeyValue
-                        ScanController.GT            // stopSearchOp 
-                        );
+    private void bulkValidateForeignKeysCore(
+        TransactionController tc, ContextManager cm, 
+        FKInfo fkInfo, long fkConglom, long pkConglom,
+        String fkConstraintName, ExecRow fullTemplate)
+        throws StandardException {
+        ExecRow 		            template;
+        GroupFetchScanController 	refScan = null;
+        GroupFetchScanController 	fkScan  = null;
 
-				if (SanityManager.DEBUG)
-				{	
-					/*
-					** Bulk insert replace calls this method regardless
-					** of whether or not any rows were inserted because
-					** it has to check any referencing foreign keys
-					** after the replace.  Otherwise, we
-					** make sure that we actually have a row in the fk.
-					** If not, we have an error because we thought that
-					** since indexRows != null, we must have gotten some
-					** rows.
-					*/ 
-					if (! bulkInsertReplace)
-					{
-						SanityManager.ASSERT(fkScan.next(),
-							"No rows in fk index, even though indexRows != null");
+        try
+        {
+
+            template = makeIndexTemplate(fkInfo, fullTemplate, cm);
+
+            /*
+            ** The indexes have been dropped and recreated, so
+            ** we need to get the new index conglomerate number.
+            */
+            fkScan = 
+                tc.openGroupFetchScan(
+                    fkConglom,
+                    false,                       // hold 
+                    0, 							 // read only
+                    // doesn't matter, already locked
+                    TransactionController.MODE_TABLE,
+                    // doesn't matter, already locked
+                    TransactionController.ISOLATION_READ_COMMITTED,
+                    (FormatableBitSet)null, 				 // retrieve all fields
+                    (DataValueDescriptor[])null, // startKeyValue
+                    ScanController.GE,           // startSearchOp
+                    null,                        // qualifier
+                    (DataValueDescriptor[])null, // stopKeyValue
+                    ScanController.GT            // stopSearchOp 
+                    );
+
+            if (SanityManager.DEBUG)
+            {	
+                /*
+                ** Bulk insert replace calls this method regardless
+                ** of whether or not any rows were inserted because
+                ** it has to check any referencing foreign keys
+                ** after the replace.  Otherwise, we
+                ** make sure that we actually have a row in the fk.
+                ** If not, we have an error because we thought that
+                ** since indexRows != null, we must have gotten some
+                ** rows.
+                */ 
+                if (! bulkInsertReplace)
+                {
+                    SanityManager.ASSERT(fkScan.next(),
+                                         "No rows in fk index, even though indexRows != null");
 			
-						/*
-						** Crank up the scan again.
-						*/	
-						fkScan.reopenScan(
-							(DataValueDescriptor[])null,    // startKeyValue
-							ScanController.GE,              // startSearchOp
-							null,                           // qualifier
-							(DataValueDescriptor[])null,    // stopKeyValue
-							ScanController.GT               // stopSearchOp 
-		                      );
-					}
-				}
-
-				/*
-				** Open the referenced key scan.  Use row locking on
-				** the referenced table unless it is self-referencing
-	 			** (in which case we don't need locks)
-				*/	
-				refScan = 
-                    tc.openGroupFetchScan(
-						pkConglom,
-						false,                       	// hold 
-						0, 								// read only
-                        (fkConglom == pkConglom) ?
-                                TransactionController.MODE_TABLE :
-                                TransactionController.MODE_RECORD,
-                        // read committed is good enough
-                        TransactionController.ISOLATION_READ_COMMITTED,
-						(FormatableBitSet)null, 					// retrieve all fields
-						(DataValueDescriptor[])null,    // startKeyValue
-						ScanController.GE,            	// startSearchOp
-						null,                         	// qualifier
-						(DataValueDescriptor[])null,    // stopKeyValue
-						ScanController.GT             	// stopSearchOp 
-						);
-
-				/*
-				** Give the scans to the bulk checker to do its
-				** magic.  It will do a merge on the two indexes. 
-				*/	
-				ExecRow firstFailedRow = template.getClone();
-                RIBulkChecker riChecker = new RIBulkChecker(activation,
-                                            refScan,
-											fkScan, 
-											template, 	
-											true, 				// fail on 1st failure
-											(ConglomerateController)null,
-                                            firstFailedRow,
-                                            fkInfo.schemaName,
-                                            fkInfo.tableName,
-                                            fkInfo.fkIds[0],
-                                            fkInfo.deferrable[0],
-                                            fkConglom,
-                                            pkConglom);
+                    /*
+                    ** Crank up the scan again.
+                    */	
+                    fkScan.reopenScan(
+                        (DataValueDescriptor[])null,    // startKeyValue
+                        ScanController.GE,              // startSearchOp
+                        null,                           // qualifier
+                        (DataValueDescriptor[])null,    // stopKeyValue
+                        ScanController.GT               // stopSearchOp 
+                        );
+                }
+            }
+
+            /*
+            ** Open the referenced key scan.  Use row locking on
+            ** the referenced table unless it is self-referencing
+            ** (in which case we don't need locks)
+            */	
+            refScan = 
+                tc.openGroupFetchScan(
+                    pkConglom,
+                    false,                       	// hold 
+                    0, 								// read only
+                    (fkConglom == pkConglom) ?
+                    TransactionController.MODE_TABLE :
+                    TransactionController.MODE_RECORD,
+                    // read committed is good enough
+                    TransactionController.ISOLATION_READ_COMMITTED,
+                    (FormatableBitSet)null, 					// retrieve all fields
+                    (DataValueDescriptor[])null,    // startKeyValue
+                    ScanController.GE,            	// startSearchOp
+                    null,                         	// qualifier
+                    (DataValueDescriptor[])null,    // stopKeyValue
+                    ScanController.GT             	// stopSearchOp 
+                    );
+
+            /*
+            ** Give the scans to the bulk checker to do its
+            ** magic.  It will do a merge on the two indexes. 
+            */	
+            ExecRow firstFailedRow = template.getClone();
+            RIBulkChecker riChecker = new RIBulkChecker(activation,
+                                                        refScan,
+                                                        fkScan, 
+                                                        template, 	
+                                                        true, 				// fail on 1st failure
+                                                        (ConglomerateController)null,
+                                                        firstFailedRow,
+                                                        fkInfo.schemaName,
+                                                        fkInfo.tableName,
+                                                        fkInfo.fkIds[0],
+                                                        fkInfo.deferrable[0],
+                                                        fkConglom,
+                                                        pkConglom);
 	
-				int numFailures = riChecker.doCheck();
-				if (numFailures > 0)
-				{
-					StandardException se = StandardException.newException(SQLState.LANG_FK_VIOLATION, fkConstraintName,
-									fkInfo.tableName,
-									StatementUtil.typeName(fkInfo.stmtType),
-									RowUtil.toString(firstFailedRow, 0, fkInfo.colArray.length - 1));
-					throw se;
-				}
-		}
-		finally
-		{
-			if (fkScan != null)

[... 1535 lines stripped ...]