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 mi...@apache.org on 2007/05/07 09:47:35 UTC

svn commit: r535770 - in /db/derby/code/trunk/java/engine/org/apache/derby: iapi/sql/dictionary/ impl/sql/execute/

Author: mikem
Date: Mon May  7 00:47:34 2007
New Revision: 535770

URL: http://svn.apache.org/viewvc?view=rev&rev=535770
Log:
DERBY-2537

This checkin fixes create index, alter table, and bulk insert to correctly
set the collation in the persistent tables and indexes that they create.


Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/IndexRowGenerator.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateIndexConstantAction.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/IndexRowGenerator.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/IndexRowGenerator.java?view=diff&rev=535770&r1=535769&r2=535770
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/IndexRowGenerator.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/IndexRowGenerator.java Mon May  7 00:47:34 2007
@@ -22,6 +22,7 @@
 package org.apache.derby.iapi.sql.dictionary;
 
 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList;
+
 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
 
 import org.apache.derby.iapi.sql.execute.ExecutionContext;
@@ -29,8 +30,9 @@
 import org.apache.derby.iapi.sql.execute.ExecRow;
 import org.apache.derby.iapi.sql.execute.ExecutionFactory;
 
-import org.apache.derby.iapi.types.RowLocation;
 import org.apache.derby.iapi.types.DataTypeDescriptor;
+import org.apache.derby.iapi.types.RowLocation;
+import org.apache.derby.iapi.types.StringDataValue;
 
 import org.apache.derby.iapi.services.io.Formatable;
 import org.apache.derby.iapi.services.io.FormatIdUtil;
@@ -241,6 +243,41 @@
 		}
 		return false;
 	}
+
+    /**
+     * Return an array of collation ids for this table.
+     * <p>
+     * Return an array of collation ids, one for each column in the
+     * columnDescriptorList.  This is useful for passing collation id info
+     * down to store, for instance in createConglomerate() to create
+     * the index.
+     *
+     * This is only expected to get called during ddl, so object allocation
+     * is ok. 
+     *
+	 * @param columnList ColumnDescriptors describing the base table.
+     *
+	 * @exception  StandardException  Standard exception policy.
+     **/
+    public int[] getColumnCollationIds(ColumnDescriptorList columnList)
+		throws StandardException
+    {
+        int[] base_cols     = id.baseColumnPositions();
+        int[] collation_ids = new int[base_cols.length + 1];
+
+		for (int i = 0; i < base_cols.length; i++)
+		{
+            collation_ids[i] =
+				columnList.elementAt(
+                    base_cols[i] - 1).getType().getCollationType();
+		}
+
+        // row location column at end is always basic collation type.
+        collation_ids[collation_ids.length - 1] = 
+            StringDataValue.COLLATION_TYPE_UCS_BASIC; 
+
+		return(collation_ids);
+    }
 
 		 
 	/**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java?view=diff&rev=535770&r1=535769&r2=535770
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java Mon May  7 00:47:34 2007
@@ -503,11 +503,14 @@
 	}
 
     /**
-     * Return an array of collation ids.
+     * Return an array of collation ids for this table.
      * <p>
      * Return an array of collation ids, one for each column in the
      * columnDescriptorList.  This is useful for passing collation id info
      * down to store, for instance in createConglomerate().
+     *
+     * This is only expected to get called during ddl, so object allocation
+     * is ok. 
      *
 	 * @exception  StandardException  Standard exception policy.
      **/

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java?view=diff&rev=535770&r1=535769&r2=535770
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java Mon May  7 00:47:34 2007
@@ -90,98 +90,101 @@
  implements RowLocationRetRowSource
 {
 
-	protected	SchemaDescriptor			sd;
-	protected	String						tableName;
-	protected	UUID						schemaId;
-	protected	int							tableType;
-	protected	long						tableConglomerateId;
-	protected	ColumnInfo[]				columnInfo;
-	protected	ConstraintConstantAction[]	constraintActions;
-	protected	char						lockGranularity;
-	private	boolean					compressTable;
-	private	boolean					sequential;
-	private int						behavior;
-
-	// Alter table compress and Drop column
-	private boolean					doneScan;
-	private boolean[]				needToDropSort;
-	private boolean[]				validRow;
-	private	int						bulkFetchSize = 16;
-	private	int						currentCompressRow;
-	private int						numIndexes;
-	private int						rowCount;
-	private long					estimatedRowCount;
-	private long[]					indexConglomerateNumbers;
-	private	long[]					sortIds;
-	private FormatableBitSet					indexedCols;
-	private ConglomerateController	compressHeapCC;
-	private ExecIndexRow[]			indexRows;
-	private ExecRow[]				baseRow;
-	private ExecRow					currentRow;
-	private	GroupFetchScanController compressHeapGSC;
-	private IndexRowGenerator[]		compressIRGs;
-	private	DataValueDescriptor[][]			baseRowArray;
-	private RowLocation[]			compressRL;
-	private SortController[]		sorters;
-	private int						columnPosition;
-	private ColumnOrdering[][]		ordering;
-	private int[][]		            collation;
-
-	private	TableDescriptor 		td;
-
-
-	//truncate table
-	private boolean                 truncateTable;
-
-	// CONSTRUCTORS
-		private LanguageConnectionContext lcc;
-		private DataDictionary dd;
-		private DependencyManager dm;
-		private TransactionController tc;
-		private Activation activation;
+    // copied from constructor args and stored locally.
+    private	    SchemaDescriptor			sd;
+    private	    String						tableName;
+    private	    UUID						schemaId;
+    private	    int							tableType;
+    private	    ColumnInfo[]				columnInfo;
+    private	    ConstraintConstantAction[]	constraintActions;
+    private	    char						lockGranularity;
+    private	    long						tableConglomerateId;
+    private	    boolean					    compressTable;
+    private     int						    behavior;
+    private	    boolean					    sequential;
+    private     boolean                     truncateTable;
+
+
+
+    // Alter table compress and Drop column
+    private     boolean					    doneScan;
+    private     boolean[]				    needToDropSort;
+    private     boolean[]				    validRow;
+    private	    int						    bulkFetchSize = 16;
+    private	    int						    currentCompressRow;
+    private     int						    numIndexes;
+    private     int						    rowCount;
+    private     long					    estimatedRowCount;
+    private     long[]					    indexConglomerateNumbers;
+    private	    long[]					    sortIds;
+    private     FormatableBitSet			indexedCols;
+    private     ConglomerateController	    compressHeapCC;
+    private     ExecIndexRow[]			    indexRows;
+    private     ExecRow[]				    baseRow;
+    private     ExecRow					    currentRow;
+    private	    GroupFetchScanController    compressHeapGSC;
+    private     IndexRowGenerator[]		    compressIRGs;
+    private	    DataValueDescriptor[][]		baseRowArray;
+    private     RowLocation[]			    compressRL;
+    private     SortController[]		    sorters;
+    private     int						    droppedColumnPosition;
+    private     ColumnOrdering[][]		    ordering;
+    private     int[][]		                collation;
+
+    private	TableDescriptor 		        td;
+
+
+
+    // CONSTRUCTORS
+    private LanguageConnectionContext lcc;
+    private DataDictionary dd;
+    private DependencyManager dm;
+    private TransactionController tc;
+    private Activation activation;
 
 	/**
 	 *	Make the AlterAction for an ALTER TABLE statement.
 	 *
-	 *  @param sd			descriptor for the schema that table lives in.
-	 *  @param tableName	Name of table.
-	 *	@param tableId		UUID of table
+	 *  @param sd			        descriptor for the table's schema.
+	 *  @param tableName	        Name of table.
+	 *	@param tableId		        UUID of table
 	 *	@param tableConglomerateId	heap conglomerate number of table
-	 *  @param tableType	Type of table (e.g., BASE).
-	 *  @param columnInfo	Information on all the columns in the table.
+	 *  @param tableType	        Type of table (e.g., BASE).
+	 *  @param columnInfo	        Information on all the columns in the table.
 	 *  @param constraintActions	ConstraintConstantAction[] for constraints
-	 * @param lockGranularity	The lock granularity.
-	 *	@param compressTable	Whether or not this is a compress table
-	 *	@param behavior		drop behavior for dropping column
-	 *	@param sequential	If compress table/drop column, whether or not sequential
-	 *  @param truncateTable	Whether or not this is a truncate table
+	 *  @param lockGranularity	    The lock granularity.
+	 *	@param compressTable	    Whether or not this is a compress table
+	 *	@param behavior		        drop behavior for dropping column
+	 *	@param sequential	        If compress table/drop column, 
+     *	                            whether or not sequential
+	 *  @param truncateTable	    Whether or not this is a truncate table
 	 */
 	AlterTableConstantAction(
-								SchemaDescriptor	sd,
-								String			tableName,
-								UUID			tableId,
-								long			tableConglomerateId,
-								int				tableType,
-								ColumnInfo[]	columnInfo,
-								ConstraintConstantAction[] constraintActions,
-								char			lockGranularity,
-								boolean			compressTable,
-								int				behavior,
-								boolean			sequential,
-								boolean         truncateTable)
+    SchemaDescriptor            sd,
+    String			            tableName,
+    UUID			            tableId,
+    long			            tableConglomerateId,
+    int				            tableType,
+    ColumnInfo[]	            columnInfo,
+    ConstraintConstantAction[]  constraintActions,
+    char			            lockGranularity,
+    boolean			            compressTable,
+    int				            behavior,
+    boolean			            sequential,
+    boolean                     truncateTable)
 	{
 		super(tableId);
-		this.sd = sd;
-		this.tableName = tableName;
-		this.tableConglomerateId = tableConglomerateId;
-		this.tableType = tableType;
-		this.columnInfo = columnInfo;
-		this.constraintActions = constraintActions;
-		this.lockGranularity = lockGranularity;
-		this.compressTable = compressTable;
-		this.behavior = behavior;
-		this.sequential = sequential;
-		this.truncateTable = truncateTable;
+		this.sd                     = sd;
+		this.tableName              = tableName;
+		this.tableConglomerateId    = tableConglomerateId;
+		this.tableType              = tableType;
+		this.columnInfo             = columnInfo;
+		this.constraintActions      = constraintActions;
+		this.lockGranularity        = lockGranularity;
+		this.compressTable          = compressTable;
+		this.behavior               = behavior;
+		this.sequential             = sequential;
+		this.truncateTable          = truncateTable;
 
 		if (SanityManager.DEBUG)
 		{
@@ -213,13 +216,18 @@
 	 *
 	 * @exception StandardException		Thrown on failure
 	 */
-	public void	executeConstantAction( Activation activation )
-						throws StandardException
+	public void	executeConstantAction(
+    Activation activation)
+        throws StandardException
 	{
-		LanguageConnectionContext lcc = activation.getLanguageConnectionContext();
-		DataDictionary dd = lcc.getDataDictionary();
-		DependencyManager dm = dd.getDependencyManager();
-		TransactionController tc = lcc.getTransactionExecute();
+		LanguageConnectionContext   lcc = 
+            activation.getLanguageConnectionContext();
+		DataDictionary              dd = lcc.getDataDictionary();
+		DependencyManager           dm = dd.getDependencyManager();
+		TransactionController       tc = lcc.getTransactionExecute();
+
+		int							numRows = 0;
+        boolean						tableScanned = false;
 
 		/*
 		** Inform the data dictionary that we are about to write to it.
@@ -235,9 +243,9 @@
 		// now do the real work
 
 		// get an exclusive lock of the heap, to avoid deadlock on rows of
-		// SYSCOLUMNS etc datadictionary tables (track 879) and phantom table
+		// SYSCOLUMNS etc datadictionary tables and phantom table
 		// descriptor, in which case table shape could be changed by a
-		// concurrent thread doing add/drop column (track 3804 and 3825)
+		// concurrent thread doing add/drop column.
 
 		// older version (or at target) has to get td first, potential deadlock
 		if (tableConglomerateId == 0)
@@ -260,50 +268,24 @@
 				SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tableName);
 		}
 
-		if(truncateTable)
+		if (truncateTable)
 			dm.invalidateFor(td, DependencyManager.TRUNCATE_TABLE, lcc);
 		else
 			dm.invalidateFor(td, DependencyManager.ALTER_TABLE, lcc);
-		execGuts( activation );
-	}
-
-
-	/**
-	  *	Wrapper for this DDL action. Factored out so that our child, 
-	  * RepAlterTableConstantAction
-	  *	could enjoy the benefits of the startWriting() method above.
-	  *
-	  *
-	  * @exception StandardException		Thrown on failure
-	  */
-	public void	execGuts( Activation activation)
-						throws StandardException
-	{
-		ColumnDescriptor			columnDescriptor;
-		int							numRows = 0;
-		boolean						tableNeedsScanning = false;
-		boolean						tableScanned = false;
-
-		LanguageConnectionContext lcc = activation.getLanguageConnectionContext();
-		DataDictionary dd = lcc.getDataDictionary();
-		DependencyManager dm = dd.getDependencyManager();
-		TransactionController tc = lcc.getTransactionExecute();
 
 		// Save the TableDescriptor off in the Activation
 		activation.setDDLTableDescriptor(td);
 
 		/*
-		** If the schema descriptor is null, then
-		** we must have just read ourselves in.  
-		** So we will get the corresponding schema
-		** descriptor from the data dictionary.
+		** If the schema descriptor is null, then we must have just read 
+        ** ourselves in.  So we will get the corresponding schema descriptor 
+        ** from the data dictionary.
 		*/
 		if (sd == null)
 		{
 			sd = getAndCheckSchemaDescriptor(dd, schemaId, "ALTER TABLE");
 		}
 		
-
 		/* Prepare all dependents to invalidate.  (This is there chance
 		 * to say that they can't be invalidated.  For example, an open
 		 * cursor referencing a table/view that the user is attempting to
@@ -317,6 +299,8 @@
 		// Are we working on columns?
 		if (columnInfo != null)
 		{
+            boolean tableNeedsScanning = false;
+
 			/* NOTE: We only allow a single column to be added within
 			 * each ALTER TABLE command at the language level.  However,
 			 * this may change some day, so we will try to plan for it.
@@ -347,11 +331,12 @@
 			if (tableNeedsScanning)
 			{
 				numRows = getSemiRowCount(tc);
-				// Don't allow user to add non-nullable column to non-empty table
+				// Don't allow add of non-nullable column to non-empty table
 				if (numRows > 0)
 				{
-					throw StandardException.newException(SQLState.LANG_ADDING_NON_NULL_COLUMN_TO_NON_EMPTY_TABLE, 
-									td.getQualifiedName());
+					throw StandardException.newException(
+                        SQLState.LANG_ADDING_NON_NULL_COLUMN_TO_NON_EMPTY_TABLE,
+                        td.getQualifiedName());
 				}
 				tableScanned = true;
 			}
@@ -367,7 +352,7 @@
 				
 				if (columnInfo[ix].action == ColumnInfo.CREATE)
 				{
-					addNewColumnToTable(activation, ix);
+					addNewColumnToTable(activation, lcc, dd, tc, ix);
 				}
 				else if (columnInfo[ix].action == 
 						 ColumnInfo.MODIFY_COLUMN_DEFAULT_RESTART ||
@@ -386,32 +371,36 @@
 				else if (columnInfo[ix].action == 
 						 ColumnInfo.MODIFY_COLUMN_CONSTRAINT)
 				{
-					modifyColumnConstraint(activation, columnInfo[ix].name, true);
+					modifyColumnConstraint(
+                        activation, columnInfo[ix].name, true);
 				}
 				else if (columnInfo[ix].action == 
 						 ColumnInfo.MODIFY_COLUMN_CONSTRAINT_NOT_NULL)
 				{
-					if (! tableScanned)
+					if (!tableScanned)
 					{
 						tableScanned = true;
 						numRows = getSemiRowCount(tc);
 					}
+
 					// check that the data in the column is not null
-					String colNames[] = new String[1];
-					colNames[0] = columnInfo[ix].name;
+					String colNames[]  = new String[1];
+					colNames[0]        = columnInfo[ix].name;
 					boolean nullCols[] = new boolean[1];
 
 					/* note validateNotNullConstraint returns true if the
 					 * column is nullable
 					 */
-					if (validateNotNullConstraint(colNames, nullCols, 
-							numRows, lcc, SQLState.LANG_NULL_DATA_IN_NON_NULL_COLUMN))
+					if (validateNotNullConstraint(
+                            colNames, nullCols, numRows, lcc, 
+                            SQLState.LANG_NULL_DATA_IN_NON_NULL_COLUMN))
 					{
 						/* nullable column - modify it to be not null
 						 * This is O.K. at this point since we would have
 						 * thrown an exception if any data was null
 						 */
-						modifyColumnConstraint(activation, columnInfo[ix].name, false);
+						modifyColumnConstraint(
+                            activation, columnInfo[ix].name, false);
 					}
 				}
 				else if (columnInfo[ix].action == ColumnInfo.DROP)
@@ -429,7 +418,9 @@
 		/* Create/Drop any constraints */
 		if (constraintActions != null)
 		{
-			for (int conIndex = 0; conIndex < constraintActions.length; conIndex++)
+			for (int conIndex = 0; 
+                 conIndex < constraintActions.length; 
+                 conIndex++)
 			{
 				ConstraintConstantAction cca = constraintActions[conIndex];
 
@@ -438,28 +429,36 @@
 					int constraintType = cca.getConstraintType();
 
 					/* Some constraint types require special checking:
-					 *		Check		- table must be empty, for now
-					 *		Primary Key - table cannot already have a primary key
+					 *   Check		 - table must be empty, for now
+					 *   Primary Key - table cannot already have a primary key
 					 */
 					switch (constraintType)
 					{
 						case DataDictionary.PRIMARYKEY_CONSTRAINT:
-							// Check to see if a constraint of the same type already exists
-							ConstraintDescriptorList cdl = dd.getConstraintDescriptors(td);
+
+							// Check to see if a constraint of the same type 
+                            // already exists
+							ConstraintDescriptorList cdl = 
+                                dd.getConstraintDescriptors(td);
+
 							if (cdl.getPrimaryKey() != null)
 							{
-								throw StandardException.newException(SQLState.LANG_ADD_PRIMARY_KEY_FAILED1, 
-											td.getQualifiedName());
+								throw StandardException.newException(
+                                    SQLState.LANG_ADD_PRIMARY_KEY_FAILED1, 
+                                    td.getQualifiedName());
 							}
-							if (! tableScanned)
+
+							if (!tableScanned)
 							{
 								tableScanned = true;
 								numRows = getSemiRowCount(tc);
 							}
 
 							break;
+
 						case DataDictionary.CHECK_CONSTRAINT:
-							if (! tableScanned)
+
+							if (!tableScanned)
 							{
 								tableScanned = true;
 								numRows = getSemiRowCount(tc);
@@ -473,10 +472,10 @@
 								** to lump together several checks.	
 								*/
 								ConstraintConstantAction.validateConstraint(
-											cca.getConstraintName(),
-											((CreateConstraintConstantAction)cca).getConstraintText(),
-											td,
-											lcc, true);
+                                    cca.getConstraintName(),
+                                    ((CreateConstraintConstantAction)cca).getConstraintText(),
+                                    td,
+                                    lcc, true);
 							}
 							break;
 					}
@@ -487,12 +486,15 @@
 					{
 						if (!(cca instanceof DropConstraintConstantAction))
 						{
-							SanityManager.THROWASSERT("constraintActions[" + conIndex + 
-							"] expected to be instanceof DropConstraintConstantAction not " +
-							cca.getClass().getName());
+							SanityManager.THROWASSERT(
+                                "constraintActions[" + conIndex + 
+                                "] expected to be instanceof " + 
+                                "DropConstraintConstantAction not " +
+                                cca.getClass().getName());
 						}
 					}
 				}
+
 				constraintActions[conIndex].executeConstantAction(activation);
 			}
 		}
@@ -506,7 +508,8 @@
 					lockGranularity != 'R')
 				{
 					SanityManager.THROWASSERT(
-						"lockGranularity expected to be 'T'or 'R', not " + lockGranularity);
+						"lockGranularity expected to be 'T'or 'R', not " + 
+                        lockGranularity);
 				}
 			}
 
@@ -527,8 +530,6 @@
 		{
 			truncateTable(activation);
 		}
-
-		
 	}
 
 	/**
@@ -538,20 +539,19 @@
 	 *						statement-- currently we allow only one.
 	 * @exception StandardException 	thrown on failure.
 	 */
-	private void addNewColumnToTable(Activation activation, 
-									 int ix) 
+	private void addNewColumnToTable(
+    Activation                  activation, 
+    LanguageConnectionContext   lcc,
+    DataDictionary              dd,
+    TransactionController       tc,
+    int                         ix) 
 	        throws StandardException
 	{
-		LanguageConnectionContext lcc = activation.getLanguageConnectionContext();
-		DataDictionary dd = lcc.getDataDictionary();
-		DependencyManager dm = dd.getDependencyManager();
-		TransactionController tc = lcc.getTransactionExecute();
-
-		ColumnDescriptor columnDescriptor = 
+		ColumnDescriptor columnDescriptor   = 
 			td.getColumnDescriptor(columnInfo[ix].name);
 		DataValueDescriptor storableDV;
-		int colNumber = td.getMaxColumnID() + ix;
-		DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();
+		int                     colNumber   = td.getMaxColumnID() + ix;
+		DataDescriptorGenerator ddg         = dd.getDataDescriptorGenerator();
 
 		/* We need to verify that the table does not have an existing
 		 * column with the same name before we try to add the new
@@ -561,11 +561,11 @@
 		{
 			throw 
 				StandardException.newException(
-											   SQLState.LANG_OBJECT_ALREADY_EXISTS_IN_OBJECT,
-											   columnDescriptor.getDescriptorType(),
-											   columnInfo[ix].name,
-											   td.getDescriptorType(),
-											   td.getQualifiedName());
+                   SQLState.LANG_OBJECT_ALREADY_EXISTS_IN_OBJECT,
+                   columnDescriptor.getDescriptorType(),
+                   columnInfo[ix].name,
+                   td.getDescriptorType(),
+                   td.getQualifiedName());
 		}
 
 		if (columnInfo[ix].defaultValue != null)
@@ -593,17 +593,18 @@
 
 		// Add the column to syscolumns. 
 		// Column ids in system tables are 1-based
-		columnDescriptor = new ColumnDescriptor(
-												   columnInfo[ix].name,
-												   colNumber + 1,
-												   columnInfo[ix].dataType,
-												   columnInfo[ix].defaultValue,
-												   columnInfo[ix].defaultInfo,
-												   td,
-												   defaultUUID,
-												   columnInfo[ix].autoincStart,
-												   columnInfo[ix].autoincInc
-												   );
+		columnDescriptor = 
+            new ColumnDescriptor(
+                   columnInfo[ix].name,
+                   colNumber + 1,
+                   columnInfo[ix].dataType,
+                   columnInfo[ix].defaultValue,
+                   columnInfo[ix].defaultInfo,
+                   td,
+                   defaultUUID,
+                   columnInfo[ix].autoincStart,
+                   columnInfo[ix].autoincInc
+                   );
 
 		dd.addDescriptor(columnDescriptor, td,
 						 DataDictionary.SYSCOLUMNS_CATALOG_NUM, false, tc);
@@ -713,9 +714,9 @@
 		{
 			throw 
 				StandardException.newException(
-									    SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, 
-										columnInfo[ix].name,
-										td.getQualifiedName());
+                    SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, 
+                    columnInfo[ix].name,
+                    td.getQualifiedName());
 		}
 
 		DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();
@@ -725,18 +726,19 @@
 		// can NOT drop a column if it is the only one in the table
 		if (size == 1)
 		{
-			throw StandardException.newException(SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
-							dm.getActionString(DependencyManager.DROP_COLUMN),
-							"THE *LAST* COLUMN " + columnInfo[ix].name,
-							"TABLE",
-							td.getQualifiedName() );
+			throw StandardException.newException(
+                    SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
+                    dm.getActionString(DependencyManager.DROP_COLUMN),
+                    "THE *LAST* COLUMN " + columnInfo[ix].name,
+                    "TABLE",
+                    td.getQualifiedName() );
 		}
 
-		columnPosition = columnDescriptor.getPosition();
+		droppedColumnPosition = columnDescriptor.getPosition();
 		boolean cascade = (behavior == StatementType.DROP_CASCADE);
 
 		FormatableBitSet toDrop = new FormatableBitSet(size + 1);
-		toDrop.set(columnPosition);
+		toDrop.set(droppedColumnPosition);
 		td.setReferencedColumnMap(toDrop);
 
 		dm.invalidateFor(td, 
@@ -747,8 +749,8 @@
 		// If column has a default we drop the default and any dependencies
 		if (columnDescriptor.getDefaultInfo() != null)
 		{
-			DefaultDescriptor defaultDesc = columnDescriptor.getDefaultDescriptor(dd);
-			dm.clearDependencies(lcc, defaultDesc);
+			dm.clearDependencies(
+                lcc, columnDescriptor.getDefaultDescriptor(dd));
 		}
 
 		// need to deal with triggers if has referencedColumns
@@ -764,24 +766,28 @@
 			boolean changed = false;
 			for (j = 0; j < refColLen; j++)
 			{
-				if (referencedCols[j] > columnPosition)
+				if (referencedCols[j] > droppedColumnPosition)
+                {
 					changed = true;
-				else if (referencedCols[j] == columnPosition)
+                }
+				else if (referencedCols[j] == droppedColumnPosition)
 				{
 					if (cascade)
 					{
                         trd.drop(lcc);
 						activation.addWarning(
-							StandardException.newWarning(SQLState.LANG_TRIGGER_DROPPED,
-								trd.getName(), td.getName()));
+							StandardException.newWarning(
+                                SQLState.LANG_TRIGGER_DROPPED, 
+                                trd.getName(), td.getName()));
 					}
 					else
 					{	// we'd better give an error if don't drop it,
 						// otherwsie there would be unexpected behaviors
-						throw StandardException.newException(SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
-										dm.getActionString(DependencyManager.DROP_COLUMN),
-										columnInfo[ix].name, "TRIGGER",
-										trd.getName() );
+						throw StandardException.newException(
+                            SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
+                            dm.getActionString(DependencyManager.DROP_COLUMN),
+                            columnInfo[ix].name, "TRIGGER",
+                            trd.getName() );
 					}
 					break;
 				}
@@ -793,7 +799,7 @@
 				dd.dropTriggerDescriptor(trd, tc);
 				for (j = 0; j < refColLen; j++)
 				{
-					if (referencedCols[j] > columnPosition)
+					if (referencedCols[j] > droppedColumnPosition)
 						referencedCols[j]--;
 				}
 				dd.addDescriptor(trd, sd,
@@ -809,7 +815,8 @@
 		// round.  This will ensure that self-referential constraints will
 		// work OK.
 		int tbr_size = 0;
-		ConstraintDescriptor[] toBeRemoved = new ConstraintDescriptor[csdl_size];
+		ConstraintDescriptor[] toBeRemoved = 
+            new ConstraintDescriptor[csdl_size];
 
 		// let's go downwards, don't want to get messed up while removing
 		for (int i = csdl_size - 1; i >= 0; i--)
@@ -820,9 +827,9 @@
 			boolean changed = false;
 			for (j = 0; j < numRefCols; j++)
 			{
-				if (referencedColumns[j] > columnPosition)
+				if (referencedColumns[j] > droppedColumnPosition)
 					changed = true;
-				if (referencedColumns[j] == columnPosition)
+				if (referencedColumns[j] == droppedColumnPosition)
 					break;
 			}
 			if (j == numRefCols)			// column not referenced
@@ -832,7 +839,7 @@
 					dd.dropConstraintDescriptor(td, cd, tc);
 					for (j = 0; j < numRefCols; j++)
 					{
-						if (referencedColumns[j] > columnPosition)
+						if (referencedColumns[j] > droppedColumnPosition)
 							referencedColumns[j]--;
 					}
 					((CheckConstraintDescriptor) cd).setReferencedColumnsDescriptor(new ReferencedColumnsDescriptorImpl(referencedColumns));
@@ -846,15 +853,16 @@
 				// Reject the DROP COLUMN, because there exists a constraint
 				// which references this column.
 				//
-				throw StandardException.newException(SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
-										dm.getActionString(DependencyManager.DROP_COLUMN),
-										columnInfo[ix].name, "CONSTRAINT",
-										cd.getConstraintName() );
+				throw StandardException.newException(
+                        SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
+                        dm.getActionString(DependencyManager.DROP_COLUMN),
+                        columnInfo[ix].name, "CONSTRAINT",
+                        cd.getConstraintName() );
 			}
 
 			if (cd instanceof ReferencedKeyConstraintDescriptor)
 			{
-				// restrict will raise an error in invalidate if really referenced
+				// restrict will raise an error in invalidate if referenced
 				toBeRemoved[tbr_size++] = cd;
 				continue;
 			}
@@ -864,32 +872,42 @@
 									lcc);
 			DropConstraintConstantAction.dropConstraintAndIndex(dm, td, dd,
 							 cd, tc, lcc, true);
-			activation.addWarning(StandardException.newWarning(SQLState.LANG_CONSTRAINT_DROPPED,
+
+			activation.addWarning(
+                StandardException.newWarning(SQLState.LANG_CONSTRAINT_DROPPED,
 				cd.getConstraintName(), td.getName()));
 		}
 
 		for (int i = tbr_size - 1; i >= 0; i--)
 		{
 			ConstraintDescriptor cd = toBeRemoved[i];
-			DropConstraintConstantAction.dropConstraintAndIndex(dm, td, dd, cd,
-						tc, lcc, false);
-			activation.addWarning(StandardException.newWarning(SQLState.LANG_CONSTRAINT_DROPPED,
-					cd.getConstraintName(), td.getName()));
+			DropConstraintConstantAction.dropConstraintAndIndex(
+                dm, td, dd, cd, tc, lcc, false);
+
+			activation.addWarning(
+                StandardException.newWarning(SQLState.LANG_CONSTRAINT_DROPPED,
+                cd.getConstraintName(), td.getName()));
 
 			if (cascade)
 			{
 				ConstraintDescriptorList fkcdl = dd.getForeignKeys(cd.getUUID());
 				for (int j = 0; j < fkcdl.size(); j++)
 				{
-					ConstraintDescriptor fkcd = (ConstraintDescriptor) fkcdl.elementAt(j);
+					ConstraintDescriptor fkcd = 
+                        (ConstraintDescriptor) fkcdl.elementAt(j);
+
 					dm.invalidateFor(fkcd,
 									DependencyManager.DROP_CONSTRAINT,
 									lcc);
 
 					DropConstraintConstantAction.dropConstraintAndIndex(
 						dm, fkcd.getTableDescriptor(), dd, fkcd, tc, lcc, true);
-					activation.addWarning(StandardException.newWarning(SQLState.LANG_CONSTRAINT_DROPPED,
-						fkcd.getConstraintName(), fkcd.getTableDescriptor().getName()));
+
+					activation.addWarning(
+                        StandardException.newWarning(
+                            SQLState.LANG_CONSTRAINT_DROPPED,
+						    fkcd.getConstraintName(), 
+                            fkcd.getTableDescriptor().getName()));
 				}
 			}
 
@@ -897,23 +915,24 @@
 			dm.clearDependencies(lcc, cd);
 		}
 
-                /*
-                 * The work we've done above, specifically the possible
-                 * dropping of primary key, foreign key, and unique constraints
-                 * and their underlying indexes, may have affected the table
-                 * descriptor. By re-reading the table descriptor here, we
-                 * ensure that the compressTable code is working with an
-                 * accurate table descriptor. Without this line, we may get
-                 * conglomerate-not-found errors and the like due to our
-                 * stale table descriptor.
-                 */
+        /*
+         * The work we've done above, specifically the possible
+         * dropping of primary key, foreign key, and unique constraints
+         * and their underlying indexes, may have affected the table
+         * descriptor. By re-reading the table descriptor here, we
+         * ensure that the compressTable code is working with an
+         * accurate table descriptor. Without this line, we may get
+         * conglomerate-not-found errors and the like due to our
+         * stale table descriptor.
+         */
 		td = dd.getTableDescriptor(tableId);
 
 		compressTable(activation);
 
 		// drop the column from syscolumns 
 		dd.dropColumnDescriptor(td.getUUID(), columnInfo[ix].name, tc);
-		ColumnDescriptor[] cdlArray = new ColumnDescriptor[size - columnDescriptor.getPosition()];
+		ColumnDescriptor[] cdlArray = 
+            new ColumnDescriptor[size - columnDescriptor.getPosition()];
 
 		for (int i = columnDescriptor.getPosition(), j = 0; i < size; i++, j++)
 		{
@@ -926,22 +945,28 @@
 							  DataDictionary.SYSCOLUMNS_CATALOG_NUM, false, tc);
 
 		List deps = dd.getProvidersDescriptorList(td.getObjectID().toString());
-		for (Iterator depsIterator = deps.listIterator(); depsIterator.hasNext();)
+		for (Iterator depsIterator = deps.listIterator(); 
+             depsIterator.hasNext();)
 		{
-			DependencyDescriptor depDesc = (DependencyDescriptor) depsIterator.next();
+			DependencyDescriptor depDesc = 
+                (DependencyDescriptor) depsIterator.next();
+
 			DependableFinder finder = depDesc.getProviderFinder();
 			if (finder instanceof DDColumnDependableFinder)
 			{
-				DDColumnDependableFinder colFinder = (DDColumnDependableFinder) finder;
-				FormatableBitSet oldColumnBitMap = new FormatableBitSet(colFinder.getColumnBitMap());
-				FormatableBitSet newColumnBitMap = new FormatableBitSet(oldColumnBitMap);
+				DDColumnDependableFinder colFinder = 
+                    (DDColumnDependableFinder) finder;
+				FormatableBitSet oldColumnBitMap = 
+                    new FormatableBitSet(colFinder.getColumnBitMap());
+				FormatableBitSet newColumnBitMap = 
+                    new FormatableBitSet(oldColumnBitMap);
 				newColumnBitMap.clear();
 				int bitLen = oldColumnBitMap.getLength();
 				for (int i = 0; i < bitLen; i++)
 				{
-					if (i < columnPosition && oldColumnBitMap.isSet(i))
+					if (i < droppedColumnPosition && oldColumnBitMap.isSet(i))
 						newColumnBitMap.set(i);
-					if (i > columnPosition && oldColumnBitMap.isSet(i))
+					if (i > droppedColumnPosition && oldColumnBitMap.isSet(i))
 						newColumnBitMap.set(i - 1);
 				}
 				if (newColumnBitMap.equals(oldColumnBitMap))
@@ -1114,22 +1139,28 @@
 		// else we are simply changing the default value
 	}
 
-
-	/* NOTE: compressTable can also be called for 
-	 * ALTER TABLE <t> DROP COLUMN <c>;
-	 */
+    /**
+     * routine to process compress table or ALTER TABLE <t> DROP COLUMN <c>;
+     * <p>
+     * Uses class level variable "compressTable" to determine if processing
+     * compress table or drop column:
+     *     if (!compressTable)
+     *         must be drop column.
+     * <p>
+     * Handles rebuilding of base conglomerate and all necessary indexes.
+     **/
 	private void compressTable(
     Activation activation)
 		throws StandardException
 	{
-		ExecRow					emptyHeapRow;
 		long					newHeapConglom;
 		Properties				properties = new Properties();
 		RowLocation				rl;
-		this.lcc = activation.getLanguageConnectionContext();
-		this.dd = lcc.getDataDictionary();
-		this.dm = dd.getDependencyManager();
-		this.tc = lcc.getTransactionExecute();
+
+		this.lcc        = activation.getLanguageConnectionContext();
+		this.dd         = lcc.getDataDictionary();
+		this.dm         = dd.getDependencyManager();
+		this.tc         = lcc.getTransactionExecute();
 		this.activation = activation;
 
 		if (SanityManager.DEBUG)
@@ -1145,13 +1176,17 @@
 			SanityManager.ASSERT(constraintActions == null,
 				"constraintActions expected to be null");
 		}
-		emptyHeapRow = td.getEmptyExecRow(lcc.getContextManager());
-		compressHeapCC = tc.openConglomerate(
-								td.getHeapConglomerateId(),
-                                false,
-                                TransactionController.OPENMODE_FORUPDATE,
-                                TransactionController.MODE_TABLE,
-                                TransactionController.ISOLATION_SERIALIZABLE);
+
+		ExecRow emptyHeapRow  = td.getEmptyExecRow(lcc.getContextManager());
+        int[]   collation_ids = td.getColumnCollationIds();
+
+		compressHeapCC = 
+            tc.openConglomerate(
+                td.getHeapConglomerateId(),
+                false,
+                TransactionController.OPENMODE_FORUPDATE,
+                TransactionController.MODE_TABLE,
+                TransactionController.ISOLATION_SERIALIZABLE);
 
 		// invalidate any prepared statements that depended on this table 
         // (including this one), this fixes problem with threads that start up 
@@ -1161,7 +1196,6 @@
 		//
 		dm.invalidateFor(td, DependencyManager.COMPRESS_TABLE, lcc);
 
-
 		rl = compressHeapCC.newRowLocationTemplate();
 
 		// Get the properties on the old heap
@@ -1176,22 +1210,35 @@
 
 		/* Set up index info */
 		getAffectedIndexes(activation);
+
 		// Get an array of RowLocation template
 		compressRL = new RowLocation[bulkFetchSize];
-		indexRows = new ExecIndexRow[numIndexes];
-		if (! compressTable)
+		indexRows  = new ExecIndexRow[numIndexes];
+		if (!compressTable)
 		{
+            // must be a drop column, thus the number of columns in the
+            // new template row and the collation template is one less.
 			ExecRow newRow = 
                 activation.getExecutionFactory().getValueRow(
                     emptyHeapRow.nColumns() - 1);
 
+            int[]   new_collation_ids = new int[collation_ids.length - 1];
+
 			for (int i = 0; i < newRow.nColumns(); i++)
 			{
-				newRow.setColumn(i + 1, i < columnPosition - 1 ?
-										 emptyHeapRow.getColumn(i + 1) :
-										 emptyHeapRow.getColumn(i + 1 + 1));
+				newRow.setColumn(
+                    i + 1, 
+                    i < droppedColumnPosition - 1 ?
+                        emptyHeapRow.getColumn(i + 1) :
+                        emptyHeapRow.getColumn(i + 1 + 1));
+
+                new_collation_ids[i] = 
+                    collation_ids[
+                        (i < droppedColumnPosition - 1) ? i : (i + 1)];
 			}
+
 			emptyHeapRow = newRow;
+			collation_ids = new_collation_ids;
 		}
 		setUpAllSorts(emptyHeapRow, rl);
 
@@ -1216,13 +1263,7 @@
                 "heap",
                 emptyHeapRow.getRowArray(),
                 null, //column sort order - not required for heap
-                (int[]) null, // TODO-COLLATION - implement correct setting of
-                              // collation ids.  This is made more tricky as
-                              // this routine could be called by either compress
-                              // table where the heap ids are same as old heap
-                              // or drop table where the collation ids need
-                              // to be shuffled about.  Setting default 
-                              // collation for now.
+                collation_ids,
                 properties,
                 TransactionController.IS_DEFAULT,
                 this,
@@ -1271,17 +1312,17 @@
 		 * back the same conglomerate number
 		 */
 		// Get the ConglomerateDescriptor for the heap
-		long oldHeapConglom = td.getHeapConglomerateId();
-		ConglomerateDescriptor cd = td.getConglomerateDescriptor(oldHeapConglom);
+		long oldHeapConglom       = td.getHeapConglomerateId();
+		ConglomerateDescriptor cd = 
+            td.getConglomerateDescriptor(oldHeapConglom);
 
 		// Update sys.sysconglomerates with new conglomerate #
 		dd.updateConglomerateDescriptor(cd, newHeapConglom, tc);
+
 		// Drop the old conglomerate
 		tc.dropConglomerate(oldHeapConglom);
 		cleanUp();
 	}
-
-
 	
 	/* 
 	 * TRUNCATE TABLE  TABLENAME; (quickly removes all the rows from table and
@@ -1508,23 +1549,27 @@
 		}
 	}
 
-	private void updateIndex(long newHeapConglom, DataDictionary dd,
-							 int index, long[] newIndexCongloms)
+	private void updateIndex(
+    long            newHeapConglom, 
+    DataDictionary  dd,
+    int             index, 
+    long[]          newIndexCongloms)
 		throws StandardException
 	{
-		ConglomerateController indexCC;
 		Properties properties = new Properties();
-		ConglomerateDescriptor cd;
+
 		// Get the ConglomerateDescriptor for the index
-		cd = td.getConglomerateDescriptor(indexConglomerateNumbers[index]);
+		ConglomerateDescriptor cd = 
+            td.getConglomerateDescriptor(indexConglomerateNumbers[index]);
 
 		// Build the properties list for the new conglomerate
-		indexCC = tc.openConglomerate(
-							indexConglomerateNumbers[index],
-                            false,
-                            TransactionController.OPENMODE_FORUPDATE,
-                            TransactionController.MODE_TABLE,
-                            TransactionController.ISOLATION_SERIALIZABLE);
+		ConglomerateController indexCC = 
+            tc.openConglomerate(
+                indexConglomerateNumbers[index],
+                false,
+                TransactionController.OPENMODE_FORUPDATE,
+                TransactionController.MODE_TABLE,
+                TransactionController.ISOLATION_SERIALIZABLE);
 
 		// Get the properties on the old index
 		indexCC.getInternalTablePropertySet(properties);
@@ -1536,62 +1581,67 @@
 		properties.put("baseConglomerateId", Long.toString(newHeapConglom));
 		if (cd.getIndexDescriptor().isUnique())
 		{
-			properties.put("nUniqueColumns", 
-						   Integer.toString(indexRowLength - 1));
+			properties.put(
+                "nUniqueColumns", Integer.toString(indexRowLength - 1));
 		}
 		else
 		{
-			properties.put("nUniqueColumns", 
-						   Integer.toString(indexRowLength));
+			properties.put(
+                "nUniqueColumns", Integer.toString(indexRowLength));
 		}
-		properties.put("rowLocationColumn", 
-						Integer.toString(indexRowLength - 1));
-		properties.put("nKeyFields", Integer.toString(indexRowLength));
+		properties.put(
+            "rowLocationColumn", Integer.toString(indexRowLength - 1));
+		properties.put(
+            "nKeyFields", Integer.toString(indexRowLength));
 
 		indexCC.close();
 
 		// We can finally drain the sorter and rebuild the index
-		// RESOLVE - all indexes are btrees right now
 		// Populate the index.
 		
-		RowLocationRetRowSource cCount = null;
-		boolean updateStatistics = false;
-		if(!truncateTable)
+		RowLocationRetRowSource cCount           = null;
+		boolean                 statisticsExist  = false;
+
+		if (!truncateTable)
 		{
 			sorters[index].completedInserts();
 			sorters[index] = null;
 
 			if (td.statisticsExist(cd))
 			{
-				cCount = new CardinalityCounter(tc.openSortRowSource(sortIds[index]));
-				updateStatistics = true;
+				cCount = 
+                    new CardinalityCounter(
+                            tc.openSortRowSource(sortIds[index]));
+
+				statisticsExist = true;
 			}
 			else
-				cCount = new CardinalityCounter(tc.openSortRowSource(sortIds[index]));
+            {
+				cCount = 
+                    new CardinalityCounter(
+                            tc.openSortRowSource(sortIds[index]));
+            }
 
-			newIndexCongloms[index] = tc.createAndLoadConglomerate(
-								   "BTREE",
-								   indexRows[index].getRowArray(),
-								   ordering[index],
-                                   (int[]) null, // TODO-COLLATION, implement 
-                                                 // collation support for alter
-                                                 // table.  Currently only
-                                                 // supports default collation
-                                                 // columns.
-								   properties,
-								   TransactionController.IS_DEFAULT,
-								   cCount,
-								   (long[]) null);
+            newIndexCongloms[index] = 
+                tc.createAndLoadConglomerate(
+                    "BTREE",
+                    indexRows[index].getRowArray(),
+                    ordering[index],
+                    collation[index],
+                    properties,
+                    TransactionController.IS_DEFAULT,
+                    cCount,
+                    (long[]) null);
 
 			//For an index, if the statistics already exist, then drop them.
 			//The statistics might not exist for an index if the index was
 			//created when the table was empty.
-			//At ALTER TABLE COMPRESS time, for both kinds of indexes 
-			//(ie one with preexisting statistics and with no statistics), 
-			//create statistics for them if the table is not empty. 
-			//DERBY-737 "SYSCS_UTIL.SYSCS_COMPRESS_TABLE should create
-			//statistics if they do not exist"
-			if (updateStatistics)
+            //
+            //For all alter table actions, including ALTER TABLE COMPRESS,
+			//for both kinds of indexes (ie. one with preexisting statistics 
+            //and with no statistics), create statistics for them if the table 
+            //is not empty. 
+			if (statisticsExist)
 				dd.dropStatisticsDescriptors(td.getUUID(), cd.getUUID(), tc);
 			
 			long numRows;
@@ -1601,12 +1651,21 @@
 				for (int i = 0; i < c.length; i++)
 				{
 					StatisticsDescriptor statDesc =
-						new StatisticsDescriptor(dd, dd.getUUIDFactory().createUUID(),
-								cd.getUUID(), td.getUUID(), "I", new StatisticsImpl(numRows, c[i]),
-								i + 1);
-					dd.addDescriptor(statDesc, null, // no parent descriptor
+						new StatisticsDescriptor(
+                            dd, 
+                            dd.getUUIDFactory().createUUID(), 
+                            cd.getUUID(), 
+                            td.getUUID(), 
+                            "I", 
+                            new StatisticsImpl(numRows, c[i]), 
+                            i + 1);
+
+					dd.addDescriptor(
+                            statDesc, 
+                            null,   // no parent descriptor
 							DataDictionary.SYSSTATISTICS_CATALOG_NUM,
-							true, tc);	// no error on duplicate.
+							true,   // no error on duplicate.
+                            tc);	
 				}
 			}
 		}
@@ -1617,9 +1676,7 @@
                     "BTREE",
                     indexRows[index].getRowArray(),
                     ordering[index],
-                    (int[]) null, // TODO-COLLATION, implement alter table 
-                                  // collation passing, 
-                                  // currently only supports default collation.
+                    collation[index],
                     properties,
                     TransactionController.IS_DEFAULT);
 
@@ -1631,16 +1688,15 @@
 		}
 
 		/* Update the DataDictionary
-		 * RESOLVE - this will change in 1.4 because we will get
-		 * back the same conglomerate number
 		 *
 		 * Update sys.sysconglomerates with new conglomerate #, we need to
 		 * update all (if any) duplicate index entries sharing this same
 		 * conglomerate.
 		 */
 		dd.updateConglomerateDescriptor(
-				td.getConglomerateDescriptors(indexConglomerateNumbers[index]),
-				newIndexCongloms[index], tc);
+            td.getConglomerateDescriptors(indexConglomerateNumbers[index]),
+            newIndexCongloms[index], 
+            tc);
 
 		// Drop the old conglomerate
 		tc.dropConglomerate(indexConglomerateNumbers[index]);
@@ -1673,7 +1729,7 @@
 				int[] baseColumnPositions = compressIRGs[i].baseColumnPositions();
 				int j;
 				for (j = 0; j < baseColumnPositions.length; j++)
-					if (baseColumnPositions[j] == columnPosition) break;
+					if (baseColumnPositions[j] == droppedColumnPosition) break;
 				if (j == baseColumnPositions.length)	// not related
 					continue;
 					
@@ -1721,9 +1777,9 @@
 				int size = baseColumnPositions.length;
 				for (int k = 0; k < size; k++)
 				{
-					if (baseColumnPositions[k] > columnPosition)
+					if (baseColumnPositions[k] > droppedColumnPosition)
 						baseColumnPositions[k]--;
-					else if (baseColumnPositions[k] == columnPosition)
+					else if (baseColumnPositions[k] == droppedColumnPosition)
 					{
 						baseColumnPositions[k] = 0;		// mark it
 						reMakeArrays = true;
@@ -1789,10 +1845,12 @@
 							   RowLocation rl)
 		throws StandardException
     {
-		ordering = new ColumnOrdering[numIndexes][];
+		ordering        = new ColumnOrdering[numIndexes][];
+        collation       = new int[numIndexes][]; 
+		needToDropSort  = new boolean[numIndexes];
+		sortIds         = new long[numIndexes];
 
-		needToDropSort = new boolean[numIndexes];
-		sortIds = new long[numIndexes];
+        int[] base_table_collation_ids = td.getColumnCollationIds();
 
 		/* For each index, build a single index row and a sorter. */
 		for (int index = 0; index < numIndexes; index++)
@@ -1800,52 +1858,64 @@
 			// create a single index row template for each index
 			indexRows[index] = compressIRGs[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.)
-			compressIRGs[index].getIndexRow(sourceRow, 
-											  rl, 
-											  indexRows[index],
-											  (FormatableBitSet) null);
+			// (This call is only necessary here because we need to pass a 
+            // template to the sorter.)
+			compressIRGs[index].getIndexRow(
+                sourceRow, rl, indexRows[index], (FormatableBitSet) null);
+
+            // Setup collation id array to be passed in on call to create index.
+            collation[index] = 
+                compressIRGs[index].getColumnCollationIds(
+                    td.getColumnDescriptorList());
 
 			/* For non-unique indexes, we order by all columns + the RID.
 			 * For unique indexes, we just order by the columns.
 			 * No need to try to enforce uniqueness here as
 			 * index should be valid.
 			 */
-			int[] baseColumnPositions = compressIRGs[index].baseColumnPositions();
-			boolean[] isAscending = compressIRGs[index].isAscending();
-			int numColumnOrderings;
-			SortObserver sortObserver = null;
+			int[]       baseColumnPositions = 
+                compressIRGs[index].baseColumnPositions();
+			boolean[]   isAscending         = 
+                compressIRGs[index].isAscending();
+			int         numColumnOrderings  = 
+                baseColumnPositions.length + 1;
+
 			/* We can only reuse the wrappers when doing an
 			 * external sort if there is only 1 index.  Otherwise,
 			 * we could get in a situation where 1 sort reuses a
 			 * wrapper that is still in use in another sort.
 			 */
 			boolean reuseWrappers = (numIndexes == 1);
-			numColumnOrderings = baseColumnPositions.length + 1;
-			sortObserver = new BasicSortObserver(false, false, 
-												 indexRows[index],
-												 reuseWrappers);
+
+			SortObserver    sortObserver = 
+                new BasicSortObserver(
+                        false, false, indexRows[index], reuseWrappers);
+
 			ordering[index] = new ColumnOrdering[numColumnOrderings];
 			for (int ii =0; ii < numColumnOrderings - 1; ii++) 
 			{
 				ordering[index][ii] = new IndexColumnOrder(ii, isAscending[ii]);
 			}
-			ordering[index][numColumnOrderings - 1] = new IndexColumnOrder(numColumnOrderings - 1);
+			ordering[index][numColumnOrderings - 1] = 
+                new IndexColumnOrder(numColumnOrderings - 1);
 
 			// create the sorters
-			sortIds[index] = tc.createSort(
-							   (Properties)null, 
-								indexRows[index].getRowArrayClone(),
-								ordering[index],
-								sortObserver,
-								false,			// not in order
-								estimatedRowCount,		// est rows	
-								-1				// est row size, -1 means no idea	
-								);
+			sortIds[index] = 
+                tc.createSort(
+                   (Properties)null, 
+                    indexRows[index].getRowArrayClone(),
+                    ordering[index],
+                    sortObserver,
+                    false,			        // not in order
+                    estimatedRowCount,		// est rows	
+                    -1				        // est row size, -1 means no idea	
+                    );
 		}
 	
         sorters = new SortController[numIndexes];
+
 		// Open the sorts
 		for (int index = 0; index < numIndexes; index++)
 		{
@@ -1897,16 +1967,25 @@
 		if (validRow[currentCompressRow])
 		{
 			if (compressTable)
+            {
 				currentRow = baseRow[currentCompressRow];
+            }
 			else
 			{
 				if (currentRow == null)
-					currentRow = activation.getExecutionFactory().getValueRow(baseRowArray[currentCompressRow].length - 1);
+                {
+					currentRow = 
+                        activation.getExecutionFactory().getValueRow(
+                            baseRowArray[currentCompressRow].length - 1);
+                }
+
 				for (int i = 0; i < currentRow.nColumns(); i++)
 				{
-					currentRow.setColumn(i + 1, i < columnPosition - 1 ?
-										baseRow[currentCompressRow].getColumn(i+1) :
-										baseRow[currentCompressRow].getColumn(i+1+1));
+					currentRow.setColumn(
+                        i + 1, 
+                        i < droppedColumnPosition - 1 ?
+                            baseRow[currentCompressRow].getColumn(i+1) :
+                            baseRow[currentCompressRow].getColumn(i+1+1));
 				}
 			}
 			currentCompressRow++;

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateIndexConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateIndexConstantAction.java?view=diff&rev=535770&r1=535769&r2=535770
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateIndexConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateIndexConstantAction.java Mon May  7 00:47:34 2007
@@ -599,7 +599,8 @@
 					indexType,
 					indexTemplateRow.getRowArray(),	// index row template
 					order, //colums sort order
-                    null,  // TODO-COLLATION, implement non-default collation
+                    indexRowGenerator.getColumnCollationIds(
+                        td.getColumnDescriptorList()),
 					indexProperties,
 					TransactionController.IS_DEFAULT, // not temporary
 					rowSource,

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?view=diff&rev=535770&r1=535769&r2=535770
==============================================================================
--- 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 Mon May  7 00:47:34 2007
@@ -133,6 +133,7 @@
                                     rowSources;
 	private	ScanController			bulkHeapSC;
 	private ColumnOrdering[][]		ordering;
+	private int[][]		            collation;
 	private SortController[]		sorters;
 	private	TemporaryRowHolderImpl	rowHolder;
 	private RowLocation				rl;
@@ -1635,15 +1636,18 @@
 		int					numIndexes = constants.irgs.length;
 		int					numColumns = td.getNumberOfColumns();
 
-		ordering = new ColumnOrdering[numIndexes][];
-		needToDropSort = new boolean[numIndexes];
-		sortIds = new long[numIndexes];
-		rowSources = new RowLocationRetRowSource[numIndexes];
+		ordering        = new ColumnOrdering[numIndexes][];
+        collation       = new int[numIndexes][];
+		needToDropSort  = new boolean[numIndexes];
+		sortIds         = new long[numIndexes];
+		rowSources      = new RowLocationRetRowSource[numIndexes];
 		// indexedCols is 1-based
-		indexedCols = new FormatableBitSet(numColumns + 1);
+		indexedCols     = new FormatableBitSet(numColumns + 1);
 
 
-		/* For each index, build a single index row and a sorter. */
+		/* For each index, build a single index row, collation templage, 
+         * and a sorter. 
+         */
 		for (int index = 0; index < numIndexes; index++)
 		{
 			// Update the bit map of indexed columns
@@ -1658,7 +1662,8 @@
 			indexRows[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.)
+			// (This call is only necessary here because we need to 
+            // pass a template to the sorter.)
 			constants.irgs[index].getIndexRow(sourceRow, 
 											  rl, 
 											  indexRows[index],
@@ -1669,13 +1674,18 @@
 			 * We create a unique index observer for unique indexes
 			 * so that we can catch duplicate key
 			 */
-			ConglomerateDescriptor cd;
+
 			// Get the ConglomerateDescriptor for the index
-			cd = td.getConglomerateDescriptor(constants.indexCIDS[index]);
-			int[] baseColumnPositions = constants.irgs[index].baseColumnPositions();
-			boolean[] isAscending = constants.irgs[index].isAscending();
+			ConglomerateDescriptor cd = 
+                td.getConglomerateDescriptor(constants.indexCIDS[index]);
+
+			int[] baseColumnPositions = 
+                constants.irgs[index].baseColumnPositions();
+			boolean[] isAscending     = constants.irgs[index].isAscending();
+           
 			int numColumnOrderings;
 			SortObserver sortObserver = null;
+
 			/* We can only reuse the wrappers when doing an
 			 * external sort if there is only 1 index.  Otherwise,
 			 * we could get in a situation where 1 sort reuses a
@@ -1688,24 +1698,28 @@
 				String[] columnNames = getColumnNames(baseColumnPositions);
 
 				String indexOrConstraintName = cd.getConglomerateName();
-				if (cd.isConstraint()) // so, the index is backing up a constraint
+				if (cd.isConstraint()) 
 				{
-					ConstraintDescriptor conDesc = dd.getConstraintDescriptor(td,
-                                                                      cd.getUUID());
+                    // so, the index is backing up a constraint
+
+					ConstraintDescriptor conDesc = 
+                        dd.getConstraintDescriptor(td, cd.getUUID());
+
 					indexOrConstraintName = conDesc.getConstraintName();
 				}
-				sortObserver = new UniqueIndexSortObserver(
-														false, // don't clone rows
-														cd.isConstraint(), 
-														indexOrConstraintName,
-														indexRows[index],
-														reuseWrappers,
-														td.getName());
+				sortObserver = 
+                    new UniqueIndexSortObserver(
+                            false, // don't clone rows
+                            cd.isConstraint(), 
+                            indexOrConstraintName,
+                            indexRows[index],
+                            reuseWrappers,
+                            td.getName());
 			}
 			else
 			{
 				numColumnOrderings = baseColumnPositions.length + 1;
-				sortObserver = new BasicSortObserver(false, false, 
+				sortObserver       = new BasicSortObserver(false, false, 
 													 indexRows[index],
 													 reuseWrappers);
 			}
@@ -1715,18 +1729,29 @@
 				ordering[index][ii] = new IndexColumnOrder(ii, isAscending[ii]);
 			}
 			if (numColumnOrderings > isAscending.length)
-				ordering[index][isAscending.length] = new IndexColumnOrder(isAscending.length);
+            {
+				ordering[index][isAscending.length] = 
+                    new IndexColumnOrder(isAscending.length);
+            }
+
+            // set collation templates for later index creation 
+            // call (createAndLoadConglomerate())
+            collation[index] = 
+                constants.irgs[index].getColumnCollationIds(
+                    td.getColumnDescriptorList());
 
 			// create the sorters
-			sortIds[index] = tc.createSort(
-								(Properties)null, 
-								indexRows[index].getRowArrayClone(),
-								ordering[index],
-								sortObserver,
-								false,			// not in order
-								(int) sourceResultSet.getEstimatedRowCount(),		// est rows	
-								-1				// est row size, -1 means no idea	
-								);
+			sortIds[index] = 
+                tc.createSort(
+                    (Properties)null, 
+                    indexRows[index].getRowArrayClone(),
+                    ordering[index],
+                    sortObserver,
+                    false,			                             // not in order
+                    (int) sourceResultSet.getEstimatedRowCount(), // est rows	
+                    -1				// est row size, -1 means no idea	
+                    );
+
 			needToDropSort[index] = true;
 		}
 
@@ -1735,7 +1760,7 @@
 		// Open the sorts
 		for (int index = 0; index < numIndexes; index++)
 		{
-			sorters[index] = tc.openSort(sortIds[index]);
+			sorters[index]        = tc.openSort(sortIds[index]);
 			needToDropSort[index] = true;
 		}
 	}
@@ -1821,13 +1846,15 @@
 			// Populate the index.
 			sorters[index].completedInserts();
 			sorters[index] = null;
-			rowSources[index] = new CardinalityCounter(tc.openSortRowSource(sortIds[index]));
+			rowSources[index] = 
+                new CardinalityCounter(tc.openSortRowSource(sortIds[index]));
+
 			newIndexCongloms[index] = 
                 tc.createAndLoadConglomerate(
                     "BTREE",
                     indexRows[index].getRowArray(),
                     ordering[index],
-                    (int[]) null, // TODO-COLLATION, set non default collation if necessary
+                    collation[index],
                     properties,
                     TransactionController.IS_DEFAULT,
                     rowSources[index],
@@ -2126,7 +2153,8 @@
 		}
 
 		// We can finally create the partial base row
-		baseRows = activation.getExecutionFactory().getValueRow(numReferencedColumns);
+		baseRows = 
+            activation.getExecutionFactory().getValueRow(numReferencedColumns);
 
 		// Fill in each base row with nulls of the correct data type
 		int colNumber = 0;
@@ -2154,7 +2182,8 @@
 			indexRows[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.)
+			// (This call is only necessary here because we need to pass a 
+            // template to the sorter.)
 			constants.irgs[index].getIndexRow(baseRows, 
 											  rl, 
 											  indexRows[index],
@@ -2178,24 +2207,26 @@
 				String[] columnNames = getColumnNames(baseColumnPositions);
 
 				String indexOrConstraintName = cd.getConglomerateName();
-				if (cd.isConstraint()) // so, the index is backing up a constraint
+				if (cd.isConstraint()) 
 				{
-					ConstraintDescriptor conDesc = dd.getConstraintDescriptor(td,
-                                                                      cd.getUUID());
+                    // so, the index is backing up a constraint
+					ConstraintDescriptor conDesc = 
+                        dd.getConstraintDescriptor(td, cd.getUUID());
 					indexOrConstraintName = conDesc.getConstraintName();
 				}
-				sortObserver = new UniqueIndexSortObserver(
-														false, // don't clone rows
-														cd.isConstraint(), 
-														indexOrConstraintName,
-														indexRows[index],
-														true,
-														td.getName());
+				sortObserver = 
+                    new UniqueIndexSortObserver(
+                            false, // don't clone rows
+                            cd.isConstraint(), 
+                            indexOrConstraintName,
+                            indexRows[index],
+                            true,
+                            td.getName());
 			}
 			else
 			{
 				numColumnOrderings = baseColumnPositions.length + 1;
-				sortObserver = new BasicSortObserver(false, false, 
+				sortObserver       = new BasicSortObserver(false, false, 
 													 indexRows[index],
 													 true);
 			}
@@ -2205,18 +2236,23 @@
 				ordering[index][ii] = new IndexColumnOrder(ii, isAscending[ii]);
 			}
 			if (numColumnOrderings > isAscending.length)
-				ordering[index][isAscending.length] = new IndexColumnOrder(isAscending.length);
+            {
+				ordering[index][isAscending.length] = 
+                    new IndexColumnOrder(isAscending.length);
+            }
 
 			// create the sorters
-			sortIds[index] = tc.createSort(
-								(Properties)null, 
-								indexRows[index].getRowArrayClone(),
-								ordering[index],
-								sortObserver,
-								false,			// not in order
-								rowCount,		// est rows	
-								-1				// est row size, -1 means no idea	
-								);
+			sortIds[index] = 
+                tc.createSort(
+                    (Properties)null, 
+                    indexRows[index].getRowArrayClone(),
+                    ordering[index],
+                    sortObserver,
+                    false,			// not in order
+                    rowCount,		// est rows	
+                    -1				// est row size, -1 means no idea	
+                    );
+
 			needToDropSort[index] = true;
 		}
 
@@ -2279,14 +2315,13 @@
 			indexCC.close();
 
 			// We can finally drain the sorter and rebuild the index
-			// RESOLVE - all indexes are btrees right now
 			// Populate the index.
 			newIndexCongloms[index] = 
                 tc.createAndLoadConglomerate(
                     "BTREE",
                     indexRows[index].getRowArray(),
                     null, //default column sort order 
-                    (int[]) null, // TODO-COLLATION - set collation based on collation of original index.
+                    collation[index],
                     properties,
                     TransactionController.IS_DEFAULT,
                     rowSources[index],
@@ -2299,8 +2334,8 @@
 			 * for those indexes need to be updated with the new number.
 			 */
 			dd.updateConglomerateDescriptor(
-						td.getConglomerateDescriptors(constants.indexCIDS[index]),
-						newIndexCongloms[index], tc);
+                td.getConglomerateDescriptors(constants.indexCIDS[index]),
+                newIndexCongloms[index], tc);
 
 			// Drop the old conglomerate
 			tc.dropConglomerate(constants.indexCIDS[index]);
@@ -2318,33 +2353,34 @@
 	{
 		if (tableScan == null)
 		{
-			tableScan = new BulkTableScanResultSet(
-							conglomId,
-							tc.getStaticCompiledConglomInfo(conglomId),
-							activation,
-							new MyRowAllocator(fullTemplate),	// result row allocator
-							0,						// result set number
-							(GeneratedMethod)null, 	// start key getter
-							0, 						// start search operator
-							(GeneratedMethod)null,	// stop key getter
-							0, 						// start search operator
-							false,
-							(Qualifier[][])null,	// qualifiers
-							"tableName",
-							(String)null,
-							(String)null,			// index name
-							false,					// is constraint
-							false,					// for update
-							-1,						// saved object for referenced bitImpl
-							-1,
-							tc.MODE_TABLE,
-							true,					// table locked
-							tc.ISOLATION_READ_COMMITTED,
-							LanguageProperties.BULK_FETCH_DEFAULT_INT,	// rows per read
-							false,					// not a 1 row per scan
-							0d,						// estimated rows
-							0d 					// estimated cost
-							);
+			tableScan = 
+                new BulkTableScanResultSet(
+                    conglomId,
+                    tc.getStaticCompiledConglomInfo(conglomId),
+                    activation,
+                    new MyRowAllocator(fullTemplate),	// result row allocator
+                    0,						// result set number
+                    (GeneratedMethod)null, 	// start key getter
+                    0, 						// start search operator
+                    (GeneratedMethod)null,	// stop key getter
+                    0, 						// start search operator
+                    false,
+                    (Qualifier[][])null,	// qualifiers
+                    "tableName",
+                    (String)null,
+                    (String)null,			// index name
+                    false,					// is constraint
+                    false,					// for update
+                    -1,						// saved object for referenced bitImpl
+                    -1,
+                    tc.MODE_TABLE,
+                    true,					// table locked
+                    tc.ISOLATION_READ_COMMITTED,
+                    LanguageProperties.BULK_FETCH_DEFAULT_INT,	// rows per read
+                    false,					// not a 1 row per scan
+                    0d,						// estimated rows
+                    0d 					// estimated cost
+                    );
 			tableScan.openCore();
 		}
 		else