@@ -78,10 +78,10 @@ static Path *generate_nonunion_path(SetOperationStmt *op, PlannerInfo *root,
7878List * refnames_tlist ,
7979List * * pTargetList ,
8080double * pNumGroups );
81- static List * recurse_union_children ( Node * setOp , PlannerInfo * root ,
82- SetOperationStmt * top_union ,
83- List * refnames_tlist ,
84- List * * tlist_list );
81+ static List * plan_union_children ( PlannerInfo * root ,
82+ SetOperationStmt * top_union ,
83+ List * refnames_tlist ,
84+ List * * tlist_list );
8585static Path * make_union_unique (SetOperationStmt * op ,Path * path ,List * tlist ,
8686PlannerInfo * root );
8787static bool choose_hashed_setop (PlannerInfo * root ,List * groupClauses ,
@@ -545,8 +545,6 @@ generate_union_path(SetOperationStmt *op, PlannerInfo *root,
545545RelOptInfo * result_rel = fetch_upper_rel (root ,UPPERREL_SETOP ,NULL );
546546double save_fraction = root -> tuple_fraction ;
547547List * pathlist ;
548- List * child_tlists1 ;
549- List * child_tlists2 ;
550548List * tlist_list ;
551549List * tlist ;
552550Path * path ;
@@ -571,13 +569,7 @@ generate_union_path(SetOperationStmt *op, PlannerInfo *root,
571569 * only one Append and unique-ification for the lot. Recurse to find such
572570 * nodes and compute their children's paths.
573571 */
574- pathlist = list_concat (recurse_union_children (op -> larg ,root ,
575- op ,refnames_tlist ,
576- & child_tlists1 ),
577- recurse_union_children (op -> rarg ,root ,
578- op ,refnames_tlist ,
579- & child_tlists2 ));
580- tlist_list = list_concat (child_tlists1 ,child_tlists2 );
572+ pathlist = plan_union_children (root ,op ,refnames_tlist ,& tlist_list );
581573
582574/*
583575 * Generate tlist for Append plan node.
@@ -797,56 +789,58 @@ generate_nonunion_path(SetOperationStmt *op, PlannerInfo *root,
797789 * generate_union_path will force a fresh sort if the top level is a UNION.
798790 */
799791static List *
800- recurse_union_children ( Node * setOp , PlannerInfo * root ,
801- SetOperationStmt * top_union ,
802- List * refnames_tlist ,
803- List * * tlist_list )
792+ plan_union_children ( PlannerInfo * root ,
793+ SetOperationStmt * top_union ,
794+ List * refnames_tlist ,
795+ List * * tlist_list )
804796{
805- List * result ;
797+ List * pending_rels = list_make1 (top_union );
798+ List * result = NIL ;
806799List * child_tlist ;
807800
808- if (IsA (setOp ,SetOperationStmt ))
801+ * tlist_list = NIL ;
802+
803+ while (pending_rels != NIL )
809804{
810- SetOperationStmt * op = (SetOperationStmt * )setOp ;
805+ Node * setOp = linitial (pending_rels );
806+
807+ pending_rels = list_delete_first (pending_rels );
811808
812- if (op -> op == top_union -> op &&
813- (op -> all == top_union -> all || op -> all )&&
814- equal (op -> colTypes ,top_union -> colTypes ))
809+ if (IsA (setOp ,SetOperationStmt ))
815810{
816- /* Same UNION, so fold children into parent's subpath list */
817- List * child_tlists1 ;
818- List * child_tlists2 ;
811+ SetOperationStmt * op = (SetOperationStmt * )setOp ;
819812
820- result = list_concat (recurse_union_children (op -> larg ,root ,
821- top_union ,
822- refnames_tlist ,
823- & child_tlists1 ),
824- recurse_union_children (op -> rarg ,root ,
825- top_union ,
826- refnames_tlist ,
827- & child_tlists2 ));
828- * tlist_list = list_concat (child_tlists1 ,child_tlists2 );
829- return result ;
813+ if (op -> op == top_union -> op &&
814+ (op -> all == top_union -> all || op -> all )&&
815+ equal (op -> colTypes ,top_union -> colTypes ))
816+ {
817+ /* Same UNION, so fold children into parent */
818+ pending_rels = lcons (op -> rarg ,pending_rels );
819+ pending_rels = lcons (op -> larg ,pending_rels );
820+ continue ;
821+ }
830822}
823+
824+ /*
825+ * Not same, so plan this child separately.
826+ *
827+ * Note we disallow any resjunk columns in child results. This is
828+ * necessary since the Append node that implements the union won't do
829+ * any projection, and upper levels will get confused if some of our
830+ * output tuples have junk and some don't. This case only arises when
831+ * we have an EXCEPT or INTERSECT as child, else there won't be
832+ * resjunk anyway.
833+ */
834+ result = lappend (result ,recurse_set_operations (setOp ,root ,
835+ top_union -> colTypes ,
836+ top_union -> colCollations ,
837+ false,-1 ,
838+ refnames_tlist ,
839+ & child_tlist ,
840+ NULL ));
841+ * tlist_list = lappend (* tlist_list ,child_tlist );
831842}
832843
833- /*
834- * Not same, so plan this child separately.
835- *
836- * Note we disallow any resjunk columns in child results. This is
837- * necessary since the Append node that implements the union won't do any
838- * projection, and upper levels will get confused if some of our output
839- * tuples have junk and some don't. This case only arises when we have an
840- * EXCEPT or INTERSECT as child, else there won't be resjunk anyway.
841- */
842- result = list_make1 (recurse_set_operations (setOp ,root ,
843- top_union -> colTypes ,
844- top_union -> colCollations ,
845- false,-1 ,
846- refnames_tlist ,
847- & child_tlist ,
848- NULL ));
849- * tlist_list = list_make1 (child_tlist );
850844return result ;
851845}
852846