@ -78,7 +78,7 @@ static Path *generate_nonunion_path(SetOperationStmt *op, PlannerInfo *root,
List * refnames_tlist ,
List * refnames_tlist ,
List * * pTargetList ,
List * * pTargetList ,
double * pNumGroups ) ;
double * pNumGroups ) ;
static List * recurse_union_children ( Node * setOp , PlannerInfo * root ,
static List * plan_union_children ( PlannerInfo * root ,
SetOperationStmt * top_union ,
SetOperationStmt * top_union ,
List * refnames_tlist ,
List * refnames_tlist ,
List * * tlist_list ) ;
List * * tlist_list ) ;
@ -545,8 +545,6 @@ generate_union_path(SetOperationStmt *op, PlannerInfo *root,
RelOptInfo * result_rel = fetch_upper_rel ( root , UPPERREL_SETOP , NULL ) ;
RelOptInfo * result_rel = fetch_upper_rel ( root , UPPERREL_SETOP , NULL ) ;
double save_fraction = root - > tuple_fraction ;
double save_fraction = root - > tuple_fraction ;
List * pathlist ;
List * pathlist ;
List * child_tlists1 ;
List * child_tlists2 ;
List * tlist_list ;
List * tlist_list ;
List * tlist ;
List * tlist ;
Path * path ;
Path * path ;
@ -571,13 +569,7 @@ generate_union_path(SetOperationStmt *op, PlannerInfo *root,
* only one Append and unique - ification for the lot . Recurse to find such
* only one Append and unique - ification for the lot . Recurse to find such
* nodes and compute their children ' s paths .
* nodes and compute their children ' s paths .
*/
*/
pathlist = list_concat ( recurse_union_children ( op - > larg , root ,
pathlist = plan_union_children ( root , op , refnames_tlist , & tlist_list ) ;
op , refnames_tlist ,
& child_tlists1 ) ,
recurse_union_children ( op - > rarg , root ,
op , refnames_tlist ,
& child_tlists2 ) ) ;
tlist_list = list_concat ( child_tlists1 , child_tlists2 ) ;
/*
/*
* Generate tlist for Append plan node .
* Generate tlist for Append plan node .
@ -797,14 +789,23 @@ generate_nonunion_path(SetOperationStmt *op, PlannerInfo *root,
* generate_union_path will force a fresh sort if the top level is a UNION .
* generate_union_path will force a fresh sort if the top level is a UNION .
*/
*/
static List *
static List *
recurse_union_children ( Node * setOp , PlannerInfo * root ,
plan_union_children ( PlannerInfo * root ,
SetOperationStmt * top_union ,
SetOperationStmt * top_union ,
List * refnames_tlist ,
List * refnames_tlist ,
List * * tlist_list )
List * * tlist_list )
{
{
List * result ;
List * pending_rels = list_make1 ( top_union ) ;
List * result = NIL ;
List * child_tlist ;
List * child_tlist ;
* tlist_list = NIL ;
while ( pending_rels ! = NIL )
{
Node * setOp = linitial ( pending_rels ) ;
pending_rels = list_delete_first ( pending_rels ) ;
if ( IsA ( setOp , SetOperationStmt ) )
if ( IsA ( setOp , SetOperationStmt ) )
{
{
SetOperationStmt * op = ( SetOperationStmt * ) setOp ;
SetOperationStmt * op = ( SetOperationStmt * ) setOp ;
@ -813,20 +814,10 @@ recurse_union_children(Node *setOp, PlannerInfo *root,
( op - > all = = top_union - > all | | op - > all ) & &
( op - > all = = top_union - > all | | op - > all ) & &
equal ( op - > colTypes , top_union - > colTypes ) )
equal ( op - > colTypes , top_union - > colTypes ) )
{
{
/* Same UNION, so fold children into parent's subpath list */
/* Same UNION, so fold children into parent */
List * child_tlists1 ;
pending_rels = lcons ( op - > rarg , pending_rels ) ;
List * child_tlists2 ;
pending_rels = lcons ( op - > larg , pending_rels ) ;
continue ;
result = list_concat ( recurse_union_children ( op - > larg , root ,
top_union ,
refnames_tlist ,
& child_tlists1 ) ,
recurse_union_children ( op - > rarg , root ,
top_union ,
refnames_tlist ,
& child_tlists2 ) ) ;
* tlist_list = list_concat ( child_tlists1 , child_tlists2 ) ;
return result ;
}
}
}
}
@ -834,19 +825,22 @@ recurse_union_children(Node *setOp, PlannerInfo *root,
* Not same , so plan this child separately .
* Not same , so plan this child separately .
*
*
* Note we disallow any resjunk columns in child results . This is
* Note we disallow any resjunk columns in child results . This is
* necessary since the Append node that implements the union won ' t do any
* necessary since the Append node that implements the union won ' t do
* projection , and upper levels will get confused if some of our output
* any projection , and upper levels will get confused if some of our
* tuples have junk and some don ' t . This case only arises when we have an
* output tuples have junk and some don ' t . This case only arises when
* EXCEPT or INTERSECT as child , else there won ' t be resjunk anyway .
* we have an EXCEPT or INTERSECT as child , else there won ' t be
* resjunk anyway .
*/
*/
result = list_make1 ( recurse_set_operations ( setOp , root ,
result = lappend ( result , recurse_set_operations ( setOp , root ,
top_union - > colTypes ,
top_union - > colTypes ,
top_union - > colCollations ,
top_union - > colCollations ,
false , - 1 ,
false , - 1 ,
refnames_tlist ,
refnames_tlist ,
& child_tlist ,
& child_tlist ,
NULL ) ) ;
NULL ) ) ;
* tlist_list = list_make1 ( child_tlist ) ;
* tlist_list = lappend ( * tlist_list , child_tlist ) ;
}
return result ;
return result ;
}
}