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 da...@apache.org on 2014/03/11 15:46:17 UTC

svn commit: r1576367 [3/4] - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/error/ engine/org/apache/derby/iapi/sql/compile/ engine/org/apache/derby/iapi/sql/conn/ engine/org/apache/derby/iapi/sql/dictionary/ engine/org/apache/derby/iapi/sq...

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/IndexChanger.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/IndexChanger.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/IndexChanger.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/IndexChanger.java Tue Mar 11 14:46:15 2014
@@ -82,7 +82,7 @@ class IndexChanger
 
     private final boolean deferrable; // supports a deferrable constraint
     private final LanguageConnectionContext lcc;
-    private BackingStoreHashtable deferredRowsHashTable; // cached for speed
+    private BackingStoreHashtable deferredDuplicates; // cached for speed
 
     /**
 	  Create an IndexChanger
@@ -528,11 +528,11 @@ class IndexChanger
                     // Save duplicate row so we can check at commit time there is
                     // no longer any duplicate.
 
-                    deferredRowsHashTable = DeferredDuplicates.rememberDuplicate(
-                            tc,
-                            indexCID,
-                            deferredRowsHashTable,
+                    deferredDuplicates =
+                        DeferredConstraintsMemory.rememberDuplicate(
                             lcc,
+                            deferredDuplicates,
+                            indexCID,
                             row.getRowArray());
                 } else { // the constraint is not deferred, so throw
                     insertStatus = ConglomerateController.ROWISDUPLICATE;

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertConstantAction.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertConstantAction.java Tue Mar 11 14:46:15 2014
@@ -91,18 +91,23 @@ public class InsertConstantAction extend
 
     /** Position of autogenerated column */
     private transient   int firstAutoGenColumn = -1;
-	
+    final public boolean hasDeferrableChecks;
+
 	// CONSTRUCTORS
 
 	/**
 	 * Public niladic constructor. Needed for Formatable interface to work.
 	 *
 	 */
-    public	InsertConstantAction() { super(); }
+    public  InsertConstantAction() {
+        super();
+        hasDeferrableChecks = false;
+    }
 
 	/**
 	 *	Make the ConstantAction for an INSERT statement.
 	 *
+     *  @param tableDescriptor
 	 *  @param conglomId	Conglomerate ID.
 	 *	@param heapSCOCI	StaticCompiledOpenConglomInfo for heap.
 	 *  @param irgs			Index descriptors
@@ -110,6 +115,8 @@ public class InsertConstantAction extend
 	 *	@param indexSCOCIs	StaticCompiledOpenConglomInfos for indexes.
 	 *  @param indexNames   Names of indices on this table for error reporting.
 	 *  @param deferred		True means process as a deferred insert.
+     *  @param hasDeferrableChecks
+     *                      The target table has deferrable CHECK constraints
 	 *  @param targetProperties	Properties on the target table.
 	 *	@param targetUUID	UUID of target table
 	 *	@param lockMode		The lockMode to use on the target table
@@ -132,6 +139,7 @@ public class InsertConstantAction extend
 								StaticCompiledOpenConglomInfo[] indexSCOCIs,
 								String[]			indexNames,
 								boolean				deferred,
+                                boolean             hasDeferrableChecks,
 								Properties			targetProperties,
 								UUID				targetUUID,
 								int 				lockMode,
@@ -168,6 +176,7 @@ public class InsertConstantAction extend
 		this.columnNames = tableDescriptor.getColumnNamesArray();
 		this.autoincIncrement = tableDescriptor.getAutoincIncrementArray();
 		this.indexNames = indexNames;
+        this.hasDeferrableChecks = hasDeferrableChecks;
 	}
 
 	// INTERFACE METHODS

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java Tue Mar 11 14:46:15 2014
@@ -21,13 +21,15 @@
 
 package org.apache.derby.impl.sql.execute;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Properties;
 import java.util.Vector;
-
+import org.apache.derby.catalog.UUID;
 import org.apache.derby.catalog.types.StatisticsImpl;
 import org.apache.derby.iapi.db.TriggerExecutionContext;
 import org.apache.derby.iapi.error.StandardException;
@@ -36,7 +38,6 @@ import org.apache.derby.iapi.services.co
 import org.apache.derby.iapi.services.io.FormatableBitSet;
 import org.apache.derby.iapi.services.io.StreamStorable;
 import org.apache.derby.iapi.services.loader.GeneratedMethod;
-import org.apache.derby.shared.common.sanity.SanityManager;
 import org.apache.derby.iapi.sql.Activation;
 import org.apache.derby.iapi.sql.LanguageProperties;
 import org.apache.derby.iapi.sql.ResultColumnDescriptor;
@@ -48,7 +49,6 @@ import org.apache.derby.iapi.sql.depend.
 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
 import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;
-import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;
 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
 import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;
 import org.apache.derby.iapi.sql.dictionary.StatisticsDescriptor;
@@ -62,6 +62,7 @@ import org.apache.derby.iapi.sql.execute
 import org.apache.derby.iapi.sql.execute.RowChanger;
 import org.apache.derby.iapi.sql.execute.TargetResultSet;
 import org.apache.derby.iapi.store.access.AccessFactoryGlobals;
+import org.apache.derby.iapi.store.access.BackingStoreHashtable;
 import org.apache.derby.iapi.store.access.ColumnOrdering;
 import org.apache.derby.iapi.store.access.ConglomerateController;
 import org.apache.derby.iapi.store.access.GroupFetchScanController;
@@ -71,11 +72,12 @@ import org.apache.derby.iapi.store.acces
 import org.apache.derby.iapi.store.access.SortController;
 import org.apache.derby.iapi.store.access.SortObserver;
 import org.apache.derby.iapi.store.access.TransactionController;
-import org.apache.derby.iapi.types.DataTypeDescriptor;
 import org.apache.derby.iapi.types.DataValueDescriptor;
 import org.apache.derby.iapi.types.NumberDataValue;
 import org.apache.derby.iapi.types.RowLocation;
+import org.apache.derby.iapi.types.SQLBoolean;
 import org.apache.derby.iapi.util.StringUtil;
+import org.apache.derby.shared.common.sanity.SanityManager;
 
 /**
  * Insert the rows from the source into the specified
@@ -134,6 +136,8 @@ class InsertResultSet extends DMLWriteRe
 		
 	private ExecIndexRow[]			indexRows;
     private final int               fullTemplateId;
+    private final String            schemaName;
+    private final String            tableName;
 	private	long[]					sortIds;
 	private RowLocationRetRowSource[]
                                     rowSources;
@@ -160,7 +164,8 @@ class InsertResultSet extends DMLWriteRe
 	 * getSetAutoincrementValues.
 	 */
 	private NumberDataValue				aiCache[];
-
+    private BackingStoreHashtable   deferredChecks; // cached ref.
+    private List<UUID>              violatingCheckConstraints;
 	/**
 	 * If set to true, implies that this (rep)insertresultset has generated
 	 * autoincrement values. During refresh for example, the autoincrement
@@ -257,7 +262,17 @@ class InsertResultSet extends DMLWriteRe
         }
 
         if (checkGM != null) {
-			evaluateCheckConstraints();
+            boolean allOk = evaluateCheckConstraints();
+            if (!allOk) {
+                if (SanityManager.DEBUG) {
+                    SanityManager.ASSERT(
+                            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)
@@ -271,23 +286,44 @@ class InsertResultSet extends DMLWriteRe
 		}
 	}
 
-	/**
-	  *	Run the check constraints against the current row. Raise an error if
-	  * a check constraint is violated.
-	  *
-	  * @exception StandardException thrown on error
-	  */
-	private	void	evaluateCheckConstraints()
-		throws StandardException
-	{
-		if (checkGM != null)
-		{
 
-			// Evaluate the check constraints. The expression evaluation
-			// will throw an exception if there is a violation, so there
-			// is no need to check the result of the expression.
-			checkGM.invoke(activation);
+    public void offendingRowLocation(RowLocation rl, long constainerId)
+            throws StandardException {
+        if (violatingCheckConstraints != null) {
+            deferredChecks =
+                    DeferredConstraintsMemory.rememberCheckViolations(
+                            lcc,
+                            heapConglom,
+                            schemaName,
+                            tableName,
+                            deferredChecks,
+                            violatingCheckConstraints,
+                            rl);
+            violatingCheckConstraints.clear();
+        }
+    }
+
+    /**
+     * Run the check constraints against the current row. Raise an error if
+     * a check constraint is violated, unless all the offending checks are
+     * deferred, in which case a false value will be returned. A NULL value
+     * will be interpreted as success (not violation).
+     *
+     * @exception StandardException thrown on error
+     */
+    private boolean evaluateCheckConstraints() throws StandardException {
+        boolean result = true;
+
+        if (checkGM != null) {
+            // Evaluate the check constraints. If all check constraint modes are
+            // immediate, a check error will throw rather than return a false
+            // value.
+            SQLBoolean allOk =
+                    (SQLBoolean)checkGM.invoke(activation);
+            result = allOk.isNull() || allOk.getBoolean();
 		}
+
+        return result;
 	}
 
     /*
@@ -302,6 +338,8 @@ class InsertResultSet extends DMLWriteRe
 						   GeneratedMethod generationClauses,
 						   GeneratedMethod checkGM,
                            int fullTemplate,
+                           String schemaName,
+                           String tableName,
 						   Activation activation)
 		throws StandardException
     {
@@ -311,6 +349,8 @@ class InsertResultSet extends DMLWriteRe
         this.generationClauses = generationClauses;
 		this.checkGM = checkGM;
         this.fullTemplateId = fullTemplate;
+        this.schemaName = schemaName;
+        this.tableName = tableName;
 		heapConglom = constants.conglomId;
 
         tc = activation.getTransactionController();
@@ -360,8 +400,11 @@ class InsertResultSet extends DMLWriteRe
 				*/
 				if (triggerInfo != null)
 				{
-					TriggerDescriptor td = triggerInfo.getTriggerArray()[0];
-					throw StandardException.newException(SQLState.LANG_NO_BULK_INSERT_REPLACE_WITH_TRIGGER_DURING_EXECUTION, constants.getTableName(), td.getName());
+                    TriggerDescriptor trD = triggerInfo.getTriggerArray()[0];
+                    throw StandardException.newException(
+                        SQLState.LANG_NO_BULK_INSERT_REPLACE_WITH_TRIGGER_DURING_EXECUTION,
+                        constants.getTableName(),
+                        trD.getName());
 				}
 			}
 		}
@@ -515,17 +558,17 @@ class InsertResultSet extends DMLWriteRe
 		throws StandardException
 	{
 		int size = columnIndexes.length;
-		TableDescriptor td = dd.getTableDescriptor(constants.targetUUID);
+        TableDescriptor tabDesc = dd.getTableDescriptor(constants.targetUUID);
 
 		// all 1-based column ids.
 		for (int i = 0; i < size; i++)
 		{
-			ColumnDescriptor cd = td.getColumnDescriptor(columnIndexes[i]);
+            ColumnDescriptor cd = tabDesc.getColumnDescriptor(columnIndexes[i]);
 			if (!verifyAutoGenColumn(cd))
 			{
 				throw StandardException.newException(
 					SQLState.LANG_INVALID_AUTOGEN_COLUMN_POSITION,
-					new Integer(columnIndexes[i]), td.getName());
+                    new Integer(columnIndexes[i]), tabDesc.getName());
 			}
 		}
 	}
@@ -538,16 +581,16 @@ class InsertResultSet extends DMLWriteRe
 	private int[] generatedColumnPositionsArray()
 		throws StandardException
 	{
-		TableDescriptor td = dd.getTableDescriptor(constants.targetUUID);
+        TableDescriptor tabDesb = dd.getTableDescriptor(constants.targetUUID);
 		ColumnDescriptor cd;
-		int size = td.getMaxColumnID();
+        int size = tabDesb.getMaxColumnID();
 
 		int[] generatedColumnPositionsArray = new int[size];
         Arrays.fill(generatedColumnPositionsArray, -1);
 		int generatedColumnNumbers = 0;
 
 		for (int i=0; i<size; i++) {
-			cd = td.getColumnDescriptor(i+1);
+            cd = tabDesb.getColumnDescriptor(i+1);
 			if (cd.isAutoincrement()) { //if the column has auto-increment value
 				generatedColumnNumbers++;
 				generatedColumnPositionsArray[i] = i+1;
@@ -574,11 +617,11 @@ class InsertResultSet extends DMLWriteRe
 		throws StandardException
 	{
 		int size = columnIndexes.length;
-		TableDescriptor td = dd.getTableDescriptor(constants.targetUUID);
+        TableDescriptor tabDesc = dd.getTableDescriptor(constants.targetUUID);
 
 		//create an array of integer (the array size = number of columns in table)
 		// valid column positions are 1...getMaxColumnID()
-		int[] uniqueColumnIndexes = new int[td.getMaxColumnID()];
+        int[] uniqueColumnIndexes = new int[tabDesc.getMaxColumnID()];
 
 		int uniqueColumnNumbers = 0;
 
@@ -618,7 +661,7 @@ class InsertResultSet extends DMLWriteRe
 		int size = columnNames.length;
 		int columnPositions[] = new int[size];
 
- 		TableDescriptor td = dd.getTableDescriptor(constants.targetUUID);
+        TableDescriptor tabDesc = dd.getTableDescriptor(constants.targetUUID);
 		ColumnDescriptor cd;
 
 		for (int i = 0; i < size; i++)
@@ -627,15 +670,15 @@ class InsertResultSet extends DMLWriteRe
 			{
 				throw StandardException.newException(
 					SQLState.LANG_INVALID_AUTOGEN_COLUMN_NAME,
-					columnNames[i], td.getName());
+                    columnNames[i], tabDesc.getName());
 			}
 
-			cd = td.getColumnDescriptor(columnNames[i]);
+            cd = tabDesc.getColumnDescriptor(columnNames[i]);
 			if (!verifyAutoGenColumn(cd))
 			{
 				throw StandardException.newException(
 					SQLState.LANG_INVALID_AUTOGEN_COLUMN_NAME,
-					columnNames[i], td.getName());
+                    columnNames[i], tabDesc.getName());
 			}
 
 			columnPositions[i] = cd.getPosition();
@@ -659,9 +702,7 @@ class InsertResultSet extends DMLWriteRe
 		return ((cd != null) && cd.isAutoincrement());
 	}
 
-	/**
-	 * @see ResultSet#getAutoGeneratedKeysResultset
-	 */
+    @Override
 	public ResultSet getAutoGeneratedKeysResultset()
 	{
 		return autoGeneratedKeysResultSet;
@@ -682,8 +723,7 @@ class InsertResultSet extends DMLWriteRe
 		getSetAutoincrementValue(int columnPosition, long increment)
 		throws StandardException
 	{
-		long startValue = 0;
-                NumberDataValue dvd;
+        NumberDataValue dvd;
 		int index = columnPosition - 1;	// all our indices are 0 based.
 
 		/* As in DB2, only for single row insert: insert into t1(c1) values (..) do
@@ -706,6 +746,8 @@ class InsertResultSet extends DMLWriteRe
 			//			System.out.println("in bulk insert");
 			if (aiCache[index].isNull())
 			{
+                long startValue;
+
 				if (bulkInsertReplace)
 				{
 					startValue = cd.getAutoincStart();
@@ -720,7 +762,7 @@ class InsertResultSet extends DMLWriteRe
 				lcc.autoincrementCreateCounter(td.getSchemaName(),
 											   td.getName(),
 											   cd.getColumnName(),
-											   new Long(startValue),
+                                               Long.valueOf(startValue),
 											   increment,
 											   columnPosition);
 			
@@ -733,7 +775,8 @@ class InsertResultSet extends DMLWriteRe
 		else
 		{
 			NumberDataValue newValue;
-			TransactionController nestedTC = null, tcToUse = tc;
+            TransactionController nestedTC = null;
+            TransactionController tcToUse;
 
 			try
 			{
@@ -854,8 +897,8 @@ class InsertResultSet extends DMLWriteRe
 		throws StandardException
 	{
 		boolean setUserIdentity = constants.hasAutoincrement() && isSingleRowResultSet();
-		ExecRow	deferredRowBuffer = null;
-                long user_autoinc=0;
+        ExecRow deferredRowBuffer;
+        long user_autoinc=0;
                         
 		/* Get or re-use the row changer.
 		 */
@@ -975,8 +1018,10 @@ class InsertResultSet extends DMLWriteRe
 			}
 			else
 			{
-				// Evaluate any check constraints on the row
-				evaluateCheckConstraints();
+                // 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)
 				{
@@ -1000,7 +1045,21 @@ class InsertResultSet extends DMLWriteRe
 							rowArray[i].getObject();
 					}
 				}
-				rowChanger.insertRow(row);
+
+                if (allOk) {
+                    rowChanger.insertRow(row, false);
+                } else {
+                    RowLocation offendingRow = rowChanger.insertRow(row, true);
+                    deferredChecks =
+                        DeferredConstraintsMemory.rememberCheckViolations(
+                            lcc,
+                            heapConglom,
+                            schemaName,
+                            tableName,
+                            deferredChecks,
+                            violatingCheckConstraints,
+                            offendingRow);
+                }
 			}
 
             rowCount++;
@@ -1105,8 +1164,23 @@ class InsertResultSet extends DMLWriteRe
 					// we have to set the source row so the check constraint
 					// sees the correct row.
 					sourceResultSet.setCurrentRow(deferredRowBuffer);
-					evaluateCheckConstraints();
-					rowChanger.insertRow(deferredRowBuffer);
+                    boolean allOk = evaluateCheckConstraints();
+
+                    if (allOk) {
+                        rowChanger.insertRow(deferredRowBuffer, false);
+                    } else {
+                        RowLocation offendingRow =
+                            rowChanger.insertRow(deferredRowBuffer, true);
+                        deferredChecks =
+                            DeferredConstraintsMemory.rememberCheckViolations(
+                                lcc,
+                                heapConglom,
+                                schemaName,
+                                tableName,
+                                deferredChecks,
+                                violatingCheckConstraints,
+                                offendingRow);
+                    }
 				}
 			} finally
 			{
@@ -1172,11 +1246,13 @@ class InsertResultSet extends DMLWriteRe
 	protected ExecRow getNextRowCore( NoPutResultSet source )
 		throws StandardException
 	{
-		ExecRow row = super.getNextRowCore( source );
+        ExecRow nextRow = super.getNextRowCore( source );
 
-        if ( (row != null) && constants.underMerge() ) { row = processMergeRow( source, row ); }
+        if ( (nextRow != null) && constants.underMerge() ) {
+            nextRow = processMergeRow( source, nextRow );
+        }
 
-        return row;
+        return nextRow;
 	}
 
     /**
@@ -1315,6 +1391,11 @@ class InsertResultSet extends DMLWriteRe
 			sourceResultSet.setNeedsRowLocation(true);
 		}
 
+        if (constants.hasDeferrableChecks) {
+            sourceResultSet.setHasDeferrableChecks();
+        }
+
+
 		dd = lcc.getDataDictionary();
 		td = dd.getTableDescriptor(constants.targetUUID);
 
@@ -1418,8 +1499,6 @@ class InsertResultSet extends DMLWriteRe
             TransactionController tc, ContextManager cm, ExecRow fullTemplate)
 		throws StandardException
 	{
-		FKInfo 			fkInfo;
-
 		/*
 		** If there are no foreign keys, then nothing to worry 
 		** about.
@@ -1433,9 +1512,8 @@ class InsertResultSet extends DMLWriteRe
 			return;
 		}
 
-		for (int i = 0; i < fkInfoArray.length; i++)
+        for (FKInfo fkInfo : fkInfoArray)
 		{
-			fkInfo = fkInfoArray[i];
 
 			/* With regular bulk insert, we only need to check the
 			 * foreign keys in the table we inserted into.  We need
@@ -1476,9 +1554,10 @@ class InsertResultSet extends DMLWriteRe
 						 * #s have changed.
 						 */
 						pkConglom = (indexConversionTable.get(
-									new Long(fkInfo.refConglomNumber))).longValue();
+                            Long.valueOf(fkInfo.refConglomNumber))).longValue();
 						fkConglom = (indexConversionTable.get(
-										new Long(fkInfo.fkConglomNumbers[index]))).longValue();
+                            Long.valueOf(fkInfo.fkConglomNumbers[index]))).
+                            longValue();
 					}
 					else
 					{
@@ -1491,9 +1570,10 @@ class InsertResultSet extends DMLWriteRe
 						 * is very simple, though not very elegant.
 						 */
 						Long pkConglomLong = indexConversionTable.get(
-												new Long(fkInfo.refConglomNumber));
+                            Long.valueOf(fkInfo.refConglomNumber));
 						Long fkConglomLong = indexConversionTable.get(
-										new Long(fkInfo.fkConglomNumbers[index]));
+                            Long.valueOf(fkInfo.fkConglomNumbers[index]));
+
 						if (pkConglomLong == null)
 						{
 							pkConglom = fkInfo.refConglomNumber;
@@ -1512,7 +1592,7 @@ class InsertResultSet extends DMLWriteRe
 						}
 					}
 					bulkValidateForeignKeysCore(
-							tc, cm, fkInfoArray[i], fkConglom, pkConglom, 
+                            tc, cm, fkInfo, fkConglom, pkConglom,
 							fkInfo.fkConstraintNames[index], fullTemplate);
 				}
 			}
@@ -1532,7 +1612,7 @@ class InsertResultSet extends DMLWriteRe
 				Long fkConglom = indexConversionTable.get(
 										new Long(fkInfo.fkConglomNumbers[0]));
 				bulkValidateForeignKeysCore(
-						tc, cm, fkInfoArray[i], fkConglom.longValue(),
+                        tc, cm, fkInfo, fkConglom.longValue(),
 						fkInfo.refConglomNumber, fkInfo.fkConstraintNames[0],
                         fullTemplate);
 			}
@@ -1655,12 +1735,10 @@ class InsertResultSet extends DMLWriteRe
 			if (fkScan != null)
 			{
 				fkScan.close();
-				fkScan = null;
 			}
 			if (refScan != null)
 			{
 				refScan.close();
-				refScan = null;
 			}
 		}
 	}
@@ -1749,7 +1827,7 @@ class InsertResultSet extends DMLWriteRe
 			boolean[] isAscending     = constants.irgs[index].isAscending();
            
 			int numColumnOrderings;
-			SortObserver sortObserver = null;
+            SortObserver sortObserver;
 
 			/* We can only reuse the wrappers when doing an
 			 * external sort if there is only 1 index.  Otherwise,
@@ -1782,8 +1860,6 @@ class InsertResultSet extends DMLWriteRe
                         indDes.isUnique() ? baseColumnPositions.length :
                         baseColumnPositions.length + 1;
 
-                String[] columnNames = getColumnNames(baseColumnPositions);
-
 				sortObserver = 
                     new UniqueIndexSortObserver(
                             tc,
@@ -2013,7 +2089,7 @@ class InsertResultSet extends DMLWriteRe
             // We recreated the index, so any old deferred constraints
             // information supported by the dropped index needs to be updated
             // with the new index.
-            DeferredDuplicates.updateIndexCID(
+            DeferredConstraintsMemory.updateIndexCID(
                     lcc, constants.indexCIDS[index], newIndexCongloms[index]);
 
 			indexConversionTable.put(new Long(constants.indexCIDS[index]),
@@ -2248,9 +2324,9 @@ class InsertResultSet extends DMLWriteRe
 		throws StandardException
 	{
 		int					numIndexes = constants.irgs.length;
-		ExecIndexRow[]		indexRows = new ExecIndexRow[numIndexes];
-		ExecRow				baseRows = null;
-		ColumnOrdering[][]	ordering = new ColumnOrdering[numIndexes][];
+        ExecIndexRow[]      idxRows = new ExecIndexRow[numIndexes];
+        ExecRow             baseRows;
+        ColumnOrdering[][]  order = new ColumnOrdering[numIndexes][];
 		int					numColumns = td.getNumberOfColumns();
         collation       = new int[numIndexes][];
 
@@ -2298,14 +2374,14 @@ class InsertResultSet extends DMLWriteRe
 		for (int index = 0; index < numIndexes; index++)
 		{
 			// create a single index row template for each index
-			indexRows[index] = constants.irgs[index].getIndexRowTemplate();
+            idxRows[index] = constants.irgs[index].getIndexRowTemplate();
 
 			// Get an index row based on the base row
 			// (This call is only necessary here because we need to pass a 
             // template to the sorter.)
 			constants.irgs[index].getIndexRow(baseRows, 
 											  rl, 
-											  indexRows[index],
+                                              idxRows[index],
 											  bitSet);
 
 			/* For non-unique indexes, we order by all columns + the RID.
@@ -2319,7 +2395,7 @@ class InsertResultSet extends DMLWriteRe
 			int[] baseColumnPositions = constants.irgs[index].baseColumnPositions();
 			boolean[] isAscending = constants.irgs[index].isAscending();
 			int numColumnOrderings;
-			SortObserver sortObserver = null;
+            SortObserver sortObserver;
             final IndexRowGenerator indDes = cd.getIndexDescriptor();
 
             if (indDes.isUnique() || indDes.isUniqueDeferrable())
@@ -2328,8 +2404,6 @@ class InsertResultSet extends DMLWriteRe
                         indDes.isUnique() ? baseColumnPositions.length :
                         baseColumnPositions.length + 1;
 
-				String[] columnNames = getColumnNames(baseColumnPositions);
-
 				String indexOrConstraintName = cd.getConglomerateName();
                 boolean deferred = false;
                 boolean uniqueDeferrable = false;
@@ -2353,7 +2427,7 @@ class InsertResultSet extends DMLWriteRe
                             uniqueDeferrable,
                             deferred,
                             indexOrConstraintName,
-                            indexRows[index],
+                            idxRows[index],
                             true,
                             td.getName());
 			}
@@ -2361,17 +2435,17 @@ class InsertResultSet extends DMLWriteRe
 			{
 				numColumnOrderings = baseColumnPositions.length + 1;
 				sortObserver       = new BasicSortObserver(false, false, 
-													 indexRows[index],
+                                                     idxRows[index],
 													 true);
 			}
-			ordering[index] = new ColumnOrdering[numColumnOrderings];
+            order[index] = new ColumnOrdering[numColumnOrderings];
 			for (int ii =0; ii < isAscending.length; ii++) 
 			{
-				ordering[index][ii] = new IndexColumnOrder(ii, isAscending[ii]);
+                order[index][ii] = new IndexColumnOrder(ii, isAscending[ii]);
 			}
 			if (numColumnOrderings > isAscending.length)
             {
-				ordering[index][isAscending.length] = 
+                order[index][isAscending.length] =
                     new IndexColumnOrder(isAscending.length);
             }
 
@@ -2379,8 +2453,8 @@ class InsertResultSet extends DMLWriteRe
 			sortIds[index] = 
                 tc.createSort(
                     (Properties)null, 
-                    indexRows[index].getRowArrayClone(),
-                    ordering[index],
+                    idxRows[index].getRowArrayClone(),
+                    order[index],
                     sortObserver,
                     false,			// not in order
                     rowCount,		// est rows	
@@ -2395,11 +2469,11 @@ class InsertResultSet extends DMLWriteRe
 		// are in the correct order. 
 		rowSources = new RowLocationRetRowSource[numIndexes];
 		// Fill in the RowSources
-		SortController[]	sorters = new SortController[numIndexes];
+        SortController[]    sorter = new SortController[numIndexes];
 		for (int index = 0; index < numIndexes; index++)
 		{
-			sorters[index] = tc.openSort(sortIds[index]);
-			sorters[index].completedInserts();
+            sorter[index] = tc.openSort(sortIds[index]);
+            sorter[index].completedInserts();
 			rowSources[index] = tc.openSortRowSource(sortIds[index]);
 		}
 
@@ -2430,7 +2504,7 @@ class InsertResultSet extends DMLWriteRe
 			/* Create the properties that language supplies when creating the
 			 * the index.  (The store doesn't preserve these.)
 			 */
-			int indexRowLength = indexRows[index].nColumns();
+            int indexRowLength = idxRows[index].nColumns();
 			properties.put("baseConglomerateId", Long.toString(newHeapConglom));
 			if (cd.getIndexDescriptor().isUnique())
 			{
@@ -2464,7 +2538,7 @@ class InsertResultSet extends DMLWriteRe
 			newIndexCongloms[index] = 
                 tc.createAndLoadConglomerate(
                     "BTREE",
-                    indexRows[index].getRowArray(),
+                    idxRows[index].getRowArray(),
                     null, //default column sort order 
                     collation[index],
                     properties,
@@ -2547,8 +2621,20 @@ class InsertResultSet extends DMLWriteRe
 		return columnNames;
 	}
 
+    @Override
 	public void finish() throws StandardException {
 		sourceResultSet.finish();
 		super.finish();
 	}
+
+    @Override
+    public void rememberConstraint(UUID cid) throws StandardException {
+        if (violatingCheckConstraints == null) {
+            violatingCheckConstraints = new ArrayList<UUID>();
+        }
+
+        if (!violatingCheckConstraints.contains(cid)) {
+            violatingCheckConstraints.add(cid);
+        }
+    }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/NoPutResultSetImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/NoPutResultSetImpl.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/NoPutResultSetImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/NoPutResultSetImpl.java Tue Mar 11 14:46:15 2014
@@ -71,7 +71,8 @@ extends BasicNoPutResultSetImpl
 
 	// fields used when being called as a RowSource
 	private boolean needsRowLocation;
-	protected ExecRow clonedExecRow;
+    private boolean needsRowLocationForDeferredCheckConstraints;
+    protected ExecRow clonedExecRow;
 	protected TargetResultSet	targetResultSet;
 
 	/* beetle 4464. compact flags into array of key column positions that we do check/skip nulls,
@@ -214,6 +215,10 @@ extends BasicNoPutResultSetImpl
 		this.needsRowLocation = needsRowLocation;
 	}
 
+    public void setHasDeferrableChecks() {
+        this.needsRowLocationForDeferredCheckConstraints = true;
+    }
+
 	// RowSource interface
 	
 	/** 
@@ -276,7 +281,12 @@ extends BasicNoPutResultSetImpl
 		return needsRowLocation;
 	}
 
-	/**
+    public boolean needsRowLocationForDeferredCheckConstraints()
+    {
+        return needsRowLocationForDeferredCheckConstraints;
+    }
+
+    /**
 	 * @see RowLocationRetRowSource#rowLocation
 	 * @exception StandardException on error
 	 */
@@ -286,7 +296,11 @@ extends BasicNoPutResultSetImpl
 		targetResultSet.changedRow(clonedExecRow, rl);
 	}
 
+    public void offendingRowLocation(
+            RowLocation rl, long containdId) throws StandardException {
 
+        targetResultSet.offendingRowLocation(rl, containdId);
+    }
 	// class implementation
 
 	/**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/NoRowsResultSetImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/NoRowsResultSetImpl.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/NoRowsResultSetImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/NoRowsResultSetImpl.java Tue Mar 11 14:46:15 2014
@@ -45,6 +45,7 @@ import org.apache.derby.iapi.sql.execute
 import org.apache.derby.iapi.sql.execute.ResultSetStatisticsFactory;
 import org.apache.derby.iapi.sql.execute.RunTimeStatistics;
 import org.apache.derby.iapi.sql.execute.xplain.XPLAINVisitor;
+import org.apache.derby.iapi.types.BooleanDataValue;
 import org.apache.derby.iapi.types.DataValueDescriptor;
 
 /**
@@ -675,32 +676,6 @@ abstract class NoRowsResultSetImpl imple
     }
     
 	/**
-	  *	Run check constraints against the current row. Raise an error if
-	  * a check constraint is violated.
-	  *
-	  *	@param	checkGM			Generated code to run the check constraint.
-	  *	@param	activation		Class in which checkGM lives.
-	  *
-	  * @exception StandardException thrown on error
-	  */
-	public	static	void	evaluateCheckConstraints
-	(
-	  GeneratedMethod checkGM,
-	  Activation activation
-	)
-		throws StandardException
-	{
-		if (checkGM != null)
-		{
-			// Evaluate the expression containing the check constraints.
-			// This expression will throw an exception if there is a
-			// violation, so there is no need to check the result.
-			checkGM.invoke(activation);
-		}
-
-	}
-	  
-	/**
 	 * Does this ResultSet cause a commit or rollback.
 	 *
 	 * @return Whether or not this ResultSet cause a commit or rollback.

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ProjectRestrictResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ProjectRestrictResultSet.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ProjectRestrictResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ProjectRestrictResultSet.java Tue Mar 11 14:46:15 2014
@@ -21,6 +21,7 @@
 
 package org.apache.derby.impl.sql.execute;
 
+import java.util.Enumeration;
 import org.apache.derby.shared.common.sanity.SanityManager;
 import org.apache.derby.iapi.services.io.StreamStorable;
 
@@ -41,6 +42,7 @@ import org.apache.derby.iapi.types.RowLo
 
 import org.apache.derby.catalog.types.ReferencedColumnsDescriptorImpl;
 import org.apache.derby.iapi.sql.execute.RowChanger;
+import org.apache.derby.iapi.types.SQLRef;
 
 
 /**
@@ -77,8 +79,11 @@ class ProjectRestrictResultSet extends N
 	private boolean shortCircuitOpen;
 
 	private ExecRow projRow;
+    private boolean validatingCheckConstraint;
+    private long validatingBaseTableCID;
+    DeferredConstraintsMemory.CheckInfo ci;
+    Enumeration rowLocations;
 
-    //
     // class interface
     //
     ProjectRestrictResultSet(NoPutResultSet s,
@@ -91,6 +96,8 @@ class ProjectRestrictResultSet extends N
                     int cloneMapItem,
 					boolean reuseResult,
 					boolean doesProjection,
+                    boolean validatingCheckConstraint,
+                    long validatingBaseTableCID,
 				    double optimizerEstimatedRowCount,
 					double optimizerEstimatedCost) 
 		throws StandardException
@@ -110,6 +117,8 @@ class ProjectRestrictResultSet extends N
 		projectMapping = ((ReferencedColumnsDescriptorImpl) a.getPreparedStatement().getSavedObject(mapRefItem)).getReferencedColumnPositions();
 		this.reuseResult = reuseResult;
 		this.doesProjection = doesProjection;
+        this.validatingCheckConstraint = validatingCheckConstraint;
+        this.validatingBaseTableCID = validatingBaseTableCID;
 
 		// Allocate a result row if all of the columns are mapped from the source
 		if (projection == null)
@@ -169,6 +178,15 @@ class ProjectRestrictResultSet extends N
 							restrictBoolean.getBoolean());
 		}
 
+        if (validatingCheckConstraint) {
+            ci = (DeferredConstraintsMemory.CheckInfo)activation.
+                getLanguageConnectionContext().
+                getDeferredHashTables().get(
+                    Long.valueOf(validatingBaseTableCID));
+            rowLocations = ci.infoRows.elements();
+        }
+
+
 		if (constantEval)
 		{
 	        source.openCore();
@@ -260,7 +278,25 @@ class ProjectRestrictResultSet extends N
 		beginTime = getCurrentTimeMillis();
 	    do 
 		{
-			candidateRow = source.getNextRowCore();
+
+            if (validatingCheckConstraint) {
+                candidateRow = null;
+
+                while (rowLocations.hasMoreElements() && candidateRow == null) {
+                    DataValueDescriptor[] row =
+                            (DataValueDescriptor[])rowLocations.nextElement();
+                    RowLocation rl = (RowLocation)((SQLRef)row[0]).getObject();
+                    ((ValidateCheckConstraintResultSet)source).
+                        positionScanAtRowLocation(rl);
+                    candidateRow = source.getNextRowCore();
+                    // if null (deleted), we move to next
+                }
+
+
+            } else {
+                candidateRow = source.getNextRowCore();
+            }
+
 			if (candidateRow != null) 
 			{
 				beginRT = getCurrentTimeMillis();

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/RowChangerImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/RowChangerImpl.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/RowChangerImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/RowChangerImpl.java Tue Mar 11 14:46:15 2014
@@ -434,7 +434,7 @@ class RowChangerImpl	implements	RowChang
 	  @param baseRow the row.
 	  @exception StandardException		Thrown on error
 	  */
-	public void insertRow(ExecRow baseRow)
+    public RowLocation insertRow(ExecRow baseRow, boolean getRL)
 		 throws StandardException
 	{
 		if (SanityManager.DEBUG)
@@ -447,16 +447,24 @@ class RowChangerImpl	implements	RowChang
 		}
 		else
 		{
-			if (isc != null)
+            if (isc != null || getRL)
 			{
+                if (baseRowLocation == null) {
+                    baseRowLocation = baseCC.newRowLocationTemplate();
+                }
 				baseCC.insertAndFetchLocation(baseRow.getRowArray(), baseRowLocation);
-				isc.insert(baseRow, baseRowLocation);
+
+                if (isc != null) {
+                    isc.insert(baseRow, baseRowLocation);
+                }
 			}
 			else
 			{
                 baseCC.insert(baseRow.getRowArray());
 			}
 		}
+
+        return getRL ? baseRowLocation : null;
 	}
 
 		

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetConstraintsConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetConstraintsConstantAction.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetConstraintsConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetConstraintsConstantAction.java Tue Mar 11 14:46:15 2014
@@ -21,11 +21,10 @@
 
 package org.apache.derby.impl.sql.execute;
 
+import java.util.ArrayList;
 import java.util.List;
-
 import org.apache.derby.iapi.error.StandardException;
 import org.apache.derby.iapi.reference.SQLState;
-import org.apache.derby.iapi.services.property.PropertyUtil;
 import org.apache.derby.iapi.sql.Activation;
 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
 import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;
@@ -33,6 +32,7 @@ import org.apache.derby.iapi.sql.diction
 import org.apache.derby.iapi.sql.dictionary.KeyConstraintDescriptor;
 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
 import org.apache.derby.iapi.sql.execute.ConstantAction;
+import org.apache.derby.iapi.util.IdUtil;
 import org.apache.derby.impl.sql.compile.TableName;
 
 /**
@@ -73,9 +73,11 @@ class SetConstraintsConstantAction exten
 	}
 
 	/**
-     *  This is the guts of the Execution-time logic for SET CONSTRAINT.
+     * This is the guts of the execution time logic for SET CONSTRAINT.
 	 *
-	 *	@see ConstantAction#executeConstantAction
+     * @param activation
+     *
+     * @see ConstantAction#executeConstantAction
 	 *
 	 * @exception StandardException		Thrown on failure
 	 */
@@ -86,15 +88,17 @@ class SetConstraintsConstantAction exten
                 activation.getLanguageConnectionContext();
 
         final DataDictionary dd = lcc.getDataDictionary();
+        final List<String> boundConstraints = new ArrayList<String>();
 
         if (constraints != null) {
             for (TableName c : constraints) {
-                SchemaDescriptor sd = dd.getSchemaDescriptor(
+
+                final SchemaDescriptor sd = dd.getSchemaDescriptor(
                     c.getSchemaName(),
                     lcc.getTransactionExecute(),
                     true);
 
-                ConstraintDescriptor cd =
+                final ConstraintDescriptor cd =
                     dd.getConstraintDescriptor(c.getTableName(), sd.getUUID());
 
                 if (cd == null) {
@@ -104,6 +108,19 @@ class SetConstraintsConstantAction exten
                             c.getFullSQLName());
                 }
 
+                final String bound =
+                        IdUtil.normalToDelimited(sd.getSchemaName()) + "." +
+                        IdUtil.normalToDelimited(cd.getConstraintName());
+
+                if (boundConstraints.contains(bound)) {
+                    throw StandardException.newException(
+                            SQLState.LANG_DB2_DUPLICATE_NAMES,
+                            cd.getConstraintName(),
+                            bound);
+                } else {
+                    boundConstraints.add(bound);
+                }
+
                 if (deferred && !cd.deferrable()) {
                     throw StandardException.newException(
                             SQLState.LANG_SET_CONSTRAINT_NOT_DEFERRABLE,
@@ -111,17 +128,20 @@ class SetConstraintsConstantAction exten
                 }
 
                 if (cd instanceof KeyConstraintDescriptor) {
-                    // Unique, primary key and foreign key
+                    // Set unique, primary key and foreign key constraints
 
-                    lcc.setDeferred(activation,
+                    lcc.setConstraintDeferred(activation,
                                     ((KeyConstraintDescriptor)cd).
                                         getIndexConglomerateDescriptor(dd).
                                         getConglomerateNumber(),
                                     deferred);
                 } else {
-                    // Check constraints
-                    throw StandardException.newException(
-                            SQLState.NOT_IMPLEMENTED, "SET CONSTRAINT");
+                    // Set check constraints
+                    lcc.setConstraintDeferred(
+                            activation,
+                            cd.getTableDescriptor().getHeapConglomerateId(),
+                            cd.getUUID(),
+                            deferred);
                 }
             }
         } else {

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/TableScanResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/TableScanResultSet.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/TableScanResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/TableScanResultSet.java Tue Mar 11 14:46:15 2014
@@ -78,7 +78,7 @@ class TableScanResultSet extends ScanRes
 	public int rowsPerRead;
 	public boolean forUpdate;
 	final boolean sameStartStopPosition;
-	private boolean nextDone;
+    protected boolean nextDone;
 	private RowLocation rlTemplate;
 
 	// Run time statistics
@@ -105,17 +105,17 @@ class TableScanResultSet extends ScanRes
 	// For Scrollable insensitive updatable result sets, only qualify a row the 
 	// first time it's been read, since an update can change a row so that it 
 	// no longer qualifies
-	private boolean qualify;
+    protected boolean qualify;
 
 	// currentRowIsValid is set to the result of positioning at a rowLocation.
 	// It will be true if the positioning was successful and false if the row 
 	// was deleted under our feet. Whenenver currentRowIsValid is false it means 
 	// that the row has been deleted.
-	private boolean currentRowIsValid;
+    protected boolean currentRowIsValid;
 	
 	// Indicates whether the scan has been positioned back to a previously read
 	// row, or it is accessing a row for the first time.
-	private boolean scanRepositioned;
+    protected boolean scanRepositioned;
 
     //
     // class interface

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/TemporaryRowHolderResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/TemporaryRowHolderResultSet.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/TemporaryRowHolderResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/TemporaryRowHolderResultSet.java Tue Mar 11 14:46:15 2014
@@ -1231,6 +1231,18 @@ class TemporaryRowHolderResultSet implem
 		return false;
 	}
 
+    public void setHasDeferrableChecks() {
+        if (SanityManager.DEBUG) {
+            SanityManager.NOTREACHED();
+        }
+    }
+
+    public boolean needsRowLocationForDeferredCheckConstraints()
+    {
+        return false;
+    }
+
+
 	/**
 		rowLocation is a callback for the drainer of the row source to return
 		the rowLocation of the current row, i.e, the row that is being returned
@@ -1270,6 +1282,13 @@ class TemporaryRowHolderResultSet implem
 	public void rowLocation(RowLocation rl) throws StandardException
 	{ }
 
+    public void offendingRowLocation(
+            RowLocation rl, long containdId) throws StandardException {
+        if (SanityManager.DEBUG) {
+            SanityManager.NOTREACHED();
+        }
+    }
+
 	/**
 	 * @see NoPutResultSet#positionScanAtRowLocation
 	 *

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UniqueIndexSortObserver.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UniqueIndexSortObserver.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UniqueIndexSortObserver.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UniqueIndexSortObserver.java Tue Mar 11 14:46:15 2014
@@ -43,7 +43,7 @@ class UniqueIndexSortObserver extends Ba
     private final TransactionController     tc;
     private final LanguageConnectionContext lcc;
     private final long                      indexCID;
-    private BackingStoreHashtable           deferredRowsHashTable;
+    private BackingStoreHashtable           deferredDuplicates;
 
     public UniqueIndexSortObserver(
             TransactionController tc,
@@ -92,12 +92,11 @@ class UniqueIndexSortObserver extends Ba
     @Override
     public void rememberDuplicate(DataValueDescriptor[] row)
             throws StandardException {
-        deferredRowsHashTable = DeferredDuplicates.rememberDuplicate(
-                    tc,
-                    indexCID,
-                    deferredRowsHashTable,
-                    lcc,
-                    row);
+        deferredDuplicates = DeferredConstraintsMemory.rememberDuplicate(
+                lcc,
+                deferredDuplicates,
+                indexCID,
+                row);
     }
 
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UniqueWithDuplicateNullsIndexSortObserver.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UniqueWithDuplicateNullsIndexSortObserver.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UniqueWithDuplicateNullsIndexSortObserver.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UniqueWithDuplicateNullsIndexSortObserver.java Tue Mar 11 14:46:15 2014
@@ -43,7 +43,7 @@ public class UniqueWithDuplicateNullsInd
     private final TransactionController     tc;
     private final LanguageConnectionContext lcc;
     private final long                      indexCID;
-    private BackingStoreHashtable           deferredRowsHashTable;
+    private BackingStoreHashtable           deferredDuplicates;
     /**
      * Constructs an object of UniqueWithDuplicateNullsIndexSortObserver
      * 
@@ -118,12 +118,11 @@ public class UniqueWithDuplicateNullsInd
     @Override
     public void rememberDuplicate(DataValueDescriptor[] row)
             throws StandardException {
-        deferredRowsHashTable = DeferredDuplicates.rememberDuplicate(
-                    tc,
-                    indexCID,
-                    deferredRowsHashTable,
-                    lcc,
-                    row);
+        deferredDuplicates = DeferredConstraintsMemory.rememberDuplicate(
+                lcc,
+                deferredDuplicates,
+                indexCID,
+                row);
     }
 
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UpdateConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UpdateConstantAction.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UpdateConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UpdateConstantAction.java Tue Mar 11 14:46:15 2014
@@ -37,6 +37,8 @@ import java.io.ObjectInput;
 import java.io.IOException;
 
 import java.util.Properties;
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
 
 /**
  *	This class  describes compiled constants that are passed into
@@ -65,6 +67,9 @@ public class UpdateConstantAction extend
 
 	int numColumns;
 
+    private String schemaName;
+    private String tableName;
+
 	// CONSTRUCTORS
 
 	/**
@@ -76,7 +81,7 @@ public class UpdateConstantAction extend
 	/**
 	 *	Make the ConstantAction for an UPDATE statement.
 	 *
-	 *  @param conglomId	Conglomerate ID.
+     *  @param targetTableDesc descriptor for the table to be updated
 	 *	@param heapSCOCI	StaticCompiledOpenConglomInfo for heap.
 	 *  @param irgs			Index descriptors
 	 *  @param indexCIDS	Conglomerate IDs of indices
@@ -100,7 +105,7 @@ public class UpdateConstantAction extend
 	 *  @param underMerge   True if this is an action of a MERGE statement.
 	 */
     UpdateConstantAction(
-								long				conglomId,
+                                TableDescriptor     targetTableDesc,
 								StaticCompiledOpenConglomInfo heapSCOCI,
 								IndexRowGenerator[]	irgs,
 								long[]				indexCIDS,
@@ -118,10 +123,11 @@ public class UpdateConstantAction extend
 								int					numColumns,
 								boolean				positionedUpdate,
 								boolean				singleRowSource,
-								boolean				underMerge)
+                                boolean             underMerge)
+            throws StandardException
 	{
 		super(
-			conglomId,
+            targetTableDesc.getHeapConglomerateId(),
 			heapSCOCI,
 			irgs,
 			indexCIDS,
@@ -143,6 +149,8 @@ public class UpdateConstantAction extend
 		this.changedColumnIds = changedColumnIds;
 		this.positionedUpdate = positionedUpdate;
 		this.numColumns = numColumns;
+        this.schemaName = targetTableDesc.getSchemaName();
+        this.tableName = targetTableDesc.getName();
 	}
 
 	// INTERFACE METHODS
@@ -186,4 +194,11 @@ public class UpdateConstantAction extend
 	public	int getTypeFormatId()	{ return StoredFormatIds.UPDATE_CONSTANT_ACTION_V01_ID; }
 
 	// CLASS METHODS
+    public String getSchemaName() {
+        return schemaName;
+    }
+
+    public String getTableName() {
+        return tableName;
+    }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UpdateResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UpdateResultSet.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UpdateResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/UpdateResultSet.java Tue Mar 11 14:46:15 2014
@@ -21,15 +21,16 @@
 
 package org.apache.derby.impl.sql.execute;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Properties;
-
+import org.apache.derby.catalog.UUID;
 import org.apache.derby.iapi.db.TriggerExecutionContext;
 import org.apache.derby.iapi.error.StandardException;
 import org.apache.derby.iapi.reference.SQLState;
 import org.apache.derby.iapi.services.io.FormatableBitSet;
 import org.apache.derby.iapi.services.io.StreamStorable;
 import org.apache.derby.iapi.services.loader.GeneratedMethod;
-import org.apache.derby.shared.common.sanity.SanityManager;
 import org.apache.derby.iapi.sql.Activation;
 import org.apache.derby.iapi.sql.ResultDescription;
 import org.apache.derby.iapi.sql.ResultSet;
@@ -45,6 +46,9 @@ import org.apache.derby.iapi.store.acces
 import org.apache.derby.iapi.types.BooleanDataValue;
 import org.apache.derby.iapi.types.DataValueDescriptor;
 import org.apache.derby.iapi.types.RowLocation;
+import org.apache.derby.iapi.types.SQLBoolean;
+import org.apache.derby.iapi.types.SQLRef;
+import org.apache.derby.shared.common.sanity.SanityManager;
 
 /**
  * Update the rows from the specified
@@ -98,6 +102,8 @@ class UpdateResultSet extends DMLWriteRe
 	boolean deferred;
 	boolean beforeUpdateCopyRequired = false;
 
+    private List<UUID>              violatingCheckConstraints;
+    private BackingStoreHashtable   deferredChecks; // cached ref.
     /*
      * class interface
      *
@@ -422,6 +428,31 @@ class UpdateResultSet extends DMLWriteRe
 		}
 	}
 
+
+    /**
+     * Run check constraints against the current row. Raise an error if
+     * a check constraint is violated, unless all the offending checks are
+     * deferred, in which case a false value will be returned. A NULL value
+     * will be interpreted as success (not violation).
+     *
+     * @exception StandardException thrown on error
+     */
+    private boolean evaluateCheckConstraints() throws StandardException     {
+        boolean result = true;
+
+        if (checkGM != null) {
+            // Evaluate the check constraints. If all check constraint modes are
+            // immediate, a check error will throw rather than return a false
+            // value.
+            SQLBoolean allOk =
+                    (SQLBoolean)checkGM.invoke(activation);
+            result = allOk.isNull() || allOk.getBoolean();
+        }
+
+        return result;
+    }
+
+
 	public boolean collectAffectedRows() throws StandardException
 	{
 
@@ -471,7 +502,23 @@ class UpdateResultSet extends DMLWriteRe
 				*/
 				if (triggerInfo == null)
 				{
-					evaluateCheckConstraints( checkGM, activation );
+                    boolean allOk = evaluateCheckConstraints();
+                    if (!allOk) {
+                        DataValueDescriptor[] rw = row.getRowArray();
+                        SQLRef r = (SQLRef)rw[rw.length - 1];
+                        RowLocation baseRowLocation =
+                            (RowLocation)r.getObject();
+
+                        deferredChecks =
+                            DeferredConstraintsMemory.rememberCheckViolations(
+                                lcc,
+                                heapConglom,
+                                constants.getSchemaName(),
+                                constants.getTableName(),
+                                deferredChecks,
+                                violatingCheckConstraints,
+                                baseRowLocation);
+                    }
 				}
 
 				/*
@@ -529,14 +576,26 @@ class UpdateResultSet extends DMLWriteRe
 			}
 			else
 			{
-				evaluateCheckConstraints( checkGM, activation );
+                boolean allOk = evaluateCheckConstraints();
 
-				/* Get the RowLocation to update 
+                /* Get the RowLocation to update
 			 	* NOTE - Column #s in the Row are 1 based.
 			 	*/
 				RowLocation baseRowLocation = (RowLocation)
 					(row.getColumn(resultWidth)).getObject();
 
+                if (!allOk) {
+                    deferredChecks =
+                        DeferredConstraintsMemory.rememberCheckViolations(
+                            lcc,
+                            heapConglom,
+                            constants.getSchemaName(),
+                            constants.getTableName(),
+                            deferredChecks,
+                            violatingCheckConstraints,
+                            baseRowLocation);
+                }
+
 				RowUtil.copyRefColumns(newBaseRow,
 										row,
 										numberOfBaseColumns,
@@ -801,10 +860,12 @@ class UpdateResultSet extends DMLWriteRe
 					** Otherwise we evaluated them as we read the
 					** rows in from the source.
 					*/
+                    boolean allOk = true;
+
 					if (triggerInfo != null)
 					{
 						source.setCurrentRow(deferredTempRow);
-						evaluateCheckConstraints(checkGM, activation);
+                        allOk = evaluateCheckConstraints();
 					}
 
 					/* 
@@ -814,7 +875,19 @@ class UpdateResultSet extends DMLWriteRe
 					DataValueDescriptor rlColumn = deferredTempRow2.getColumn(numberOfBaseColumns + 1);
 					RowLocation baseRowLocation = 
 							(RowLocation) (rlColumn).getObject();
-	
+
+                    if (!allOk) {
+                        deferredChecks =
+                            DeferredConstraintsMemory.rememberCheckViolations(
+                                lcc,
+                                heapConglom,
+                                constants.getSchemaName(),
+                                constants.getTableName(),
+                                deferredChecks,
+                                violatingCheckConstraints,
+                                baseRowLocation);
+                    }
+
 					/* Get the base row at the given RowLocation */
 					boolean row_exists = 
 						deferredBaseCC.fetch(
@@ -1056,4 +1129,12 @@ class UpdateResultSet extends DMLWriteRe
 		rowChanger.finish();
 	}
 
+    @Override
+    public void rememberConstraint(UUID cid) throws StandardException {
+        if (violatingCheckConstraints == null) {
+            violatingCheckConstraints = new ArrayList<UUID>();
+        }
+
+        violatingCheckConstraints.add(cid);
+    }
 }

Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ValidateCheckConstraintResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ValidateCheckConstraintResultSet.java?rev=1576367&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ValidateCheckConstraintResultSet.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ValidateCheckConstraintResultSet.java Tue Mar 11 14:46:15 2014
@@ -0,0 +1,216 @@
+/*
+
+   Derby - Class org.apache.derby.impl.sql.execute.ValidateCheckConstraintResultSet
+
+   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.execute;
+
+import org.apache.derby.iapi.error.ExceptionUtil;
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.iapi.services.loader.GeneratedMethod;
+import org.apache.derby.iapi.sql.Activation;
+import org.apache.derby.iapi.sql.execute.CursorResultSet;
+import org.apache.derby.iapi.sql.execute.ExecRow;
+import org.apache.derby.iapi.store.access.Qualifier;
+import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;
+import org.apache.derby.iapi.types.RowLocation;
+import org.apache.derby.shared.common.sanity.SanityManager;
+
+/**
+ * Special result set used when checking deferred CHECK constraints.  Activated
+ * by a special {@code --DERBY_PROPERTY validateCheckConstraint=<conglomId>}
+ * override on a SELECT query, cf DeferredConstraintsMemory#validateCheck.  It
+ * relies on having a correct row location set prior to invoking {@code
+ * getNewtRowCore}, cf. the special code path in
+ * {@code ProjectRestrictResultSet#getNextRowCore} activated by
+ * {@code #validatingCheckConstraint}.
+ *
+ */
+final class ValidateCheckConstraintResultSet extends TableScanResultSet
+    implements CursorResultSet, Cloneable
+{
+
+    ValidateCheckConstraintResultSet(long conglomId,
+        StaticCompiledOpenConglomInfo scoci,
+        Activation activation,
+        int resultRowTemplate,
+        int resultSetNumber,
+        GeneratedMethod startKeyGetter, int startSearchOperator,
+        GeneratedMethod stopKeyGetter, int stopSearchOperator,
+        boolean sameStartStopPosition,
+        Qualifier[][] qualifiers,
+        String tableName,
+        String userSuppliedOptimizerOverrides,
+        String indexName,
+        boolean isConstraint,
+        boolean forUpdate,
+        int colRefItem,
+        int indexColItem,
+        int lockMode,
+        boolean tableLocked,
+        int isolationLevel,
+        int rowsPerRead,
+        boolean oneRowScan,
+        double optimizerEstimatedRowCount,
+        double optimizerEstimatedCost)
+            throws StandardException
+    {
+        super(conglomId,
+                scoci,
+                activation,
+                resultRowTemplate,
+                resultSetNumber,
+                startKeyGetter, startSearchOperator,
+                stopKeyGetter, stopSearchOperator,
+                sameStartStopPosition,
+                qualifiers,
+                tableName,
+                userSuppliedOptimizerOverrides,
+                indexName,
+                isConstraint,
+                forUpdate,
+                colRefItem,
+                indexColItem,
+                lockMode,
+                tableLocked,
+                isolationLevel,
+                rowsPerRead,
+                oneRowScan,
+                optimizerEstimatedRowCount,
+                optimizerEstimatedCost);
+    }
+
+    /**
+     * Return the current row (if any) from the base table scan, positioned
+     * correctly by our caller (ProjectRestrictNode). It overrides
+     * getNextRowCore from TableSCanResultSet, by using "fetch" instead of
+     * "fetchNext" on the underlying controller, otherwise it's identical.
+     * (This means it's probably over-general for the usage we have of it,
+     * but it felt safer to keep the code as similar as possible.)
+     * @return the row retrieved
+     * @exception StandardException thrown on failure to get next row
+     */
+    @Override
+    public ExecRow getNextRowCore() throws StandardException    {
+        if (isXplainOnlyMode()) {
+            return null;
+        }
+
+        checkCancellationFlag();
+
+        if (SanityManager.DEBUG) {
+            SanityManager.ASSERT(scanRepositioned);
+        }
+
+        if (currentRow == null || scanRepositioned) {
+            currentRow = getCompactRow(candidate, accessedCols, isKeyed);
+        }
+
+        beginTime = getCurrentTimeMillis();
+
+        ExecRow result = null;
+
+        if (isOpen  && !nextDone) {
+            // Only need to do 1 next per scan for 1 row scans.
+            nextDone = oneRowScan;
+
+            if (scanControllerOpened) {
+                boolean moreRows = true;
+
+                while (moreRows) {
+                    try {
+                        scanController.fetch(candidate.getRowArray());
+                    } catch (StandardException e) {
+                        // Offending rows may have been deleted in the
+                        // transaction.  As for compress, we won't even get here
+                        // since we use a normal SELECT query then.
+                        if (e.getSQLState().equals(
+                                ExceptionUtil.getSQLStateFromIdentifier(
+                                        SQLState.AM_RECORD_NOT_FOUND))) {
+                            moreRows = false;
+                            break;
+                        } else {
+                            throw e;
+                        }
+                    }
+
+                    rowsSeen++;
+                    rowsThisScan++;
+
+                    /*
+                    ** Skip rows where there are start or stop positioners
+                    ** that do not implement ordered null semantics and
+                    ** there are columns in those positions that contain
+                    ** null.
+                    ** No need to check if start and stop positions are the
+                    ** same, since all predicates in both will be ='s,
+                    ** and hence evaluated in the store.
+                    */
+                    if ((! sameStartStopPosition) && skipRow(candidate)) {
+                        rowsFiltered++;
+                        continue;
+                    }
+
+                    /* beetle 3865, updateable cursor use index. If we have a
+                     * hash table that holds updated records, and we hit it
+                     * again, skip it, and remove it from hash since we can't
+                     * hit it again, and we have a space in hash, so can stop
+                     * scanning forward.
+                     */
+                    if (past2FutureTbl != null) {
+                        RowLocation rowLoc = (RowLocation)currentRow.getColumn(
+                            currentRow.nColumns());
+                        if (past2FutureTbl.remove(rowLoc) != null) {
+                            continue;
+                        }
+                    }
+
+                    result = currentRow;
+                    break;
+                }
+
+                /*
+                ** If we just finished a full scan of the heap, update
+                ** the number of rows in the scan controller.
+                **
+                ** NOTE: It would be more efficient to only update the
+                ** scan controller if the optimizer's estimated number of
+                ** rows were wrong by more than some threshold (like 10%).
+                ** This would require a little more work than I have the
+                ** time for now, however, as the row estimate that is given
+                ** to this result set is the total number of rows for all
+                ** scans, not the number of rows per scan.
+                */
+                if (! moreRows) {
+                    setRowCountIfPossible(rowsThisScan);
+                    currentRow = null;
+                }
+            }
+        }
+
+        setCurrentRow(result);
+        currentRowIsValid = true;
+        scanRepositioned = false;
+        qualify = true;
+
+        nextTime += getElapsedMillis(beginTime);
+        return result;
+    }
+}

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/heap/HeapController.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/heap/HeapController.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/heap/HeapController.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/heap/HeapController.java Tue Mar 11 14:46:15 2014
@@ -21,6 +21,8 @@
 
 package org.apache.derby.impl.store.access.heap;
 
+import java.util.List;
+import org.apache.derby.catalog.UUID;
 import org.apache.derby.iapi.reference.SQLState;
 
 import org.apache.derby.shared.common.sanity.SanityManager;
@@ -50,6 +52,7 @@ import org.apache.derby.impl.store.acces
 import org.apache.derby.impl.store.access.conglomerate.RowPosition;
 
 import org.apache.derby.iapi.services.io.FormatableBitSet;
+import org.apache.derby.impl.sql.execute.DeferredConstraintsMemory;
 
 /**
 
@@ -382,7 +385,8 @@ public class HeapController 
 		RecordHandle rh;
 		HeapRowLocation rowlocation;
 
-		if (callbackWithRowLocation)
+        if (callbackWithRowLocation ||
+            rowSource.needsRowLocationForDeferredCheckConstraints())
 			rowlocation = new HeapRowLocation();
 		else
 			rowlocation = null;
@@ -449,6 +453,12 @@ public class HeapController 
 					rowlocation.setFrom(rh);
 					rowSource.rowLocation(rowlocation);
 				}
+
+                if (rowSource.needsRowLocationForDeferredCheckConstraints()) {
+                    rowlocation.setFrom(rh);
+                    rowSource.offendingRowLocation(rowlocation,
+                                                   heap.getContainerid());
+                }
 			}
 			page.unlatch();
 			page = null;

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/sort/MergeScanRowSource.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/sort/MergeScanRowSource.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/sort/MergeScanRowSource.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/sort/MergeScanRowSource.java Tue Mar 11 14:46:15 2014
@@ -101,7 +101,12 @@ public class MergeScanRowSource extends 
 		return false;
 	}
 
-	/**
+    public boolean needsRowLocationForDeferredCheckConstraints()
+    {
+        return false;
+    }
+
+/**
 	 * @see org.apache.derby.iapi.store.access.RowSource#needsToClone
 	 */
 	public boolean needsToClone()
@@ -119,6 +124,12 @@ public class MergeScanRowSource extends 
 			SanityManager.THROWASSERT("unexpected call to RowSource.rowLocation");
 	}
 
+    public void offendingRowLocation(
+            RowLocation rl, long containdId) throws StandardException {
+        if (SanityManager.DEBUG) {
+            SanityManager.NOTREACHED();
+        }
+    }
 
 	/**
 		All columns are always set from a sorter

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/sort/SortBufferRowSource.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/sort/SortBufferRowSource.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/sort/SortBufferRowSource.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/sort/SortBufferRowSource.java Tue Mar 11 14:46:15 2014
@@ -102,6 +102,12 @@ public class SortBufferRowSource extends
 		return false;
 	}
 
+    public boolean needsRowLocationForDeferredCheckConstraints()
+    {
+        return false;
+    }
+
+
 	/**
 	 * @see org.apache.derby.iapi.store.access.RowSource#needsToClone
 	 */
@@ -116,6 +122,12 @@ public class SortBufferRowSource extends
 			SanityManager.THROWASSERT("unexpected call to RowSource.rowLocation");
 	}
 
+    public void offendingRowLocation(
+            RowLocation rl, long containdId) throws StandardException {
+        if (SanityManager.DEBUG) {
+            SanityManager.NOTREACHED();
+        }
+    }
 
 	/**
 		All columns are always set from a sorter

Modified: db/derby/code/trunk/java/engine/org/apache/derby/jdbc/EmbedXAResource.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/jdbc/EmbedXAResource.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/jdbc/EmbedXAResource.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/jdbc/EmbedXAResource.java Tue Mar 11 14:46:15 2014
@@ -307,9 +307,8 @@ class EmbedXAResource implements XAResou
             } catch (SQLException sqle) {
                 XAException xe = wrapInXAException(sqle);
 
-                if (sqle.getSQLState().equals(
-                      ExceptionUtil.getSQLStateFromIdentifier(
-                        SQLState.LANG_DEFERRED_DUPLICATE_KEY_CONSTRAINT_T))) {
+                if (ExceptionUtil.
+                        isDeferredConstraintViolation(sqle.getSQLState())) {
                     // We are rolling back
                     returnConnectionToResource(tranState, xid_im);
                 }
@@ -831,10 +830,11 @@ class EmbedXAResource implements XAResou
             xaErrorCode = XAException.XA_RBTIMEOUT;
         else if (seErrorCode >=  ExceptionSeverity.SESSION_SEVERITY)
             xaErrorCode = XAException.XAER_RMFAIL;
-        else if (sqlstate.equals(StandardException.getSQLStateFromIdentifier(SQLState.LANG_DEFERRED_DUPLICATE_KEY_CONSTRAINT_T)))
+        else if (ExceptionUtil.isDeferredConstraintViolation(sqlstate)) {
             xaErrorCode = XAException.XA_RBINTEGRITY;
-        else
+        } else {
             xaErrorCode = XAException.XAER_RMERR;
+        }
         
         xae = new XAException(message);
         xae.errorCode = xaErrorCode;

Modified: db/derby/code/trunk/java/engine/org/apache/derby/jdbc/XATransactionState.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/jdbc/XATransactionState.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/jdbc/XATransactionState.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/jdbc/XATransactionState.java Tue Mar 11 14:46:15 2014
@@ -365,9 +365,7 @@ final class XATransactionState extends C
         try {
             retVal = conn.xa_prepare();
         } catch (SQLException e) {
-            if (e.getSQLState().equals(
-                  ExceptionUtil.getSQLStateFromIdentifier(
-                    SQLState.LANG_DEFERRED_DUPLICATE_KEY_CONSTRAINT_T))) {
+            if (ExceptionUtil.isDeferredConstraintViolation(e.getSQLState())) {
                 // we are rolling back
                 xa_finalize();
             }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml Tue Mar 11 14:46:15 2014
@@ -898,6 +898,22 @@ Guide.
                 <arg>constraintName</arg>
             </msg>
 
+            <msg>
+                <name>23514.T.1</name>
+                <text>The transaction was aborted because of a deferred constraint violation: Check constraint identified by '{0}' defined on '{1}' as '{2}'.</text>
+                <arg>indexOrConstraintName</arg>
+                <arg>tableName</arg>
+                <arg>constraintText</arg>
+            </msg>
+
+            <msg>
+                <name>23515.S.1</name>
+                <text>Deferred constraint violation: Check constraint identified by '{0}' defined on '{1}' as '{2}'.</text>
+                <arg>indexOrConstraintName</arg>
+                <arg>tableName</arg>
+                <arg>constraintText</arg>
+            </msg>
+
         </family>
 
 

Modified: db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java?rev=1576367&r1=1576366&r2=1576367&view=diff
==============================================================================
--- db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java (original)
+++ db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java Tue Mar 11 14:46:15 2014
@@ -744,6 +744,8 @@ public interface SQLState {
     String LANG_DEFERRED_DUPLICATE_KEY_CONSTRAINT_S                    = "23507.S.1";
 	String LANG_FK_VIOLATION                                           = "23503";
 	String LANG_CHECK_CONSTRAINT_VIOLATED                              = "23513";
+    String LANG_DEFERRED_CHECK_CONSTRAINT_T                            = "23514.T.1";
+    String LANG_DEFERRED_CHECK_CONSTRAINT_S                            = "23515.S.1";
 
 	// From SQL/XML[2006] spec; there are others, but
 	// these are the ones we actually use with our