diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c
index 04cdab9fa1510e6778659002ef752c6ad9003284..7e4d5de38b8c964a50c0827ca1a8e5a96771b875 100644
--- a/src/backend/executor/nodeSubqueryscan.c
+++ b/src/backend/executor/nodeSubqueryscan.c
@@ -99,14 +99,9 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
 	/* check for unsupported flags */
 	Assert(!(eflags & EXEC_FLAG_MARK));
 
-	/*
-	 * SubqueryScan should not have any "normal" children.	Also, if planner
-	 * left anything in subrtable/subrowmark, it's fishy.
-	 */
+	/* SubqueryScan should not have any "normal" children */
 	Assert(outerPlan(node) == NULL);
 	Assert(innerPlan(node) == NULL);
-	Assert(node->subrtable == NIL);
-	Assert(node->subrowmark == NIL);
 
 	/*
 	 * create state structure
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index afc1c61876c42ab21978a9be90bcd2c73b800f91..661a5162e634762eba47e389fa73b0add3bbbb05 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -456,8 +456,6 @@ _copySubqueryScan(SubqueryScan *from)
 	 * copy remainder of node
 	 */
 	COPY_NODE_FIELD(subplan);
-	COPY_NODE_FIELD(subrtable);
-	COPY_NODE_FIELD(subrowmark);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 93ab08a7d77d67c9a6e52df53c3aa4167fd25428..88cde3956c12ff7ad31110ff8ab4188014473c55 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -489,8 +489,6 @@ _outSubqueryScan(StringInfo str, SubqueryScan *node)
 	_outScanInfo(str, (Scan *) node);
 
 	WRITE_NODE_FIELD(subplan);
-	WRITE_NODE_FIELD(subrtable);
-	WRITE_NODE_FIELD(subrowmark);
 }
 
 static void
@@ -1656,8 +1654,7 @@ _outPlannerGlobal(StringInfo str, PlannerGlobal *node)
 	/* NB: this isn't a complete set of fields */
 	WRITE_NODE_FIELD(paramlist);
 	WRITE_NODE_FIELD(subplans);
-	WRITE_NODE_FIELD(subrtables);
-	WRITE_NODE_FIELD(subrowmarks);
+	WRITE_NODE_FIELD(subroots);
 	WRITE_BITMAPSET_FIELD(rewindPlanIDs);
 	WRITE_NODE_FIELD(finalrtable);
 	WRITE_NODE_FIELD(finalrowmarks);
@@ -1734,8 +1731,7 @@ _outRelOptInfo(StringInfo str, RelOptInfo *node)
 	WRITE_UINT_FIELD(pages);
 	WRITE_FLOAT_FIELD(tuples, "%.0f");
 	WRITE_NODE_FIELD(subplan);
-	WRITE_NODE_FIELD(subrtable);
-	WRITE_NODE_FIELD(subrowmark);
+	WRITE_NODE_FIELD(subroot);
 	WRITE_NODE_FIELD(baserestrictinfo);
 	WRITE_NODE_FIELD(joininfo);
 	WRITE_BOOL_FIELD(has_eclass_joins);
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index a14b809a14ca7f95311071429724b4cd4807e309..b42148182876d388de8487080b7c33c7f64ac748 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -791,11 +791,10 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
 									root,
 									false, tuple_fraction,
 									&subroot);
-	rel->subrtable = subroot->parse->rtable;
-	rel->subrowmark = subroot->rowMarks;
+	rel->subroot = subroot;
 
 	/* Mark rel with estimated output rows, width, etc */
-	set_subquery_size_estimates(root, rel, subroot);
+	set_subquery_size_estimates(root, rel);
 
 	/* Convert subquery pathkeys to outer representation */
 	pathkeys = convert_subquery_pathkeys(root, rel, subroot->query_pathkeys);
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index c853bd8dcb6ca6758b6b515abea577712aa07889..7812a8628fc94335aaf1f506c4ea5ebb7960f8d8 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -3221,9 +3221,9 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
  * We set the same fields as set_baserel_size_estimates.
  */
 void
-set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel,
-							PlannerInfo *subroot)
+set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel)
 {
+	PlannerInfo *subroot = rel->subroot;
 	RangeTblEntry *rte;
 	ListCell   *lc;
 
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index a3a82ec123407c9f7182dc54b4d5aad4cf8ee778..b674afe42645719239cf437233574532ba9ad37a 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -1557,9 +1557,7 @@ create_subqueryscan_plan(PlannerInfo *root, Path *best_path,
 	scan_plan = make_subqueryscan(tlist,
 								  scan_clauses,
 								  scan_relid,
-								  best_path->parent->subplan,
-								  best_path->parent->subrtable,
-								  best_path->parent->subrowmark);
+								  best_path->parent->subplan);
 
 	copy_path_costsize(&scan_plan->scan.plan, best_path);
 
@@ -2931,9 +2929,7 @@ SubqueryScan *
 make_subqueryscan(List *qptlist,
 				  List *qpqual,
 				  Index scanrelid,
-				  Plan *subplan,
-				  List *subrtable,
-				  List *subrowmark)
+				  Plan *subplan)
 {
 	SubqueryScan *node = makeNode(SubqueryScan);
 	Plan	   *plan = &node->scan.plan;
@@ -2952,8 +2948,6 @@ make_subqueryscan(List *qptlist,
 	plan->righttree = NULL;
 	node->scan.scanrelid = scanrelid;
 	node->subplan = subplan;
-	node->subrtable = subrtable;
-	node->subrowmark = subrowmark;
 
 	return node;
 }
diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c
index ff39d5754dc989a087102523ca77adca79a89e17..55311058e590937a25f2a3a22727794aa37ceed8 100644
--- a/src/backend/optimizer/plan/planmain.c
+++ b/src/backend/optimizer/plan/planmain.c
@@ -98,7 +98,6 @@ query_planner(PlannerInfo *root, List *tlist,
 	Path	   *cheapestpath;
 	Path	   *sortedpath;
 	Index		rti;
-	ListCell   *lc;
 	double		total_pages;
 
 	/* Make tuple_fraction, limit_tuples accessible to lower-level routines */
@@ -128,15 +127,11 @@ query_planner(PlannerInfo *root, List *tlist,
 	}
 
 	/*
-	 * Init planner lists to empty, and set up the array to hold RelOptInfos
-	 * for "simple" rels.
+	 * Init planner lists to empty.
 	 *
 	 * NOTE: append_rel_list was set up by subquery_planner, so do not touch
 	 * here; eq_classes and minmax_aggs may contain data already, too.
 	 */
-	root->simple_rel_array_size = list_length(parse->rtable) + 1;
-	root->simple_rel_array = (RelOptInfo **)
-		palloc0(root->simple_rel_array_size * sizeof(RelOptInfo *));
 	root->join_rel_list = NIL;
 	root->join_rel_hash = NULL;
 	root->join_rel_level = NULL;
@@ -151,17 +146,10 @@ query_planner(PlannerInfo *root, List *tlist,
 
 	/*
 	 * Make a flattened version of the rangetable for faster access (this is
-	 * OK because the rangetable won't change any more).
+	 * OK because the rangetable won't change any more), and set up an
+	 * empty array for indexing base relations.
 	 */
-	root->simple_rte_array = (RangeTblEntry **)
-		palloc0(root->simple_rel_array_size * sizeof(RangeTblEntry *));
-	rti = 1;
-	foreach(lc, parse->rtable)
-	{
-		RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
-
-		root->simple_rte_array[rti++] = rte;
-	}
+	setup_simple_rel_arrays(root);
 
 	/*
 	 * Construct RelOptInfo nodes for all base relations in query, and
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 484d44108ef0d94d47deede0abd8efb30810e1bf..64b5eb4d9cc3fc50b3238940d9d2e8331086bf0c 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -21,6 +21,9 @@
 #include "executor/nodeAgg.h"
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
+#ifdef OPTIMIZER_DEBUG
+#include "nodes/print.h"
+#endif
 #include "optimizer/clauses.h"
 #include "optimizer/cost.h"
 #include "optimizer/pathnode.h"
@@ -31,11 +34,9 @@
 #include "optimizer/prep.h"
 #include "optimizer/subselect.h"
 #include "optimizer/tlist.h"
-#ifdef OPTIMIZER_DEBUG
-#include "nodes/print.h"
-#endif
 #include "parser/analyze.h"
 #include "parser/parsetree.h"
+#include "rewrite/rewriteManip.h"
 #include "utils/rel.h"
 
 
@@ -135,8 +136,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
 	PlannerInfo *root;
 	Plan	   *top_plan;
 	ListCell   *lp,
-			   *lrt,
-			   *lrm;
+			   *lr;
 
 	/* Cursor options may come from caller or from DECLARE CURSOR stmt */
 	if (parse->utilityStmt &&
@@ -154,8 +154,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
 	glob->boundParams = boundParams;
 	glob->paramlist = NIL;
 	glob->subplans = NIL;
-	glob->subrtables = NIL;
-	glob->subrowmarks = NIL;
+	glob->subroots = NIL;
 	glob->rewindPlanIDs = NULL;
 	glob->finalrtable = NIL;
 	glob->finalrowmarks = NIL;
@@ -212,24 +211,15 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
 	Assert(glob->finalrtable == NIL);
 	Assert(glob->finalrowmarks == NIL);
 	Assert(glob->resultRelations == NIL);
-	top_plan = set_plan_references(glob, top_plan,
-								   root->parse->rtable,
-								   root->rowMarks);
+	top_plan = set_plan_references(root, top_plan);
 	/* ... and the subplans (both regular subplans and initplans) */
-	Assert(list_length(glob->subplans) == list_length(glob->subrtables));
-	Assert(list_length(glob->subplans) == list_length(glob->subrowmarks));
-	lrt = list_head(glob->subrtables);
-	lrm = list_head(glob->subrowmarks);
-	foreach(lp, glob->subplans)
+	Assert(list_length(glob->subplans) == list_length(glob->subroots));
+	forboth(lp, glob->subplans, lr, glob->subroots)
 	{
 		Plan	   *subplan = (Plan *) lfirst(lp);
-		List	   *subrtable = (List *) lfirst(lrt);
-		List	   *subrowmark = (List *) lfirst(lrm);
+		PlannerInfo *subroot = (PlannerInfo *) lfirst(lr);
 
-		lfirst(lp) = set_plan_references(glob, subplan,
-										 subrtable, subrowmark);
-		lrt = lnext(lrt);
-		lrm = lnext(lrm);
+		lfirst(lp) = set_plan_references(subroot, subplan);
 	}
 
 	/* build the PlannedStmt result */
@@ -550,7 +540,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
 				List	   *rlist;
 
 				Assert(parse->resultRelation);
-				rlist = set_returning_clause_references(root->glob,
+				rlist = set_returning_clause_references(root,
 														parse->returningList,
 														plan,
 													  parse->resultRelation);
@@ -735,55 +725,164 @@ inheritance_planner(PlannerInfo *root)
 {
 	Query	   *parse = root->parse;
 	int			parentRTindex = parse->resultRelation;
+	List	   *final_rtable = NIL;
+	int			save_rel_array_size = 0;
+	RelOptInfo **save_rel_array = NULL;
 	List	   *subplans = NIL;
 	List	   *resultRelations = NIL;
 	List	   *returningLists = NIL;
-	List	   *rtable = NIL;
 	List	   *rowMarks;
-	List	   *tlist;
-	PlannerInfo subroot;
-	ListCell   *l;
+	ListCell   *lc;
 
-	foreach(l, root->append_rel_list)
+	/*
+	 * We generate a modified instance of the original Query for each target
+	 * relation, plan that, and put all the plans into a list that will be
+	 * controlled by a single ModifyTable node.  All the instances share the
+	 * same rangetable, but each instance must have its own set of subquery
+	 * RTEs within the finished rangetable because (1) they are likely to get
+	 * scribbled on during planning, and (2) it's not inconceivable that
+	 * subqueries could get planned differently in different cases.  We need
+	 * not create duplicate copies of other RTE kinds, in particular not the
+	 * target relations, because they don't have either of those issues.  Not
+	 * having to duplicate the target relations is important because doing so
+	 * (1) would result in a rangetable of length O(N^2) for N targets, with
+	 * at least O(N^3) work expended here; and (2) would greatly complicate
+	 * management of the rowMarks list.
+	 */
+	foreach(lc, root->append_rel_list)
 	{
-		AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
+		AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
+		PlannerInfo subroot;
 		Plan	   *subplan;
+		Index		rti;
 
 		/* append_rel_list contains all append rels; ignore others */
 		if (appinfo->parent_relid != parentRTindex)
 			continue;
 
 		/*
-		 * Generate modified query with this rel as target.
+		 * We need a working copy of the PlannerInfo so that we can control
+		 * propagation of information back to the main copy.
 		 */
 		memcpy(&subroot, root, sizeof(PlannerInfo));
+
+		/*
+		 * Generate modified query with this rel as target.  We first apply
+		 * adjust_appendrel_attrs, which copies the Query and changes
+		 * references to the parent RTE to refer to the current child RTE,
+		 * then fool around with subquery RTEs.
+		 */
 		subroot.parse = (Query *)
 			adjust_appendrel_attrs((Node *) parse,
 								   appinfo);
-		subroot.init_plans = NIL;
-		subroot.hasInheritedTarget = true;
+
+		/*
+		 * The rowMarks list might contain references to subquery RTEs, so
+		 * make a copy that we can apply ChangeVarNodes to.  (Fortunately,
+		 * the executor doesn't need to see the modified copies --- we can
+		 * just pass it the original rowMarks list.)
+		 */
+		subroot.rowMarks = (List *) copyObject(root->rowMarks);
+
+		/*
+		 * Add placeholders to the child Query's rangetable list to fill the
+		 * RT indexes already reserved for subqueries in previous children.
+		 * These won't be referenced, so there's no need to make them very
+		 * valid-looking.
+		 */
+		while (list_length(subroot.parse->rtable) < list_length(final_rtable))
+			subroot.parse->rtable = lappend(subroot.parse->rtable,
+											makeNode(RangeTblEntry));
+
+		/*
+		 * If this isn't the first child Query, generate duplicates of all
+		 * subquery RTEs, and adjust Var numbering to reference the duplicates.
+		 * To simplify the loop logic, we scan the original rtable not the
+		 * copy just made by adjust_appendrel_attrs; that should be OK since
+		 * subquery RTEs couldn't contain any references to the target rel.
+		 */
+		if (final_rtable != NIL)
+		{
+			ListCell   *lr;
+
+			rti = 1;
+			foreach(lr, parse->rtable)
+			{
+				RangeTblEntry *rte = (RangeTblEntry *) lfirst(lr);
+
+				if (rte->rtekind == RTE_SUBQUERY)
+				{
+					Index	newrti;
+
+					/*
+					 * The RTE can't contain any references to its own RT
+					 * index, so we can save a few cycles by applying
+					 * ChangeVarNodes before we append the RTE to the
+					 * rangetable.
+					 */
+					newrti = list_length(subroot.parse->rtable) + 1;
+					ChangeVarNodes((Node *) subroot.parse, rti, newrti, 0);
+					ChangeVarNodes((Node *) subroot.rowMarks, rti, newrti, 0);
+					rte = copyObject(rte);
+					subroot.parse->rtable = lappend(subroot.parse->rtable,
+													rte);
+				}
+				rti++;
+			}
+		}
+
 		/* We needn't modify the child's append_rel_list */
 		/* 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);
+		/* build a separate list of initplans for each child */
+		subroot.init_plans = NIL;
+		/* hack to mark target relation as an inheritance partition */
+		subroot.hasInheritedTarget = true;
 
 		/* Generate plan */
 		subplan = grouping_planner(&subroot, 0.0 /* retrieve all tuples */ );
 
 		/*
 		 * If this child rel was excluded by constraint exclusion, exclude it
-		 * from the plan.
+		 * from the result plan.
 		 */
 		if (is_dummy_plan(subplan))
 			continue;
 
-		/* Save rtable from first rel for use below */
-		if (subplans == NIL)
-			rtable = subroot.parse->rtable;
-
 		subplans = lappend(subplans, subplan);
 
+		/*
+		 * If this is the first non-excluded child, its post-planning rtable
+		 * becomes the initial contents of final_rtable; otherwise, append
+		 * just its modified subquery RTEs to final_rtable.
+		 */
+		if (final_rtable == NIL)
+			final_rtable = subroot.parse->rtable;
+		else
+			final_rtable = list_concat(final_rtable,
+									   list_copy_tail(subroot.parse->rtable,
+													  list_length(final_rtable)));
+
+		/*
+		 * We need to collect all the RelOptInfos from all child plans into
+		 * the main PlannerInfo, since setrefs.c will need them.  We use the
+		 * last child's simple_rel_array (previous ones are too short), so we
+		 * have to propagate forward the RelOptInfos that were already built
+		 * in previous children.
+		 */
+		Assert(subroot.simple_rel_array_size >= save_rel_array_size);
+		for (rti = 1; rti < save_rel_array_size; rti++)
+		{
+			RelOptInfo *brel = save_rel_array[rti];
+
+			if (brel)
+				subroot.simple_rel_array[rti] = brel;
+		}
+		save_rel_array_size = subroot.simple_rel_array_size;
+		save_rel_array = subroot.simple_rel_array;
+
 		/* Make sure any initplans from this rel get into the outer list */
 		root->init_plans = list_concat(root->init_plans, subroot.init_plans);
 
@@ -795,7 +894,7 @@ inheritance_planner(PlannerInfo *root)
 		{
 			List	   *rlist;
 
-			rlist = set_returning_clause_references(root->glob,
+			rlist = set_returning_clause_references(&subroot,
 												subroot.parse->returningList,
 													subplan,
 													appinfo->child_relid);
@@ -813,6 +912,8 @@ inheritance_planner(PlannerInfo *root)
 	if (subplans == NIL)
 	{
 		/* although dummy, it must have a valid tlist for executor */
+		List	   *tlist;
+
 		tlist = preprocess_targetlist(root, parse->targetList);
 		return (Plan *) make_result(root,
 									tlist,
@@ -822,17 +923,11 @@ inheritance_planner(PlannerInfo *root)
 	}
 
 	/*
-	 * Planning might have modified the rangetable, due to changes of the
-	 * Query structures inside subquery RTEs.  We have to ensure that this
-	 * gets propagated back to the master copy.  But can't do this until we
-	 * are done planning, because all the calls to grouping_planner need
-	 * virgin sub-Queries to work from.  (We are effectively assuming that
-	 * sub-Queries will get planned identically each time, or at least that
-	 * the impacts on their rangetables will be the same each time.)
-	 *
-	 * XXX should clean this up someday
+	 * Put back the final adjusted rtable into the master copy of the Query.
 	 */
-	parse->rtable = rtable;
+	parse->rtable = final_rtable;
+	root->simple_rel_array_size = save_rel_array_size;
+	root->simple_rel_array = save_rel_array;
 
 	/*
 	 * If there was a FOR UPDATE/SHARE clause, the LockRows node will have
@@ -3149,13 +3244,8 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid)
 	rte->inFromCl = true;
 	query->rtable = list_make1(rte);
 
-	/* ... and insert it into PlannerInfo */
-	root->simple_rel_array_size = 2;
-	root->simple_rel_array = (RelOptInfo **)
-		palloc0(root->simple_rel_array_size * sizeof(RelOptInfo *));
-	root->simple_rte_array = (RangeTblEntry **)
-		palloc0(root->simple_rel_array_size * sizeof(RangeTblEntry *));
-	root->simple_rte_array[1] = rte;
+	/* Set up RTE/RelOptInfo arrays */
+	setup_simple_rel_arrays(root);
 
 	/* Build RelOptInfo */
 	rel = build_simple_rel(root, 1, RELOPT_BASEREL);
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 8508d25316c002aebd6227eec0b288df4e90d16e..d60163379b2dd3445145cc1d293eb33450ebe8b7 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -20,6 +20,7 @@
 #include "catalog/pg_type.h"
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
+#include "optimizer/pathnode.h"
 #include "optimizer/planmain.h"
 #include "optimizer/tlist.h"
 #include "utils/lsyscache.h"
@@ -45,13 +46,13 @@ typedef struct
 
 typedef struct
 {
-	PlannerGlobal *glob;
+	PlannerInfo *root;
 	int			rtoffset;
 } fix_scan_expr_context;
 
 typedef struct
 {
-	PlannerGlobal *glob;
+	PlannerInfo *root;
 	indexed_tlist *outer_itlist;
 	indexed_tlist *inner_itlist;
 	Index		acceptable_rel;
@@ -60,7 +61,7 @@ typedef struct
 
 typedef struct
 {
-	PlannerGlobal *glob;
+	PlannerInfo *root;
 	indexed_tlist *subplan_itlist;
 	int			rtoffset;
 } fix_upper_expr_context;
@@ -76,19 +77,19 @@ typedef struct
 	(((con)->consttype == REGCLASSOID || (con)->consttype == OIDOID) && \
 	 !(con)->constisnull)
 
-#define fix_scan_list(glob, lst, rtoffset) \
-	((List *) fix_scan_expr(glob, (Node *) (lst), rtoffset))
+#define fix_scan_list(root, lst, rtoffset) \
+	((List *) fix_scan_expr(root, (Node *) (lst), rtoffset))
 
-static Plan *set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset);
-static Plan *set_subqueryscan_references(PlannerGlobal *glob,
+static Plan *set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset);
+static Plan *set_subqueryscan_references(PlannerInfo *root,
 							SubqueryScan *plan,
 							int rtoffset);
 static bool trivial_subqueryscan(SubqueryScan *plan);
-static Node *fix_scan_expr(PlannerGlobal *glob, Node *node, int rtoffset);
+static Node *fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset);
 static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context);
 static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context);
-static void set_join_references(PlannerGlobal *glob, Join *join, int rtoffset);
-static void set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset);
+static void set_join_references(PlannerInfo *root, Join *join, int rtoffset);
+static void set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset);
 static void set_dummy_tlist_references(Plan *plan, int rtoffset);
 static indexed_tlist *build_tlist_index(List *tlist);
 static Var *search_indexed_tlist_for_var(Var *var,
@@ -102,14 +103,14 @@ static Var *search_indexed_tlist_for_sortgroupref(Node *node,
 									  Index sortgroupref,
 									  indexed_tlist *itlist,
 									  Index newvarno);
-static List *fix_join_expr(PlannerGlobal *glob,
+static List *fix_join_expr(PlannerInfo *root,
 			  List *clauses,
 			  indexed_tlist *outer_itlist,
 			  indexed_tlist *inner_itlist,
 			  Index acceptable_rel, int rtoffset);
 static Node *fix_join_expr_mutator(Node *node,
 					  fix_join_expr_context *context);
-static Node *fix_upper_expr(PlannerGlobal *glob,
+static Node *fix_upper_expr(PlannerInfo *root,
 			   Node *node,
 			   indexed_tlist *subplan_itlist,
 			   int rtoffset);
@@ -117,7 +118,7 @@ static Node *fix_upper_expr_mutator(Node *node,
 					   fix_upper_expr_context *context);
 static bool fix_opfuncids_walker(Node *node, void *context);
 static bool extract_query_dependencies_walker(Node *node,
-								  PlannerGlobal *context);
+								  PlannerInfo *context);
 
 
 /*****************************************************************************
@@ -163,20 +164,14 @@ static bool extract_query_dependencies_walker(Node *node,
  *
  * set_plan_references recursively traverses the whole plan tree.
  *
- * Inputs:
- *	glob: global data for planner run
- *	plan: the topmost node of the plan
- *	rtable: the rangetable for the current subquery
- *	rowmarks: the PlanRowMark list for the current subquery
- *
  * The return value is normally the same Plan node passed in, but can be
  * different when the passed-in Plan is a SubqueryScan we decide isn't needed.
  *
- * The flattened rangetable entries are appended to glob->finalrtable.
- * Also, rowmarks entries are appended to glob->finalrowmarks, and the
- * RT indexes of ModifyTable result relations to glob->resultRelations.
- * Plan dependencies are appended to glob->relationOids (for relations)
- * and glob->invalItems (for everything else).
+ * The flattened rangetable entries are appended to root->glob->finalrtable.
+ * Also, rowmarks entries are appended to root->glob->finalrowmarks, and the
+ * RT indexes of ModifyTable result relations to root->glob->resultRelations.
+ * Plan dependencies are appended to root->glob->relationOids (for relations)
+ * and root->glob->invalItems (for everything else).
  *
  * Notice that we modify Plan nodes in-place, but use expression_tree_mutator
  * to process targetlist and qual expressions.	We can assume that the Plan
@@ -184,9 +179,9 @@ static bool extract_query_dependencies_walker(Node *node,
  * it's not so safe to assume that for expression tree nodes.
  */
 Plan *
-set_plan_references(PlannerGlobal *glob, Plan *plan,
-					List *rtable, List *rowmarks)
+set_plan_references(PlannerInfo *root, Plan *plan)
 {
+	PlannerGlobal *glob = root->glob;
 	int			rtoffset = list_length(glob->finalrtable);
 	ListCell   *lc;
 
@@ -198,7 +193,7 @@ set_plan_references(PlannerGlobal *glob, Plan *plan,
 	 * which are needed for executor-startup permissions checking and for
 	 * trigger event checking.
 	 */
-	foreach(lc, rtable)
+	foreach(lc, root->parse->rtable)
 	{
 		RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
 		RangeTblEntry *newrte;
@@ -242,7 +237,7 @@ set_plan_references(PlannerGlobal *glob, Plan *plan,
 	/*
 	 * Adjust RT indexes of PlanRowMarks and add to final rowmarks list
 	 */
-	foreach(lc, rowmarks)
+	foreach(lc, root->rowMarks)
 	{
 		PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
 		PlanRowMark *newrc;
@@ -261,14 +256,14 @@ set_plan_references(PlannerGlobal *glob, Plan *plan,
 	}
 
 	/* Now fix the Plan tree */
-	return set_plan_refs(glob, plan, rtoffset);
+	return set_plan_refs(root, plan, rtoffset);
 }
 
 /*
  * set_plan_refs: recurse through the Plan nodes of a single subquery level
  */
 static Plan *
-set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
+set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
 {
 	ListCell   *l;
 
@@ -286,9 +281,9 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 
 				splan->scanrelid += rtoffset;
 				splan->plan.targetlist =
-					fix_scan_list(glob, splan->plan.targetlist, rtoffset);
+					fix_scan_list(root, splan->plan.targetlist, rtoffset);
 				splan->plan.qual =
-					fix_scan_list(glob, splan->plan.qual, rtoffset);
+					fix_scan_list(root, splan->plan.qual, rtoffset);
 			}
 			break;
 		case T_IndexScan:
@@ -297,17 +292,17 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 
 				splan->scan.scanrelid += rtoffset;
 				splan->scan.plan.targetlist =
-					fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
+					fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
 				splan->scan.plan.qual =
-					fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
+					fix_scan_list(root, splan->scan.plan.qual, rtoffset);
 				splan->indexqual =
-					fix_scan_list(glob, splan->indexqual, rtoffset);
+					fix_scan_list(root, splan->indexqual, rtoffset);
 				splan->indexqualorig =
-					fix_scan_list(glob, splan->indexqualorig, rtoffset);
+					fix_scan_list(root, splan->indexqualorig, rtoffset);
 				splan->indexorderby =
-					fix_scan_list(glob, splan->indexorderby, rtoffset);
+					fix_scan_list(root, splan->indexorderby, rtoffset);
 				splan->indexorderbyorig =
-					fix_scan_list(glob, splan->indexorderbyorig, rtoffset);
+					fix_scan_list(root, splan->indexorderbyorig, rtoffset);
 			}
 			break;
 		case T_BitmapIndexScan:
@@ -319,9 +314,9 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 				Assert(splan->scan.plan.targetlist == NIL);
 				Assert(splan->scan.plan.qual == NIL);
 				splan->indexqual =
-					fix_scan_list(glob, splan->indexqual, rtoffset);
+					fix_scan_list(root, splan->indexqual, rtoffset);
 				splan->indexqualorig =
-					fix_scan_list(glob, splan->indexqualorig, rtoffset);
+					fix_scan_list(root, splan->indexqualorig, rtoffset);
 			}
 			break;
 		case T_BitmapHeapScan:
@@ -330,11 +325,11 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 
 				splan->scan.scanrelid += rtoffset;
 				splan->scan.plan.targetlist =
-					fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
+					fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
 				splan->scan.plan.qual =
-					fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
+					fix_scan_list(root, splan->scan.plan.qual, rtoffset);
 				splan->bitmapqualorig =
-					fix_scan_list(glob, splan->bitmapqualorig, rtoffset);
+					fix_scan_list(root, splan->bitmapqualorig, rtoffset);
 			}
 			break;
 		case T_TidScan:
@@ -343,16 +338,16 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 
 				splan->scan.scanrelid += rtoffset;
 				splan->scan.plan.targetlist =
-					fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
+					fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
 				splan->scan.plan.qual =
-					fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
+					fix_scan_list(root, splan->scan.plan.qual, rtoffset);
 				splan->tidquals =
-					fix_scan_list(glob, splan->tidquals, rtoffset);
+					fix_scan_list(root, splan->tidquals, rtoffset);
 			}
 			break;
 		case T_SubqueryScan:
 			/* Needs special treatment, see comments below */
-			return set_subqueryscan_references(glob,
+			return set_subqueryscan_references(root,
 											   (SubqueryScan *) plan,
 											   rtoffset);
 		case T_FunctionScan:
@@ -361,11 +356,11 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 
 				splan->scan.scanrelid += rtoffset;
 				splan->scan.plan.targetlist =
-					fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
+					fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
 				splan->scan.plan.qual =
-					fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
+					fix_scan_list(root, splan->scan.plan.qual, rtoffset);
 				splan->funcexpr =
-					fix_scan_expr(glob, splan->funcexpr, rtoffset);
+					fix_scan_expr(root, splan->funcexpr, rtoffset);
 			}
 			break;
 		case T_ValuesScan:
@@ -374,11 +369,11 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 
 				splan->scan.scanrelid += rtoffset;
 				splan->scan.plan.targetlist =
-					fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
+					fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
 				splan->scan.plan.qual =
-					fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
+					fix_scan_list(root, splan->scan.plan.qual, rtoffset);
 				splan->values_lists =
-					fix_scan_list(glob, splan->values_lists, rtoffset);
+					fix_scan_list(root, splan->values_lists, rtoffset);
 			}
 			break;
 		case T_CteScan:
@@ -387,9 +382,9 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 
 				splan->scan.scanrelid += rtoffset;
 				splan->scan.plan.targetlist =
-					fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
+					fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
 				splan->scan.plan.qual =
-					fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
+					fix_scan_list(root, splan->scan.plan.qual, rtoffset);
 			}
 			break;
 		case T_WorkTableScan:
@@ -398,9 +393,9 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 
 				splan->scan.scanrelid += rtoffset;
 				splan->scan.plan.targetlist =
-					fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
+					fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
 				splan->scan.plan.qual =
-					fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
+					fix_scan_list(root, splan->scan.plan.qual, rtoffset);
 			}
 			break;
 		case T_ForeignScan:
@@ -409,16 +404,16 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 
 				splan->scan.scanrelid += rtoffset;
 				splan->scan.plan.targetlist =
-					fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
+					fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
 				splan->scan.plan.qual =
-					fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
+					fix_scan_list(root, splan->scan.plan.qual, rtoffset);
 			}
 			break;
 
 		case T_NestLoop:
 		case T_MergeJoin:
 		case T_HashJoin:
-			set_join_references(glob, (Join *) plan, rtoffset);
+			set_join_references(root, (Join *) plan, rtoffset);
 			break;
 
 		case T_Hash:
@@ -477,20 +472,20 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 				Assert(splan->plan.qual == NIL);
 
 				splan->limitOffset =
-					fix_scan_expr(glob, splan->limitOffset, rtoffset);
+					fix_scan_expr(root, splan->limitOffset, rtoffset);
 				splan->limitCount =
-					fix_scan_expr(glob, splan->limitCount, rtoffset);
+					fix_scan_expr(root, splan->limitCount, rtoffset);
 			}
 			break;
 		case T_Agg:
 		case T_Group:
-			set_upper_references(glob, plan, rtoffset);
+			set_upper_references(root, plan, rtoffset);
 			break;
 		case T_WindowAgg:
 			{
 				WindowAgg  *wplan = (WindowAgg *) plan;
 
-				set_upper_references(glob, plan, rtoffset);
+				set_upper_references(root, plan, rtoffset);
 
 				/*
 				 * Like Limit node limit/offset expressions, WindowAgg has
@@ -498,9 +493,9 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 				 * variable refs, so fix_scan_expr works for them.
 				 */
 				wplan->startOffset =
-					fix_scan_expr(glob, wplan->startOffset, rtoffset);
+					fix_scan_expr(root, wplan->startOffset, rtoffset);
 				wplan->endOffset =
-					fix_scan_expr(glob, wplan->endOffset, rtoffset);
+					fix_scan_expr(root, wplan->endOffset, rtoffset);
 			}
 			break;
 		case T_Result:
@@ -512,17 +507,17 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 				 * like a scan node than an upper node.
 				 */
 				if (splan->plan.lefttree != NULL)
-					set_upper_references(glob, plan, rtoffset);
+					set_upper_references(root, plan, rtoffset);
 				else
 				{
 					splan->plan.targetlist =
-						fix_scan_list(glob, splan->plan.targetlist, rtoffset);
+						fix_scan_list(root, splan->plan.targetlist, rtoffset);
 					splan->plan.qual =
-						fix_scan_list(glob, splan->plan.qual, rtoffset);
+						fix_scan_list(root, splan->plan.qual, rtoffset);
 				}
 				/* resconstantqual can't contain any subplan variable refs */
 				splan->resconstantqual =
-					fix_scan_expr(glob, splan->resconstantqual, rtoffset);
+					fix_scan_expr(root, splan->resconstantqual, rtoffset);
 			}
 			break;
 		case T_ModifyTable:
@@ -549,7 +544,7 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 				}
 				foreach(l, splan->plans)
 				{
-					lfirst(l) = set_plan_refs(glob,
+					lfirst(l) = set_plan_refs(root,
 											  (Plan *) lfirst(l),
 											  rtoffset);
 				}
@@ -560,9 +555,9 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 				 * resultRelIndex to reflect their starting position in the
 				 * global list.
 				 */
-				splan->resultRelIndex = list_length(glob->resultRelations);
-				glob->resultRelations =
-					list_concat(glob->resultRelations,
+				splan->resultRelIndex = list_length(root->glob->resultRelations);
+				root->glob->resultRelations =
+					list_concat(root->glob->resultRelations,
 								list_copy(splan->resultRelations));
 			}
 			break;
@@ -578,7 +573,7 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 				Assert(splan->plan.qual == NIL);
 				foreach(l, splan->appendplans)
 				{
-					lfirst(l) = set_plan_refs(glob,
+					lfirst(l) = set_plan_refs(root,
 											  (Plan *) lfirst(l),
 											  rtoffset);
 				}
@@ -596,7 +591,7 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 				Assert(splan->plan.qual == NIL);
 				foreach(l, splan->mergeplans)
 				{
-					lfirst(l) = set_plan_refs(glob,
+					lfirst(l) = set_plan_refs(root,
 											  (Plan *) lfirst(l),
 											  rtoffset);
 				}
@@ -616,7 +611,7 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 				Assert(splan->plan.qual == NIL);
 				foreach(l, splan->bitmapplans)
 				{
-					lfirst(l) = set_plan_refs(glob,
+					lfirst(l) = set_plan_refs(root,
 											  (Plan *) lfirst(l),
 											  rtoffset);
 				}
@@ -631,7 +626,7 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 				Assert(splan->plan.qual == NIL);
 				foreach(l, splan->bitmapplans)
 				{
-					lfirst(l) = set_plan_refs(glob,
+					lfirst(l) = set_plan_refs(root,
 											  (Plan *) lfirst(l),
 											  rtoffset);
 				}
@@ -651,8 +646,8 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
 	 * reference-adjustments bottom-up, then we would fail to match this
 	 * plan's var nodes against the already-modified nodes of the children.
 	 */
-	plan->lefttree = set_plan_refs(glob, plan->lefttree, rtoffset);
-	plan->righttree = set_plan_refs(glob, plan->righttree, rtoffset);
+	plan->lefttree = set_plan_refs(root, plan->lefttree, rtoffset);
+	plan->righttree = set_plan_refs(root, plan->righttree, rtoffset);
 
 	return plan;
 }
@@ -665,19 +660,19 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
  * to do the normal processing on it.
  */
 static Plan *
-set_subqueryscan_references(PlannerGlobal *glob,
+set_subqueryscan_references(PlannerInfo *root,
 							SubqueryScan *plan,
 							int rtoffset)
 {
+	RelOptInfo *rel;
 	Plan	   *result;
 
-	/* First, recursively process the subplan */
-	plan->subplan = set_plan_references(glob, plan->subplan,
-										plan->subrtable, plan->subrowmark);
+	/* Need to look up the subquery's RelOptInfo, since we need its subroot */
+	rel = find_base_rel(root, plan->scan.scanrelid);
+	Assert(rel->subplan == plan->subplan);
 
-	/* subrtable/subrowmark are no longer needed in the plan tree */
-	plan->subrtable = NIL;
-	plan->subrowmark = NIL;
+	/* Recursively process the subplan */
+	plan->subplan = set_plan_references(rel->subroot, plan->subplan);
 
 	if (trivial_subqueryscan(plan))
 	{
@@ -720,9 +715,9 @@ set_subqueryscan_references(PlannerGlobal *glob,
 		 */
 		plan->scan.scanrelid += rtoffset;
 		plan->scan.plan.targetlist =
-			fix_scan_list(glob, plan->scan.plan.targetlist, rtoffset);
+			fix_scan_list(root, plan->scan.plan.targetlist, rtoffset);
 		plan->scan.plan.qual =
-			fix_scan_list(glob, plan->scan.plan.qual, rtoffset);
+			fix_scan_list(root, plan->scan.plan.qual, rtoffset);
 
 		result = (Plan *) plan;
 	}
@@ -810,59 +805,59 @@ copyVar(Var *var)
  *
  * This is code that is common to all variants of expression-fixing.
  * We must look up operator opcode info for OpExpr and related nodes,
- * add OIDs from regclass Const nodes into glob->relationOids,
- * and add catalog TIDs for user-defined functions into glob->invalItems.
+ * add OIDs from regclass Const nodes into root->glob->relationOids, and
+ * add catalog TIDs for user-defined functions into root->glob->invalItems.
  *
  * We assume it's okay to update opcode info in-place.  So this could possibly
  * scribble on the planner's input data structures, but it's OK.
  */
 static void
-fix_expr_common(PlannerGlobal *glob, Node *node)
+fix_expr_common(PlannerInfo *root, Node *node)
 {
 	/* We assume callers won't call us on a NULL pointer */
 	if (IsA(node, Aggref))
 	{
-		record_plan_function_dependency(glob,
+		record_plan_function_dependency(root,
 										((Aggref *) node)->aggfnoid);
 	}
 	else if (IsA(node, WindowFunc))
 	{
-		record_plan_function_dependency(glob,
+		record_plan_function_dependency(root,
 										((WindowFunc *) node)->winfnoid);
 	}
 	else if (IsA(node, FuncExpr))
 	{
-		record_plan_function_dependency(glob,
+		record_plan_function_dependency(root,
 										((FuncExpr *) node)->funcid);
 	}
 	else if (IsA(node, OpExpr))
 	{
 		set_opfuncid((OpExpr *) node);
-		record_plan_function_dependency(glob,
+		record_plan_function_dependency(root,
 										((OpExpr *) node)->opfuncid);
 	}
 	else if (IsA(node, DistinctExpr))
 	{
 		set_opfuncid((OpExpr *) node);	/* rely on struct equivalence */
-		record_plan_function_dependency(glob,
+		record_plan_function_dependency(root,
 										((DistinctExpr *) node)->opfuncid);
 	}
 	else if (IsA(node, NullIfExpr))
 	{
 		set_opfuncid((OpExpr *) node);	/* rely on struct equivalence */
-		record_plan_function_dependency(glob,
+		record_plan_function_dependency(root,
 										((NullIfExpr *) node)->opfuncid);
 	}
 	else if (IsA(node, ScalarArrayOpExpr))
 	{
 		set_sa_opfuncid((ScalarArrayOpExpr *) node);
-		record_plan_function_dependency(glob,
+		record_plan_function_dependency(root,
 									 ((ScalarArrayOpExpr *) node)->opfuncid);
 	}
 	else if (IsA(node, ArrayCoerceExpr))
 	{
 		if (OidIsValid(((ArrayCoerceExpr *) node)->elemfuncid))
-			record_plan_function_dependency(glob,
+			record_plan_function_dependency(root,
 									 ((ArrayCoerceExpr *) node)->elemfuncid);
 	}
 	else if (IsA(node, Const))
@@ -871,8 +866,8 @@ fix_expr_common(PlannerGlobal *glob, Node *node)
 
 		/* Check for regclass reference */
 		if (ISREGCLASSCONST(con))
-			glob->relationOids =
-				lappend_oid(glob->relationOids,
+			root->glob->relationOids =
+				lappend_oid(root->glob->relationOids,
 							DatumGetObjectId(con->constvalue));
 	}
 }
@@ -883,17 +878,17 @@ fix_expr_common(PlannerGlobal *glob, Node *node)
  *
  * This consists of incrementing all Vars' varnos by rtoffset,
  * looking up operator opcode info for OpExpr and related nodes,
- * and adding OIDs from regclass Const nodes into glob->relationOids.
+ * and adding OIDs from regclass Const nodes into root->glob->relationOids.
  */
 static Node *
-fix_scan_expr(PlannerGlobal *glob, Node *node, int rtoffset)
+fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset)
 {
 	fix_scan_expr_context context;
 
-	context.glob = glob;
+	context.root = root;
 	context.rtoffset = rtoffset;
 
-	if (rtoffset != 0 || glob->lastPHId != 0)
+	if (rtoffset != 0 || root->glob->lastPHId != 0)
 	{
 		return fix_scan_expr_mutator(node, &context);
 	}
@@ -949,7 +944,7 @@ fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
 
 		return fix_scan_expr_mutator((Node *) phv->phexpr, context);
 	}
-	fix_expr_common(context->glob, node);
+	fix_expr_common(context->root, node);
 	return expression_tree_mutator(node, fix_scan_expr_mutator,
 								   (void *) context);
 }
@@ -960,7 +955,7 @@ fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
 	if (node == NULL)
 		return false;
 	Assert(!IsA(node, PlaceHolderVar));
-	fix_expr_common(context->glob, node);
+	fix_expr_common(context->root, node);
 	return expression_tree_walker(node, fix_scan_expr_walker,
 								  (void *) context);
 }
@@ -971,10 +966,10 @@ fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
  *	  subplans, by setting the varnos to OUTER or INNER and setting attno
  *	  values to the result domain number of either the corresponding outer
  *	  or inner join tuple item.  Also perform opcode lookup for these
- *	  expressions. and add regclass OIDs to glob->relationOids.
+ *	  expressions. and add regclass OIDs to root->glob->relationOids.
  */
 static void
-set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
+set_join_references(PlannerInfo *root, Join *join, int rtoffset)
 {
 	Plan	   *outer_plan = join->plan.lefttree;
 	Plan	   *inner_plan = join->plan.righttree;
@@ -985,19 +980,19 @@ set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
 	inner_itlist = build_tlist_index(inner_plan->targetlist);
 
 	/* All join plans have tlist, qual, and joinqual */
-	join->plan.targetlist = fix_join_expr(glob,
+	join->plan.targetlist = fix_join_expr(root,
 										  join->plan.targetlist,
 										  outer_itlist,
 										  inner_itlist,
 										  (Index) 0,
 										  rtoffset);
-	join->plan.qual = fix_join_expr(glob,
+	join->plan.qual = fix_join_expr(root,
 									join->plan.qual,
 									outer_itlist,
 									inner_itlist,
 									(Index) 0,
 									rtoffset);
-	join->joinqual = fix_join_expr(glob,
+	join->joinqual = fix_join_expr(root,
 								   join->joinqual,
 								   outer_itlist,
 								   inner_itlist,
@@ -1014,7 +1009,7 @@ set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
 		{
 			NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
 
-			nlp->paramval = (Var *) fix_upper_expr(glob,
+			nlp->paramval = (Var *) fix_upper_expr(root,
 												   (Node *) nlp->paramval,
 												   outer_itlist,
 												   rtoffset);
@@ -1024,7 +1019,7 @@ set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
 	{
 		MergeJoin  *mj = (MergeJoin *) join;
 
-		mj->mergeclauses = fix_join_expr(glob,
+		mj->mergeclauses = fix_join_expr(root,
 										 mj->mergeclauses,
 										 outer_itlist,
 										 inner_itlist,
@@ -1035,7 +1030,7 @@ set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
 	{
 		HashJoin   *hj = (HashJoin *) join;
 
-		hj->hashclauses = fix_join_expr(glob,
+		hj->hashclauses = fix_join_expr(root,
 										hj->hashclauses,
 										outer_itlist,
 										inner_itlist,
@@ -1052,7 +1047,7 @@ set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
  *	  Update the targetlist and quals of an upper-level plan node
  *	  to refer to the tuples returned by its lefttree subplan.
  *	  Also perform opcode lookup for these expressions, and
- *	  add regclass OIDs to glob->relationOids.
+ *	  add regclass OIDs to root->glob->relationOids.
  *
  * This is used for single-input plan types like Agg, Group, Result.
  *
@@ -1066,7 +1061,7 @@ set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
  * the expression.
  */
 static void
-set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset)
+set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
 {
 	Plan	   *subplan = plan->lefttree;
 	indexed_tlist *subplan_itlist;
@@ -1090,13 +1085,13 @@ set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset)
 													  subplan_itlist,
 													  OUTER);
 			if (!newexpr)
-				newexpr = fix_upper_expr(glob,
+				newexpr = fix_upper_expr(root,
 										 (Node *) tle->expr,
 										 subplan_itlist,
 										 rtoffset);
 		}
 		else
-			newexpr = fix_upper_expr(glob,
+			newexpr = fix_upper_expr(root,
 									 (Node *) tle->expr,
 									 subplan_itlist,
 									 rtoffset);
@@ -1107,7 +1102,7 @@ set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset)
 	plan->targetlist = output_targetlist;
 
 	plan->qual = (List *)
-		fix_upper_expr(glob,
+		fix_upper_expr(root,
 					   (Node *) plan->qual,
 					   subplan_itlist,
 					   rtoffset);
@@ -1385,7 +1380,7 @@ search_indexed_tlist_for_sortgroupref(Node *node,
  *	   changing the varno/varattno values of variables in the clauses
  *	   to reference target list values from the outer and inner join
  *	   relation target lists.  Also perform opcode lookup and add
- *	   regclass OIDs to glob->relationOids.
+ *	   regclass OIDs to root->glob->relationOids.
  *
  * This is used in two different scenarios: a normal join clause, where
  * all the Vars in the clause *must* be replaced by OUTER or INNER references;
@@ -1409,7 +1404,7 @@ search_indexed_tlist_for_sortgroupref(Node *node,
  * not modified.
  */
 static List *
-fix_join_expr(PlannerGlobal *glob,
+fix_join_expr(PlannerInfo *root,
 			  List *clauses,
 			  indexed_tlist *outer_itlist,
 			  indexed_tlist *inner_itlist,
@@ -1418,7 +1413,7 @@ fix_join_expr(PlannerGlobal *glob,
 {
 	fix_join_expr_context context;
 
-	context.glob = glob;
+	context.root = root;
 	context.outer_itlist = outer_itlist;
 	context.inner_itlist = inner_itlist;
 	context.acceptable_rel = acceptable_rel;
@@ -1508,7 +1503,7 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
 		if (newvar)
 			return (Node *) newvar;
 	}
-	fix_expr_common(context->glob, node);
+	fix_expr_common(context->root, node);
 	return expression_tree_mutator(node,
 								   fix_join_expr_mutator,
 								   (void *) context);
@@ -1518,7 +1513,7 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
  * fix_upper_expr
  *		Modifies an expression tree so that all Var nodes reference outputs
  *		of a subplan.  Also performs opcode lookup, and adds regclass OIDs to
- *		glob->relationOids.
+ *		root->glob->relationOids.
  *
  * This is used to fix up target and qual expressions of non-join upper-level
  * plan nodes.
@@ -1542,14 +1537,14 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
  * The original tree is not modified.
  */
 static Node *
-fix_upper_expr(PlannerGlobal *glob,
+fix_upper_expr(PlannerInfo *root,
 			   Node *node,
 			   indexed_tlist *subplan_itlist,
 			   int rtoffset)
 {
 	fix_upper_expr_context context;
 
-	context.glob = glob;
+	context.root = root;
 	context.subplan_itlist = subplan_itlist;
 	context.rtoffset = rtoffset;
 	return fix_upper_expr_mutator(node, &context);
@@ -1599,7 +1594,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
 		if (newvar)
 			return (Node *) newvar;
 	}
-	fix_expr_common(context->glob, node);
+	fix_expr_common(context->root, node);
 	return expression_tree_mutator(node,
 								   fix_upper_expr_mutator,
 								   (void *) context);
@@ -1618,7 +1613,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
  * original varno, but Vars for other rels will have varno OUTER.
  *
  * We also must perform opcode lookup and add regclass OIDs to
- * glob->relationOids.
+ * root->glob->relationOids.
  *
  * 'rlist': the RETURNING targetlist to be fixed
  * 'topplan': the top subplan node that will be just below the ModifyTable
@@ -1629,7 +1624,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
  * they are not coming from a subplan.
  */
 List *
-set_returning_clause_references(PlannerGlobal *glob,
+set_returning_clause_references(PlannerInfo *root,
 								List *rlist,
 								Plan *topplan,
 								Index resultRelation)
@@ -1652,7 +1647,7 @@ set_returning_clause_references(PlannerGlobal *glob,
 	 */
 	itlist = build_tlist_index_other_vars(topplan->targetlist, resultRelation);
 
-	rlist = fix_join_expr(glob,
+	rlist = fix_join_expr(root,
 						  rlist,
 						  itlist,
 						  NULL,
@@ -1738,7 +1733,7 @@ set_sa_opfuncid(ScalarArrayOpExpr *opexpr)
  * dependency on a function that it's removed from the plan tree.
  */
 void
-record_plan_function_dependency(PlannerGlobal *glob, Oid funcid)
+record_plan_function_dependency(PlannerInfo *root, Oid funcid)
 {
 	/*
 	 * For performance reasons, we don't bother to track built-in functions;
@@ -1764,7 +1759,7 @@ record_plan_function_dependency(PlannerGlobal *glob, Oid funcid)
 			DatumGetUInt32(DirectFunctionCall1(hashoid,
 											   ObjectIdGetDatum(funcid)));
 
-		glob->invalItems = lappend(glob->invalItems, inval_item);
+		root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
 	}
 }
 
@@ -1783,21 +1778,26 @@ extract_query_dependencies(Node *query,
 						   List **invalItems)
 {
 	PlannerGlobal glob;
+	PlannerInfo root;
 
-	/* Make up a dummy PlannerGlobal so we can use this module's machinery */
+	/* Make up dummy planner state so we can use this module's machinery */
 	MemSet(&glob, 0, sizeof(glob));
 	glob.type = T_PlannerGlobal;
 	glob.relationOids = NIL;
 	glob.invalItems = NIL;
 
-	(void) extract_query_dependencies_walker(query, &glob);
+	MemSet(&root, 0, sizeof(root));
+	root.type = T_PlannerInfo;
+	root.glob = &glob;
+
+	(void) extract_query_dependencies_walker(query, &root);
 
 	*relationOids = glob.relationOids;
 	*invalItems = glob.invalItems;
 }
 
 static bool
-extract_query_dependencies_walker(Node *node, PlannerGlobal *context)
+extract_query_dependencies_walker(Node *node, PlannerInfo *context)
 {
 	if (node == NULL)
 		return false;
@@ -1828,8 +1828,8 @@ extract_query_dependencies_walker(Node *node, PlannerGlobal *context)
 			RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
 
 			if (rte->rtekind == RTE_RELATION)
-				context->relationOids = lappend_oid(context->relationOids,
-													rte->relid);
+				context->glob->relationOids =
+					lappend_oid(context->glob->relationOids, rte->relid);
 		}
 
 		/* And recurse into the query's subexpressions */
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 4d4e6bf78e7d236da537616a24fe1d85f8e6072a..2e308c625ad897171ba97012f4fa6c3dbfa7c91b 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -52,8 +52,7 @@ typedef struct finalize_primnode_context
 } finalize_primnode_context;
 
 
-static Node *build_subplan(PlannerInfo *root, Plan *plan,
-			  List *rtable, List *rowmarks,
+static Node *build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot,
 			  SubLinkType subLinkType, Node *testexpr,
 			  bool adjust_testexpr, bool unknownEqFalse);
 static List *generate_subquery_params(PlannerInfo *root, List *tlist,
@@ -389,8 +388,7 @@ make_subplan(PlannerInfo *root, Query *orig_subquery, SubLinkType subLinkType,
 							&subroot);
 
 	/* And convert to SubPlan or InitPlan format. */
-	result = build_subplan(root, plan,
-						   subroot->parse->rtable, subroot->rowMarks,
+	result = build_subplan(root, plan, subroot,
 						   subLinkType, testexpr, true, isTopQual);
 
 	/*
@@ -430,9 +428,7 @@ make_subplan(PlannerInfo *root, Query *orig_subquery, SubLinkType subLinkType,
 				AlternativeSubPlan *asplan;
 
 				/* OK, convert to SubPlan format. */
-				hashplan = (SubPlan *) build_subplan(root, plan,
-													 subroot->parse->rtable,
-													 subroot->rowMarks,
+				hashplan = (SubPlan *) build_subplan(root, plan, subroot,
 													 ANY_SUBLINK, newtestexpr,
 													 false, true);
 				/* Check we got what we expected */
@@ -460,7 +456,7 @@ make_subplan(PlannerInfo *root, Query *orig_subquery, SubLinkType subLinkType,
  * as explained in the comments for make_subplan.
  */
 static Node *
-build_subplan(PlannerInfo *root, Plan *plan, List *rtable, List *rowmarks,
+build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot,
 			  SubLinkType subLinkType, Node *testexpr,
 			  bool adjust_testexpr, bool unknownEqFalse)
 {
@@ -644,11 +640,10 @@ build_subplan(PlannerInfo *root, Plan *plan, List *rtable, List *rowmarks,
 	}
 
 	/*
-	 * Add the subplan and its rtable to the global lists.
+	 * Add the subplan and its PlannerInfo to the global lists.
 	 */
 	root->glob->subplans = lappend(root->glob->subplans, plan);
-	root->glob->subrtables = lappend(root->glob->subrtables, rtable);
-	root->glob->subrowmarks = lappend(root->glob->subrowmarks, rowmarks);
+	root->glob->subroots = lappend(root->glob->subroots, subroot);
 	splan->plan_id = list_length(root->glob->subplans);
 
 	if (isInitPlan)
@@ -1018,13 +1013,10 @@ SS_process_ctes(PlannerInfo *root)
 		splan->setParam = list_make1_int(prm->paramid);
 
 		/*
-		 * Add the subplan and its rtable to the global lists.
+		 * Add the subplan and its PlannerInfo to the global lists.
 		 */
 		root->glob->subplans = lappend(root->glob->subplans, plan);
-		root->glob->subrtables = lappend(root->glob->subrtables,
-										 subroot->parse->rtable);
-		root->glob->subrowmarks = lappend(root->glob->subrowmarks,
-										  subroot->rowMarks);
+		root->glob->subroots = lappend(root->glob->subroots, subroot);
 		splan->plan_id = list_length(root->glob->subplans);
 
 		root->init_plans = lappend(root->init_plans, splan);
@@ -2406,14 +2398,10 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
 	SS_finalize_plan(root, plan, false);
 
 	/*
-	 * Add the subplan and its rtable to the global lists.
+	 * Add the subplan and its PlannerInfo to the global lists.
 	 */
-	root->glob->subplans = lappend(root->glob->subplans,
-								   plan);
-	root->glob->subrtables = lappend(root->glob->subrtables,
-									 root->parse->rtable);
-	root->glob->subrowmarks = lappend(root->glob->subrowmarks,
-									  root->rowMarks);
+	root->glob->subplans = lappend(root->glob->subplans, plan);
+	root->glob->subroots = lappend(root->glob->subroots, root);
 
 	/*
 	 * Create a SubPlan node and add it to the outer list of InitPlans. Note
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 31b101b7a110bfd5cae1d36ada5be87bbdfe9cfa..b6ab0f53f52b887552735e4cfaa949526e9a0185 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -130,6 +130,7 @@ plan_set_operations(PlannerInfo *root, double tuple_fraction,
 	Query	   *parse = root->parse;
 	SetOperationStmt *topop = (SetOperationStmt *) parse->setOperations;
 	Node	   *node;
+	RangeTblEntry *leftmostRTE;
 	Query	   *leftmostQuery;
 
 	Assert(topop && IsA(topop, SetOperationStmt));
@@ -142,6 +143,13 @@ plan_set_operations(PlannerInfo *root, double tuple_fraction,
 	Assert(parse->windowClause == NIL);
 	Assert(parse->distinctClause == NIL);
 
+	/*
+	 * We'll need to build RelOptInfos for each of the leaf subqueries,
+	 * which are RTE_SUBQUERY rangetable entries in this Query.  Prepare the
+	 * index arrays for that.
+	 */
+	setup_simple_rel_arrays(root);
+
 	/*
 	 * Find the leftmost component Query.  We need to use its column names for
 	 * all generated tlists (else SELECT INTO won't work right).
@@ -150,8 +158,8 @@ plan_set_operations(PlannerInfo *root, double tuple_fraction,
 	while (node && IsA(node, SetOperationStmt))
 		node = ((SetOperationStmt *) node)->larg;
 	Assert(node && IsA(node, RangeTblRef));
-	leftmostQuery = rt_fetch(((RangeTblRef *) node)->rtindex,
-							 parse->rtable)->subquery;
+	leftmostRTE = root->simple_rte_array[((RangeTblRef *) node)->rtindex];
+	leftmostQuery = leftmostRTE->subquery;
 	Assert(leftmostQuery != NULL);
 
 	/*
@@ -206,14 +214,22 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
 	if (IsA(setOp, RangeTblRef))
 	{
 		RangeTblRef *rtr = (RangeTblRef *) setOp;
-		RangeTblEntry *rte = rt_fetch(rtr->rtindex, root->parse->rtable);
+		RangeTblEntry *rte = root->simple_rte_array[rtr->rtindex];
 		Query	   *subquery = rte->subquery;
+		RelOptInfo *rel;
 		PlannerInfo *subroot;
 		Plan	   *subplan,
 				   *plan;
 
 		Assert(subquery != NULL);
 
+		/*
+		 * We need to build a RelOptInfo for each leaf subquery.  This isn't
+		 * used for anything here, but it carries the subroot data structures
+		 * forward to setrefs.c processing.
+		 */
+		rel = build_simple_rel(root, rtr->rtindex, RELOPT_BASEREL);
+
 		/*
 		 * Generate plan for primitive subquery
 		 */
@@ -222,6 +238,10 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
 								   false, tuple_fraction,
 								   &subroot);
 
+		/* Save subroot and subplan in RelOptInfo for setrefs.c */
+		rel->subplan = subplan;
+		rel->subroot = subroot;
+
 		/*
 		 * Estimate number of groups if caller wants it.  If the subquery used
 		 * grouping or aggregation, its output is probably mostly unique
@@ -250,9 +270,7 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
 												   refnames_tlist),
 							  NIL,
 							  rtr->rtindex,
-							  subplan,
-							  subroot->parse->rtable,
-							  subroot->rowMarks);
+							  subplan);
 
 		/*
 		 * We don't bother to determine the subquery's output ordering since
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index efa986e5214bdf1e1dce2e2a84f2cfa60a176f96..baa90fa9b202b8ffebf5918187b58c9747d3e848 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -57,7 +57,7 @@ typedef struct
 typedef struct
 {
 	ParamListInfo boundParams;
-	PlannerGlobal *glob;
+	PlannerInfo *root;
 	List	   *active_fns;
 	Node	   *case_val;
 	bool		estimate;
@@ -2058,15 +2058,10 @@ eval_const_expressions(PlannerInfo *root, Node *node)
 	eval_const_expressions_context context;
 
 	if (root)
-	{
 		context.boundParams = root->glob->boundParams;	/* bound Params */
-		context.glob = root->glob;		/* for inlined-function dependencies */
-	}
 	else
-	{
 		context.boundParams = NULL;
-		context.glob = NULL;
-	}
+	context.root = root;		/* for inlined-function dependencies */
 	context.active_fns = NIL;	/* nothing being recursively simplified */
 	context.case_val = NULL;	/* no CASE being examined */
 	context.estimate = false;	/* safe transformations only */
@@ -2097,7 +2092,7 @@ estimate_expression_value(PlannerInfo *root, Node *node)
 
 	context.boundParams = root->glob->boundParams;		/* bound Params */
 	/* we do not need to mark the plan as depending on inlined functions */
-	context.glob = NULL;
+	context.root = NULL;
 	context.active_fns = NIL;	/* nothing being recursively simplified */
 	context.case_val = NULL;	/* no CASE being examined */
 	context.estimate = true;	/* unsafe transformations OK */
@@ -4123,8 +4118,8 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid,
 	 * Since there is now no trace of the function in the plan tree, we must
 	 * explicitly record the plan's dependency on the function.
 	 */
-	if (context->glob)
-		record_plan_function_dependency(context->glob, funcid);
+	if (context->root)
+		record_plan_function_dependency(context->root, funcid);
 
 	/*
 	 * Recursively try to simplify the modified expression.  Here we must add
@@ -4559,7 +4554,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
 	 * Since there is now no trace of the function in the plan tree, we must
 	 * explicitly record the plan's dependency on the function.
 	 */
-	record_plan_function_dependency(root->glob, func_oid);
+	record_plan_function_dependency(root, func_oid);
 
 	return querytree;
 
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index b59eb090aa0db2d53b9120757f5637694ddebc78..1df727d9fc80b0841c0d42c5d0dce4700b989ccd 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -45,6 +45,35 @@ static List *subbuild_joinrel_joinlist(RelOptInfo *joinrel,
 						  List *new_joininfo);
 
 
+/*
+ * setup_simple_rel_arrays
+ *	  Prepare the arrays we use for quickly accessing base relations.
+ */
+void
+setup_simple_rel_arrays(PlannerInfo *root)
+{
+	Index		rti;
+	ListCell   *lc;
+
+	/* Arrays are accessed using RT indexes (1..N) */
+	root->simple_rel_array_size = list_length(root->parse->rtable) + 1;
+
+	/* simple_rel_array is initialized to all NULLs */
+	root->simple_rel_array = (RelOptInfo **)
+		palloc0(root->simple_rel_array_size * sizeof(RelOptInfo *));
+
+	/* simple_rte_array is an array equivalent of the rtable list */
+	root->simple_rte_array = (RangeTblEntry **)
+		palloc0(root->simple_rel_array_size * sizeof(RangeTblEntry *));
+	rti = 1;
+	foreach(lc, root->parse->rtable)
+	{
+		RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
+
+		root->simple_rte_array[rti++] = rte;
+	}
+}
+
 /*
  * build_simple_rel
  *	  Construct a new RelOptInfo for a base relation or 'other' relation.
@@ -81,8 +110,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
 	rel->pages = 0;
 	rel->tuples = 0;
 	rel->subplan = NULL;
-	rel->subrtable = NIL;
-	rel->subrowmark = NIL;
+	rel->subroot = NULL;
 	rel->baserestrictinfo = NIL;
 	rel->baserestrictcost.startup = 0;
 	rel->baserestrictcost.per_tuple = 0;
@@ -335,8 +363,7 @@ build_join_rel(PlannerInfo *root,
 	joinrel->pages = 0;
 	joinrel->tuples = 0;
 	joinrel->subplan = NULL;
-	joinrel->subrtable = NIL;
-	joinrel->subrowmark = NIL;
+	joinrel->subroot = NULL;
 	joinrel->baserestrictinfo = NIL;
 	joinrel->baserestrictcost.startup = 0;
 	joinrel->baserestrictcost.per_tuple = 0;
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index d3985b2093e9cdbbeeb763ab8f5023fabf7b923b..5bd916862af8ace9b8ebcf1df1eb5ec152d97eeb 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -16,6 +16,7 @@
 #include "catalog/pg_type.h"
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
+#include "nodes/plannodes.h"
 #include "optimizer/clauses.h"
 #include "parser/parse_coerce.h"
 #include "parser/parse_relation.h"
@@ -375,6 +376,7 @@ OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context)
 		/* fall through to examine children */
 	}
 	/* Shouldn't need to handle other planner auxiliary nodes here */
+	Assert(!IsA(node, PlanRowMark));
 	Assert(!IsA(node, SpecialJoinInfo));
 	Assert(!IsA(node, PlaceHolderInfo));
 	Assert(!IsA(node, MinMaxAggInfo));
@@ -529,6 +531,19 @@ ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context)
 		}
 		/* fall through to examine children */
 	}
+	if (IsA(node, PlanRowMark))
+	{
+		PlanRowMark *rowmark = (PlanRowMark *) node;
+
+		if (context->sublevels_up == 0)
+		{
+			if (rowmark->rti == context->rt_index)
+				rowmark->rti = context->new_index;
+			if (rowmark->prti == context->rt_index)
+				rowmark->prti = context->new_index;
+		}
+		return false;
+	}
 	if (IsA(node, AppendRelInfo))
 	{
 		AppendRelInfo *appinfo = (AppendRelInfo *) node;
@@ -810,6 +825,7 @@ rangeTableEntry_used_walker(Node *node,
 	}
 	/* Shouldn't need to handle planner auxiliary nodes here */
 	Assert(!IsA(node, PlaceHolderVar));
+	Assert(!IsA(node, PlanRowMark));
 	Assert(!IsA(node, SpecialJoinInfo));
 	Assert(!IsA(node, AppendRelInfo));
 	Assert(!IsA(node, PlaceHolderInfo));
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 852ef775309937e82dfe5b53263772eb7387a4a5..535eca77a7e8c173e29e8f9e4994c4ff2debe796 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -380,18 +380,12 @@ typedef struct TidScan
  * the generic lefttree field as you might expect.	This is because we do
  * not want plan-tree-traversal routines to recurse into the subplan without
  * knowing that they are changing Query contexts.
- *
- * Note: subrtable is used just to carry the subquery rangetable from
- * createplan.c to setrefs.c; it should always be NIL by the time the
- * executor sees the plan.	Similarly for subrowmark.
  * ----------------
  */
 typedef struct SubqueryScan
 {
 	Scan		scan;
 	Plan	   *subplan;
-	List	   *subrtable;		/* temporary workspace for planner */
-	List	   *subrowmark;		/* temporary workspace for planner */
 } SubqueryScan;
 
 /* ----------------
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 722567df5c0a6bdf9f97cbe202d2bdc057024091..ecbbc1cd39af181d0f3d86012f2cc28c3979bbb5 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -79,9 +79,7 @@ typedef struct PlannerGlobal
 
 	List	   *subplans;		/* Plans for SubPlan nodes */
 
-	List	   *subrtables;		/* Rangetables for SubPlan nodes */
-
-	List	   *subrowmarks;	/* PlanRowMarks for SubPlan nodes */
+	List	   *subroots;		/* PlannerInfos for SubPlan nodes */
 
 	Bitmapset  *rewindPlanIDs;	/* indices of subplans that require REWIND */
 
@@ -322,10 +320,9 @@ typedef struct PlannerInfo
  *		pages - number of disk pages in relation (zero if not a table)
  *		tuples - number of tuples in relation (not considering restrictions)
  *		subplan - plan for subquery (NULL if it's not a subquery)
- *		subrtable - rangetable for subquery (NIL if it's not a subquery)
- *		subrowmark - rowmarks for subquery (NIL if it's not a subquery)
+ *		subroot - PlannerInfo for subquery (NULL if it's not a subquery)
  *
- *		Note: for a subquery, tuples and subplan are not set immediately
+ *		Note: for a subquery, tuples, subplan, subroot are not set immediately
  *		upon creation of the RelOptInfo object; they are filled in when
  *		set_base_rel_pathlist processes the object.
  *
@@ -408,8 +405,7 @@ typedef struct RelOptInfo
 	BlockNumber pages;
 	double		tuples;
 	struct Plan *subplan;		/* if subquery */
-	List	   *subrtable;		/* if subquery */
-	List	   *subrowmark;		/* if subquery */
+	PlannerInfo *subroot;		/* if subquery */
 
 	/* used by various scans and joins: */
 	List	   *baserestrictinfo;		/* RestrictInfo structures (if base
diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h
index 2763863af2724b3bc04df79ea0e2e45dcf4dfb2d..604df335d2d7e657098bef547a23e9a29cc8f541 100644
--- a/src/include/optimizer/cost.h
+++ b/src/include/optimizer/cost.h
@@ -121,8 +121,7 @@ extern void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
 						   RelOptInfo *inner_rel,
 						   SpecialJoinInfo *sjinfo,
 						   List *restrictlist);
-extern void set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel,
-							PlannerInfo *subroot);
+extern void set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel);
 extern void set_function_size_estimates(PlannerInfo *root, RelOptInfo *rel);
 extern void set_values_size_estimates(PlannerInfo *root, RelOptInfo *rel);
 extern void set_cte_size_estimates(PlannerInfo *root, RelOptInfo *rel,
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index 1da2131b096fe6ef3a2056153ee6b81e8f1c9f3f..ee02732fe1cf1f623fe059153ceea3595bf48a36 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -96,6 +96,7 @@ extern HashPath *create_hashjoin_path(PlannerInfo *root,
 /*
  * prototypes for relnode.c
  */
+extern void setup_simple_rel_arrays(PlannerInfo *root);
 extern RelOptInfo *build_simple_rel(PlannerInfo *root, int relid,
 				 RelOptKind reloptkind);
 extern RelOptInfo *find_base_rel(PlannerInfo *root, int relid);
diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h
index 69ba6b6923ff24f13dbc7e964a10dede7c390850..3b4bcdff74dc99b36a8ff718d32421c2e438edaa 100644
--- a/src/include/optimizer/planmain.h
+++ b/src/include/optimizer/planmain.h
@@ -41,8 +41,7 @@ extern Plan *optimize_minmax_aggregates(PlannerInfo *root, List *tlist,
  */
 extern Plan *create_plan(PlannerInfo *root, Path *best_path);
 extern SubqueryScan *make_subqueryscan(List *qptlist, List *qpqual,
-				  Index scanrelid, Plan *subplan,
-				  List *subrtable, List *subrowmark);
+				  Index scanrelid, Plan *subplan);
 extern Append *make_append(List *appendplans, List *tlist);
 extern RecursiveUnion *make_recursive_union(List *tlist,
 					 Plan *lefttree, Plan *righttree, int wtParam,
@@ -118,18 +117,15 @@ extern List *remove_useless_joins(PlannerInfo *root, List *joinlist);
 /*
  * prototypes for plan/setrefs.c
  */
-extern Plan *set_plan_references(PlannerGlobal *glob,
-					Plan *plan,
-					List *rtable,
-					List *rowmarks);
-extern List *set_returning_clause_references(PlannerGlobal *glob,
+extern Plan *set_plan_references(PlannerInfo *root, Plan *plan);
+extern List *set_returning_clause_references(PlannerInfo *root,
 								List *rlist,
 								Plan *topplan,
 								Index resultRelation);
 extern void fix_opfuncids(Node *node);
 extern void set_opfuncid(OpExpr *opexpr);
 extern void set_sa_opfuncid(ScalarArrayOpExpr *opexpr);
-extern void record_plan_function_dependency(PlannerGlobal *glob, Oid funcid);
+extern void record_plan_function_dependency(PlannerInfo *root, Oid funcid);
 extern void extract_query_dependencies(Node *query,
 						   List **relationOids,
 						   List **invalItems);