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 bp...@apache.org on 2007/10/06 04:56:54 UTC

svn commit: r582439 - in /db/derby/code/branches/10.3/java: engine/org/apache/derby/impl/sql/compile/ testing/org/apache/derbyTesting/functionTests/tests/lang/

Author: bpendleton
Date: Fri Oct  5 19:56:53 2007
New Revision: 582439

URL: http://svn.apache.org/viewvc?rev=582439&view=rev
Log:
DERBY-3033: NullPointerExceptions with flattening of NOT EXISTS subqueries

Merged from the trunk by svn merge -r 581942:581943

Added:
    db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ExistsWithSubqueriesTest.java
      - copied unchanged from r581943, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ExistsWithSubqueriesTest.java
Removed:
    db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ExistsWithSetOpsTest.java
Modified:
    db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/sql/compile/FromList.java
    db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java
    db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java

Modified: db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/sql/compile/FromList.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/sql/compile/FromList.java?rev=582439&r1=582438&r2=582439&view=diff
==============================================================================
--- db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/sql/compile/FromList.java (original)
+++ db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/sql/compile/FromList.java Fri Oct  5 19:56:53 2007
@@ -1550,6 +1550,42 @@
 	}
 
 	/**
+	 * determine whether this table is NOT EXISTS.
+	 *
+	 * This routine searches for the indicated table number in the fromlist
+	 * and returns TRUE if the table is present in the from list and is 
+	 * marked NOT EXISTS, false otherwise.
+	 *
+	 * A table may be present in the from list for NOT EXISTS if it is used
+	 * as a correlated NOT EXISTS subquery. In such a situation, when the
+	 * subquery is flattened, it is important that we remember that this is
+	 * a NOT EXISTS subquery, because the join semantics are different 
+	 * (we're looking for rows that do NOT match, rather than rows
+	 * that do). And since the join semantics are different, we cannot
+	 * include this table into a transitive closure of equijoins
+	 * (See DERBY-3033 for a situation where this occurs).
+	 *
+	 * @param tableNumber	which table to check
+	 * @return true if this table is in the from list as NOT EXISTS
+	 */
+	boolean tableNumberIsNotExists(int tableNumber)
+		throws StandardException
+	{
+		int size = size();
+		for (int index = 0; index < size; index++)
+		{
+			ProjectRestrictNode prn = (ProjectRestrictNode) elementAt(index);
+			if (! (prn.getChildResult() instanceof FromTable))
+			{
+				continue;
+			}
+			FromTable ft = (FromTable) prn.getChildResult();
+			if (ft.getTableNumber() == tableNumber)
+				return ft.isNotExists();
+		}
+		return false;
+	}
+	/**
 	 * Get the lock mode for the target of an update statement
 	 * (a delete or update).  The update mode will always be row for
 	 * CurrentOfNodes.  It will be table if there is no where clause.

Modified: db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java?rev=582439&r1=582438&r2=582439&view=diff
==============================================================================
--- db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java (original)
+++ db/derby/code/branches/10.3/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java Fri Oct  5 19:56:53 2007
@@ -1818,6 +1818,14 @@
      * between outer and inner.  If so, then we simply assign it to the same 
      * equivalence class.  If not, then we add the new equijoin clause.
 	 *
+	 * Note that an equijoin predicate between two tables CANNOT be
+	 * used for transitive closure, if either of the tables is in the
+	 * fromlist for NOT EXISTS. In that case, the join predicate
+	 * actually specifies that the rows from the indicated table must
+	 * NOT exist, and therefore those non-existent rows cannot be
+	 * transitively joined to the other matching tables. See DERBY-3033
+	 * for a description of a situation in which this actually arises.
+	 *
 	 * @param numTables	The number of tables in the query
 	 * @param fromList	The FromList in question.
 	 * @param cc		The CompilerContext to use
@@ -1867,7 +1875,9 @@
 				ColumnReference leftCR = (ColumnReference) left;
 				ColumnReference rightCR = (ColumnReference) right;
 				if (leftCR.getSourceLevel() == rightCR.getSourceLevel() &&
-					leftCR.getTableNumber() != rightCR.getTableNumber())
+					leftCR.getTableNumber() != rightCR.getTableNumber() &&
+					!fromList.tableNumberIsNotExists(leftCR.getTableNumber()) &&
+					!fromList.tableNumberIsNotExists(rightCR.getTableNumber()))
 				{
 					// Add the equijoin clause to each of the lists
 					joinClauses[leftCR.getTableNumber()].addElement(predicate);

Modified: db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java?rev=582439&r1=582438&r2=582439&view=diff
==============================================================================
--- db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java (original)
+++ db/derby/code/branches/10.3/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java Fri Oct  5 19:56:53 2007
@@ -63,7 +63,7 @@
         suite.addTest(CreateTableFromQueryTest.suite());
         suite.addTest(DatabaseClassLoadingTest.suite());
         suite.addTest(DynamicLikeOptimizationTest.suite());
-        suite.addTest(ExistsWithSetOpsTest.suite());
+        suite.addTest(ExistsWithSubqueriesTest.suite());
         suite.addTest(GrantRevokeTest.suite());
         suite.addTest(GroupByExpressionTest.suite());
 		suite.addTest(LangScripts.suite());