diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index b4be3d8d0c1b0b07797602697e5c728c6def7472..241ad668072524c64a3f8424114903bd5de7b42d 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.51 2008/08/14 18:47:59 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.52 2008/08/14 20:31:29 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,7 +47,8 @@ static Node *pull_up_simple_subquery(PlannerInfo *root, Node *jtnode,
 static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
 						 RangeTblEntry *rte);
 static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
-						   int parentRTindex, Query *setOpQuery);
+						  int parentRTindex, Query *setOpQuery,
+						  int childRToffset);
 static void make_setop_translation_lists(Query *query,
 							 Index newvarno,
 							 List **col_mappings, List **translated_vars);
@@ -560,14 +561,34 @@ pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
 {
 	int			varno = ((RangeTblRef *) jtnode)->rtindex;
 	Query	   *subquery = rte->subquery;
+	int			rtoffset;
+	List	   *rtable;
 
 	/*
-	 * Recursively scan the subquery's setOperations tree and copy the leaf
-	 * subqueries into the parent rangetable.  Add AppendRelInfo nodes for
-	 * them to the parent's append_rel_list, too.
+	 * Append the subquery rtable entries to upper query.
+	 */
+	rtoffset = list_length(root->parse->rtable);
+
+	/*
+	 * Append child RTEs to parent rtable.
+	 *
+	 * Upper-level vars in subquery are now one level closer to their
+	 * parent than before.	We don't have to worry about offsetting
+	 * varnos, though, because any such vars must refer to stuff above the
+	 * level of the query we are pulling into.
+	 */
+	rtable = copyObject(subquery->rtable);
+	IncrementVarSublevelsUp_rtable(rtable, -1, 1);
+	root->parse->rtable = list_concat(root->parse->rtable, rtable);
+
+	/*
+	 * Recursively scan the subquery's setOperations tree and add
+	 * AppendRelInfo nodes for leaf subqueries to the parent's
+	 * append_rel_list.
 	 */
 	Assert(subquery->setOperations);
-	pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery);
+	pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery,
+							   rtoffset);
 
 	/*
 	 * Mark the parent as an append relation.
@@ -583,41 +604,26 @@ pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
  * Note that setOpQuery is the Query containing the setOp node, whose rtable
  * is where to look up the RTE if setOp is a RangeTblRef.  This is *not* the
  * same as root->parse, which is the top-level Query we are pulling up into.
+ *
  * parentRTindex is the appendrel parent's index in root->parse->rtable.
+ *
+ * The child RTEs have already been copied to the parent. childRToffset
+ * tells us where in the parent's range table they were copied.
  */
 static void
 pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
-						   Query *setOpQuery)
+						   Query *setOpQuery, int childRToffset)
 {
 	if (IsA(setOp, RangeTblRef))
 	{
 		RangeTblRef *rtr = (RangeTblRef *) setOp;
-		RangeTblEntry *rte = rt_fetch(rtr->rtindex, setOpQuery->rtable);
-		Query	   *subquery;
 		int			childRTindex;
 		AppendRelInfo *appinfo;
-		Query	   *parse = root->parse;
-
-		/*
-		 * Make a modifiable copy of the child RTE and contained query.
-		 */
-		rte = copyObject(rte);
-		subquery = rte->subquery;
-		Assert(subquery != NULL);
-
-		/*
-		 * Upper-level vars in subquery are now one level closer to their
-		 * parent than before.	We don't have to worry about offsetting
-		 * varnos, though, because any such vars must refer to stuff above the
-		 * level of the query we are pulling into.
-		 */
-		IncrementVarSublevelsUp((Node *) subquery, -1, 1);
 
 		/*
-		 * Attach child RTE to parent rtable.
+		 * Calculate the index in the parent's range table
 		 */
-		parse->rtable = lappend(parse->rtable, rte);
-		childRTindex = list_length(parse->rtable);
+		childRTindex = childRToffset + rtr->rtindex;
 
 		/*
 		 * Build a suitable AppendRelInfo, and attach to parent's list.
@@ -649,8 +655,10 @@ pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
 		SetOperationStmt *op = (SetOperationStmt *) setOp;
 
 		/* Recurse to reach leaf queries */
-		pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery);
-		pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery);
+		pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,
+								   childRToffset);
+		pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,
+								   childRToffset);
 	}
 	else
 	{
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index 60492fe3d091fa52b349f5190a082531ec5277ea..1202c31314dd04ae6e5999743bcad3126636c2d1 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.108 2008/08/14 18:47:59 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.109 2008/08/14 20:31:29 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -533,6 +533,25 @@ IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
 									0);
 }
 
+/*
+ * IncrementVarSublevelsUp_rtable -
+ *	Same as IncrementVarSublevelsUp, but to be invoked on a range table.
+ */
+void
+IncrementVarSublevelsUp_rtable(List *rtable, int delta_sublevels_up,
+							   int min_sublevels_up)
+{
+	IncrementVarSublevelsUp_context context;
+
+	context.delta_sublevels_up = delta_sublevels_up;
+	context.min_sublevels_up = min_sublevels_up;
+
+	range_table_walker(rtable,
+					   IncrementVarSublevelsUp_walker,
+					   (void *) &context,
+					   0);
+}
+
 
 /*
  * rangeTableEntry_used - detect whether an RTE is referenced somewhere
diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h
index 05da127ffae935e5377b125bb45fed19fd454060..110d8ac0d119c44cf26b436d5306f4ffe5a96c30 100644
--- a/src/include/rewrite/rewriteManip.h
+++ b/src/include/rewrite/rewriteManip.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/rewrite/rewriteManip.h,v 1.44 2008/01/01 19:45:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/rewrite/rewriteManip.h,v 1.45 2008/08/14 20:31:29 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,6 +22,8 @@ extern void ChangeVarNodes(Node *node, int old_varno, int new_varno,
 			   int sublevels_up);
 extern void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
 						int min_sublevels_up);
+extern void IncrementVarSublevelsUp_rtable(List *rtable,
+							   int delta_sublevels_up,	int min_sublevels_up);
 
 extern bool rangeTableEntry_used(Node *node, int rt_index,
 					 int sublevels_up);