Heikki Linnakangas wrote:
Tom Lane wrote:
Seriously, I think what this shows is that piecemeal pullup is wrong in
principle, and that the right approach is always to concat the
subquery's rtable in toto to the upper level, and then go from there on
adjusting varnos.  Do you want to look into that approach?

You mean like pull_up_simple_subquery() does? Yeah, I can try that. This isn't really something I'm familiar with, but it's great exercise :-).

Here we go. Now that I see it, I do like this approach better.

--
  Heikki Linnakangas
  EnterpriseDB   http://www.enterprisedb.com
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	12 Aug 2008 18:22:28 -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,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, 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.
--- 477,521 ----
  {
  	int			varno = ((RangeTblRef *) jtnode)->rtindex;
  	Query	   *subquery = rte->subquery;
+ 	ListCell   *l;
+ 	int			rtoffset;
  
  	/*
! 	 * Append the subquery rtable entries to upper query.
! 	 */
! 	rtoffset = list_length(root->parse->rtable);
! 	foreach(l, subquery->rtable)
! 	{
! 		RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
! 
! 		/*
! 		 * Make a modifiable copy of the child RTE and contained query.
! 		 */
! 		rte = copyObject(rte);
! 		Assert(rte->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 *) rte->subquery, -1, 1);
! 
! 		/*
! 		 * Attach child RTE to parent rtable.
! 		 */
! 		root->parse->rtable = lappend(root->parse->rtable, rte);
! 	}
! 
! 	/*
! 	 * 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.
***************
*** 501,540 ****
   * 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.
--- 532,555 ----
   * 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
  	{
--- 581,590 ----
  		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
  	{
-- 
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Reply via email to