diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 79674ac4b94881a74c2efe343459d07c6f40183d..94ce4446fa27073a2e9b1cf98ee2699de78c9a3e 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -49,7 +49,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.125 2004/02/17 00:52:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.126 2004/04/06 18:46:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -918,23 +918,31 @@ cost_mergejoin(MergePath *path, Query *root)
 	 * all mergejoin paths associated with the merge clause, we cache the
 	 * results in the RestrictInfo node.
 	 */
-	firstclause = (RestrictInfo *) lfirst(mergeclauses);
-	if (firstclause->left_mergescansel < 0)		/* not computed yet? */
-		mergejoinscansel(root, (Node *) firstclause->clause,
-						 &firstclause->left_mergescansel,
-						 &firstclause->right_mergescansel);
-
-	if (bms_is_subset(firstclause->left_relids, outer_path->parent->relids))
+	if (mergeclauses)
 	{
-		/* left side of clause is outer */
-		outerscansel = firstclause->left_mergescansel;
-		innerscansel = firstclause->right_mergescansel;
+		firstclause = (RestrictInfo *) lfirst(mergeclauses);
+		if (firstclause->left_mergescansel < 0)	/* not computed yet? */
+			mergejoinscansel(root, (Node *) firstclause->clause,
+							 &firstclause->left_mergescansel,
+							 &firstclause->right_mergescansel);
+
+		if (bms_is_subset(firstclause->left_relids, outer_path->parent->relids))
+		{
+			/* left side of clause is outer */
+			outerscansel = firstclause->left_mergescansel;
+			innerscansel = firstclause->right_mergescansel;
+		}
+		else
+		{
+			/* left side of clause is inner */
+			outerscansel = firstclause->right_mergescansel;
+			innerscansel = firstclause->left_mergescansel;
+		}
 	}
 	else
 	{
-		/* left side of clause is inner */
-		outerscansel = firstclause->right_mergescansel;
-		innerscansel = firstclause->left_mergescansel;
+		/* cope with clauseless mergejoin */
+		outerscansel = innerscansel = 1.0;
 	}
 
 	/* convert selectivity to row count; must scan at least one row */
diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index 8a666e80d8920dbae0e552e39fe0920d27804d63..ac6838d26e01fa604bed2305999b982f66bb2f11 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.85 2004/01/05 05:07:35 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.86 2004/04/06 18:46:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -489,9 +489,27 @@ match_unsorted_outer(Query *root,
 													  outerpath->pathkeys,
 													  mergeclause_list);
 
-		/* Done with this outer path if no chance for a mergejoin */
+		/*
+		 * Done with this outer path if no chance for a mergejoin.
+		 *
+		 * Special corner case: for "x FULL JOIN y ON true", there will be
+		 * no join clauses at all.  Ordinarily we'd generate a clauseless
+		 * nestloop path, but since mergejoin is our only join type that
+		 * supports FULL JOIN, it's necessary to generate a clauseless
+		 * mergejoin path instead.
+		 *
+		 * Unfortunately this can't easily be extended to handle the case
+		 * where there are joinclauses but none of them use mergejoinable
+		 * operators; nodeMergejoin.c can only do a full join correctly if
+		 * all the joinclauses are mergeclauses.
+		 */
 		if (mergeclauses == NIL)
-			continue;
+		{
+			if (jointype == JOIN_FULL && restrictlist == NIL)
+				/* okay to try for mergejoin */ ;
+			else
+				continue;
+		}
 		if (useallclauses && length(mergeclauses) != length(mergeclause_list))
 			continue;