diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c
index 240c529fa401c7d421664495ad9cd264d2527048..af140d4acb5d8ff0c7bdf8bdfc2279c9848024b3 100644
--- a/src/backend/optimizer/plan/planagg.c
+++ b/src/backend/optimizer/plan/planagg.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.40 2008/07/10 01:17:29 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.41 2008/07/10 02:14:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -486,7 +486,6 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info)
 	 */
 	memcpy(&subroot, root, sizeof(PlannerInfo));
 	subroot.parse = subparse = (Query *) copyObject(root->parse);
-	subroot.init_plans = NIL;
 	subparse->commandType = CMD_SELECT;
 	subparse->resultRelation = 0;
 	subparse->returningList = NIL;
@@ -564,11 +563,9 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info)
 											 -1);
 
 	/*
-	 * Make sure the InitPlan gets into the outer list.  It has to appear
-	 * after any other InitPlans it might depend on, too (see comments in
-	 * ExecReScan).
+	 * Put the updated list of InitPlans back into the outer PlannerInfo.
 	 */
-	root->init_plans = list_concat(root->init_plans, subroot.init_plans);
+	root->init_plans = subroot.init_plans;
 }
 
 /*
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index a6ad9dbdcec3c8b7d40eb8f1f8cbfb156830aa55..9248022d8b352b851c555fc7ffe62d55fa5a6a74 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.233 2008/05/02 21:26:09 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.234 2008/07/10 02:14:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -459,7 +459,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
 	 */
 	if (list_length(glob->subplans) != num_old_subplans ||
 		root->query_level > 1)
-		SS_finalize_plan(root, plan);
+		SS_finalize_plan(root, plan, true);
 
 	/* Return internal info if caller wants it */
 	if (subroot)
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 460b5ad1c761c1a2c49b87e3f839c62701d2dac8..72e951abd05ead554613c12d72eba6295adf045b 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.131 2008/07/10 01:17:29 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.132 2008/07/10 02:14:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1027,11 +1027,12 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context)
  * SS_finalize_plan - do final sublink processing for a completed Plan.
  *
  * This recursively computes the extParam and allParam sets for every Plan
- * node in the given plan tree.  It also attaches any generated InitPlans
- * to the top plan node.
+ * node in the given plan tree.  It also optionally attaches any previously
+ * generated InitPlans to the top plan node.  (Any InitPlans should already
+ * have been put through SS_finalize_plan.)
  */
 void
-SS_finalize_plan(PlannerInfo *root, Plan *plan)
+SS_finalize_plan(PlannerInfo *root, Plan *plan, bool attach_initplans)
 {
 	Bitmapset  *valid_params,
 			   *initExtParam,
@@ -1041,14 +1042,45 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan)
 	ListCell   *l;
 
 	/*
-	 * First, scan the param list to discover the sets of params that are
-	 * available from outer query levels and my own query level. We do this
-	 * once to save time in the per-plan recursion steps.  (This calculation
-	 * is overly generous: it can include a lot of params that actually
-	 * shouldn't be referenced here.  However, valid_params is just used as
-	 * a debugging crosscheck, so it's not worth trying to be exact.)
+	 * Examine any initPlans to determine the set of external params they
+	 * reference, the set of output params they supply, and their total cost.
+	 * We'll use at least some of this info below.  (Note we are assuming that
+	 * finalize_plan doesn't touch the initPlans.)
+	 *
+	 * In the case where attach_initplans is false, we are assuming that the
+	 * existing initPlans are siblings that might supply params needed by the
+	 * current plan.
+	 */
+	initExtParam = initSetParam = NULL;
+	initplan_cost = 0;
+	foreach(l, root->init_plans)
+	{
+		SubPlan    *initsubplan = (SubPlan *) lfirst(l);
+		Plan	   *initplan = planner_subplan_get_plan(root, initsubplan);
+		ListCell   *l2;
+
+		initExtParam = bms_add_members(initExtParam, initplan->extParam);
+		foreach(l2, initsubplan->setParam)
+		{
+			initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
+		}
+		initplan_cost += get_initplan_cost(root, initsubplan);
+	}
+
+	/*
+	 * Now determine the set of params that are validly referenceable in this
+	 * query level; to wit, those available from outer query levels plus the
+	 * output parameters of any initPlans.  (We do not include output
+	 * parameters of regular subplans.  Those should only appear within the
+	 * testexpr of SubPlan nodes, and are taken care of locally within
+	 * finalize_primnode.)
+	 *
+	 * Note: this is a bit overly generous since some parameters of upper
+	 * query levels might belong to query subtrees that don't include this
+	 * query.  However, valid_params is only a debugging crosscheck, so it
+	 * doesn't seem worth expending lots of cycles to try to be exact.
 	 */
-	valid_params = NULL;
+	valid_params = bms_copy(initSetParam);
 	paramid = 0;
 	foreach(l, root->glob->paramlist)
 	{
@@ -1059,12 +1091,6 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan)
 			/* valid outer-level parameter */
 			valid_params = bms_add_member(valid_params, paramid);
 		}
-		else if (pitem->abslevel == root->query_level &&
-				 IsA(pitem->item, Param))
-		{
-			/* valid local parameter (i.e., a setParam of my child) */
-			valid_params = bms_add_member(valid_params, paramid);
-		}
 
 		paramid++;
 	}
@@ -1088,37 +1114,25 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan)
 	 * top node.  This is a conservative overestimate, since in fact each
 	 * initPlan might be executed later than plan startup, or even not at all.
 	 */
-	plan->initPlan = root->init_plans;
-	root->init_plans = NIL;		/* make sure they're not attached twice */
-
-	initExtParam = initSetParam = NULL;
-	initplan_cost = 0;
-	foreach(l, plan->initPlan)
+	if (attach_initplans)
 	{
-		SubPlan    *initsubplan = (SubPlan *) lfirst(l);
-		Plan	   *initplan = planner_subplan_get_plan(root, initsubplan);
-		ListCell   *l2;
-
-		initExtParam = bms_add_members(initExtParam, initplan->extParam);
-		foreach(l2, initsubplan->setParam)
-		{
-			initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
-		}
-		initplan_cost += get_initplan_cost(root, initsubplan);
+		plan->initPlan = root->init_plans;
+		root->init_plans = NIL;		/* make sure they're not attached twice */
+
+		/* allParam must include all these params */
+		plan->allParam = bms_add_members(plan->allParam, initExtParam);
+		plan->allParam = bms_add_members(plan->allParam, initSetParam);
+		/* extParam must include any child extParam */
+		plan->extParam = bms_add_members(plan->extParam, initExtParam);
+		/* but extParam shouldn't include any setParams */
+		plan->extParam = bms_del_members(plan->extParam, initSetParam);
+		/* ensure extParam is exactly NULL if it's empty */
+		if (bms_is_empty(plan->extParam))
+			plan->extParam = NULL;
+
+		plan->startup_cost += initplan_cost;
+		plan->total_cost += initplan_cost;
 	}
-	/* allParam must include all these params */
-	plan->allParam = bms_add_members(plan->allParam, initExtParam);
-	plan->allParam = bms_add_members(plan->allParam, initSetParam);
-	/* extParam must include any child extParam */
-	plan->extParam = bms_add_members(plan->extParam, initExtParam);
-	/* but extParam shouldn't include any setParams */
-	plan->extParam = bms_del_members(plan->extParam, initSetParam);
-	/* ensure extParam is exactly NULL if it's empty */
-	if (bms_is_empty(plan->extParam))
-		plan->extParam = NULL;
-
-	plan->startup_cost += initplan_cost;
-	plan->total_cost += initplan_cost;
 }
 
 /*
@@ -1412,29 +1426,22 @@ Param *
 SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
 						   Oid resulttype, int32 resulttypmod)
 {
-	List	   *saved_init_plans;
 	SubPlan    *node;
 	Param	   *prm;
 
 	/*
 	 * We must run SS_finalize_plan(), since that's normally done before a
-	 * subplan gets put into the initplan list.  However it will try to attach
-	 * any pre-existing initplans to this one, which we don't want (they are
-	 * siblings not children of this initplan).  So, a quick kluge to hide
-	 * them.  (This is something else that could perhaps be cleaner if we did
-	 * extParam/allParam processing in setrefs.c instead of here?  See notes
-	 * for materialize_finished_plan.)
+	 * subplan gets put into the initplan list.  Tell it not to attach any
+	 * pre-existing initplans to this one, since they are siblings not
+	 * children of this initplan.  (This is something else that could perhaps
+	 * be cleaner if we did extParam/allParam processing in setrefs.c instead
+	 * of here?  See notes for materialize_finished_plan.)
 	 */
-	saved_init_plans = root->init_plans;
-	root->init_plans = NIL;
 
 	/*
 	 * Build extParam/allParam sets for plan nodes.
 	 */
-	SS_finalize_plan(root, plan);
-
-	/* Restore outer initplan list */
-	root->init_plans = saved_init_plans;
+	SS_finalize_plan(root, plan, false);
 
 	/*
 	 * Add the subplan and its rtable to the global lists.
@@ -1446,6 +1453,8 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
 
 	/*
 	 * Create a SubPlan node and add it to the outer list of InitPlans.
+	 * Note it has to appear after any other InitPlans it might depend on
+	 * (see comments in ExecReScan).
 	 */
 	node = makeNode(SubPlan);
 	node->subLinkType = EXPR_SUBLINK;
diff --git a/src/include/optimizer/subselect.h b/src/include/optimizer/subselect.h
index 150eaaf002d65f06e610cb8465b8205f0a239319..bb60aac9d4f089301b564761d902fe6410a228d8 100644
--- a/src/include/optimizer/subselect.h
+++ b/src/include/optimizer/subselect.h
@@ -5,7 +5,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.30 2008/01/01 19:45:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.31 2008/07/10 02:14:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,7 +18,8 @@
 extern Node *convert_IN_to_join(PlannerInfo *root, SubLink *sublink);
 extern Node *SS_replace_correlation_vars(PlannerInfo *root, Node *expr);
 extern Node *SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual);
-extern void SS_finalize_plan(PlannerInfo *root, Plan *plan);
+extern void SS_finalize_plan(PlannerInfo *root, Plan *plan,
+							 bool attach_initplans);
 extern Param *SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
 						   Oid resulttype, int32 resulttypmod);