Index: java/engine/org/apache/derby/impl/sql/compile/SelectNode.java
===================================================================
--- java/engine/org/apache/derby/impl/sql/compile/SelectNode.java	(revision 614447)
+++ java/engine/org/apache/derby/impl/sql/compile/SelectNode.java	(working copy)
@@ -868,6 +868,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 
+			// WHERE EXISTS subqueries.
+			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 614447)
+++ 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
@@ -614,9 +617,11 @@
          *  o It is not a subquery in a having clause (DERBY-3257)
 		 *  o It is an expression subquery on the right side
 		 *	  of a BinaryComparisonOperatorNode.
+		 *  o It is not a nested WHERE EXISTS subquery in a WHERE EXISTS clause (DERBY-3301)
 		 */
 		flattenable = (resultSet instanceof RowResultSetNode) &&
 					  underTopAndNode && !havingSubquery &&
+					  !hasNestedWhereExistsClause() &&
 					  parentComparisonOperator instanceof BinaryComparisonOperatorNode;
 		if (flattenable)
 		{
@@ -677,11 +682,13 @@
 		 *
 		 *	OR,
 		 *  o The subquery is NOT EXISTS, NOT IN, ALL (beetle 5173).
+		 *  o Is not a nested WHERE EXISTS subquery in a WHERE EXISTS clause (DERBY-3301)
 		 */
 		boolean flattenableNotExists = (isNOT_EXISTS() || canAllBeFlattened());
 
 		flattenable = (resultSet instanceof SelectNode) &&
 					  underTopAndNode && !havingSubquery &&
+					  !hasNestedWhereExistsClause() &&
 					  (isIN() || isANY() || isEXISTS() || flattenableNotExists ||
                        parentComparisonOperator != null);
 
@@ -2310,4 +2317,64 @@
     public void setHavingSubquery(boolean havingSubquery) {
         this.havingSubquery = havingSubquery;
     }
+	
+
+	/**
+	 * 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;
+	}
+
+	/**
+	 * Check whether this subquery is a nested WHERE EXISTS clause
+	 * 
+	 * @return true if this subquery is a nested WHERE EXISTS clause
+	 */
+	public boolean hasNestedWhereExistsClause() {
+		if ( isWhereSubquery() && isEXISTS() ) {						
+			if (resultSet instanceof SelectNode){				
+				SelectNode sn = (SelectNode) resultSet;
+				if (sn.whereSubquerys != null){
+					/* DERBY-3301
+					 * For a WHERE EXISTS subquery with another WHERE EXISTS as its 
+					 * where clause we can flatten only the bottom WHERE EXISTS subquery.
+					 * Flatteing the upper WHERE EXISTS subquery into the parent query 
+					 * may produce the wrong results.
+					 * 
+					 * RESOLVE:
+					 * Make this condition even more specific.
+					 * sn.whereSubquery != null is only the first indication that there 
+					 * is a SubqueryNode here, or once was a SubqueryNode here that now 
+					 * has been flattened into this subquery. Once flattening of the child
+					 * WHERE EXISTS subquery has been performed we drop that SubqueryNode 
+					 * from this.whereSubquerys. This means we cannot peek down from the
+					 * parent WHERE EXISTS subquery to check the child, and there is 
+					 * currently no way to look up from the child either.
+					 * 
+					 * With the current implementation both the child and parent WHERE EXISTS
+					 * subqueries return true.
+					 */
+
+					/* This subquery is the upper WHERE EXISTS subquery with anohter subquery in the where clause. */
+					return true;
+				}			
+			}
+			/* This is a WHERE (EXISTS) subquery, but does not contain a WHERE (EXISTS) subquery */
+			return false;
+		} else {
+			/* This isn't a WHERE EXISTS subquery */
+			return false;
+		}
+	}
 }
Index: java/engine/org/apache/derby/impl/sql/compile/SubqueryList.java
===================================================================
--- java/engine/org/apache/derby/impl/sql/compile/SubqueryList.java	(revision 614447)
+++ java/engine/org/apache/derby/impl/sql/compile/SubqueryList.java	(working copy)
@@ -255,5 +255,20 @@
 	        subqueryNode.setHavingSubquery(true);
 	    }
 	}
+
+	/**
+	 * Mark all of the subqueries in this list as being part of a where clause
+	 * so we can avoid flattening later if needed.
+	 */
+	public void markWhereSubqueries() {
+		int size = size();
+		for (int index = 0; index < size; index++)
+		{
+			SubqueryNode    subqueryNode;
+
+			subqueryNode = (SubqueryNode) elementAt(index);
+			subqueryNode.setWhereSubquery(true);
+		}
+	}
 }
 
