Index: java/engine/org/apache/derby/impl/sql/compile/SelectNode.java
===================================================================
--- java/engine/org/apache/derby/impl/sql/compile/SelectNode.java	(revision 633833)
+++ java/engine/org/apache/derby/impl/sql/compile/SelectNode.java	(working copy)
@@ -591,7 +591,18 @@
 	public void bindTargetExpressions(FromList fromListParam)
 					throws StandardException
 	{
-		bindTargetListOnly = true;
+		/*
+		 * With a FromSubquery in the FromList we cannot bind target expressions 
+		 * at this level (DERBY-3321)
+		 */
+		CollectNodesVisitor cnv = new CollectNodesVisitor(FromSubquery.class, 
+														  FromSubquery.class);
+		fromList.accept(cnv);
+		if (!cnv.getList().isEmpty()){		
+			bindTargetListOnly = false;
+		} else {
+			bindTargetListOnly = true;				
+		}		
 		bindExpressions(fromListParam);
 		bindTargetListOnly = false;
 	}
Index: java/testing/org/apache/derbyTesting/functionTests/tests/lang/NestedWhereSubqueryTest.java
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/tests/lang/NestedWhereSubqueryTest.java	(revision 633833)
+++ java/testing/org/apache/derbyTesting/functionTests/tests/lang/NestedWhereSubqueryTest.java	(working copy)
@@ -356,6 +356,33 @@
 		JDBC.assertUnorderedResultSet(rs, expectedRows);
 		
 		/*
+		 * DERBY-3321 revealed an NPE with a subquery in the [NOT] EXIST subuery FromList.
+		 */
+		s.executeUpdate("create table a (aa int, bb int)");
+		s.executeUpdate("create table b (bb int)");
+		s.executeUpdate("insert into a values (1,1),(1,2),(2,2)");
+		s.executeUpdate("insert into b values (1)");
+		
+		/* NOT EXISTS */
+		sb = new StringBuffer();
+		sb.append("select * from a ");
+		sb.append("where not exists ");
+		sb.append("(select bb from (select bb from b) p where a.bb=p.bb)");
+		rs = s.executeQuery(sb.toString());
+		expectedRows = new String [][] {{"1","2"},		
+										{"2","2"}};
+		JDBC.assertUnorderedResultSet(rs, expectedRows);		
+		
+		/* EXISTS */
+		sb = new StringBuffer();
+		sb.append("select * from a ");
+		sb.append("where exists ");
+		sb.append("(select bb from (select bb from b) p where a.bb=p.bb)");
+		rs = s.executeQuery(sb.toString());
+		expectedRows = new String [][] {{"1","1"}};										
+		JDBC.assertUnorderedResultSet(rs, expectedRows);	
+		
+		/*
 		 * Clean up the tables used.
 		 */				
 		s.executeUpdate("drop table project_employees");	
@@ -363,6 +390,9 @@
 		s.executeUpdate("drop table employees");
 		s.executeUpdate("drop table departments");			
 		
+		s.executeUpdate("drop table a");	
+		s.executeUpdate("drop table b");	
+		
 		s.close();
 	}
 
