Tom Lane wrote:
Hm, the "Assert(rte->subquery != NULL)" doesn't seem right ...
couldn't there be non-RTE_SUBQUERY rtes in the child?  I think the
original coding was guaranteed to visit only subquery-type RTEs
but I'm much less convinced about this one.  It might
be better to say
        if (rte->rtekind == RTE_SUBQUERY)
                IncrementVarSublevelsUp(...);

Or maybe it's okay; I'm too lazy to recheck the representation of
UNION ALL right now.

Oh, indeed it's not okay. The original UNION ALL view is a prime example of that. I didn't notice because I was testing without assertions.

Hmm, do we need the copyObject() call for non-subquery RTEs? I'm guessing no, because they're not modified.

--
  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	13 Aug 2008 06:41:49 -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,520 ----
  {
  	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);
! 
! 		/*
! 		 * 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.
! 		 */
! 		if (rte->subquery)
! 		{
! 			/* Make a modifiable copy of the child RTE and contained query. */
! 			rte = copyObject(rte);
! 			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.
***************
*** 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.
--- 530,555 ----
   * 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
  	{
--- 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