Index: src/backend/optimizer/prep/prepjointree.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/optimizer/prep/prepjointree.c,v
retrieving revision 1.44
diff -c -r1.44 prepjointree.c
*** src/backend/optimizer/prep/prepjointree.c	4 Oct 2006 00:29:54 -0000	1.44
--- src/backend/optimizer/prep/prepjointree.c	14 Aug 2008 11:50:22 -0000
***************
*** 46,52 ****
  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);
  static void make_setop_translation_lists(Query *query,
  							 Index newvarno,
  							 List **col_mappings, List **translated_vars);
--- 46,53 ----
  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 childRToffset);
  static void make_setop_translation_lists(Query *query,
  							 Index newvarno,
  							 List **col_mappings, List **translated_vars);
***************
*** 477,490 ****
  {
  	int			varno = ((RangeTblRef *) jtnode)->rtindex;
  	Query	   *subquery = rte->subquery;
  
  	/*
! 	 * 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.
  	 */
  	Assert(subquery->setOperations);
! 	pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery);
  
  	/*
  	 * Mark the parent as an append relation.
--- 478,511 ----
  {
  	int			varno = ((RangeTblRef *) jtnode)->rtindex;
  	Query	   *subquery = rte->subquery;
+ 	int			rtoffset;
+ 	List	   *rtable;
  
  	/*
! 	 * 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,
! 							   rtoffset);
  
  	/*
  	 * Mark the parent as an append relation.
***************
*** 500,540 ****
   * 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.
   */
  static void
  pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
! 						   Query *setOpQuery)
  {
  	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.
  		 */
! 		parse->rtable = lappend(parse->rtable, rte);
! 		childRTindex = list_length(parse->rtable);
  
  		/*
  		 * Build a suitable AppendRelInfo, and attach to parent's list.
--- 521,546 ----
   * 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, int childRToffset)
  {
  	if (IsA(setOp, RangeTblRef))
  	{
  		RangeTblRef *rtr = (RangeTblRef *) setOp;
  		int			childRTindex;
  		AppendRelInfo *appinfo;
  
  		/*
! 		 * Calculate the index in the parent's range table
  		 */
! 		childRTindex = childRToffset + rtr->rtindex;
  
  		/*
  		 * Build a suitable AppendRelInfo, and attach to parent's list.
***************
*** 566,573 ****
  		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);
  	}
  	else
  	{
--- 572,581 ----
  		SetOperationStmt *op = (SetOperationStmt *) setOp;
  
  		/* Recurse to reach leaf queries */
! 		pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,
! 								   childRToffset);
! 		pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,
! 								   childRToffset);
  	}
  	else
  	{
Index: src/backend/rewrite/rewriteManip.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/rewrite/rewriteManip.c,v
retrieving revision 1.102
diff -c -r1.102 rewriteManip.c
*** src/backend/rewrite/rewriteManip.c	4 Oct 2006 00:29:56 -0000	1.102
--- src/backend/rewrite/rewriteManip.c	14 Aug 2008 11:50:36 -0000
***************
*** 509,514 ****
--- 509,529 ----
  									0);
  }
  
+ 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
Index: src/include/rewrite/rewriteManip.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/rewrite/rewriteManip.h,v
retrieving revision 1.42
diff -c -r1.42 rewriteManip.h
*** src/include/rewrite/rewriteManip.h	5 Mar 2006 15:58:58 -0000	1.42
--- src/include/rewrite/rewriteManip.h	14 Aug 2008 11:38:08 -0000
***************
*** 22,27 ****
--- 22,29 ----
  			   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);
