@@ -78,10 +78,10 @@ static Path *generate_nonunion_path(SetOperationStmt *op, PlannerInfo *root,
7878 List * refnames_tlist ,
7979 List * * pTargetList ,
8080 double * 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 ,
8686 PlannerInfo * root );
8787static bool choose_hashed_setop (PlannerInfo * root , List * groupClauses ,
@@ -545,8 +545,6 @@ generate_union_path(SetOperationStmt *op, PlannerInfo *root,
545545 RelOptInfo * result_rel = fetch_upper_rel (root , UPPERREL_SETOP , NULL );
546546 double save_fraction = root -> tuple_fraction ;
547547 List * pathlist ;
548- List * child_tlists1 ;
549- List * child_tlists2 ;
550548 List * tlist_list ;
551549 List * tlist ;
552550 Path * 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 ;
806799 List * 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 );
850844 return result ;
851845}
852846
0 commit comments