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/28 00:35:40 UTC
svn commit: r990292 [3/3] - in /db/derby/code/trunk/java:
engine/org/apache/derby/impl/sql/compile/
testing/org/apache/derbyTesting/functionTests/master/
testing/org/apache/derbyTesting/functionTests/suites/
testing/org/apache/derbyTesting/functionTest...
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=990292&r1=990291&r2=990292&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 27 22:35:39 2010
@@ -1,4 +1,3 @@
-
/*
Derby - Class org.apache.derbyTesting.functionTests.tests.lang.OuterJoinTest
@@ -36,6 +35,7 @@ import org.apache.derbyTesting.junit.Bas
import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
import org.apache.derbyTesting.junit.RuntimeStatisticsParser;
import org.apache.derbyTesting.junit.TestConfiguration;
+import org.apache.derby.iapi.services.sanity.SanityManager;
public final class OuterJoinTest extends BaseJDBCTestCase
{
@@ -52,7 +52,6 @@ public final class OuterJoinTest extends
{
//Add the test case into the test suite
TestSuite suite = new TestSuite("OuterJoinTest Test");
- suite.addTest(TestConfiguration.defaultSuite(OuterJoinTest.class));
return TestConfiguration.defaultSuite(OuterJoinTest.class);
}
@@ -2174,7 +2173,7 @@ public final class OuterJoinTest extends
rs.close();
}
- public void TestdDerby5659() throws SQLException
+ public void testdDerby5659() throws SQLException
{
// Test fix for bug 5659
@@ -2392,6 +2391,532 @@ public final class OuterJoinTest extends
}
+ /**
+ * Test that left outer join reordering works as expected. This fixture is
+ * the first repro mentioned for this issue, DERBY-4471. It checks for
+ * correct results, and should fail prior to applying issue patch due to
+ * erroneous reordering.
+ * <p/>
+ * The results asserted in these tests for DERBY-4471 are the same as Derby
+ * gives without the reordering enabled and the same as Postgres yields.
+ * <p/>
+ * Note that the patch also opens up for correct reorderings of some
+ * queries in the seen in the original lojreorder.sql test (converted to
+ * JUnit as LojReorderTest in this patch) that did <em>not</em> happen
+ * earlier, in addition to denying the wrong ones documented in DERBY-4471
+ * and tested below. These new reorderings are tested, cf the comments in
+ * LojReorderTest. Look for the string 4471.
+
+ */
+ public void testDerby_4471a() throws SQLException {
+ setAutoCommit(false);
+ Statement s = createStatement();
+
+ s.executeUpdate("create table r(c1 char(1))");
+ s.executeUpdate("create table s(c1 char(1), c2 char(1))");
+ s.executeUpdate("create table t(c1 char(1))");
+
+ s.executeUpdate("insert into r values 'a'");
+ s.executeUpdate("insert into s values ('b', default)");
+ s.executeUpdate("insert into t values ('c')");
+
+ ResultSet rs = s.executeQuery(
+ "select * from r left outer join (s left outer join t " +
+ " on s.c2=t.c1 or s.c2 is null)" +
+ " on r.c1=s.c1");
+ JDBC.assertFullResultSet(rs, new String[][]{{"a", null, null, null}});
+ }
+
+ /**
+ * Test that left outer join reordering works as expected. The schema here
+ * is taken from the another issue which also saw this error;
+ * DERBY-4712/DERBY-4736. This fixture checks for correct results. The
+ * first query should fail prior to applying issue patch due to erroneous
+ * reordering, the second is OK to reorder (and would be reordered also
+ * prior to the patch).
+ */
+ public void testDerby_4471b() 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)");
+
+ // The theory exposed in Galindo-Legaria, C. & Rosenthal, A.:
+ // "Outerjoin simplification and reordering for query optimization",
+ // ACM Transactions on Database Systems, Vol 22, No 1, March 1997 uses
+ // two assumption for its general case which involves full outer joins
+ // as well: no duplicate rows and no rows consisting of only nulls. We
+ // cannot make that assumption, this being SQL, but for our restricted
+ // OJ rewrites, this should work ok, so we throw in both into the test
+ // mix:
+
+ // Make duplicates
+ s.executeUpdate("insert into t2 select * from t2");
+ s.executeUpdate("insert into t3 select * from t3");
+ s.executeUpdate("insert into t4 select * from t4");
+
+ // Insert full NULL tuples
+ s.executeUpdate("insert into t2 values cast(null as int)");
+ s.executeUpdate("insert into t3 values cast(null as int)");
+ s.executeUpdate("insert into t4 values cast(null as int)");
+
+ // This query was wrong prior to DERBY-4471: 1=1 is not allowed, since
+ // the inner join predicate does not reference T3 and T4 as required.
+ ResultSet rs = s.executeQuery(
+ "SELECT * FROM (T2 LEFT JOIN (T3 left outer JOIN T4 " +
+ " ON 1=1) " +
+ " ON T2.X = T3.X)");
+
+ JDBC.assertUnorderedResultSet(
+ rs,
+ new String[][] {
+ {"4", null, null},
+ {"5", null, null},
+ {"6", null, null},
+ {"7", null, null},
+ {"12", "12", "0"},
+ {"12", "12", "1"},
+ {"12", "12", "2"},
+ {"12", "12", "3"},
+ {"12", "12", "0"},
+ {"12", "12", "1"},
+ {"12", "12", "2"},
+ {"12", "12", "3"},
+ {"12", "12", null},
+ {"12", "12", "0"},
+ {"12", "12", "1"},
+ {"12", "12", "2"},
+ {"12", "12", "3"},
+ {"12", "12", "0"},
+ {"12", "12", "1"},
+ {"12", "12", "2"},
+ {"12", "12", "3"},
+ {"12", "12", null},
+ {"13", "13", "0"},
+ {"13", "13", "1"},
+ {"13", "13", "2"},
+ {"13", "13", "3"},
+ {"13", "13", "0"},
+ {"13", "13", "1"},
+ {"13", "13", "2"},
+ {"13", "13", "3"},
+ {"13", "13", null},
+ {"13", "13", "0"},
+ {"13", "13", "1"},
+ {"13", "13", "2"},
+ {"13", "13", "3"},
+ {"13", "13", "0"},
+ {"13", "13", "1"},
+ {"13", "13", "2"},
+ {"13", "13", "3"},
+ {"13", "13", null},
+ {"14", "14", "0"},
+ {"14", "14", "1"},
+ {"14", "14", "2"},
+ {"14", "14", "3"},
+ {"14", "14", "0"},
+ {"14", "14", "1"},
+ {"14", "14", "2"},
+ {"14", "14", "3"},
+ {"14", "14", null},
+ {"14", "14", "0"},
+ {"14", "14", "1"},
+ {"14", "14", "2"},
+ {"14", "14", "3"},
+ {"14", "14", "0"},
+ {"14", "14", "1"},
+ {"14", "14", "2"},
+ {"14", "14", "3"},
+ {"14", "14", null},
+ {"15", "15", "0"},
+ {"15", "15", "1"},
+ {"15", "15", "2"},
+ {"15", "15", "3"},
+ {"15", "15", "0"},
+ {"15", "15", "1"},
+ {"15", "15", "2"},
+ {"15", "15", "3"},
+ {"15", "15", null},
+ {"15", "15", "0"},
+ {"15", "15", "1"},
+ {"15", "15", "2"},
+ {"15", "15", "3"},
+ {"15", "15", "0"},
+ {"15", "15", "1"},
+ {"15", "15", "2"},
+ {"15", "15", "3"},
+ {"15", "15", null},
+ {"4", null, null},
+ {"5", null, null},
+ {"6", null, null},
+ {"7", null, null},
+ {"12", "12", "0"},
+ {"12", "12", "1"},
+ {"12", "12", "2"},
+ {"12", "12", "3"},
+ {"12", "12", "0"},
+ {"12", "12", "1"},
+ {"12", "12", "2"},
+ {"12", "12", "3"},
+ {"12", "12", null},
+ {"12", "12", "0"},
+ {"12", "12", "1"},
+ {"12", "12", "2"},
+ {"12", "12", "3"},
+ {"12", "12", "0"},
+ {"12", "12", "1"},
+ {"12", "12", "2"},
+ {"12", "12", "3"},
+ {"12", "12", null},
+ {"13", "13", "0"},
+ {"13", "13", "1"},
+ {"13", "13", "2"},
+ {"13", "13", "3"},
+ {"13", "13", "0"},
+ {"13", "13", "1"},
+ {"13", "13", "2"},
+ {"13", "13", "3"},
+ {"13", "13", null},
+ {"13", "13", "0"},
+ {"13", "13", "1"},
+ {"13", "13", "2"},
+ {"13", "13", "3"},
+ {"13", "13", "0"},
+ {"13", "13", "1"},
+ {"13", "13", "2"},
+ {"13", "13", "3"},
+ {"13", "13", null},
+ {"14", "14", "0"},
+ {"14", "14", "1"},
+ {"14", "14", "2"},
+ {"14", "14", "3"},
+ {"14", "14", "0"},
+ {"14", "14", "1"},
+ {"14", "14", "2"},
+ {"14", "14", "3"},
+ {"14", "14", null},
+ {"14", "14", "0"},
+ {"14", "14", "1"},
+ {"14", "14", "2"},
+ {"14", "14", "3"},
+ {"14", "14", "0"},
+ {"14", "14", "1"},
+ {"14", "14", "2"},
+ {"14", "14", "3"},
+ {"14", "14", null},
+ {"15", "15", "0"},
+ {"15", "15", "1"},
+ {"15", "15", "2"},
+ {"15", "15", "3"},
+ {"15", "15", "0"},
+ {"15", "15", "1"},
+ {"15", "15", "2"},
+ {"15", "15", "3"},
+ {"15", "15", null},
+ {"15", "15", "0"},
+ {"15", "15", "1"},
+ {"15", "15", "2"},
+ {"15", "15", "3"},
+ {"15", "15", "0"},
+ {"15", "15", "1"},
+ {"15", "15", "2"},
+ {"15", "15", "3"},
+ {"15", "15", null},
+ {null, null, null}});
+
+ s.execute("CALL SYSCS_UTIL.SYSCS_SET_RUNTIMESTATISTICS(1)");
+
+ // This one *can* be reordered
+ rs = s.executeQuery(
+ "SELECT * FROM (T2 LEFT JOIN (T3 left outer JOIN T4 " +
+ " ON t3.x=t4.x) " +
+ " ON T2.X = T3.X)");
+
+ JDBC.assertUnorderedResultSet(
+ rs,
+ new String[][] {
+ {"4", null, null},
+ {"4", null, null},
+ {"5", null, null},
+ {"5", null, null},
+ {"6", null, null},
+ {"6", null, null},
+ {"7", null, null},
+ {"7", null, null},
+ {"12", "12", null},
+ {"12", "12", null},
+ {"12", "12", null},
+ {"12", "12", null},
+ {"13", "13", null},
+ {"13", "13", null},
+ {"13", "13", null},
+ {"13", "13", null},
+ {"14", "14", null},
+ {"14", "14", null},
+ {"14", "14", null},
+ {"14", "14", null},
+ {"15", "15", null},
+ {"15", "15", null},
+ {"15", "15", null},
+ {"15", "15", null},
+ {null, null, null}});
+
+ JDBC.checkPlan(s,
+ new String[] {
+ "Hash Left Outer Join ResultSet:",
+ "Left result set:",
+ "_Hash Left Outer Join ResultSet:"});
+ }
+
+ /**
+ * Check that ordering actually takes place as well as checking that the
+ * results are correct.
+ */
+ public void testDerby_4471c() throws SQLException {
+ setAutoCommit(false);
+ Statement s = createStatement();
+
+ s.execute("create table t1(c1 int)");
+ s.execute("create table t2(c1 int)");
+ s.execute("create table t3(c1 int)");
+
+ s.execute("insert into t1 values 1, 2, 2, 3, 4");
+ s.execute("insert into t2 values 1, 3, 3, 5, 6");
+ s.execute("insert into t3 values 2, 3, 5, 5, 7");
+
+ s.execute("CALL SYSCS_UTIL.SYSCS_SET_RUNTIMESTATISTICS(1)");
+
+ PreparedStatement ps = prepareStatement(
+ "select * from t1 left outer join " +
+ " (t2 left outer join t3 on t2.c1 = t3.c1)" +
+ " on t1.c1 = t2.c1");
+
+ ResultSet rs = ps.executeQuery();
+
+ JDBC.assertUnorderedResultSet(
+ rs,
+ new String[][] {
+ {"1", "1", null},
+ {"2", null, null},
+ {"2", null, null},
+ {"3", "3", "3"},
+ {"3", "3", "3"},
+ {"4", null, null}});
+
+ JDBC.checkPlan(s,
+ new String[] {
+ "Hash Left Outer Join ResultSet:",
+ "Left result set:",
+ "_Hash Left Outer Join ResultSet:"});
+ }
+
+ /**
+ * Check that ordering actually takes place (more complex: nested
+ * reordering) as well as checking that the results are correct.
+ */
+ public void testDerby_4471d() throws SQLException {
+ setAutoCommit(false);
+ Statement s = createStatement();
+
+ s.execute("create table t1(c1 int)");
+ s.execute("create table t2(c2 int)");
+ s.execute("create table t3(c3 int)");
+
+ s.execute("insert into t1 values 1, 2, 2, 3, 4");
+ s.execute("insert into t2 values 1, 3, 3, 5, 6");
+ s.execute("insert into t3 values 2, 3, 5, 5, 7");
+
+ s.execute("CALL SYSCS_UTIL.SYSCS_SET_RUNTIMESTATISTICS(1)");
+
+
+
+ PreparedStatement ps = prepareStatement(
+ "select * from t1 t1_o left outer join " +
+ " ((t1 left outer join t2 on t1.c1 = t2.c2) left outer join " +
+ " t3 on t2.c2 = t3.c3)" +
+ " on t1_o.c1 = t2.c2");
+
+ // Expect one reordering, cf. rtsp.assertSequence below:
+ //
+ // LOJ1 [t1_o.c1 = t2.c2] LOJ1 [t2.c2=t3.c3]
+ // / \ / \
+ // / \ / t3
+ // / \ LOJ2 [t1_o.c1 = t2.c2]
+ // t1_o LOJ2 [t2.c2=t3.c3] / \
+ // / \ / LOJ3 [t2.c2=t3.c3]
+ // / \ => t1_o / \
+ // / t3 / \
+ // / t1 t2
+ // LOJ3 [t1.c1=t2.c2]
+ // / \
+ // / \
+ // t1 t2
+ //
+ // The reason we don't get two reorderings here is that the predicate
+ // on LOJ1, "t1_o.c1 = t2.c2" refrences LOJ3's null producing side,
+ // t2. Contrast with next example below.
+
+ ResultSet rs = ps.executeQuery();
+
+ JDBC.assertUnorderedResultSet(
+ rs,
+ new String[][] {
+ {"1", "1", "1", null},
+ {"2", null, null, null},
+ {"2", null, null, null},
+ {"3", "3", "3", "3"},
+ {"3", "3", "3", "3"},
+ {"4", null, null, null}});
+
+ JDBC.checkPlan(s,
+ new String[] {
+ "Hash Left Outer Join ResultSet:",
+ "Left result set:",
+ "_Nested Loop Left Outer Join ResultSet:",
+ "_Left result set:",
+ "_Right result set:",
+ "__Source result set:",
+ "___Hash Left Outer Join ResultSet:"});
+
+ ps = prepareStatement(
+ "select * from " +
+ " t1 t1_o left outer join " +
+ " ((t1 t1_i left outer join t2 " +
+ " on t1_i.c1 = t2.c2) left outer join t3 " +
+ " on t1_i.c1 = t3.c3)" +
+ " on t1_o.c1 = t1_i.c1");
+
+ // Expect two reorderings, cf. rtsp.assertSequence below:
+ //
+ // LOJ1 [t1_o.c1 = t1_i.c1] LOJ1 [t2.c2=t3.c3]
+ // / \ / \
+ // / \ / t3
+ // / \ LOJ2 [t1_o.c1 = t1_i.c1]
+ // t1_o LOJ2 [t1_i.c1=t3.c3] / \
+ // / \ / LOJ3 [t1.c1=t2.c2]
+ // / \ => t1_o / \
+ // / t3 / \
+ // LOJ3 [t1_i.c1=t2.c2] t1_i t2
+ // / \
+ // / \
+ // t1_i t2 =>
+ // LOJ1 [t2.c2=t3.c3]
+ // / \
+ // / t3
+ // LOJ2 [t2.c2=t3.c3]
+ // / \
+ // / t2
+ // LOJ3 [t1_o.c1 = t1_i.c1]
+ // / \
+ // t1_o t1_i
+ //
+ // In this example, LOJ1's predicate references LOJ3's row preserving
+ // side (t1_i), so we get two reorderings.
+
+ rs = ps.executeQuery();
+
+ JDBC.assertUnorderedResultSet(
+ rs,
+ new String[][] {
+ {"1", "1", "1", null},
+ {"2", "2", null, "2"},
+ {"2", "2", null, "2"},
+ {"2", "2", null, "2"},
+ {"2", "2", null, "2"},
+ {"3", "3", "3", "3"},
+ {"3", "3", "3", "3"},
+ {"4", "4", null, null}});
+
+ JDBC.checkPlan(s,
+ new String[] {
+ "Hash Left Outer Join ResultSet:",
+ "Left result set:",
+ "_Hash Left Outer Join ResultSet:",
+ "_Left result set:",
+ "__Hash Left Outer Join ResultSet:"});
+ }
+
+
/**
* This fixture would give:
* <pre>
@@ -2608,4 +3133,4 @@ public final class OuterJoinTest extends
JDBC.assertFullResultSet(rs, expRS);
}
- }
+}
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java?rev=990292&r1=990291&r2=990292&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java Fri Aug 27 22:35:39 2010
@@ -77,6 +77,7 @@ public class _Suite extends BaseTestCase
suite.addTest(InsertTest.suite());
suite.addTest(JoinTest.suite());
suite.addTest(LangScripts.suite());
+ suite.addTest(LojReorderTest.suite());
suite.addTest(MathTrigFunctionsTest.suite());
suite.addTest(OuterJoinTest.suite());
suite.addTest(PredicateTest.suite());
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/JDBC.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/JDBC.java?rev=990292&r1=990291&r2=990292&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/JDBC.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/JDBC.java Fri Aug 27 22:35:39 2010
@@ -907,6 +907,45 @@ public class JDBC {
Object [][] expectedRows, boolean allAsTrimmedStrings, boolean closeResultSet)
throws SQLException
{
+ assertFullResultSetMinion(rs, expectedRows, allAsTrimmedStrings,
+ closeResultSet, null);
+ }
+
+
+ /**
+ * assertFullResultSet() using trimmed string comparisions.
+ * Equal to
+ * <code>
+ * assertFullResultSet(rs, expectedRows, true)
+ * </code>
+ *
+ * As a side effect, this method closes the result set.
+ * <p/>
+ * Additionally, also assert that the given warnings are seen. The array
+ * {@code warnings} should contain null or a warning (SQLState string). The
+ * array entry is asserted against the result set after having read the
+ * corresponding row in the result set. <b>NOTE: only asserted for embedded
+ * result sets, cf DERBY-159</b>
+ * <p/>
+ * For now, we only look at the first warning if there is a chain
+ * of warnings.
+ */
+ public static void assertFullResultSet(ResultSet rs,
+ Object [][] expectedRows, String[] warnings)
+ throws SQLException
+ {
+ assertFullResultSetMinion(rs, expectedRows, true, true, warnings);
+ }
+
+
+ private static void assertFullResultSetMinion(
+ ResultSet rs,
+ Object [][] expectedRows,
+ boolean allAsTrimmedStrings,
+ boolean closeResultSet,
+ String[] warnings)
+ throws SQLException
+ {
int rows;
ResultSetMetaData rsmd = rs.getMetaData();
@@ -920,6 +959,25 @@ public class JDBC {
for (rows = 0; rs.next(); rows++)
{
+
+ // Assert warnings on result set, but only for embedded, cf
+ // DERBY-159.
+ if (TestConfiguration.getCurrent().getJDBCClient().isEmbedded() &&
+ warnings != null) {
+
+ SQLWarning w = rs.getWarnings();
+ String wstr = null;
+
+ if (w != null) {
+ wstr = w.getSQLState();
+ }
+
+ Assert.assertEquals(
+ "Warning assertion error on row " + (rows+1),
+ warnings[rows],
+ wstr);
+ }
+
/* If we have more actual rows than expected rows, don't
* try to assert the row. Instead just keep iterating
* to see exactly how many rows the actual result set has.
@@ -937,6 +995,7 @@ public class JDBC {
Assert.assertEquals("Unexpected row count:", expectedRows.length, rows);
}
+
/**
* Similar to assertFullResultSet(...) above, except that this
* method takes a BitSet and checks the received expectedRows
@@ -1453,5 +1512,32 @@ public class JDBC {
}
}
-
+ /**
+ * Get run-time statistics and check that a sequence of string exist in the
+ * statistics, using the given statement.
+ * <p/>
+ * For the format of the strings, see RuntimeStatisticsParser#assertSequence
+ *
+ * @see RuntimeStatisticsParser#assertSequence
+ *
+ * @param s the statement presumed to just have been executed, and for
+ * which we want to check the run-time statistics
+ * @param sequence the sequnce of strings we expect to see in the run-time
+ * statistics
+ * @throws SQLException standard
+ */
+ public static void checkPlan(Statement s, String[] sequence)
+ throws SQLException {
+
+ ResultSet rs = s.executeQuery(
+ "values SYSCS_UTIL.SYSCS_GET_RUNTIMESTATISTICS()");
+ rs.next();
+
+ String rts = rs.getString(1);
+ rs.close();
+
+ RuntimeStatisticsParser rtsp = new RuntimeStatisticsParser(rts);
+ rtsp.assertSequence(sequence);
+ }
+
}