db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From d..@apache.org
Subject svn commit: r884163 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/sql/compile/ testing/org/apache/derbyTesting/functionTests/tests/lang/
Date Wed, 25 Nov 2009 15:57:51 GMT
Author: dag
Date: Wed Nov 25 15:57:50 2009
New Revision: 884163

URL: http://svn.apache.org/viewvc?rev=884163&view=rev
Log:
DERBY-4451 ArrayIndexOutOfBoundsException or ASSERT FAILED when inserting generated columns
out of order

This patch fixes this issue as well as DERBY-4448, since they share
the same underlying problem: the former way of checking for illegal
override of generated columns in the presence of an explicit target
column list failed to look below the top level UnionNode in a table
constructor.

This specialized treatment for the case of an explicit target column
list has been removed for INSERT (it was shared with logic for
UPDATE), so checking is now done by the code for the case of no
explicit targte column list.


Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/DMLModStatementNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/InsertNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UpdateNode.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/impl/sql/compile/DMLModStatementNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/DMLModStatementNode.java?rev=884163&r1=884162&r2=884163&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/DMLModStatementNode.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/DMLModStatementNode.java
Wed Nov 25 15:57:50 2009
@@ -408,87 +408,6 @@
 	}
 
     /**
-     * Do not allow generation clauses to be overriden. Throws an exception
-     * if the user attempts to override the value of a generated column.
-     * The only value allowed in a generated column is DEFAULT. If we find
-     * a generated column which is being explicitly set to DEFAULT in an INSERT, we remove
-     * it from the column lists--it will be added back in during the enhance
-     * phase. For an update, addedGeneratedColumns will be non-null and we will
-     * use this list to pass through the generated columns which have already
-     * been added to the update list.
-     *
-     * @param targetRCL  the row in the table being INSERTed or UPDATEd
-     * @param forUpdate  true if this is an UPDATE. false otherwise.
-     * @param addedGeneratedColumns generated columns which the compiler added earlier on
-     */
-    void forbidGenerationOverrides( ResultColumnList targetRCL, boolean forUpdate, ColumnDescriptorList
addedGeneratedColumns )
-        throws StandardException
-    {
-        int  count = targetRCL.size();
-
-        ResultColumnList    resultRCL = resultSet.getResultColumns();
-        
-        for ( int i = 0; i < count; i++ )
-        {
-            ResultColumn    rc = (ResultColumn) targetRCL.elementAt( i );
-
-            if ( rc.hasGenerationClause() )
-            {
-                ValueNode   resultExpression = ((ResultColumn) resultRCL.elementAt( i )).getExpression();
-
-                if ( !( resultExpression instanceof DefaultNode) )
-                {
-                    //
-                    // For updates, we may have added the generation clause
-                    // ourselves. Here we forgive ourselves for this pro-active behavior.
-                    //
-                    boolean allIsForgiven = false;
-                    
-                    if ( forUpdate )
-                    {
-                        String      columnName = rc.getTableColumnDescriptor().getColumnName();
-                        int         addedCount = addedGeneratedColumns.size();
-
-                        for ( int j = 0; j < addedCount; j++ )
-                        {
-                            String  addedColumnName = addedGeneratedColumns.elementAt( j
).getColumnName();
-
-                            if ( columnName.equals( addedColumnName ) )
-                            {
-                                allIsForgiven = true;
-                                break;
-                            }
-                        }
-                    }
-                    if ( allIsForgiven ) { continue; }
-                    
-                    throw StandardException.newException
-                        ( SQLState.LANG_CANT_OVERRIDE_GENERATION_CLAUSE, rc.getName() );
-                }
-                else
-                {
-                    // skip this step if we're working on an update statement.
-                    // for updates, the target list has already been enhanced.
-                    if ( forUpdate ) { continue; }
-                    
-                    // Prune the generated column and its default. They will be
-                    // added back in during the enhance phase.
-                    targetRCL.removeElementAt( i );
-                    resultRCL.removeElementAt( i );
-
-                    targetRCL.resetVirtualColumnIds();
-                    resultRCL.resetVirtualColumnIds();
-
-                    // account for the dropped entries
-                    count--;
-                    i--;
-                }
-            }
-
-        }
-    }
-    
-    /**
      * Parse and bind the generating expressions of computed columns.
      *
      * @param dataDictionary    metadata

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/InsertNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/InsertNode.java?rev=884163&r1=884162&r2=884163&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/InsertNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/InsertNode.java Wed
Nov 25 15:57:50 2009
@@ -284,9 +284,6 @@
 														this);
 			}
 			getCompilerContext().popCurrentPrivType();
-
-            // don't allow overriding of generation clauses
-            forbidGenerationOverrides( targetColumnList, false, null );
 		}
 
 		/* Verify that all underlying ResultSets reclaimed their FromList */

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=884163&r1=884162&r2=884163&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 Wed
Nov 25 15:57:50 2009
@@ -374,7 +374,8 @@
 		getCompilerContext().popCurrentPrivType();
 
         // don't allow overriding of generation clauses
-        forbidGenerationOverrides( resultSet.getResultColumns(), true, addedGeneratedColumns
);
+        forbidGenerationOverrides( resultSet.getResultColumns(),
+								   addedGeneratedColumns );
         
 		LanguageConnectionContext lcc = getLanguageConnectionContext();
 		if (lcc.getAutoincrementUpdate() == false)
@@ -1293,4 +1294,75 @@
 		super.normalizeSynonymColumns(rcl, tableNameNode);
 	}
     
+    /**
+     * Do not allow generation clauses to be overriden. Throws an exception if
+     * the user attempts to override the value of a generated column.  The only
+     * value allowed in a generated column is DEFAULT. We will use
+     * addedGeneratedColumns list to pass through the generated columns which
+     * have already been added to the update list.
+     *
+     * @param targetRCL  the row in the table being UPDATEd
+     * @param addedGeneratedColumns generated columns which the compiler added
+     *        earlier on
+     * @throws StandardException on error
+     */
+    private void forbidGenerationOverrides(
+        ResultColumnList targetRCL,
+        ColumnDescriptorList addedGeneratedColumns)
+            throws StandardException
+    {
+        int  count = targetRCL.size();
+
+        ResultColumnList    resultRCL = resultSet.getResultColumns();
+
+        for ( int i = 0; i < count; i++ )
+        {
+            ResultColumn    rc = (ResultColumn) targetRCL.elementAt( i );
+
+            if ( rc.hasGenerationClause() )
+            {
+                ValueNode   resultExpression =
+                    ((ResultColumn) resultRCL.elementAt( i )).getExpression();
+
+                if ( !( resultExpression instanceof DefaultNode) )
+                {
+                    //
+                    // We may have added the generation clause
+                    // ourselves. Here we forgive ourselves for this
+                    // pro-active behavior.
+                    //
+                    boolean allIsForgiven = false;
+
+                    String columnName =
+                        rc.getTableColumnDescriptor().getColumnName();
+
+                    int addedCount = addedGeneratedColumns.size();
+
+                    for ( int j = 0; j < addedCount; j++ )
+                    {
+                        String addedColumnName = addedGeneratedColumns.
+                            elementAt(j).getColumnName();
+
+                        if ( columnName.equals( addedColumnName ) )
+                        {
+                            allIsForgiven = true;
+                            break;
+                        }
+                    }
+                    if ( allIsForgiven ) { continue; }
+
+                    throw StandardException.newException
+                        (SQLState.LANG_CANT_OVERRIDE_GENERATION_CLAUSE,
+                         rc.getName() );
+                }
+                else
+                {
+                    // Skip this step if we're working on an update
+                    // statement. For updates, the target list has already
+                    // been enhanced.
+                    continue;
+                }
+            }
+        }
+    }
 } // end of UpdateNode

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=884163&r1=884162&r2=884163&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
Wed Nov 25 15:57:50 2009
@@ -122,6 +122,118 @@
     ///////////////////////////////////////////////////////////////////////////////////
 
     /**
+     * Test for DERBY-4448 and DERBY-4451: removal of explicitly given values
+     * for generated column failed if there is more than one row in the VALUES
+     * clause.
+     */
+    public void testDerby_4448_4451() throws SQLException {
+
+        //  DERBY-4451
+
+        Statement s = createStatement();
+        ResultSet rs = null;
+        setAutoCommit(false);
+
+        s.execute("create table t(a int, b generated always as (-a))");
+        s.execute("insert into t(b,a) values (default,1)");
+
+
+        // Trying to override a generation clause
+
+        expectCompilationError
+            (
+             CANT_OVERRIDE_GENERATION_CLAUSE,
+             "insert into t(b,a) select a,b from t union select a,b from t"
+             );
+
+        expectCompilationError
+            (
+             CANT_OVERRIDE_GENERATION_CLAUSE,
+             "insert into t(a,b) select * from t union select * from t"
+             );
+
+        expectCompilationError
+            (
+             CANT_OVERRIDE_GENERATION_CLAUSE,
+             "insert into t(b,a) select * from t union select * from t"
+             );
+
+        expectCompilationError
+            (
+             CANT_OVERRIDE_GENERATION_CLAUSE,
+             "insert into t(b,a) select * from t intersect select * from t"
+             );
+        expectCompilationError
+            (
+             CANT_OVERRIDE_GENERATION_CLAUSE,
+             "insert into t(b,a) select * from t except select * from t"
+             );
+
+        expectCompilationError
+            (
+             CANT_OVERRIDE_GENERATION_CLAUSE,
+             "insert into t(b,a) select a,b from t"
+             );
+
+        expectCompilationError
+            (
+             CANT_OVERRIDE_GENERATION_CLAUSE,
+             "insert into t(a,b) values (1,1)"
+             );
+
+        expectCompilationError
+            (
+             CANT_OVERRIDE_GENERATION_CLAUSE,
+             "insert into t(b,a) values (default,1), (2, 2)"
+             );
+
+        expectCompilationError
+            (
+             CANT_OVERRIDE_GENERATION_CLAUSE,
+             "insert into t(b,a) values (default,1), (default, 2),(3,3)"
+             );
+
+        expectCompilationError
+            (
+             CANT_OVERRIDE_GENERATION_CLAUSE,
+             "insert into t(b,a) values (1,1), (default, 2),(default,3)"
+             );
+
+        // Originally repro: failed prior to fix with array out of bounds
+        // (insane), or ASSERT (sane):
+        s.execute("insert into t(b,a) values (default,1), (default, 2)");
+
+        rs = s.executeQuery("select * from t");
+        JDBC.assertFullResultSet(rs, new String[][]{
+                {"1", "-1"},
+                {"1", "-1"},
+                {"2", "-2"}});
+
+        // DERBY-4448:
+        expectCompilationError
+            (
+             CANT_OVERRIDE_GENERATION_CLAUSE,
+             "insert into t(b) values (2)"
+            );
+
+        // Originally repro for DERBY-4448: failed with array out of bounds
+        // prior to fix:
+        expectCompilationError
+            (
+             CANT_OVERRIDE_GENERATION_CLAUSE,
+             "insert into t(b) values (default), (2)"
+            );
+
+        expectCompilationError
+            (
+             CANT_OVERRIDE_GENERATION_CLAUSE,
+             "insert into t(b) values (default), (default), (2)"
+            );
+
+        rollback();
+    }
+
+    /**
      * <p>
      * Test that the stored system procedures and functions are non-deterministic. If you
want
      * a particular procedure/function to be deterministic, add some logic here.
@@ -5323,6 +5435,8 @@
                 new String[][] { {"1","2"},{"2","4"},{"3","6"}}, false);
     }
 
+
+
     ///////////////////////////////////////////////////////////////////////////////////
     //
     // MINIONS



Mime
View raw message