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 da...@apache.org on 2010/08/20 17:11:06 UTC

svn commit: r987539 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/sql/compile/SelectNode.java testing/org/apache/derbyTesting/functionTests/tests/lang/OuterJoinTest.java testing/org/apache/derbyTesting/junit/RuntimeStatisticsParser.java

Author: dag
Date: Fri Aug 20 15:11:06 2010
New Revision: 987539

URL: http://svn.apache.org/viewvc?rev=987539&view=rev
Log:
DERBY-4736 ASSERT FAIL when code generating a column reference in a join predicate in presence of other outer join reordering

Patch derby-4736-1d, which fixes this bug, by adding a missing call to
bindResultColumns in SelectNode#preprocess if we have detected that
the outer join reordering has kicked in, cf call to LOJ_reorderable.

A new test case, testDerby_4736 was added to OuterJoinTest.


Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OuterJoinTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/RuntimeStatisticsParser.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java?rev=987539&r1=987538&r2=987539&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java Fri Aug 20 15:11:06 2010
@@ -1000,6 +1000,7 @@ public class SelectNode extends ResultSe
 																	 getNodeFactory().doJoinOrderOptimization(),
 																	 getContextManager());
 			bindExpressions(afromList);
+            bindResultColumns(afromList);
 		}
 
 		/* Preprocess the fromList.  For each FromTable, if it is a FromSubquery

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OuterJoinTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OuterJoinTest.java?rev=987539&r1=987538&r2=987539&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OuterJoinTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OuterJoinTest.java Fri Aug 20 15:11:06 2010
@@ -2390,4 +2390,159 @@ public final class OuterJoinTest extends
        expRS=new String[][]{};
        JDBC.assertFullResultSet(rs, expRS,true);
     }
+
+
+   /**
+    * This fixture would give:
+    * <pre>
+    *   ASSERT FAILED sourceResultSetNumber expected to be >= 0 for T2.X
+    * </pre>
+    * error in sane mode prior to DERBY-4736 due to a missing rebinding
+    * operation as a result a the LOJ reordering.  Schema and query originally
+    * stems from DERBY-4712 (parent issue of DERBY-4736).
+    */
+    public void testDerby_4736() throws SQLException {
+        setAutoCommit(false);
+        Statement s = createStatement();
+
+        s.executeUpdate("create table t0(x int)");
+        s.executeUpdate("create table t1(x int)");
+        s.executeUpdate("create table t2(x int)");
+        s.executeUpdate("create table t3(x int)");
+        s.executeUpdate("create table t4(x int)");
+        s.executeUpdate("insert into t4 values(0)");
+        s.executeUpdate("insert into t4 values(1)");
+        s.executeUpdate("insert into t4 values(2)");
+        s.executeUpdate("insert into t4 values(3)");
+        s.executeUpdate("create table t5(x int)");
+        s.executeUpdate("insert into t5 values(0)");
+        s.executeUpdate("insert into t5 values(1)");
+        s.executeUpdate("insert into t5 values(2)");
+        s.executeUpdate("insert into t5 values(3)");
+        s.executeUpdate("insert into t5 values(4)");
+        s.executeUpdate("create table t6(x int)");
+        s.executeUpdate("insert into t6 values(0)");
+        s.executeUpdate("insert into t6 values(1)");
+        s.executeUpdate("insert into t6 values(2)");
+        s.executeUpdate("insert into t6 values(3)");
+        s.executeUpdate("insert into t6 values(4)");
+        s.executeUpdate("insert into t6 values(5)");
+        s.executeUpdate("create table t7(x int)");
+        s.executeUpdate("insert into t7 values(0)");
+        s.executeUpdate("insert into t7 values(1)");
+        s.executeUpdate("insert into t7 values(2)");
+        s.executeUpdate("insert into t7 values(3)");
+        s.executeUpdate("insert into t7 values(4)");
+        s.executeUpdate("insert into t7 values(5)");
+        s.executeUpdate("insert into t7 values(6)");
+        s.executeUpdate("create table t8(x int)");
+        s.executeUpdate("insert into t8 values(0)");
+        s.executeUpdate("insert into t8 values(1)");
+        s.executeUpdate("insert into t8 values(2)");
+        s.executeUpdate("insert into t8 values(3)");
+        s.executeUpdate("insert into t8 values(4)");
+        s.executeUpdate("insert into t8 values(5)");
+        s.executeUpdate("insert into t8 values(6)");
+        s.executeUpdate("insert into t8 values(7)");
+        s.executeUpdate("create table t9(x int)");
+        s.executeUpdate("insert into t9 values(0)");
+        s.executeUpdate("insert into t9 values(1)");
+        s.executeUpdate("insert into t9 values(2)");
+        s.executeUpdate("insert into t9 values(3)");
+        s.executeUpdate("insert into t9 values(4)");
+        s.executeUpdate("insert into t9 values(5)");
+        s.executeUpdate("insert into t9 values(6)");
+        s.executeUpdate("insert into t9 values(7)");
+        s.executeUpdate("insert into t9 values(8)");
+        s.executeUpdate("insert into t0 values(1)");
+        s.executeUpdate("insert into t1 values(2)");
+        s.executeUpdate("insert into t0 values(3)");
+        s.executeUpdate("insert into t1 values(3)");
+        s.executeUpdate("insert into t2 values(4)");
+        s.executeUpdate("insert into t0 values(5)");
+        s.executeUpdate("insert into t2 values(5)");
+        s.executeUpdate("insert into t1 values(6)");
+        s.executeUpdate("insert into t2 values(6)");
+        s.executeUpdate("insert into t0 values(7)");
+        s.executeUpdate("insert into t1 values(7)");
+        s.executeUpdate("insert into t2 values(7)");
+        s.executeUpdate("insert into t3 values(8)");
+        s.executeUpdate("insert into t0 values(9)");
+        s.executeUpdate("insert into t3 values(9)");
+        s.executeUpdate("insert into t1 values(10)");
+        s.executeUpdate("insert into t3 values(10)");
+        s.executeUpdate("insert into t0 values(11)");
+        s.executeUpdate("insert into t1 values(11)");
+        s.executeUpdate("insert into t3 values(11)");
+        s.executeUpdate("insert into t2 values(12)");
+        s.executeUpdate("insert into t3 values(12)");
+        s.executeUpdate("insert into t0 values(13)");
+        s.executeUpdate("insert into t2 values(13)");
+        s.executeUpdate("insert into t3 values(13)");
+        s.executeUpdate("insert into t1 values(14)");
+        s.executeUpdate("insert into t2 values(14)");
+        s.executeUpdate("insert into t3 values(14)");
+        s.executeUpdate("insert into t0 values(15)");
+        s.executeUpdate("insert into t1 values(15)");
+        s.executeUpdate("insert into t2 values(15)");
+        s.executeUpdate("insert into t3 values(15)");
+
+        s.execute("CALL SYSCS_UTIL.SYSCS_SET_RUNTIMESTATISTICS(1)");
+
+        ResultSet rs = s.executeQuery(
+            "select t0.x , t1.x , t2.x , t3.x , t4.x , t5.x , t6.x from " +
+            "    ((t0 right outer join " +
+            "         (t1 right outer join " +
+            //            t2 LOJ (t3 LOJ t4) will be reordered
+            "             (t2 left outer join " +
+            "                 (t3 left outer join t4 on t3.x = t4.x ) " +
+            "              on t2.x = t3.x ) " +
+            "          on t1.x = t3.x ) " +
+            "      on t0.x = t1.x ) " +
+            "     left outer join " +
+            "      (t5 inner join t6 on t5.x = t6.x ) " +
+            "     on t2.x = t5.x)" );
+
+        // The expected result below has been verified to the one we get if we
+        // don't reorder LOJ.
+        JDBC.assertUnorderedResultSet(
+            rs,
+            new String[][] {
+                {null, null, "4", null, null, "4", "4"},
+                {null, null, "5", null, null, null, null},
+                {null, null, "6", null, null, null, null},
+                {null, null, "7", null, null, null, null},
+                {null, null, "12", "12", null, null, null},
+                {null, null, "13", "13", null, null, null},
+                {null, "14", "14", "14", null, null, null},
+                {"15", "15", "15", "15", null, null, null}});
+
+        rs = s.executeQuery("values SYSCS_UTIL.SYSCS_GET_RUNTIMESTATISTICS()");
+        rs.next();
+        String rts = rs.getString(1);
+
+        // Now verify that we actually *did* reorder
+        RuntimeStatisticsParser rtsp = new RuntimeStatisticsParser(rts);
+        rtsp.assertSequence(
+            new String[] {
+                "_Nested Loop Left Outer Join ResultSet:",
+                "_Left result set:",
+                "__Hash Left Outer Join ResultSet:",
+                "__Left result set:",
+                "___Hash Left Outer Join ResultSet:",
+                "___Left result set:",
+                "____Hash Left Outer Join ResultSet:",
+                "____Left result set:",
+                "_____Hash Left Outer Join ResultSet:",
+                // Note: T2 and T3 are in innermost LOJ as expected
+                // whereas originally it was T3 and T4
+                "_____Left result set:",
+                "______Table Scan ResultSet for T2 ",
+                "_____Right result set:",
+                "______Hash Scan ResultSet for T3 ",
+                "____Right result set:",
+                "_____Hash Scan ResultSet for T4"});
+
+        rs.close();
+    }
 }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/RuntimeStatisticsParser.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/RuntimeStatisticsParser.java?rev=987539&r1=987538&r2=987539&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/RuntimeStatisticsParser.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/RuntimeStatisticsParser.java Fri Aug 20 15:11:06 2010
@@ -461,5 +461,45 @@ public class RuntimeStatisticsParser {
             return null;
     }
 
+    /**
+     * Assert that a sequence of string exists in the statistics.
+     * <p>/
+     * The strings in the argument are each assumed to start a line. Leading
+     * underscores are converted to tab characters before comparing.
+     *
+     * @param strings The sequence of string expected to be found.
+     */
+    public void assertSequence(String[] strings) {
+
+        // Make strings ready for comparison:
+        for (int i=0; i < strings.length; i++) {
+            StringBuffer sb = new StringBuffer();
+
+            sb.append('\n');
+            
+            for (int j=0; j < strings[i].length(); j++) {
+                if (strings[i].charAt(j) == '_') {
+                    sb.append('\t');
+                } else {
+                    sb.append(strings[i].substring(j));
+                    break;
+                }
+            }
+            strings[i] = sb.toString();
+        }
+
+        int matchIdx = 0; // which string to match next
+        String window = statistics;
+        for (int i = 0; i < strings.length; i++) {
+            int pos = window.indexOf(strings[i]);
+
+            if (pos == -1) {
+                throw new AssertionError(
+                    "Sequence not found in statistics");
+            }
+
+            window = window.substring(pos + 1);
+        }
+    }
 }