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/09/17 17:10:53 UTC

svn commit: r998170 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/sql/execute/BaseActivation.java testing/org/apache/derbyTesting/functionTests/tests/lang/OuterJoinTest.java

Author: dag
Date: Fri Sep 17 15:10:53 2010
New Revision: 998170

URL: http://svn.apache.org/viewvc?rev=998170&view=rev
Log:
DERBY-4798 NPE in nested outer join

Patch derby-4798a.

Reintroduces the bailout code in BaseActivation#getColumnFromRow which
was removed in DERBY-3097 until we understand why it is needed. 

Adds the repro for this issue to OuterJoinTest


Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/OuterJoinTest.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java?rev=998170&r1=998169&r2=998170&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java Fri Sep 17 15:10:53 2010
@@ -1474,7 +1474,23 @@ public abstract class BaseActivation imp
 	protected final DataValueDescriptor getColumnFromRow(int rsNumber, int colId)
 		throws StandardException {
 
-		return row[rsNumber].getColumn(colId);
+        if (row[rsNumber] == null) {
+            /* This actually happens. NoPutResultSetImpl.clearOrderableCache
+             * attempts to prefetch invariant values into a cache. This fails
+             * in some deeply nested joins. See Beetle 4736 and 4880.*/
+
+            /*
+             * Update: DERBY-4798 shows a query for which we get an NPE unless
+             * this escape is in place (once removed by DERBY-3097, but
+             * reintroduced by DERBY-4798 until we understand how we can get
+             * rid of this anomaly). Thus, for now,
+             * OuterJoinTest#testDerby_4798_NPE will provoke an NPE if this
+             * code is removed.
+             */
+            return null;
+        }
+
+        return row[rsNumber].getColumn(colId);
 	}
 
     /**

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=998170&r1=998169&r2=998170&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 Sep 17 15:10:53 2010
@@ -35,7 +35,6 @@ 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
 {
@@ -3379,4 +3378,121 @@ public final class OuterJoinTest extends
 
         JDBC.assertFullResultSet(rs, expRS);
     }
+
+
+    /**
+     * Test the queries reported in DERBY-4798 as giving null pointer
+     * exceptions. Should fail with NPE before the fix went in.
+     */
+    public void testDerby_4798_NPE() throws Exception
+    {
+        setAutoCommit(false);
+
+        Statement st = createStatement();
+        ResultSet rs = null;
+        String [][] expRS;
+
+        st.executeUpdate("create table t0(x0 int)");
+        st.executeUpdate("create table t1(x1 int)");
+        st.executeUpdate("create table t2(x2 int)");
+        st.executeUpdate("create table t3(x3 int)");
+        st.executeUpdate("create table t4(x4 int)");
+        st.executeUpdate("insert into t4 values(0)");
+        st.executeUpdate("insert into t4 values(1)");
+        st.executeUpdate("insert into t4 values(2)");
+        st.executeUpdate("insert into t4 values(3)");
+        st.executeUpdate("create table t5(x5 int)");
+        st.executeUpdate("insert into t5 values(0)");
+        st.executeUpdate("insert into t5 values(1)");
+        st.executeUpdate("insert into t5 values(2)");
+        st.executeUpdate("insert into t5 values(3)");
+        st.executeUpdate("insert into t5 values(4)");
+        st.executeUpdate("create table t6(x6 int)");
+        st.executeUpdate("insert into t6 values(0)");
+        st.executeUpdate("insert into t6 values(1)");
+        st.executeUpdate("insert into t6 values(2)");
+        st.executeUpdate("insert into t6 values(3)");
+        st.executeUpdate("insert into t6 values(4)");
+        st.executeUpdate("insert into t6 values(5)");
+        st.executeUpdate("create table t7(x7 int)");
+        st.executeUpdate("insert into t7 values(0)");
+        st.executeUpdate("insert into t7 values(1)");
+        st.executeUpdate("insert into t7 values(2)");
+        st.executeUpdate("insert into t7 values(3)");
+        st.executeUpdate("insert into t7 values(4)");
+        st.executeUpdate("insert into t7 values(5)");
+        st.executeUpdate("insert into t7 values(6)");
+        st.executeUpdate("insert into t0 values(1)");
+        st.executeUpdate("insert into t1 values(2)");
+        st.executeUpdate("insert into t0 values(3)");
+        st.executeUpdate("insert into t1 values(3)");
+        st.executeUpdate("insert into t2 values(4)");
+        st.executeUpdate("insert into t0 values(5)");
+        st.executeUpdate("insert into t2 values(5)");
+        st.executeUpdate("insert into t1 values(6)");
+        st.executeUpdate("insert into t2 values(6)");
+        st.executeUpdate("insert into t0 values(7)");
+        st.executeUpdate("insert into t1 values(7)");
+        st.executeUpdate("insert into t2 values(7)");
+        st.executeUpdate("insert into t3 values(8)");
+        st.executeUpdate("insert into t0 values(9)");
+        st.executeUpdate("insert into t3 values(9)");
+        st.executeUpdate("insert into t1 values(10)");
+        st.executeUpdate("insert into t3 values(10)");
+        st.executeUpdate("insert into t0 values(11)");
+        st.executeUpdate("insert into t1 values(11)");
+        st.executeUpdate("insert into t3 values(11)");
+        st.executeUpdate("insert into t2 values(12)");
+        st.executeUpdate("insert into t3 values(12)");
+        st.executeUpdate("insert into t0 values(13)");
+        st.executeUpdate("insert into t2 values(13)");
+        st.executeUpdate("insert into t3 values(13)");
+        st.executeUpdate("insert into t1 values(14)");
+        st.executeUpdate("insert into t2 values(14)");
+        st.executeUpdate("insert into t3 values(14)");
+        st.executeUpdate("insert into t0 values(15)");
+        st.executeUpdate("insert into t1 values(15)");
+        st.executeUpdate("insert into t2 values(15)");
+        st.executeUpdate("insert into t3 values(15)");
+
+        rs = st.executeQuery(
+        "SELECT t0.x0, " +
+        "       t1.x1," +
+        "       t2.x2," +
+        "       t3.x3," +
+        "       t4.x4," +
+        "       t5.x5," +
+        "       t6.x6," +
+        "       t7.x7 " +
+        "FROM         " +
+        " ((t0                                                               " +
+        "   LEFT OUTER JOIN ((t1                                             " +
+        "                     LEFT OUTER JOIN (t2                            " +
+        "                                      LEFT OUTER JOIN t3            " +
+        "                                        ON t2.x2 = t3.x3 )          " +
+        "                       ON t1.x1 = t2.x2 )                           " +
+        "                    LEFT OUTER JOIN (t4                             " +
+        "                                     INNER JOIN (t5                 " +
+        "                                                 LEFT OUTER JOIN t6 " +
+        "                                                   ON t5.x5 = t6.x6)" +
+        "                                       ON t4.x4 = t5.x5 )           " +
+        "                      ON t1.x1 = t5.x5 )                            " +
+        "     ON t0.x0 = t5.x5 )                                             " +
+        "  LEFT OUTER JOIN t7                                                " +
+        "    ON t3.x3 = t7.x7 )                                              ");
+
+        expRS = new String [][]
+        {
+            {"1", "1", null, null, null, null, null, null},
+            {"3", "3", "3", null, "3", "3", "3", null},
+            {"5", "5", null, null, null, null, null, null},
+            {"7", "7", null, null, null, null, null, null},
+            {"9", "9", null, null, null, null, null, null},
+            {"11", "11", null, null, null, null, null, null},
+            {"13", "13", null, null, null, null, null, null},
+            {"15", "15", null, null, null, null, null, null}
+        };
+
+        JDBC.assertFullResultSet(rs, expRS);
+    }
 }