Index: java/engine/org/apache/derby/impl/sql/compile/SelectNode.java
===================================================================
--- java/engine/org/apache/derby/impl/sql/compile/SelectNode.java	(revision 611144)
+++ java/engine/org/apache/derby/impl/sql/compile/SelectNode.java	(working copy)
@@ -865,6 +865,12 @@
 		 */
 		if (whereClause != null)
 		{
+			// DERBY-3301
+			// Mark subqueries that are part of the where clause as such so
+			// that we can avoid flattening later, particularly for nested EXIST 
+			// subqueries in the where clause.
+			if (whereSubquerys != null)
+				whereSubquerys.markWhereSubqueries();
 			whereClause.preprocess(numTables,
 								   fromList, whereSubquerys,
 								   wherePredicates);
Index: java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java
===================================================================
--- java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java	(revision 611144)
+++ java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java	(working copy)
@@ -110,6 +110,9 @@
 	/* Whether or not this subquery began life as a distinct expression subquery */
 	boolean			distinctExpression;
 
+	/* Whether or not this subquery began life as a subquery in a where clause */
+	boolean			whereSubquery;
+	
 	/* Since we do not have separate subquery operator nodes, the
 	 * type of the subquery is stored in the subqueryType field.  Most subquery
 	 * types take a left operand (except for expression and exists).  We could
@@ -607,9 +610,11 @@
 		 *  o It is not under an OR.
 		 *  o It is an expression subquery on the right side
 		 *	  of a BinaryComparisonOperatorNode.
+		 *  o It is not a nested EXIST in a where clause
 		 */
 		flattenable = (resultSet instanceof RowResultSetNode) &&
-					  underTopAndNode &&
+					  underTopAndNode && 
+					  !whereSubquery &&
 					  parentComparisonOperator instanceof BinaryComparisonOperatorNode;
 		if (flattenable)
 		{
@@ -666,7 +671,8 @@
 		 *  o There is a uniqueness condition that ensures
 		 *	  that the flattening of the subquery will not
 		 *	  introduce duplicates into the result set.
-		 *
+		 *  o Is not part of a nested EXIST in a where clause (DERBY-3301)
+		 * 
 		 *	OR,
 		 *  o The subquery is NOT EXISTS, NOT IN, ALL (beetle 5173).
 		 */
@@ -674,6 +680,7 @@
 
 		flattenable = (resultSet instanceof SelectNode) &&
 					  underTopAndNode &&
+					  !whereSubquery &&
 					  (isIN() || isANY() || isEXISTS() || flattenableNotExists ||
                        parentComparisonOperator != null);
 
@@ -2285,4 +2292,22 @@
     {
     	return false;
     }
+
+	/**
+	 * Is this subquery part of a whereclause?
+	 *
+	 * @return true if it is part of a where clause, otherwise false
+	 */
+	public boolean isWhereSubquery() {
+		return whereSubquery;
+	}
+   
+	/**
+	 * Mark this subquery as being part of a where clause.
+	 * @param whereSubquery
+	 */
+	public void setWhereSubquery(boolean whereSubquery) {
+		this.whereSubquery = whereSubquery;
+	}
+
 }
Index: java/engine/org/apache/derby/impl/sql/compile/SubqueryList.java
===================================================================
--- java/engine/org/apache/derby/impl/sql/compile/SubqueryList.java	(revision 611144)
+++ java/engine/org/apache/derby/impl/sql/compile/SubqueryList.java	(working copy)
@@ -237,5 +237,21 @@
 			((SubqueryNode) elementAt(index)).getResultSet().decrementLevel(decrement);
 		}
 	}
+
+	/**
+	 * Mark all of the subqueries in this list as being part of a where clause,
+	 * so we can avoid flattenning later.
+	 */
+	public void markWhereSubqueries() {
+		int size = size();
+
+		for (int index = 0; index < size; index++)
+		{
+			SubqueryNode    subqueryNode;
+
+			subqueryNode = (SubqueryNode) elementAt(index);
+			subqueryNode.setWhereSubquery(true);
+		}
+	}
 }
 
