diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c
index 171724983dc223e70255f92467f4bcc09857d4d6..0a1d1d1559f8267bfb99c473f98b7d490675275c 100644
--- a/src/backend/optimizer/plan/planmain.c
+++ b/src/backend/optimizer/plan/planmain.c
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.111 2008/10/21 20:42:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.112 2008/10/22 20:17:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -133,7 +133,7 @@ query_planner(PlannerInfo *root, List *tlist,
 	 * for "simple" rels.
 	 *
 	 * NOTE: append_rel_list was set up by subquery_planner, so do not touch
-	 * here; ditto placeholder_list; eq_classes may contain data already, too.
+	 * here; eq_classes may contain data already, too.
 	 */
 	root->simple_rel_array_size = list_length(parse->rtable) + 1;
 	root->simple_rel_array = (RelOptInfo **)
@@ -145,6 +145,7 @@ query_planner(PlannerInfo *root, List *tlist,
 	root->right_join_clauses = NIL;
 	root->full_join_clauses = NIL;
 	root->join_info_list = NIL;
+	root->placeholder_list = NIL;
 	root->initial_rels = NIL;
 
 	/*
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 05de001a8775ab1084722c09167fb56fe56f35e1..467ff39a31be17f90acdce2a3cc368fb49976938 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.245 2008/10/21 20:42:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.246 2008/10/22 20:17:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -55,7 +55,7 @@ planner_hook_type planner_hook = NULL;
 #define EXPRKIND_RTFUNC		2
 #define EXPRKIND_VALUES		3
 #define EXPRKIND_LIMIT		4
-#define EXPRKIND_AUXINFO	5
+#define EXPRKIND_APPINFO	5
 
 
 static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
@@ -274,7 +274,6 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
 	root->cte_plan_ids = NIL;
 	root->eq_classes = NIL;
 	root->append_rel_list = NIL;
-	root->placeholder_list = NIL;
 
 	root->hasRecursion = hasRecursion;
 	if (hasRecursion)
@@ -380,10 +379,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
 
 	root->append_rel_list = (List *)
 		preprocess_expression(root, (Node *) root->append_rel_list,
-							  EXPRKIND_AUXINFO);
-	root->placeholder_list = (List *)
-		preprocess_expression(root, (Node *) root->placeholder_list,
-							  EXPRKIND_AUXINFO);
+							  EXPRKIND_APPINFO);
 
 	/* Also need to preprocess expressions for function and values RTEs */
 	foreach(l, parse->rtable)
@@ -664,11 +660,10 @@ inheritance_planner(PlannerInfo *root)
 		subroot.returningLists = NIL;
 		subroot.init_plans = NIL;
 		/* We needn't modify the child's append_rel_list */
-		subroot.placeholder_list = (List *)
-			adjust_appendrel_attrs((Node *) root->placeholder_list,
-								   appinfo);
 		/* There shouldn't be any OJ info to translate, as yet */
 		Assert(subroot.join_info_list == NIL);
+		/* and we haven't created PlaceHolderInfos, either */
+		Assert(subroot.placeholder_list == NIL);
 
 		/* Generate plan */
 		subplan = grouping_planner(&subroot, 0.0 /* retrieve all tuples */ );
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 45de509619874b518b8b6c624d752ab1b48efb81..b15a0e5dd4000f1faff2398bc6fd8806dd7caffc 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -16,7 +16,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.57 2008/10/21 20:42:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.58 2008/10/22 20:17:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -565,7 +565,6 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
 	subroot->cte_plan_ids = NIL;
 	subroot->eq_classes = NIL;
 	subroot->append_rel_list = NIL;
-	subroot->placeholder_list = NIL;
 	subroot->hasRecursion = false;
 	subroot->wt_param_id = -1;
 	subroot->non_recursive_plan = NULL;
@@ -627,12 +626,11 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
 	/*
 	 * Adjust level-0 varnos in subquery so that we can append its rangetable
 	 * to upper query's.  We have to fix the subquery's append_rel_list
-	 * and placeholder_list as well.
+	 * as well.
 	 */
 	rtoffset = list_length(parse->rtable);
 	OffsetVarNodes((Node *) subquery, rtoffset, 0);
 	OffsetVarNodes((Node *) subroot->append_rel_list, rtoffset, 0);
-	OffsetVarNodes((Node *) subroot->placeholder_list, rtoffset, 0);
 
 	/*
 	 * Upper-level vars in subquery are now one level closer to their parent
@@ -640,7 +638,6 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
 	 */
 	IncrementVarSublevelsUp((Node *) subquery, -1, 1);
 	IncrementVarSublevelsUp((Node *) subroot->append_rel_list, -1, 1);
-	IncrementVarSublevelsUp((Node *) subroot->placeholder_list, -1, 1);
 
 	/*
 	 * The subquery's targetlist items are now in the appropriate form to
@@ -706,48 +703,42 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
 	parse->rowMarks = list_concat(parse->rowMarks, subquery->rowMarks);
 
 	/*
-	 * We also have to fix the relid sets of any FlattenedSubLink,
-	 * PlaceHolderVar, and PlaceHolderInfo nodes in the parent query.
-	 * (This could perhaps be done by ResolveNew, but it would clutter that
-	 * routine's API unreasonably.)  Note in particular that any placeholder
-	 * nodes just created by insert_targetlist_placeholders() wiil be adjusted.
+	 * We also have to fix the relid sets of any FlattenedSubLink and
+	 * PlaceHolderVar nodes in the parent query.  (This could perhaps be done
+	 * by ResolveNew, but it would clutter that routine's API unreasonably.)
+	 * Note in particular that any PlaceHolderVar nodes just created by
+	 * insert_targetlist_placeholders() will be adjusted, so having created
+	 * them with the subquery's varno is correct.
 	 *
 	 * Likewise, relids appearing in AppendRelInfo nodes have to be fixed (but
 	 * we took care of their translated_vars lists above).	We already checked
 	 * that this won't require introducing multiple subrelids into the
 	 * single-slot AppendRelInfo structs.
 	 */
-	if (parse->hasSubLinks || root->placeholder_list || root->append_rel_list)
+	if (parse->hasSubLinks || root->glob->lastPHId != 0 ||
+		root->append_rel_list)
 	{
 		Relids		subrelids;
 
 		subrelids = get_relids_in_jointree((Node *) subquery->jointree, false);
-		substitute_multiple_relids((Node *) parse,
-								   varno, subrelids);
-		substitute_multiple_relids((Node *) root->placeholder_list,
-								   varno, subrelids);
-		fix_append_rel_relids(root->append_rel_list,
-							  varno, subrelids);
+		substitute_multiple_relids((Node *) parse, varno, subrelids);
+		fix_append_rel_relids(root->append_rel_list, varno, subrelids);
 	}
 
 	/*
-	 * And now add subquery's AppendRelInfos and PlaceHolderInfos to our lists.
-	 * Note that any placeholders pulled up from the subquery will appear
-	 * after any we just created; this preserves the property that placeholders
-	 * can only refer to other placeholders that appear later in the list
-	 * (needed by fix_placeholder_eval_levels).
+	 * And now add subquery's AppendRelInfos to our list.
 	 */
 	root->append_rel_list = list_concat(root->append_rel_list,
 										subroot->append_rel_list);
-	root->placeholder_list = list_concat(root->placeholder_list,
-										 subroot->placeholder_list);
 
 	/*
 	 * We don't have to do the equivalent bookkeeping for outer-join info,
-	 * because that hasn't been set up yet.
+	 * because that hasn't been set up yet.  placeholder_list likewise.
 	 */
 	Assert(root->join_info_list == NIL);
 	Assert(subroot->join_info_list == NIL);
+	Assert(root->placeholder_list == NIL);
+	Assert(subroot->placeholder_list == NIL);
 
 	/*
 	 * Miscellaneous housekeeping.
@@ -1606,10 +1597,10 @@ reduce_outer_joins_pass2(Node *jtnode,
  * substitute_multiple_relids - adjust node relid sets after pulling up
  * a subquery
  *
- * Find any FlattenedSubLink, PlaceHolderVar, or PlaceHolderInfo nodes in the
- * given tree that reference the pulled-up relid, and change them to reference
- * the replacement relid(s).  We do not need to recurse into subqueries, since
- * no subquery of the current top query could (yet) contain such a reference.
+ * Find any FlattenedSubLink or PlaceHolderVar nodes in the given tree that
+ * reference the pulled-up relid, and change them to reference the replacement
+ * relid(s).  We do not need to recurse into subqueries, since no subquery of
+ * the current top query could (yet) contain such a reference.
  *
  * NOTE: although this has the form of a walker, we cheat and modify the
  * nodes in-place.  This should be OK since the tree was copied by ResolveNew
@@ -1662,26 +1653,11 @@ substitute_multiple_relids_walker(Node *node,
 		}
 		/* fall through to examine children */
 	}
-	if (IsA(node, PlaceHolderInfo))
-	{
-		PlaceHolderInfo *phinfo = (PlaceHolderInfo *) node;
+	/* Shouldn't need to handle planner auxiliary nodes here */
+	Assert(!IsA(node, SpecialJoinInfo));
+	Assert(!IsA(node, AppendRelInfo));
+	Assert(!IsA(node, PlaceHolderInfo));
 
-		if (bms_is_member(context->varno, phinfo->ph_eval_at))
-		{
-			phinfo->ph_eval_at = bms_union(phinfo->ph_eval_at,
-										   context->subrelids);
-			phinfo->ph_eval_at = bms_del_member(phinfo->ph_eval_at,
-												context->varno);
-		}
-		if (bms_is_member(context->varno, phinfo->ph_needed))
-		{
-			phinfo->ph_needed = bms_union(phinfo->ph_needed,
-										  context->subrelids);
-			phinfo->ph_needed = bms_del_member(phinfo->ph_needed,
-											   context->varno);
-		}
-		/* fall through to examine children */
-	}
 	return expression_tree_walker(node, substitute_multiple_relids_walker,
 								  (void *) context);
 }
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 0efd150f6bf096730a50587294bd3766958fe12c..dd7f2f28e0adfdc32b6d3b0c9fd9f054a5528ed3 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -22,7 +22,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.159 2008/10/21 20:42:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.160 2008/10/22 20:17:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1599,26 +1599,10 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
 										   context->child_relid);
 		return (Node *) phv;
 	}
-	if (IsA(node, PlaceHolderInfo))
-	{
-		/* Copy the PlaceHolderInfo node with correct mutation of subnodes */
-		PlaceHolderInfo *phinfo;
-
-		phinfo = (PlaceHolderInfo *) expression_tree_mutator(node,
-											  adjust_appendrel_attrs_mutator,
-															 (void *) context);
-		/* now fix PlaceHolderInfo's relid sets */
-		phinfo->ph_eval_at = adjust_relid_set(phinfo->ph_eval_at,
-											  context->parent_relid,
-											  context->child_relid);
-		phinfo->ph_needed = adjust_relid_set(phinfo->ph_needed,
-											 context->parent_relid,
-											 context->child_relid);
-		return (Node *) phinfo;
-	}
-	/* Shouldn't need to handle other planner auxiliary nodes here */
+	/* Shouldn't need to handle planner auxiliary nodes here */
 	Assert(!IsA(node, SpecialJoinInfo));
 	Assert(!IsA(node, AppendRelInfo));
+	Assert(!IsA(node, PlaceHolderInfo));
 
 	/*
 	 * We have to process RestrictInfo nodes specially.
diff --git a/src/backend/optimizer/util/placeholder.c b/src/backend/optimizer/util/placeholder.c
index aef212b3604ae589664e5c7373e28e1d5603ced1..3e2feea1cbf952b300ecf3edc48b834d8c0188ab 100644
--- a/src/backend/optimizer/util/placeholder.c
+++ b/src/backend/optimizer/util/placeholder.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/util/placeholder.c,v 1.1 2008/10/21 20:42:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/util/placeholder.c,v 1.2 2008/10/22 20:17:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,8 +25,7 @@
 
 /*
  * make_placeholder_expr
- *		Make a PlaceHolderVar (and corresponding PlaceHolderInfo)
- *		for the given expression.
+ *		Make a PlaceHolderVar for the given expression.
  *
  * phrels is the syntactic location (as a set of baserels) to attribute
  * to the expression.
@@ -35,34 +34,25 @@ PlaceHolderVar *
 make_placeholder_expr(PlannerInfo *root, Expr *expr, Relids phrels)
 {
 	PlaceHolderVar *phv = makeNode(PlaceHolderVar);
-	PlaceHolderInfo *phinfo = makeNode(PlaceHolderInfo);
 
 	phv->phexpr = expr;
 	phv->phrels = phrels;
 	phv->phid = ++(root->glob->lastPHId);
 	phv->phlevelsup = 0;
 
-	phinfo->phid = phv->phid;
-	phinfo->ph_var = copyObject(phv);
-	phinfo->ph_eval_at = pull_varnos((Node *) phv);
-	/* ph_eval_at may change later, see fix_placeholder_eval_levels */
-	phinfo->ph_needed = NULL;		/* initially it's unused */
-	/* for the moment, estimate width using just the datatype info */
-	phinfo->ph_width = get_typavgwidth(exprType((Node *) expr),
-									   exprTypmod((Node *) expr));
-
-	root->placeholder_list = lappend(root->placeholder_list, phinfo);
-
 	return phv;
 }
 
 /*
  * find_placeholder_info
- *		Fetch the PlaceHolderInfo for the given PHV; error if not found
+ *		Fetch the PlaceHolderInfo for the given PHV; create it if not found
+ *
+ * Note: this should only be called after query_planner() has started.
  */
 PlaceHolderInfo *
 find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv)
 {
+	PlaceHolderInfo *phinfo;
 	ListCell   *lc;
 
 	/* if this ever isn't true, we'd need to be able to look in parent lists */
@@ -70,20 +60,33 @@ find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv)
 
 	foreach(lc, root->placeholder_list)
 	{
-		PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
-
+		phinfo = (PlaceHolderInfo *) lfirst(lc);
 		if (phinfo->phid == phv->phid)
 			return phinfo;
 	}
-	elog(ERROR, "could not find PlaceHolderInfo with id %u", phv->phid);
-	return NULL;				/* keep compiler quiet */
+
+	/* Not found, so create it */
+	phinfo = makeNode(PlaceHolderInfo);
+
+	phinfo->phid = phv->phid;
+	phinfo->ph_var = copyObject(phv);
+	phinfo->ph_eval_at = pull_varnos((Node *) phv);
+	/* ph_eval_at may change later, see fix_placeholder_eval_levels */
+	phinfo->ph_needed = NULL;		/* initially it's unused */
+	/* for the moment, estimate width using just the datatype info */
+	phinfo->ph_width = get_typavgwidth(exprType((Node *) phv->phexpr),
+									   exprTypmod((Node *) phv->phexpr));
+
+	root->placeholder_list = lappend(root->placeholder_list, phinfo);
+
+	return phinfo;
 }
 
 /*
  * fix_placeholder_eval_levels
  *		Adjust the target evaluation levels for placeholders
  *
- * The initial eval_at level set by make_placeholder_expr was the set of
+ * The initial eval_at level set by find_placeholder_info was the set of
  * rels used in the placeholder's expression (or the whole subselect if
  * the expr is variable-free).  If the subselect contains any outer joins
  * that can null any of those rels, we must delay evaluation to above those
@@ -103,19 +106,9 @@ fix_placeholder_eval_levels(PlannerInfo *root)
 		PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc1);
 		Relids		syn_level = phinfo->ph_var->phrels;
 		Relids		eval_at = phinfo->ph_eval_at;
-		BMS_Membership eval_membership;
 		bool		found_some;
 		ListCell   *lc2;
 
-		/*
-		 * Ignore unreferenced placeholders.  Note: if a placeholder is
-		 * referenced only by some other placeholder's expr, we will do
-		 * the right things because the referencing placeholder must appear
-		 * earlier in the list.
-		 */
-		if (bms_is_empty(phinfo->ph_needed))
-			continue;
-
 		/*
 		 * Check for delays due to lower outer joins.  This is the same logic
 		 * as in check_outerjoin_delay in initsplan.c, except that we don't
@@ -160,11 +153,13 @@ fix_placeholder_eval_levels(PlannerInfo *root)
 		/*
 		 * Now that we know where to evaluate the placeholder, make sure that
 		 * any vars or placeholders it uses will be available at that join
-		 * level.  (Note that this has to be done within this loop to make
-		 * sure we don't skip over such placeholders when we get to them.)
+		 * level.  NOTE: this could cause more PlaceHolderInfos to be added
+		 * to placeholder_list.  That is okay because we'll process them
+		 * before falling out of the foreach loop.  Also, it could cause
+		 * the ph_needed sets of existing list entries to expand, which
+		 * is also okay because this loop doesn't examine those.
 		 */
-		eval_membership = bms_membership(eval_at);
-		if (eval_membership == BMS_MULTIPLE)
+		if (bms_membership(eval_at) == BMS_MULTIPLE)
 		{
 			List	   *vars = pull_var_clause((Node *) phinfo->ph_var->phexpr,
 											   true);
@@ -172,14 +167,22 @@ fix_placeholder_eval_levels(PlannerInfo *root)
 			add_vars_to_targetlist(root, vars, eval_at);
 			list_free(vars);
 		}
+	}
 
-		/*
-		 * Also, if the placeholder can be computed at a base rel and is
-		 * needed above it, add it to that rel's targetlist.  (This is
-		 * essentially the same logic as in add_placeholders_to_joinrel, but
-		 * we can't do that part until joinrels are formed.)
-		 */
-		if (eval_membership == BMS_SINGLETON)
+	/*
+	 * Now, if any placeholder can be computed at a base rel and is needed
+	 * above it, add it to that rel's targetlist.  (This is essentially the
+	 * same logic as in add_placeholders_to_joinrel, but we can't do that part
+	 * until joinrels are formed.)  We have to do this as a separate step
+	 * because the ph_needed values aren't stable until the previous loop
+	 * finishes.
+	 */
+	foreach(lc1, root->placeholder_list)
+	{
+		PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc1);
+		Relids		eval_at = phinfo->ph_eval_at;
+
+		if (bms_membership(eval_at) == BMS_SINGLETON)
 		{
 			int			varno = bms_singleton_member(eval_at);
 			RelOptInfo *rel = find_base_rel(root, varno);
diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c
index 31749e46c0536e09b4cabca13a166eae6354a035..235e465d18f471ac086f1400789066947cd52f0f 100644
--- a/src/backend/optimizer/util/var.c
+++ b/src/backend/optimizer/util/var.c
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.81 2008/10/21 20:42:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.82 2008/10/22 20:17:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -800,24 +800,6 @@ flatten_join_alias_vars_mutator(Node *node,
 		}
 		return (Node *) phv;
 	}
-	if (IsA(node, PlaceHolderInfo))
-	{
-		/* Copy the PlaceHolderInfo node with correct mutation of subnodes */
-		PlaceHolderInfo *phinfo;
-
-		phinfo = (PlaceHolderInfo *) expression_tree_mutator(node,
-											 flatten_join_alias_vars_mutator,
-															 (void *) context);
-		/* now fix PlaceHolderInfo's relid sets */
-		if (context->sublevels_up == 0)
-		{
-			phinfo->ph_eval_at = alias_relid_set(context->root,
-												 phinfo->ph_eval_at);
-			phinfo->ph_needed = alias_relid_set(context->root,
-												phinfo->ph_needed);
-		}
-		return (Node *) phinfo;
-	}
 
 	if (IsA(node, Query))
 	{
@@ -834,6 +816,9 @@ flatten_join_alias_vars_mutator(Node *node,
 	}
 	/* Already-planned tree not supported */
 	Assert(!IsA(node, SubPlan));
+	/* Shouldn't need to handle these planner auxiliary nodes here */
+	Assert(!IsA(node, SpecialJoinInfo));
+	Assert(!IsA(node, PlaceHolderInfo));
 
 	return expression_tree_mutator(node, flatten_join_alias_vars_mutator,
 								   (void *) context);
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index 8ab486bfc2dc04bee9f7e56bb0b2adf572cd0fcc..0322c58f3f02a687f40394f9d477f63976832012 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.116 2008/10/21 20:42:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.117 2008/10/22 20:17:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -298,19 +298,10 @@ OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context)
 		}
 		/* fall through to examine children */
 	}
-	if (IsA(node, PlaceHolderInfo))
-	{
-		PlaceHolderInfo *phinfo = (PlaceHolderInfo *) node;
+	/* Shouldn't need to handle other planner auxiliary nodes here */
+	Assert(!IsA(node, SpecialJoinInfo));
+	Assert(!IsA(node, PlaceHolderInfo));
 
-		if (context->sublevels_up == 0)
-		{
-			phinfo->ph_eval_at = offset_relid_set(phinfo->ph_eval_at,
-												  context->offset);
-			phinfo->ph_needed = offset_relid_set(phinfo->ph_needed,
-												 context->offset);
-		}
-		/* fall through to examine children */
-	}
 	if (IsA(node, Query))
 	{
 		/* Recurse into subselects */
@@ -489,21 +480,10 @@ ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context)
 		}
 		/* fall through to examine children */
 	}
-	if (IsA(node, PlaceHolderInfo))
-	{
-		PlaceHolderInfo *phinfo = (PlaceHolderInfo *) node;
+	/* Shouldn't need to handle other planner auxiliary nodes here */
+	Assert(!IsA(node, SpecialJoinInfo));
+	Assert(!IsA(node, PlaceHolderInfo));
 
-		if (context->sublevels_up == 0)
-		{
-			phinfo->ph_eval_at = adjust_relid_set(phinfo->ph_eval_at,
-												  context->rt_index,
-												  context->new_index);
-			phinfo->ph_needed = adjust_relid_set(phinfo->ph_needed,
-												 context->rt_index,
-												 context->new_index);
-		}
-		/* fall through to examine children */
-	}
 	if (IsA(node, Query))
 	{
 		/* Recurse into subselects */
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index b5eb00a7a67ec7d5ca599aae1de7b8d434d05ba7..4ce13f808a29e108de8fa8a6ee7c0781643b47f2 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.162 2008/10/21 20:42:53 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.163 2008/10/22 20:17:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1290,6 +1290,9 @@ typedef struct AppendRelInfo
  * The idea is to evaluate the expression at (only) the ph_eval_at join level,
  * then allow it to bubble up like a Var until the ph_needed join level.
  * ph_needed has the same definition as attr_needed for a regular Var.
+ *
+ * We create a PlaceHolderInfo only after determining that the PlaceHolderVar
+ * is actually referenced in the plan tree.
  */
 
 typedef struct PlaceHolderInfo