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);
+ }
+ }
}