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 ka...@apache.org on 2009/10/06 16:19:09 UTC

svn commit: r822289 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/sql/compile/BetweenOperatorNode.java testing/org/apache/derbyTesting/functionTests/tests/lang/InbetweenTest.java

Author: kahatlen
Date: Tue Oct  6 14:19:07 2009
New Revision: 822289

URL: http://svn.apache.org/viewvc?rev=822289&view=rev
Log:
DERBY-4388: NullPointerException in RIGHT JOIN with NOT BETWEEN

Clone the left operand when performing not-elimination in
BetweenOperatorNode to prevent ColumnReferences from being shared, as
they can be remapped during optimization.

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

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BetweenOperatorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BetweenOperatorNode.java?rev=822289&r1=822288&r2=822289&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BetweenOperatorNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BetweenOperatorNode.java Tue Oct  6 14:19:07 2009
@@ -127,11 +127,17 @@
 		/* Set type info for the operator node */
 		leftBCO.bindComparisonOperator();
 
+        // DERBY-4388: If leftOperand is a ColumnReference, it may be remapped
+        // during optimization, and that requires the less-than node and the
+        // greater-than node to have separate objects.
+        ValueNode leftClone = (leftOperand instanceof ColumnReference) ?
+            leftOperand.getClone() : leftOperand;
+
 		/* leftO > rightOList.elementAt(1) */
 		rightBCO = (BinaryComparisonOperatorNode) 
 					nodeFactory.getNode(
 								C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE,
-								leftOperand, 
+								leftClone,
 								rightOperandList.elementAt(1),
 								cm);
 		/* Set type info for the operator node */

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/InbetweenTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/InbetweenTest.java?rev=822289&r1=822288&r2=822289&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/InbetweenTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/InbetweenTest.java Tue Oct  6 14:19:07 2009
@@ -4501,4 +4501,27 @@
         conn.rollback();
         st.close();
     }
+
+    /**
+     * Regression test cases for DERBY-4388, where the not elimination in
+     * BetweenOperatorNode could make column references point to the wrong
+     * result sets after optimization, causing NullPointerExceptions.
+     */
+    public void testDerby4388NotElimination() throws SQLException {
+        setAutoCommit(false); // for easy cleanup with rollback() in tearDown()
+        Statement s = createStatement();
+        s.execute("create table d4388_t1(a int)");
+        s.execute("create table d4388_t2(b int)");
+        s.execute("insert into d4388_t1 values 0,1,2,3,4,5,6");
+        s.execute("insert into d4388_t2 values 0,1,2,3");
+        // The queries below used to cause NullPointerException.
+        JDBC.assertFullResultSet(
+                s.executeQuery("select * from d4388_t1 left join d4388_t2 " +
+                               "on a=b where b not between 1 and 5"),
+                new String[][]{{"0", "0"}});
+        JDBC.assertFullResultSet(
+                s.executeQuery("select * from d4388_t2 right join d4388_t1 " +
+                               "on a=b where b not between 1 and 5"),
+                new String[][]{{"0", "0"}});
+    }
 }