db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From d..@apache.org
Subject svn commit: r887246 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/sql/compile/PredicateList.java testing/org/apache/derbyTesting/functionTests/tests/lang/JoinTest.java
Date Fri, 04 Dec 2009 16:10:04 GMT
Author: dag
Date: Fri Dec  4 16:10:04 2009
New Revision: 887246

URL: http://svn.apache.org/viewvc?rev=887246&view=rev
Log:
DERBY-4387 Infinite loop in PredicateList.joinClauseTransitiveClosure()

This patch, derby-4387, fixes a corner case of the closure code in
which the outer and the inner table is the same. This led to adding
the same, new predicate twice to the same table, causing the infinite
loop. The patch also adds a test case, which, without the fix, shows
the infinite loop.



Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/JoinTest.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java?rev=887246&r1=887245&r2=887246&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java Fri
Dec  4 16:10:04 2009
@@ -2179,7 +2179,14 @@
 					{
 						outerJCL.addElement(newPred);
 					}
-					innerJCL.addElement(newPred);
+
+                    if (outerJCL != innerJCL) {
+                        innerJCL.addElement(newPred);
+                    } else {
+                        // DERBY-4387: Avoid adding <t1>.a = <t1>.b twice to
+                        // the same predicate list, so do nothing since we
+                        // already added predicate to outerJCL above.
+                    }
 				}
 			}
 		}

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/JoinTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/JoinTest.java?rev=887246&r1=887245&r2=887246&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/JoinTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/JoinTest.java
Fri Dec  4 16:10:04 2009
@@ -739,4 +739,50 @@
             "select * from t1 join t2 on exists " +
             "(select * from t3 x left join t3 y on 1=0 where y.c=1)"));
     }
+
+
+    /**
+     * Test that computation of transitive closure of equi-join does not give
+     * rise to eternal loop in a case where a predicate of type T1.x = T1.y is
+     * added to the closure.
+     * @throws SQLException
+     */
+    public void testDerby4387() throws SQLException {
+        setAutoCommit(false);
+        Statement s = createStatement();
+        ResultSet rs;
+
+
+        s.executeUpdate("create table c (a int, b int, c int)");
+        s.executeUpdate("create table cc (aa int)");
+
+        // Compiling this query gave an infinite loop (would eventually run out
+        // of memory though) before the fix:
+        rs = s.executeQuery("select * from cc t1, c t2, cc t3 " +
+                            "    where t3.aa = t2.a and " +
+                            "          t3.aa = t2.b and " +
+                            "          t3.aa = t2.c");
+
+        // After the fix the correct joinClauses table should look like this
+        // when done (see PredicateList#joinClauseTransitiveClosure variable
+        // joinClauses), where EC is equivalence class assigned, and a *
+        // denotes a predicate added by the closure computation.
+        //
+        // [0]: (t1)
+        // [1]: (t2)
+        //    [0]: 2.1 = 1.1 EC: 0     i.e.  t3.aa == t2.a
+        //    [1]: 1.1 = 1.3 EC: 0           t2.a  == t2.c *
+        //    [2]: 1.1 = 1.2 EC: 0           t2.a  == t2.b *
+        //    [3]: 2.1 = 1.2 EC: 0           t3.aa == t2.b
+        //    [4]: 2.1 = 1.3 EC: 0           t3.aa == t2.c
+        // [2]: (t3)
+        //    [0]: 2.1 = 1.1 EC: 0           t3.aa == t2.a
+        //    [1]: 2.1 = 1.2 EC: 0           t3.aa == t2.b
+        //    [2]: 2.1 = 1.3 EC: 0           t3.aa == t2.c
+        //
+        // Before the fix, the derived predicates (e.g. t2.a == t2.b) were
+        // added twice and caused an infinite loop.
+
+        rollback();
+    }
 }



Mime
View raw message