Index: java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java
===================================================================
--- java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java	(revision 604092)
+++ java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java	(working copy)
@@ -482,6 +482,23 @@
 
 			if (ilon != null)
 			{
+				/* Depending on the shape of the query and on where
+				 * this probe predicate ultimately ends up (that is,
+				 * where it gets pushed to), this.leftOperand *may*
+				 * have been transformed or remapped one or more
+				 * times.  Now that we're giving up on the probe
+				 * predicate and falling back to a "normal" IN list
+				 * restriction, we have to make sure that all of the
+				 * changes that were made to this.leftOperand are
+				 * reflected in the InListOperatorNode's leftOperand,
+				 * as well, so that we can generate the correct
+				 * operand for the IN list w.r.t. its final location
+				 * in the query tree.  The easiest way to do that is
+				 * to just set the InListOperatorNode's leftOperand
+				 * to be this.leftOperand, so do that before we try
+				 * generating the IN list.  DERBY-3253.
+				 */
+				ilon.setLeftOperand(this.leftOperand);
 				ilon.generateExpression(acb, mb);
 				return;
 			}
Index: java/testing/org/apache/derbyTesting/functionTests/tests/lang/InListMultiProbeTest.java
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/tests/lang/InListMultiProbeTest.java	(revision 604092)
+++ java/testing/org/apache/derbyTesting/functionTests/tests/lang/InListMultiProbeTest.java	(working copy)
@@ -212,11 +212,10 @@
     }
 
     /**
-     * The one test fixture for this test.  Executes three different types
-     * of queries ("strategies") repeatedly with an increasing number of
-     * values in the IN list.  Underneath we will check the query plan
-     * for each query to make sure that Derby is doing multi-probing as
-     * expected.
+     * Executes three different types of queries ("strategies") repeatedly
+     * with an increasing number of values in the IN list.  Underneath we
+     * will check the query plan for each query to make sure that Derby is
+     * doing multi-probing as expected.
      */
     public void testMultiProbing() throws Exception
     {
@@ -499,6 +498,54 @@
     }
 
     /**
+     * Test the scenario in which Derby creates an IN-list probe
+     * predicate, remaps its left operand to point to a nested
+     * SELECT query, and then decides to *not* use the probe
+     * predicate in the final plan.  The remapping of the left
+     * operand will cause the probe predicate's left operand to
+     * be set to a different ColumnReference object--one that
+     * points to the target table in the subselect.  Then when
+     * the optimizer decides to *not* use the probe predicate
+     * in the final query, we'll revert back to the original IN
+     * list (InListOperatorNode) and generate that for the query.
+     * When we do so, the left operand of the InListOperatorNode
+     * must reflect the fact that the IN operation's left operand
+     * has changed (it now points to the table from the subselect).
+     * Otherwise the InListOperatorNode will generate an invalid
+     * ColumnReference.  DERBY-3253.
+     */
+    public void testProbePredPushedIntoSelectThenReverted()
+        throws Exception
+    {
+        Statement st = createStatement();
+
+        st.execute("create table d3253 (i int, vc varchar(10))");
+        st.execute("insert into d3253 values " +
+            "(1, 'one'), (2, 'two'), (3, 'three'), (1, 'un')");
+
+        /* Before DERBY-3253 was fixed, this query would have thrown
+         * an execution time NPE due to the fact the generated column
+         * reference was pointing to the wrong place.
+         */
+        JDBC.assertUnorderedResultSet(st.executeQuery(
+            "select x.* from d3253, (select * from d3253) x " +
+            "where d3253.i = x.i and x.vc in ('un', 'trois')"),
+            new String [][] {{"1","un"},{"1","un"}});
+
+        JDBC.assertUnorderedResultSet(st.executeQuery(
+            "select x.* from d3253, (select * from d3253) x " +
+            "where d3253.i = x.i and x.i in (2, 3)"),
+            new String [][] {{"2","two"},{"3","three"}});
+
+        JDBC.assertEmpty(st.executeQuery(
+            "select x.* from d3253, (select * from d3253) x " +
+            "where d3253.i = x.i and x.vc in ('uno', 'tres')"));
+
+        st.execute("drop table d3253");
+        st.close();
+    }
+
+    /**
      * Insert the received number of rows into DATA_TABLE via
      * batch processing.
      */
