diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index 837837bece0c69c53576b014048d79aa2a784266..4534845b5272e583fdb8810966cf5649c72ff3b0 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.94 2008/08/14 18:47:58 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.95 2008/08/15 19:20:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -264,36 +264,34 @@ ExecHashJoin(HashJoinState *node)
 					node->hj_NeedNewOuter = true;
 					break;		/* out of loop over hash bucket */
 				}
-				else
+
+				/*
+				 * In a semijoin, we'll consider returning the first match,
+				 * but after that we're done with this outer tuple.
+				 */
+				if (node->js.jointype == JOIN_SEMI)
+					node->hj_NeedNewOuter = true;
+
+				if (otherqual == NIL || ExecQual(otherqual, econtext, false))
 				{
-					/*
-					 * In a semijoin, we'll consider returning the first match,
-					 * but after that we're done with this outer tuple.
-					 */
-					if (node->js.jointype == JOIN_SEMI)
-						node->hj_NeedNewOuter = true;
-
-					if (otherqual == NIL || ExecQual(otherqual, econtext, false))
-					{
-						TupleTableSlot *result;
+					TupleTableSlot *result;
 
-						result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
+					result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
 
-						if (isDone != ExprEndResult)
-						{
-							node->js.ps.ps_TupFromTlist =
-								(isDone == ExprMultipleResult);
-							return result;
-						}
+					if (isDone != ExprEndResult)
+					{
+						node->js.ps.ps_TupFromTlist =
+							(isDone == ExprMultipleResult);
+						return result;
 					}
-
-					/*
-					 * If semijoin and we didn't return the tuple, we're still
-					 * done with this outer tuple.
-					 */
-					if (node->js.jointype == JOIN_SEMI)
-						break;		/* out of loop over hash bucket */
 				}
+
+				/*
+				 * If semijoin and we didn't return the tuple, we're still
+				 * done with this outer tuple.
+				 */
+				if (node->js.jointype == JOIN_SEMI)
+					break;		/* out of loop over hash bucket */
 			}
 		}
 
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index e9deb5c8da7ca01e0ff8457ea2d7252545144797..d460349ad4505a36aec8df35dffed08788091062 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.92 2008/08/14 18:47:58 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.93 2008/08/15 19:20:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -757,15 +757,9 @@ ExecMergeJoin(MergeJoinState *node)
 				innerTupleSlot = node->mj_InnerTupleSlot;
 				econtext->ecxt_innertuple = innerTupleSlot;
 
-				if (node->js.jointype == JOIN_SEMI &&
-					node->mj_MatchedOuter)
-					qualResult = false;
-				else
-				{
-					qualResult = (joinqual == NIL ||
-								  ExecQual(joinqual, econtext, false));
-					MJ_DEBUG_QUAL(joinqual, qualResult);
-				}
+				qualResult = (joinqual == NIL ||
+							  ExecQual(joinqual, econtext, false));
+				MJ_DEBUG_QUAL(joinqual, qualResult);
 
 				if (qualResult)
 				{
@@ -774,7 +768,17 @@ ExecMergeJoin(MergeJoinState *node)
 
 					/* In an antijoin, we never return a matched tuple */
 					if (node->js.jointype == JOIN_ANTI)
+					{
+						node->mj_JoinState = EXEC_MJ_NEXTOUTER;
 						break;
+					}
+
+					/*
+					 * In a semijoin, we'll consider returning the first match,
+					 * but after that we're done with this outer tuple.
+					 */
+					if (node->js.jointype == JOIN_SEMI)
+						node->mj_JoinState = EXEC_MJ_NEXTOUTER;
 
 					qualResult = (otherqual == NIL ||
 								  ExecQual(otherqual, econtext, false));
diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c
index c6a33228582c24e138a7b2e534b3fa853fa29524..27e3582649ec7382e6d1466faab5f48b2b644c02 100644
--- a/src/backend/executor/nodeNestloop.c
+++ b/src/backend/executor/nodeNestloop.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/nodeNestloop.c,v 1.47 2008/08/14 18:47:58 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/nodeNestloop.c,v 1.48 2008/08/15 19:20:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -226,35 +226,36 @@ ExecNestLoop(NestLoopState *node)
 
 			/* In an antijoin, we never return a matched tuple */
 			if (node->js.jointype == JOIN_ANTI)
+			{
 				node->nl_NeedNewOuter = true;
-			else
+				continue;		/* return to top of loop */
+			}
+
+			/*
+			 * In a semijoin, we'll consider returning the first match,
+			 * but after that we're done with this outer tuple.
+			 */
+			if (node->js.jointype == JOIN_SEMI)
+				node->nl_NeedNewOuter = true;
+
+			if (otherqual == NIL || ExecQual(otherqual, econtext, false))
 			{
 				/*
-				 * In a semijoin, we'll consider returning the first match,
-				 * but after that we're done with this outer tuple.
+				 * qualification was satisfied so we project and return the
+				 * slot containing the result tuple using ExecProject().
 				 */
-				if (node->js.jointype == JOIN_SEMI)
-					node->nl_NeedNewOuter = true;
-				if (otherqual == NIL || ExecQual(otherqual, econtext, false))
-				{
-					/*
-					 * qualification was satisfied so we project and return
-					 * the slot containing the result tuple using
-					 * ExecProject().
-					 */
-					TupleTableSlot *result;
-					ExprDoneCond isDone;
+				TupleTableSlot *result;
+				ExprDoneCond isDone;
 
-					ENL1_printf("qualification succeeded, projecting tuple");
+				ENL1_printf("qualification succeeded, projecting tuple");
 
-					result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
+				result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
 
-					if (isDone != ExprEndResult)
-					{
-						node->js.ps.ps_TupFromTlist =
-							(isDone == ExprMultipleResult);
-						return result;
-					}
+				if (isDone != ExprEndResult)
+				{
+					node->js.ps.ps_TupFromTlist =
+						(isDone == ExprMultipleResult);
+					return result;
 				}
 			}
 		}