db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhille...@apache.org
Subject svn commit: r722623 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/sql/compile/ testing/org/apache/derbyTesting/functionTests/tests/lang/
Date Tue, 02 Dec 2008 21:43:30 GMT
Author: rhillegas
Date: Tue Dec  2 13:43:30 2008
New Revision: 722623

URL: http://svn.apache.org/viewvc?rev=722623&view=rev
Log:
DERBY-3964: Fix NPE in evaluation of generated columns while processing an ON DELETE SET NULL
referential action.

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=722623&r1=722622&r2=722623&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
Tue Dec  2 13:43:30 2008
@@ -575,7 +575,6 @@
                         {
                             newRC.setName( rc.getName() );
                             newRC.setResultSetNumber( updateResultSet.getResultSetNumber()
);
-                            
                             sourceRCL.setElementAt( newRC, j );
                             
                         }
@@ -1582,6 +1581,7 @@
       *
       * @param rcl  describes the row of expressions to be put into the bas table
       * @param resultSetNumber  index of base table into array of ResultSets
+      * @param isUpdate true if this is for an UPDATE statement
       * @param ecb code generation state variable
       * @param mb the method being generated
       *
@@ -1591,6 +1591,7 @@
 	(
         ResultColumnList            rcl,
         int                                 resultSetNumber,
+        boolean                         isUpdate,
 		ExpressionClassBuilder	ecb,
 		MethodBuilder			mb
     )
@@ -1637,7 +1638,7 @@
 		}
 		else
 		{
-			MethodBuilder	userExprFun = generateGenerationClauses( rcl, resultSetNumber, ecb);
+			MethodBuilder	userExprFun = generateGenerationClauses( rcl, resultSetNumber, isUpdate,
ecb);
 
 	   		// generation clause evaluation is used in the final result set 
 			// as an access of the new static
@@ -1651,6 +1652,7 @@
       *
       * @param rcl  describes the row of expressions to be put into the bas table
       * @param rsNumber  index of base table into array of ResultSets
+      * @param isUpdate true if this is for an UPDATE statement
       * @param ecb code generation state variable
       *
 	  */
@@ -1658,6 +1660,7 @@
 	(
         ResultColumnList            rcl,
         int                                 rsNumber,
+        boolean                         isUpdate,
 		ExpressionClassBuilder	ecb
     )
 		throws StandardException
@@ -1666,7 +1669,7 @@
 		// generates:
 		// 	java.lang.Object userExprFun( ) { }
 		MethodBuilder userExprFun = ecb.newUserExprFun();
-		
+
 		/* Declare the field and load it with the current row */
 		LocalField field = ecb.newFieldDeclaration(Modifier.PRIVATE, ClassName.ExecRow);
         userExprFun.pushThis();
@@ -1674,10 +1677,21 @@
         userExprFun.callMethod(VMOpcode.INVOKEVIRTUAL, ClassName.BaseActivation, "getCurrentRow",
ClassName.Row, 1);
         userExprFun.putField( field );
 
-		// loop through the result columns, computing generated columns
-        // as we go
+		// Loop through the result columns, computing generated columns
+        // as we go. 
         int     size = rcl.size();
-        for ( int i = 0; i < size; i++ )
+        int     startColumn = 0;
+        // For UPDATEs, we only compute the updated value for the
+        // column. The updated value lives in the second half of the row.
+        // This means we ignore the first half of the row, which holds
+        // the before-images of the columns.
+        if ( isUpdate )
+        {
+            // throw away the last cell in the row, which is the row id
+            startColumn = size - 1;
+            startColumn = startColumn / 2;
+        }
+        for ( int i = startColumn; i < size; i++ )
         {
             ResultColumn    rc = (ResultColumn) rcl.elementAt( i );
 

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=722623&r1=722622&r2=722623&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 Tue
Dec  2 13:43:30 2008
@@ -849,7 +849,7 @@
 			resultSet.generate(acb, mb);
 
 			// arg 2 generate code to evaluate generation clauses
-			generateGenerationClauses( resultColumnList, resultSet.getResultSetNumber(), acb, mb );
+			generateGenerationClauses( resultColumnList, resultSet.getResultSetNumber(), false, acb,
mb );
 
 			// arg 3 generate code to evaluate CHECK CONSTRAINTS
 			generateCheckConstraints( checkConstraints, acb, mb );

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=722623&r1=722622&r2=722623&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 Tue
Dec  2 13:43:30 2008
@@ -844,7 +844,7 @@
         else
         {
 			// arg 2 generate code to evaluate generation clauses
-			generateGenerationClauses( resultColumnList, resultSet.getResultSetNumber(), acb, mb );
+			generateGenerationClauses( resultColumnList, resultSet.getResultSetNumber(), true, acb,
mb );
 
             // generate code to evaluate CHECK CONSTRAINTS
             generateCheckConstraints( checkConstraints, acb, mb ); // arg 3

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=722623&r1=722622&r2=722623&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
Tue Dec  2 13:43:30 2008
@@ -4573,10 +4573,77 @@
              false
              );
         conn.commit();
+        conn.setAutoCommit( true );
 
         stmt.close();
     }
 
+    /**
+     * <p>
+     * Test that we correctly handle foreign keys with ON DELETE SET NULL
+     * clauses. DERBY-3964.
+     * </p>
+     */
+    public  void    test_026_onDeleteSetNull()
+        throws Exception
+    {
+        Connection  conn = getConnection();
+
+        //
+        // Setup
+        //
+        goodStatement
+            (
+             conn,
+             "create table t_dhw_1( a int primary key )"
+             );
+        goodStatement
+            (
+             conn,
+             "create table t_dhw_2( a int references t_dhw_1( a ) on delete set null check
( a is null or a > 0 ), b int generated always as ( -a ) check ( b is null or b < 0
) )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dhw_1( a ) values ( 1 ), ( 2 )"
+             );
+        goodStatement
+            (
+             conn,
+             "insert into t_dhw_2( a ) values( 1 )"
+             );
+
+        //
+        // Verify that when you delete from the primary table, the foreign key
+        // table is updated and the update percolates through to the generated column.
+        //
+        goodStatement
+            (
+             conn,
+             "delete from t_dhw_1 where a = 1"
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dhw_1 order by a",
+             new String[][]
+             {
+                 { "2", },
+             },
+             false
+             );
+        assertResults
+            (
+             conn,
+             "select * from t_dhw_2 order by a",
+             new String[][]
+             {
+                 { null, null, },
+             },
+             false
+             );
+    }
+    
     ///////////////////////////////////////////////////////////////////////////////////
     //
     // MINIONS



Mime
View raw message