db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhille...@apache.org
Subject svn commit: r712400 - in /db/derby/code/trunk/java: engine/org/apache/derby/catalog/ engine/org/apache/derby/catalog/types/ engine/org/apache/derby/iapi/sql/dictionary/ engine/org/apache/derby/impl/sql/compile/ engine/org/apache/derby/impl/sql/execute/...
Date Sat, 08 Nov 2008 15:03:19 GMT
Author: rhillegas
Date: Sat Nov  8 07:03:18 2008
New Revision: 712400

URL: http://svn.apache.org/viewvc?rev=712400&view=rev
Log:
DERBY-481: DROP COLUMN support for generated columns.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/catalog/DefaultInfo.java
    db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/DefaultInfoImpl.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/compile/TableElementList.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UpdateNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java
    db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
    db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GeneratedColumnsTest.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/catalog/DefaultInfo.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/catalog/DefaultInfo.java?rev=712400&r1=712399&r2=712400&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/catalog/DefaultInfo.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/catalog/DefaultInfo.java Sat Nov  8 07:03:18 2008
@@ -34,10 +34,10 @@
 	public String getDefaultText();
 	
 	/**
-	 * If this default is a generation clause, then return the 1-based ids of
+	 * If this default is a generation clause, then return the names of
 	 * other columns in the row which the generation clause references.
 	 */
-	public int[] getReferencedColumnIDs();
+	public String[] getReferencedColumnNames();
 	
 	
 	/**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/DefaultInfoImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/DefaultInfoImpl.java?rev=712400&r1=712399&r2=712400&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/DefaultInfoImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/DefaultInfoImpl.java Sat Nov  8 07:03:18 2008
@@ -55,7 +55,7 @@
 	private DataValueDescriptor	defaultValue;
 	private String				defaultText;
 	private int                     type;
-    private int[]                   referencedColumnIDs;
+    private String[]                   referencedColumnNames;
 
 	final private static int BITS_MASK_IS_DEFAULTVALUE_AUTOINC = 0x1 << 0;
 	final private static int BITS_MASK_IS_GENERATED_COLUMN = 0x2;
@@ -86,14 +86,14 @@
 	public DefaultInfoImpl
         (
          String defaultText,
-         int[]    referencedColumnIDs
+         String[]    referencedColumnNames
          )
 	{
-        if ( referencedColumnIDs == null ) { referencedColumnIDs = new int[0]; }
+        if ( referencedColumnNames == null ) { referencedColumnNames = new String[0]; }
         
 		this.type = BITS_MASK_IS_GENERATED_COLUMN;
 		this.defaultText = defaultText;
-		this.referencedColumnIDs = referencedColumnIDs;
+		this.referencedColumnNames = referencedColumnNames;
 	}
 
 	/**
@@ -105,11 +105,11 @@
 	}
 
 	/**
-	 * @see DefaultInfo#getReferencedColumnIDs
+	 * @see DefaultInfo#getReferencedColumnNames
 	 */
-	public int[] getReferencedColumnIDs()
+	public String[] getReferencedColumnNames()
 	{
-		return referencedColumnIDs;
+		return referencedColumnNames;
 	}
 
 	public String	toString()
@@ -144,8 +144,8 @@
         if ( isGeneratedColumn() )
         {
             int count = in.readInt();
-            referencedColumnIDs = new int[ count ];
-            for ( int i = 0; i < count; i++ ) { referencedColumnIDs[ i ] = in.readInt(); }
+            referencedColumnNames = new String[ count ];
+            for ( int i = 0; i < count; i++ ) { referencedColumnNames[ i ] = (String) in.readObject(); }
         }
 	}
 
@@ -165,9 +165,9 @@
         
         if ( isGeneratedColumn() )
         {
-            int count = referencedColumnIDs.length;
+            int count = referencedColumnNames.length;
             out.writeInt( count );
-            for ( int i = 0; i < count; i++ ) { out.writeInt( referencedColumnIDs[ i ] ); }
+            for ( int i = 0; i < count; i++ ) { out.writeObject( referencedColumnNames[ i ] ); }
         }
 	}
  

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?rev=712400&r1=712399&r2=712400&view=diff
==============================================================================
--- 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 Sat Nov  8 07:03:18 2008
@@ -926,6 +926,22 @@
 	}
 
 	/**
+	 * Turn an array of column names into the corresponding 1-based column positions.
+	 */
+	public int[]    getColumnIDs( String[] names )
+	{
+        int     count = names.length;
+        int[]    result = new int[ count];
+        
+        for ( int i = 0; i < count; i++ )
+        {
+            result[ i ] = getColumnDescriptor( names[ i ] ).getPosition();
+        }
+        
+		return result;
+	}
+
+	/**
 	 * Gets the constraint descriptor list
 	 *
 	 * @return	The constraint descriptor list for this table descriptor

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementList.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementList.java?rev=712400&r1=712399&r2=712400&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementList.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementList.java Sat Nov  8 07:03:18 2008
@@ -768,14 +768,21 @@
 			ResultColumnList rcl = table.getResultColumns();
 			int		numReferenced = rcl.countReferencedColumns();
 			int[]	generationClauseColumnReferences = new int[numReferenced];
-
             int     position = rcl.getPosition( cdn.getColumnName(), 1 );
+
             generatedColumns.set( position );
         
 			rcl.recordColumnReferences(generationClauseColumnReferences, 1);
 
+            String[]    referencedColumnNames = new String[ numReferenced ];
+
+            for ( int i = 0; i < numReferenced; i++ )
+            {
+                referencedColumnNames[ i ] = ((ResultColumn)rcl.elementAt( generationClauseColumnReferences[ i ] - 1 )).getName();
+            }
+
             DefaultInfoImpl dii = new DefaultInfoImpl
-                ( generationClauseNode.getExpressionText(), generationClauseColumnReferences );
+                ( generationClauseNode.getExpressionText(), referencedColumnNames );
             cdn.setDefaultInfo( dii );
 
 			/* Clear the column references in the RCL so each generation clause
@@ -788,6 +795,7 @@
         // Now verify that none of the generated columns reference other
         // generated columns.
         //
+        ResultColumnList rcl = table.getResultColumns();
 		for (int index = 0; index < size; index++)
 		{
 			ColumnDefinitionNode cdn;
@@ -799,12 +807,14 @@
 
 			if (!cdn.hasGenerationClause()) { continue; }
 
-            int[]   referencedColumns = cdn.getDefaultInfo().getReferencedColumnIDs();
-            int     count = referencedColumns.length;
+            String[]   referencedColumnNames = cdn.getDefaultInfo().getReferencedColumnNames();
+            int     count = referencedColumnNames.length;
 
             for ( int i = 0; i < count; i++ )
             {
-                int         referencedColumnID = referencedColumns[ i ]; 
+                String      name = referencedColumnNames[ i ];
+                int         referencedColumnID = rcl.getPosition( name, 1 );
+
                 if ( generatedColumns.isSet( referencedColumnID ) )
                 {
                     throw StandardException.newException(SQLState.LANG_CANT_REFERENCE_GENERATED_COLUMN, cdn.getColumnName());

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UpdateNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UpdateNode.java?rev=712400&r1=712399&r2=712400&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UpdateNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UpdateNode.java Sat Nov  8 07:03:18 2008
@@ -1041,7 +1041,7 @@
         // Add all columns mentioned by generation clauses which are affected
         // by the columns being updated.
         //
-        addGeneratedColumnPrecursors( affectedGeneratedColumns, columnMap );
+        addGeneratedColumnPrecursors( baseTable, affectedGeneratedColumns, columnMap );
         
 		/*
 	 	** If we have any triggers, then get all the columns
@@ -1070,8 +1070,9 @@
      */
     private static  void    addGeneratedColumnPrecursors
 	(
-        ColumnDescriptorList    affectedGeneratedColumns,
-		FormatableBitSet        columnMap
+     TableDescriptor         baseTable,
+     ColumnDescriptorList    affectedGeneratedColumns,
+     FormatableBitSet        columnMap
 	)
 		throws StandardException
 	{
@@ -1080,7 +1081,8 @@
         for ( int gcIdx = 0; gcIdx < generatedColumnCount; gcIdx++ )
         {
             ColumnDescriptor    gc = affectedGeneratedColumns.elementAt( gcIdx );
-            int[]                       mentionedColumns = gc.getDefaultInfo().getReferencedColumnIDs();
+            String[]                       mentionedColumnNames = gc.getDefaultInfo().getReferencedColumnNames();
+            int[]                       mentionedColumns = baseTable.getColumnIDs( mentionedColumnNames );
             int                         mentionedColumnCount = mentionedColumns.length;
 
             for ( int mcIdx = 0; mcIdx < mentionedColumnCount; mcIdx++ )
@@ -1128,8 +1130,8 @@
         {
             ColumnDescriptor    gc = generatedColumns.elementAt( gcIdx );
             DefaultInfo             defaultInfo = gc.getDefaultInfo();
-            int[]                       mentionedColumns = defaultInfo.getReferencedColumnIDs();
-            int                         mentionedColumnCount = mentionedColumns.length;
+            String[]                       mentionedColumnNames = defaultInfo.getReferencedColumnNames();
+            int                         mentionedColumnCount = mentionedColumnNames.length;
 
             // handle the case of setting a generated column to the DEFAULT
             // literal
@@ -1139,8 +1141,7 @@
             // update
             for ( int mcIdx = 0; mcIdx < mentionedColumnCount; mcIdx++ )
             {
-                ColumnDescriptor    mentionedColumn = baseTable.getColumnDescriptor( mentionedColumns[ mcIdx ] );
-                String                      mentionedColumnName = mentionedColumn.getColumnName();
+                String                      mentionedColumnName = mentionedColumnNames[ mcIdx ];
 
                 if ( updatedColumns.contains( mentionedColumnName ) )
                 {

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?rev=712400&r1=712399&r2=712400&view=diff
==============================================================================
--- 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 Sat Nov  8 07:03:18 2008
@@ -499,7 +499,7 @@
 				}
 				else if (columnInfo[ix].action == ColumnInfo.DROP)
 				{
-					dropColumnFromTable(activation, ix);
+					dropColumnFromTable(activation, columnInfo[ix].name);
 				}
 				else if (SanityManager.DEBUG)
 				{
@@ -1407,50 +1407,102 @@
 	 *    entire index is dropped. 
 	 *
      * @param   activation  the current activation
-	 * @param   ix 			the index of the column specfication in the ALTER 
+	 * @param   columnName the name of the column specfication in the ALTER 
 	 *						statement-- currently we allow only one.
 	 * @exception StandardException 	thrown on failure.
 	 */
-	private void dropColumnFromTable(Activation activation,
-									 int ix) 
+	private void dropColumnFromTable(Activation activation, String columnName )
 	        throws StandardException
 	{
 		LanguageConnectionContext lcc = activation.getLanguageConnectionContext();
 		DataDictionary dd = lcc.getDataDictionary();
 		DependencyManager dm = dd.getDependencyManager();
 		TransactionController tc = lcc.getTransactionExecute();
+		boolean cascade = (behavior == StatementType.DROP_CASCADE);
 
-
-		ColumnDescriptor columnDescriptor = 
-			td.getColumnDescriptor(columnInfo[ix].name);
-
-		// We already verified this in bind, but do it again
-		if (columnDescriptor == null)
-		{
-			throw 
-				StandardException.newException(
-                    SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, 
-                    columnInfo[ix].name,
-                    td.getQualifiedName());
-		}
+        // drop any generated columns which reference this column
+        ColumnDescriptorList    generatedColumnList = td.getGeneratedColumns();
+        int                                 generatedColumnCount = generatedColumnList.size();
+        ArrayList                   cascadedDroppedColumns = new ArrayList();
+        for ( int i = 0; i < generatedColumnCount; i++ )
+        {
+            ColumnDescriptor    generatedColumn = generatedColumnList.elementAt( i );
+            String[]                       referencedColumnNames = generatedColumn.getDefaultInfo().getReferencedColumnNames();
+            int                         referencedColumnCount = referencedColumnNames.length;
+            for ( int j = 0; j < referencedColumnCount; j++ )
+            {
+                if ( columnName.equals( referencedColumnNames[ j ] ) )
+                {
+                    String      generatedColumnName = generatedColumn.getColumnName();
+                    
+                    // ok, the current generated column references the column
+                    // we're trying to drop
+                    if (! cascade)
+                    {
+                        // Reject the DROP COLUMN, because there exists a
+                        // generated column which references this column.
+                        //
+                        throw StandardException.newException
+                            (
+                             SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
+                             dm.getActionString(DependencyManager.DROP_COLUMN),
+                             columnName, "GENERATED COLUMN",
+                             generatedColumnName
+                             );
+                    }
+                    else
+                    {
+                        cascadedDroppedColumns.add( generatedColumnName );
+                    }
+                }
+            }
+        }
 
 		DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();
-		ColumnDescriptorList tab_cdl = td.getColumnDescriptorList();
-		int size = tab_cdl.size();
+        int                             cascadedDrops = cascadedDroppedColumns.size();
+		int sizeAfterCascadedDrops = td.getColumnDescriptorList().size() - cascadedDrops;
 
 		// can NOT drop a column if it is the only one in the table
-		if (size == 1)
+		if (sizeAfterCascadedDrops == 1)
 		{
 			throw StandardException.newException(
                     SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
                     dm.getActionString(DependencyManager.DROP_COLUMN),
-                    "THE *LAST* COLUMN " + columnInfo[ix].name,
+                    "THE *LAST* COLUMN " + columnName,
                     "TABLE",
                     td.getQualifiedName() );
 		}
 
+        // now drop dependent generated columns
+        for ( int i = 0; i < cascadedDrops; i++ )
+        {
+            String      generatedColumnName = (String) cascadedDroppedColumns.get( i );
+            
+            activation.addWarning
+                ( StandardException.newWarning( SQLState.LANG_GEN_COL_DROPPED, generatedColumnName, td.getName() ) );
+            dropColumnFromTable( activation, generatedColumnName );
+        }
+
+        /*
+         * Cascaded drops of dependent generated columns may require us to
+         * rebuild the table descriptor.
+         */
+		td = dd.getTableDescriptor(tableId);
+
+		ColumnDescriptor columnDescriptor = td.getColumnDescriptor( columnName );
+
+		// We already verified this in bind, but do it again
+		if (columnDescriptor == null)
+		{
+			throw 
+				StandardException.newException(
+                    SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, 
+                    columnName,
+                    td.getQualifiedName());
+		}
+
+		int size = td.getColumnDescriptorList().size();
 		droppedColumnPosition = columnDescriptor.getPosition();
-		boolean cascade = (behavior == StatementType.DROP_CASCADE);
 
 		FormatableBitSet toDrop = new FormatableBitSet(size + 1);
 		toDrop.set(droppedColumnPosition);
@@ -1501,7 +1553,7 @@
 						throw StandardException.newException(
                             SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
                             dm.getActionString(DependencyManager.DROP_COLUMN),
-                            columnInfo[ix].name, "TRIGGER",
+                            columnName, "TRIGGER",
                             trd.getName() );
 					}
 					break;
@@ -1573,7 +1625,7 @@
 				throw StandardException.newException(
                         SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
                         dm.getActionString(DependencyManager.DROP_COLUMN),
-                        columnInfo[ix].name, "CONSTRAINT",
+                        columnName, "CONSTRAINT",
                         cd.getConstraintName() );
 			}
 
@@ -1656,8 +1708,10 @@
 
 		compressTable(activation);
 
+		ColumnDescriptorList tab_cdl = td.getColumnDescriptorList();
+
 		// drop the column from syscolumns 
-		dd.dropColumnDescriptor(td.getUUID(), columnInfo[ix].name, tc);
+		dd.dropColumnDescriptor(td.getUUID(), columnName, tc);
 		ColumnDescriptor[] cdlArray = 
             new ColumnDescriptor[size - columnDescriptor.getPosition()];
 
@@ -1677,6 +1731,7 @@
 				cd.setAutoinc_create_or_modify_Start_Increment(
 						ColumnDefinitionNode.CREATE_AUTOINCREMENT);
 			}
+
 			cdlArray[j] = cd;
 		}
 		dd.addDescriptorArray(cdlArray, td,
@@ -1719,6 +1774,11 @@
 		// Adjust the column permissions rows in SYSCOLPERMS to reflect the
 		// changed column positions due to the dropped column:
 		dd.updateSYSCOLPERMSforDropColumn(td.getUUID(), tc, columnDescriptor);
+
+        // remove column descriptor from table descriptor. this fixes up the
+        // list in case we were called recursively in order to cascade-drop a
+        // dependent generated column.
+        tab_cdl.remove( td.getColumnDescriptor( columnName ) );
 	}
 
 	private void modifyColumnType(Activation activation,

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=712400&r1=712399&r2=712400&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 Sat Nov  8 07:03:18 2008
@@ -93,6 +93,13 @@
             </msg>
 
             <msg>
+                <name>01009</name>
+                <text>Generated column {0} dropped from table {1}.</text>
+                <arg>columnName</arg>
+                <arg>tableName</arg>
+            </msg>
+
+            <msg>
                 <name>0100E</name>
                 <text>XX Attempt to return too many result sets. </text>
             </msg>
@@ -2000,6 +2007,13 @@
             </msg>
 
             <msg>
+                <name>42XA7</name>
+                <text>Dropping column '{0}' would orphan the generated column '{1}' which references it. You must drop the generated column first.</text>
+                <arg>columnName</arg>
+                <arg>columnName</arg>
+            </msg>
+
+            <msg>
                 <name>42Y00</name>
                 <text>Class '{0}' does not implement org.apache.derby.iapi.db.AggregateDefinition and thus cannot be used as an aggregate expression.</text>
                 <arg>className</arg>

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=712400&r1=712399&r2=712400&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 Sat Nov  8 07:03:18 2008
@@ -657,6 +657,7 @@
 	String LANG_PRIVILEGE_NOT_REVOKED						   		   = "01006";
 	String LANG_ROLE_NOT_REVOKED                                       = "01007";
 	String LANG_WITH_ADMIN_OPTION_NOT_REVOKED                          = "01008";
+	String LANG_GEN_COL_DROPPED                                         = "01009";
 
 	String LANG_NO_ROW_FOUND									   	   = "02000";
 
@@ -900,6 +901,7 @@
     String LANG_CANT_REFERENCE_GENERATED_COLUMN                  = "42XA4";
     String LANG_ROUTINE_CANT_PERMIT_SQL                                   = "42XA5";
     String LANG_BAD_FK_ON_GENERATED_COLUMN                           = "42XA6";
+    String LANG_CASCADED_GEN_COL_DROP                                     = "42XA7";
 	String LANG_INVALID_USER_AGGREGATE_DEFINITION2                     = "42Y00";
 	String LANG_INVALID_CHECK_CONSTRAINT                               = "42Y01";
 	// String LANG_NO_ALTER_TABLE_COMPRESS_ON_TARGET_TABLE                = "42Y02";

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GeneratedColumnsTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GeneratedColumnsTest.java?rev=712400&r1=712399&r2=712400&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GeneratedColumnsTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GeneratedColumnsTest.java Sat Nov  8 07:03:18 2008
@@ -69,7 +69,12 @@
     private static  final   String  ILLEGAL_DUPLICATE = "23505";
     private static  final   String  SYNTAX_ERROR = "42X01";
     private static  final   String  COLUMN_OUT_OF_SCOPE = "42X04";
+    private static  final   String  OPERATION_FORBIDDEN = "X0Y25";
 
+    private static  final   String  CASCADED_COLUMN_DROP_WARNING = "01009";
+    private static  final   String  CONSTRAINT_DROPPED_WARNING = "01500";
+    private static  final   String  TRIGGER_DROPPED_WARNING = "01502";
+    
     ///////////////////////////////////////////////////////////////////////////////////
     //
     // STATE
@@ -80,6 +85,9 @@
 
     private static  ArrayList   _triggerReports = new ArrayList();
 
+    private String  _clearingProcName;
+    private String  _triggerReportVTIName;
+
     ///////////////////////////////////////////////////////////////////////////////////
     //
     // CONSTRUCTOR
@@ -816,6 +824,9 @@
              "for each statement\n" +
              "call report_proc( 'after_delete_statement_trigger', -1, -1, -1 )\n"
              );
+
+        _clearingProcName = "clearTriggerReports";
+        _triggerReportVTIName = "triggerReports";
         
         //
         // Now run the tests.
@@ -1008,19 +1019,19 @@
         assertDefaultInfo
             (
              conn, "T_DI_1", "B",
-             new int[] {},
+             new String[] {},
              "1"
              );
         assertDefaultInfo
             (
              conn, "T_DI_2", "B",
-             new int[] { 1 },
+             new String[] { "A" },
              "-a"
              );
         assertDefaultInfo
             (
              conn, "T_DI_3", "B",
-             new int[] { 1, 3 },
+             new String[] { "A", "C" },
              "a + c"
              );
              
@@ -2491,126 +2502,853 @@
              );
     }
     
-    ///////////////////////////////////////////////////////////////////////////////////
-    //
-    // MINIONS
-    //
-    ///////////////////////////////////////////////////////////////////////////////////
-
-
-    /**
-     * Run good DDL.
-     * @throws SQLException 
-     */
-    private void    goodStatement( Connection conn, String ddl ) throws SQLException
-    {
-        PreparedStatement    ps = chattyPrepare( conn, ddl );
-
-        ps.execute();
-        ps.close();
-    }
-    
-    /**
-     * Prepare a statement and report its sql text.
-     */
-    private PreparedStatement   chattyPrepare( Connection conn, String text )
-        throws SQLException
-    {
-        println( "Preparing statement:\n\t" + text );
-        
-        return conn.prepareStatement( text );
-    }
-
-    /**
-     * Assert that the statement text, when compiled, raises an exception
-     */
-    private void    expectCompilationError( String sqlState, String query )
-    {
-        println( "\nExpecting " + sqlState + " when preparing:\n\t" + query );
-
-        assertCompileError( sqlState, query );
-    }
-
     /**
-     * Assert that the statement text, when executed, raises an error.
+     * <p>
+     * Test ALTER TABLE DROP COLUMN
+     * </p>
      */
-    private void    expectExecutionError( Connection conn, String sqlState, String query )
+    public  void    test_019_dropColumn()
         throws Exception
     {
-        println( "\nExpecting " + sqlState + " when executing:\n\t"  );
-        PreparedStatement   ps = chattyPrepare( conn, query );
-
-        assertStatementError( sqlState, ps );
-    }
+        Connection  conn = getConnection();
 
-    /**
-     * Assert that triggers fire correctly
-     */
-    private void assertTriggerStatus( Connection conn, String query, String[][] rows )
-        throws Exception
-    {
+        //
+        // Verify that you can directly drop generated columns
+        //
         goodStatement
             (
              conn,
-             "call clearTriggerReports()\n"
+             "create table t_dc_1( a int, b int, c int generated always as ( -b ), d int )"
              );
         goodStatement
             (
              conn,
-             query
+             "insert into t_dc_1( b, d ) values ( 1, 1 )"
              );
-        PreparedStatement   ps = chattyPrepare( conn, "select * from table( triggerReports() ) s" );
-        ResultSet                   rs = ps.executeQuery();
-
-        assertResults( rs, rows, true );
-
-        rs.close();
-        ps.close();
-    }
-
-    /**
-     * <p>
-     * Assert whether a routine is expected to be DETERMINISTIC.
-     * </p>
-     */
-    public  void    assertDeterministic( Connection conn, String routineName, boolean isDeterministic )
-        throws Exception
-    {
-        PreparedStatement   ps = conn.prepareStatement
+        goodStatement
             (
-             "select a.aliasinfo\n" +
-             "from sys.sysaliases a\n" +
-             "where alias =  ?"
+             conn,
+             "alter table t_dc_1 drop column c restrict"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_1( b, d ) values ( 1, 1 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_1 order by d",
+             new String[][]
+             {
+                 { null, "1", "1", },
+                 { null, "1", "1", },
+             },
+             false
              );
-        ps.setString( 1, routineName );
-        ResultSet               rs = ps.executeQuery();
-
-        rs.next();
-        RoutineAliasInfo    rai = (RoutineAliasInfo) rs.getObject( 1 );
-
-        assertEquals( isDeterministic, rai.isDeterministic() );
-
-        rs.close();
-        ps.close();
-    }
-
-    /**
-     * Assert that the statement returns the correct results.
-     */
-    private void assertResults( Connection conn, String query, String[][] rows, boolean trimResults )
-        throws Exception
-    {
-        PreparedStatement   ps = chattyPrepare( conn, query );
-        ResultSet                   rs = ps.executeQuery();
 
-        assertResults( rs, rows, trimResults );
+        //
+        // Verify that a generated column blocks the RESTRICTed drop of columns
+        // that it references.
+        //
+        goodStatement
+            (
+             conn,
+             "create table t_dc_2( a int, b int, c int generated always as ( -b ), d int )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_2( b, d ) values ( 1, 1 )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_2( d ) values ( 2 )"
+             );
+        expectExecutionError
+            (
+             conn,
+             OPERATION_FORBIDDEN,
+             "alter table t_dc_2 drop column b restrict"
+             );
+        expectExecutionWarning
+            (
+             conn,
+             CASCADED_COLUMN_DROP_WARNING,
+             "alter table t_dc_2 drop column b"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_2( d ) values ( 2 )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_2( a, d ) values ( 3, 3 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_2 order by d",
+             new String[][]
+             {
+                 { null, "1", },
+                 { null, "2", },
+                 { null, "2", },
+                 { "3", "3", },
+             },
+             false
+             );
+        goodStatement
+            (
+             conn,
+             "alter table t_dc_2 drop column a restrict"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_2( d ) values ( 4 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_2 order by d",
+             new String[][]
+             {
+                 { "1", },
+                 { "2", },
+                 { "2", },
+                 { "3", },
+                 { "4", },
+             },
+             false
+             );
 
-        rs.close();
-        ps.close();
-    }
+        //
+        // Verify that dropping columns before and after a generated column
+        // correctly recompiles INSERT statements on the table.
+        //        
+        goodStatement
+            (
+             conn,
+             "create table t_dc_3( a int, b int, c int, d int generated always as ( -c ), e int, f int )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_3( b, c, f ) values ( 1, 1, 1 )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_3( c ) values ( 2 )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_3( f ) values ( 3 )"
+             );
+        goodStatement
+            (
+             conn,
+             "alter table t_dc_3 drop column a restrict"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_3( b, c, f ) values ( 1, 1, 1 )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_3( c ) values ( 2 )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_3( f ) values ( 3 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_3 order by f",
+             new String[][]
+             {
+                 { "1", "1", "-1", null, "1", },
+                 { "1", "1", "-1", null, "1", },
+                 { null, null, null, null, "3", },
+                 { null, null, null, null, "3", },
+                 { null, "2", "-2", null, null, },
+                 { null, "2", "-2", null, null, },
+             },
+             false
+             );
+        goodStatement
+            (
+             conn,
+             "alter table t_dc_3 drop column e restrict"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_3( b, c, f ) values ( 1, 1, 1 )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_3( c ) values ( 2 )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_3( f ) values ( 3 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_3 order by f",
+             new String[][]
+             {
+                 { "1", "1", "-1", "1", },
+                 { "1", "1", "-1", "1", },
+                 { "1", "1", "-1", "1", },
+                 { null, null, null, "3", },
+                 { null, null, null, "3", },
+                 { null, null, null, "3", },
+                 { null, "2", "-2", null, },
+                 { null, "2", "-2", null, },
+                 { null, "2", "-2", null, },
+             },
+             false
+             );
+        goodStatement
+            (
+             conn,
+             "alter table t_dc_3 drop column c"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_3( f ) values ( 3 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_3 order by f",
+             new String[][]
+             {
+                 { "1", "1", },
+                 { "1", "1", },
+                 { "1", "1", },
+                 { null, "3", },
+                 { null, "3", },
+                 { null, "3", },
+                 { null, "3", },
+                 { null, null, },
+                 { null, null, },
+                 { null, null, },
+             },
+             false
+             );
         
-    /**
-     * Assert that the ResultSet returns the desired rows.
+        //
+        // Verify that a generated column blocks the RESTRICTed drop of the
+        // columns it depends on even when there's more than one.
+        //        
+        goodStatement
+            (
+             conn,
+             "create table t_dc_4( a int, b int, c int, d int generated always as ( -(a + e) ), e int, f int )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_4( a, f ) values ( 1, 1 )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_4( a, e, f ) values ( 2, 2, 2 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_4 order by f",
+             new String[][]
+             {
+                 { "1", null, null, null, null, "1", },
+                 { "2", null, null, "-4", "2", "2", },
+             },
+             false
+             );
+        expectExecutionError
+            (
+             conn,
+             OPERATION_FORBIDDEN,
+             "alter table t_dc_4 drop column a restrict"
+             );
+        expectExecutionError
+            (
+             conn,
+             OPERATION_FORBIDDEN,
+             "alter table t_dc_4 drop column e restrict"
+             );
+        expectExecutionWarning
+            (
+             conn,
+             CASCADED_COLUMN_DROP_WARNING,
+             "alter table t_dc_4 drop column e"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_4( a, f ) values ( 1, 1 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_4 order by f",
+             new String[][]
+             {
+                 { "1", null, null, "1", },
+                 { "1", null, null, "1", },
+                 { "2", null, null, "2", },
+             },
+             false
+             );
+        
+        //
+        // Verify that the cascaded drop of a generated column raises a warning
+        // noting that the dependent column was dropped.
+        //        
+        goodStatement
+            (
+             conn,
+             "create table t_dc_5( a int generated always as ( -b ), b int, c int )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_5( b, c ) values ( 100, 1 )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_5( c ) values ( 2 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_5 order by c",
+             new String[][]
+             {
+                 { "-100", "100", "1", },
+                 { null, null, "2", },
+             },
+             false
+             );
+        expectExecutionError
+            (
+             conn,
+             OPERATION_FORBIDDEN,
+             "alter table t_dc_5 drop column b restrict"
+             );
+        expectExecutionWarning
+            (
+             conn,
+             CASCADED_COLUMN_DROP_WARNING,
+             "alter table t_dc_5 drop column b"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_5( c ) values ( 2 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_5 order by c",
+             new String[][]
+             {
+                 { "1", },
+                 { "2", },
+                 { "2", },
+             },
+             false
+             );
+
+        //
+        // Verify that the cascaded drop of a generated column also drops
+        // primary and foreign keys which depend on it.
+        //        
+        goodStatement
+            (
+             conn,
+             "create table t_dc_6_prim( a int generated always as ( -b ) primary key, b int, c int )"
+             );
+        goodStatement
+            (
+             conn,
+             "create table t_dc_6_for( a int references t_dc_6_prim( a ) )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_6_prim( b, c ) values ( 100, 1 )"
+             );
+        expectExecutionError
+            (
+             conn,
+             ILLEGAL_DUPLICATE,
+             "insert into t_dc_6_prim( b, c ) values ( 100, 2 )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_6_for( a ) values ( -100 )"
+             );
+        expectExecutionError
+            (
+             conn,
+             FOREIGN_KEY_VIOLATION,
+             "insert into t_dc_6_for( a ) values ( -101 )"
+             );
+        expectExecutionWarnings
+            (
+             conn,
+             new String[] { CASCADED_COLUMN_DROP_WARNING, CONSTRAINT_DROPPED_WARNING, CONSTRAINT_DROPPED_WARNING, },
+             "alter table t_dc_6_prim drop column b"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_6_prim( c ) values ( 2 )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_6_for( a ) values ( -101 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_6_prim order by c",
+             new String[][]
+             {
+                 { "1", },
+                 { "2", },
+             },
+             false
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_6_for order by a",
+             new String[][]
+             {
+                 { "-101", },
+                 { "-100", },
+             },
+             false
+             );
+        
+        //
+        // Verify that cascaded drops of generated columns drop triggers which
+        // mention the generated columns in their UPDATE OF clauses.
+        //        
+        goodStatement
+            (
+             conn,
+             "create table t_dc_7( a int generated always as ( -b ), b int, c int )"
+             );
+        goodStatement
+            (
+             conn,
+             "create function dc_triggerReports()\n" +
+             "returns TABLE\n" +
+             "  (\n" +
+             "     contents varchar( 100 )\n" +
+             "  )\n" +
+             "language java\n" +
+             "parameter style DERBY_JDBC_RESULT_SET\n" +
+             "no sql\n" +
+             "external name 'org.apache.derbyTesting.functionTests.tests.lang.GeneratedColumnsTest.triggerReport'\n"
+             );
+        goodStatement
+            (
+             conn,
+             "create procedure dc_clearTriggerReports\n" +
+             "()\n" +
+             "language java\n" +
+             "parameter style java\n" +
+             "no sql\n" +
+             "external name 'org.apache.derbyTesting.functionTests.tests.lang.GeneratedColumnsTest.clearTriggerReports'\n"
+             );
+        goodStatement
+            (
+             conn,
+             "create procedure dc_report_proc\n" +
+             "( tag varchar( 40 ), a int, b int, c int )\n" +
+             "language java\n" +
+             "parameter style java\n" +
+             "no sql\n" +
+             "external name 'org.apache.derbyTesting.functionTests.tests.lang.GeneratedColumnsTest.showValues'\n"
+             );
+        goodStatement
+            (
+             conn,
+             "create trigger t_dc_7_trig_after_update\n" +
+             "after update of a\n" +
+             "on t_dc_7\n" +
+             "referencing new as ar\n" +
+             "for each row\n" +
+             "call dc_report_proc( 'after_update_row_trigger', ar.a, ar.a, ar.a ) \n"
+             );
+        _clearingProcName = "dc_clearTriggerReports";
+        _triggerReportVTIName = "dc_triggerReports";
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_7( b, c ) values ( 100, 1 )"
+             );
+        assertTriggerStatus
+            (
+             conn,
+             "update t_dc_7 set b = 101",
+             new String[][]
+             {
+                 { "after_update_row_trigger: [ -101, -101, -101 ]" },
+             }
+             );
+        
+        expectExecutionWarnings
+            (
+             conn,
+             new String[] { CASCADED_COLUMN_DROP_WARNING, TRIGGER_DROPPED_WARNING, },
+             "alter table t_dc_7 drop column b"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_7( c ) values ( 2 )"
+             );
+        assertTriggerStatus
+            (
+             conn,
+             "update t_dc_7 set c = c + 1000",
+             new String[][] {}
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_7 order by c",
+             new String[][]
+             {
+                 { "1001", },
+                 { "1002", },
+             },
+             false
+             );
+
+        //
+        // Verify that cascaded drops of generated columns prevent you from
+        // dropping columns that they reference if you would end up with a table
+        // that has no columns in it.
+        //        
+        goodStatement
+            (
+             conn,
+             "create table t_dc_8( a int generated always as ( -b ), b int )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_8( b ) values ( 1 )"
+             );
+        expectExecutionError
+            (
+             conn,
+             OPERATION_FORBIDDEN,
+             "alter table t_dc_8 drop column b"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_8( b ) values ( 2 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_8 order by b",
+             new String[][]
+             {
+                 { "-1", "1", },
+                 { "-2", "2", },
+             },
+             false
+             );
+        
+        //
+        // Verify that cascaded drops of generated columns drop the indexes
+        // built on them.
+        //        
+        goodStatement
+            (
+             conn,
+             "create table t_dc_9( a int generated always as ( -b ), b int, c int )"
+             );
+        goodStatement
+            (
+             conn,
+             "create unique index t_dc_9_a_idx on t_dc_9( a )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_9( c ) values ( 1 )"
+             );
+        expectExecutionError
+            (
+             conn,
+             ILLEGAL_DUPLICATE,
+             "insert into t_dc_9( c ) values ( 1 )"
+             );
+        expectExecutionWarning
+            (
+             conn,
+             CASCADED_COLUMN_DROP_WARNING,
+             "alter table t_dc_9 drop column b"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_9( c ) values ( 1 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_9 order by c",
+             new String[][]
+             {
+                 { "1", },
+                 { "1", },
+             },
+             false
+             );
+        
+        //
+        // Verify that dropping a generated column also drops check constraints
+        // on it.
+        //        
+        goodStatement
+            (
+             conn,
+             "create table t_dc_10( a int generated always as ( -b ) check ( a is not null ), b int, c int )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_10( b, c ) values ( 1, 1 )"
+             );
+        expectExecutionError
+            (
+             conn,
+             CONSTRAINT_VIOLATION,
+             "insert into t_dc_10( c ) values ( 2 )"
+             );
+        expectExecutionError
+            (
+             conn,
+             OPERATION_FORBIDDEN,
+             "alter table t_dc_10 drop column a restrict"
+             );
+        expectExecutionWarnings
+            (
+             conn,
+             new String[] { CASCADED_COLUMN_DROP_WARNING, CONSTRAINT_DROPPED_WARNING, },
+             "alter table t_dc_10 drop column b"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dc_10( c ) values ( 2 )"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dc_10 order by c",
+             new String[][]
+             {
+                 { "1", },
+                 { "2", },
+             },
+             false
+             );
+    }
+    
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // MINIONS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Run good DDL.
+     * @throws SQLException 
+     */
+    private void    goodStatement( Connection conn, String ddl ) throws SQLException
+    {
+        PreparedStatement    ps = chattyPrepare( conn, ddl );
+
+        ps.execute();
+        ps.close();
+    }
+    
+    /**
+     * Prepare a statement and report its sql text.
+     */
+    private PreparedStatement   chattyPrepare( Connection conn, String text )
+        throws SQLException
+    {
+        println( "Preparing statement:\n\t" + text );
+        
+        return conn.prepareStatement( text );
+    }
+
+    /**
+     * Assert that the statement text, when compiled, raises an exception
+     */
+    private void    expectCompilationError( String sqlState, String query )
+    {
+        println( "\nExpecting " + sqlState + " when preparing:\n\t" + query );
+
+        assertCompileError( sqlState, query );
+    }
+
+    /**
+     * Assert that the statement text, when executed, raises an error.
+     */
+    private void    expectExecutionError( Connection conn, String sqlState, String query )
+        throws Exception
+    {
+        println( "\nExpecting " + sqlState + " when executing:\n\t"  );
+        PreparedStatement   ps = chattyPrepare( conn, query );
+
+        assertStatementError( sqlState, ps );
+    }
+
+    /**
+     * Assert that the statement text, when executed, raises a warning.
+     */
+    private void    expectExecutionWarning( Connection conn, String sqlState, String query )
+        throws Exception
+    {
+        expectExecutionWarnings( conn, new String[] { sqlState }, query );
+    }
+
+    /**
+     * Assert that the statement text, when executed, raises a warning.
+     */
+    private void    expectExecutionWarnings( Connection conn, String[] sqlStates, String query )
+        throws Exception
+    {
+        println( "\nExpecting warnings " + fill( sqlStates ).toString() + " when executing:\n\t"  );
+        PreparedStatement   ps = chattyPrepare( conn, query );
+
+        ps.execute();
+
+        int idx = 0;
+
+        for ( SQLWarning sqlWarning = ps.getWarnings(); sqlWarning != null; sqlWarning = sqlWarning.getNextWarning() )
+        {
+            String          actualSQLState = sqlWarning.getSQLState();
+
+            if ( idx >= sqlStates.length )
+            {
+                fail( "Got more warnings than we expected." );
+            }
+
+            String  expectedSqlState = sqlStates[ idx++ ];
+
+            assertEquals( expectedSqlState, actualSQLState );
+        }
+
+        assertEquals( idx, sqlStates.length );
+
+        ps.close();
+    }
+
+    /**
+     * Assert that triggers fire correctly
+     */
+    private void assertTriggerStatus( Connection conn, String query, String[][] rows )
+        throws Exception
+    {
+        goodStatement
+            (
+             conn,
+             "call " + _clearingProcName + "()\n"
+             );
+        goodStatement
+            (
+             conn,
+             query
+             );
+        PreparedStatement   ps = chattyPrepare( conn, "select * from table( " + _triggerReportVTIName + "() ) s" );
+        ResultSet                   rs = ps.executeQuery();
+
+        assertResults( rs, rows, true );
+
+        rs.close();
+        ps.close();
+    }
+
+    /**
+     * <p>
+     * Assert whether a routine is expected to be DETERMINISTIC.
+     * </p>
+     */
+    public  void    assertDeterministic( Connection conn, String routineName, boolean isDeterministic )
+        throws Exception
+    {
+        PreparedStatement   ps = conn.prepareStatement
+            (
+             "select a.aliasinfo\n" +
+             "from sys.sysaliases a\n" +
+             "where alias =  ?"
+             );
+        ps.setString( 1, routineName );
+        ResultSet               rs = ps.executeQuery();
+
+        rs.next();
+        RoutineAliasInfo    rai = (RoutineAliasInfo) rs.getObject( 1 );
+
+        assertEquals( isDeterministic, rai.isDeterministic() );
+
+        rs.close();
+        ps.close();
+    }
+
+    /**
+     * Assert that the statement returns the correct results.
+     */
+    private void assertResults( Connection conn, String query, String[][] rows, boolean trimResults )
+        throws Exception
+    {
+        PreparedStatement   ps = chattyPrepare( conn, query );
+        ResultSet                   rs = ps.executeQuery();
+
+        assertResults( rs, rows, trimResults );
+
+        rs.close();
+        ps.close();
+    }
+        
+    /**
+     * Assert that the ResultSet returns the desired rows.
      */
     private void assertResults( ResultSet rs, String[][] rows, boolean trimResults )
         throws Exception
@@ -2670,13 +3408,14 @@
      * </p>
      */
     private void assertDefaultInfo
-        ( Connection conn, String tableName, String columnName, int[] expectedReferenceColumns, String expectedDefaultText )
+        ( Connection conn, String tableName, String columnName, String[] expectedReferenceColumns, String expectedDefaultText )
         throws Exception
     {
         DefaultInfo di = getColumnDefault( conn, tableName, columnName );
+        String[]        actualReferenceColumns = di.getReferencedColumnNames();
 
         assertEquals
-            ( StringUtil.stringify( expectedReferenceColumns ), StringUtil.stringify( di.getReferencedColumnIDs() ) );
+            ( fill( expectedReferenceColumns ).toString(), fill( actualReferenceColumns ).toString() );
         assertEquals( expectedDefaultText, di.getDefaultText() );
 
         assertTrue( di.isGeneratedColumn() );
@@ -2684,6 +3423,21 @@
     
     /**
      * <p>
+     * Fill an ArrayList from an array.
+     * </p>
+     */
+    private ArrayList   fill( Object[] raw )
+    {
+        ArrayList   result = new ArrayList();
+        int             count = raw.length;
+
+        for ( int i = 0; i < count; i++ ) { result.add( raw[ i ] ); }
+
+        return result;
+    }
+    
+    /**
+     * <p>
      * Returns the column default for a column.
      * </p>
      */



Mime
View raw message