From 2007bfd7306d824b5c78cfe59ca281850d5becba Mon Sep 17 00:00:00 2001 From: Lukas Fittl Date: Sun, 11 Jan 2026 12:08:22 -0800 Subject: [PATCH] WIP: Rework child append relids to be passed via struct --- src/backend/optimizer/path/allpaths.c | 187 +++++++++++-------------- src/backend/optimizer/path/joinrels.c | 5 +- src/backend/optimizer/plan/planner.c | 8 +- src/backend/optimizer/prep/prepunion.c | 42 +++--- src/backend/optimizer/util/pathnode.c | 27 ++-- src/include/optimizer/pathnode.h | 10 +- src/tools/pgindent/typedefs.list | 1 + 7 files changed, 135 insertions(+), 145 deletions(-) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6b9ad1c8aa7..9ff52685bbf 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1390,7 +1390,6 @@ set_grouped_rel_pathlist(PlannerInfo *root, RelOptInfo *rel) } } - /* * add_paths_to_append_rel * Generate paths for the given append relation given the set of non-dummy @@ -1406,26 +1405,21 @@ void add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, List *live_childrels) { - List *subpaths = NIL; - bool subpaths_valid = true; - List *subpath_cars = NIL; - List *startup_subpaths = NIL; - bool startup_subpaths_valid = true; - List *startup_subpath_cars = NIL; - List *partial_subpaths = NIL; - List *partial_subpath_cars = NIL; - List *pa_partial_subpaths = NIL; - List *pa_nonpartial_subpaths = NIL; - List *pa_subpath_cars = NIL; - bool partial_subpaths_valid = true; - bool pa_subpaths_valid; + AppendPathInput unparameterized = {0}; + AppendPathInput startup = {0}; + AppendPathInput partial_only = {0}; + AppendPathInput parallel_append = {0}; + bool unparameterized_valid = true; + bool startup_valid = true; + bool partial_only_valid = true; + bool parallel_append_valid = true; List *all_child_pathkeys = NIL; List *all_child_outers = NIL; ListCell *l; double partial_rows = -1; /* If appropriate, consider parallel append */ - pa_subpaths_valid = enable_parallel_append && rel->consider_parallel; + parallel_append_valid = enable_parallel_append && rel->consider_parallel; /* * For every non-dummy child, remember the cheapest path. Also, identify @@ -1449,9 +1443,9 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, if (childrel->pathlist != NIL && childrel->cheapest_total_path->param_info == NULL) accumulate_append_subpath(childrel->cheapest_total_path, - &subpaths, NULL, &subpath_cars); + &unparameterized.subpaths, NULL, &unparameterized.child_append_relid_sets); else - subpaths_valid = false; + unparameterized_valid = false; /* * When the planner is considering cheap startup plans, we'll also @@ -1477,12 +1471,12 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, /* cheapest_startup_path must not be a parameterized path. */ Assert(cheapest_path->param_info == NULL); accumulate_append_subpath(cheapest_path, - &startup_subpaths, + &startup.subpaths, NULL, - &startup_subpath_cars); + &startup.child_append_relid_sets); } else - startup_subpaths_valid = false; + startup_valid = false; /* Same idea, but for a partial plan. */ @@ -1490,17 +1484,17 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, { cheapest_partial_path = linitial(childrel->partial_pathlist); accumulate_append_subpath(cheapest_partial_path, - &partial_subpaths, NULL, - &partial_subpath_cars); + &partial_only.partial_subpaths, NULL, + &partial_only.child_append_relid_sets); } else - partial_subpaths_valid = false; + partial_only_valid = false; /* * Same idea, but for a parallel append mixing partial and non-partial * paths. */ - if (pa_subpaths_valid) + if (parallel_append_valid) { Path *nppath = NULL; @@ -1510,7 +1504,7 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, if (cheapest_partial_path == NULL && nppath == NULL) { /* Neither a partial nor a parallel-safe path? Forget it. */ - pa_subpaths_valid = false; + parallel_append_valid = false; } else if (nppath == NULL || (cheapest_partial_path != NULL && @@ -1519,9 +1513,9 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, /* Partial path is cheaper or the only option. */ Assert(cheapest_partial_path != NULL); accumulate_append_subpath(cheapest_partial_path, - &pa_partial_subpaths, - &pa_nonpartial_subpaths, - &pa_subpath_cars); + ¶llel_append.partial_subpaths, + ¶llel_append.subpaths, + ¶llel_append.child_append_relid_sets); } else { @@ -1539,9 +1533,9 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, * figure that out. */ accumulate_append_subpath(nppath, - &pa_nonpartial_subpaths, + ¶llel_append.subpaths, NULL, - &pa_subpath_cars); + ¶llel_append.child_append_relid_sets); } } @@ -1615,30 +1609,28 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, * unparameterized Append path for the rel. (Note: this is correct even * if we have zero or one live subpath due to constraint exclusion.) */ - if (subpaths_valid) - add_path(rel, (Path *) create_append_path(root, rel, subpaths, - NIL, subpath_cars, + if (unparameterized_valid) + add_path(rel, (Path *) create_append_path(root, rel, unparameterized, NIL, NULL, 0, false, -1)); /* build an AppendPath for the cheap startup paths, if valid */ - if (startup_subpaths_valid) - add_path(rel, (Path *) create_append_path(root, rel, startup_subpaths, - NIL, startup_subpath_cars, + if (startup_valid) + add_path(rel, (Path *) create_append_path(root, rel, startup, NIL, NULL, 0, false, -1)); /* * Consider an append of unordered, unparameterized partial paths. Make * it parallel-aware if possible. */ - if (partial_subpaths_valid && partial_subpaths != NIL) + if (partial_only_valid && partial_only.partial_subpaths != NIL) { AppendPath *appendpath; ListCell *lc; int parallel_workers = 0; /* Find the highest number of workers requested for any subpath. */ - foreach(lc, partial_subpaths) + foreach(lc, partial_only.partial_subpaths) { Path *path = lfirst(lc); @@ -1665,8 +1657,7 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, Assert(parallel_workers > 0); /* Generate a partial append path. */ - appendpath = create_append_path(root, rel, NIL, partial_subpaths, - partial_subpath_cars, + appendpath = create_append_path(root, rel, partial_only, NIL, NULL, parallel_workers, enable_parallel_append, -1); @@ -1687,7 +1678,7 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, * a non-partial path that is substantially cheaper than any partial path; * otherwise, we should use the append path added in the previous step.) */ - if (pa_subpaths_valid && pa_nonpartial_subpaths != NIL) + if (parallel_append_valid && parallel_append.subpaths != NIL) { AppendPath *appendpath; ListCell *lc; @@ -1697,7 +1688,7 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, * Find the highest number of workers requested for any partial * subpath. */ - foreach(lc, pa_partial_subpaths) + foreach(lc, parallel_append.partial_subpaths) { Path *path = lfirst(lc); @@ -1715,9 +1706,7 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, max_parallel_workers_per_gather); Assert(parallel_workers > 0); - appendpath = create_append_path(root, rel, pa_nonpartial_subpaths, - pa_partial_subpaths, - pa_subpath_cars, + appendpath = create_append_path(root, rel, parallel_append, NIL, NULL, parallel_workers, true, partial_rows); add_partial_path(rel, (Path *) appendpath); @@ -1727,7 +1716,7 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, * Also build unparameterized ordered append paths based on the collected * list of child pathkeys. */ - if (subpaths_valid) + if (unparameterized_valid) generate_orderedappend_paths(root, rel, live_childrels, all_child_pathkeys); @@ -1748,11 +1737,10 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, { Relids required_outer = (Relids) lfirst(l); ListCell *lcr; + AppendPathInput parameterized = {0}; + bool parameterized_valid = true; /* Select the child paths for an Append with this parameterization */ - subpaths = NIL; - subpath_cars = NIL; - subpaths_valid = true; foreach(lcr, live_childrels) { RelOptInfo *childrel = (RelOptInfo *) lfirst(lcr); @@ -1761,7 +1749,7 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, if (childrel->pathlist == NIL) { /* failed to make a suitable path for this child */ - subpaths_valid = false; + parameterized_valid = false; break; } @@ -1771,16 +1759,16 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, if (subpath == NULL) { /* failed to make a suitable path for this child */ - subpaths_valid = false; + parameterized_valid = false; break; } - accumulate_append_subpath(subpath, &subpaths, NULL, - &subpath_cars); + accumulate_append_subpath(subpath, ¶meterized.subpaths, NULL, + ¶meterized.child_append_relid_sets); } - if (subpaths_valid) + if (parameterized_valid) add_path(rel, (Path *) - create_append_path(root, rel, subpaths, NIL, subpath_cars, + create_append_path(root, rel, parameterized, NIL, required_outer, 0, false, -1)); } @@ -1801,14 +1789,16 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, { Path *path = (Path *) lfirst(l); AppendPath *appendpath; + AppendPathInput append = {0}; + + append.partial_subpaths = list_make1(path); + append.child_append_relid_sets = list_make1(rel->relids); /* skip paths with no pathkeys. */ if (path->pathkeys == NIL) continue; - appendpath = create_append_path(root, rel, NIL, list_make1(path), - list_make1(rel->relids), - NIL, NULL, + appendpath = create_append_path(root, rel, append, NIL, NULL, path->parallel_workers, true, partial_rows); add_partial_path(rel, (Path *) appendpath); @@ -1890,12 +1880,9 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel, foreach(lcp, all_child_pathkeys) { List *pathkeys = (List *) lfirst(lcp); - List *startup_subpaths = NIL; - List *startup_subpath_cars = NIL; - List *total_subpaths = NIL; - List *total_subpath_cars = NIL; - List *fractional_subpaths = NIL; - List *fractional_subpath_cars = NIL; + AppendPathInput startup = {0}; + AppendPathInput total = {0}; + AppendPathInput fractional = {0}; bool startup_neq_total = false; bool fraction_neq_total = false; bool match_partition_order; @@ -2060,21 +2047,21 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel, */ cheapest_startup = get_singleton_append_subpath(cheapest_startup, - &startup_subpath_cars); + &startup.child_append_relid_sets); cheapest_total = get_singleton_append_subpath(cheapest_total, - &total_subpath_cars); + &total.child_append_relid_sets); - startup_subpaths = lappend(startup_subpaths, cheapest_startup); - total_subpaths = lappend(total_subpaths, cheapest_total); + startup.subpaths = lappend(startup.subpaths, cheapest_startup); + total.subpaths = lappend(total.subpaths, cheapest_total); if (cheapest_fractional) { cheapest_fractional = get_singleton_append_subpath(cheapest_fractional, - &fractional_subpath_cars); - fractional_subpaths = - lappend(fractional_subpaths, cheapest_fractional); + &fractional.child_append_relid_sets); + fractional.subpaths = + lappend(fractional.subpaths, cheapest_fractional); } } else @@ -2084,16 +2071,16 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel, * child paths for the MergeAppend. */ accumulate_append_subpath(cheapest_startup, - &startup_subpaths, NULL, - &startup_subpath_cars); + &startup.subpaths, NULL, + &startup.child_append_relid_sets); accumulate_append_subpath(cheapest_total, - &total_subpaths, NULL, - &total_subpath_cars); + &total.subpaths, NULL, + &total.child_append_relid_sets); if (cheapest_fractional) accumulate_append_subpath(cheapest_fractional, - &fractional_subpaths, NULL, - &fractional_subpath_cars); + &fractional.subpaths, NULL, + &fractional.child_append_relid_sets); } } @@ -2103,9 +2090,7 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel, /* We only need Append */ add_path(rel, (Path *) create_append_path(root, rel, - startup_subpaths, - NIL, - startup_subpath_cars, + startup, pathkeys, NULL, 0, @@ -2114,49 +2099,45 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel, if (startup_neq_total) add_path(rel, (Path *) create_append_path(root, rel, - total_subpaths, - NIL, - total_subpath_cars, + total, pathkeys, NULL, 0, false, -1)); - if (fractional_subpaths && fraction_neq_total) - add_path(rel, (Path *) create_append_path(root, - rel, - fractional_subpaths, - NIL, - fractional_subpath_cars, - pathkeys, - NULL, - 0, - false, - -1)); + if (fractional.subpaths && fraction_neq_total) + add_path(rel, (Path *) (root, + rel, + fractional, + pathkeys, + NULL, + 0, + false, + -1)); } else { /* We need MergeAppend */ add_path(rel, (Path *) create_merge_append_path(root, rel, - startup_subpaths, - startup_subpath_cars, + startup.subpaths, + startup.child_append_relid_sets, pathkeys, NULL)); if (startup_neq_total) add_path(rel, (Path *) create_merge_append_path(root, rel, - total_subpaths, - total_subpath_cars, + total.subpaths, + total.child_append_relid_sets, pathkeys, NULL)); - if (fractional_subpaths && fraction_neq_total) + if (fractional.subpaths && fraction_neq_total) add_path(rel, (Path *) create_merge_append_path(root, rel, - fractional_subpaths, - fractional_subpath_cars, + fractional.subpaths, + fractional.child_append_relid_sets, pathkeys, NULL)); } @@ -2360,6 +2341,8 @@ get_singleton_append_subpath(Path *path, List **child_append_relid_sets) static void set_dummy_rel_pathlist(RelOptInfo *rel) { + AppendPathInput in = {0}; + /* Set dummy size estimates --- we leave attr_widths[] as zeroes */ rel->rows = 0; rel->reltarget->width = 0; @@ -2369,7 +2352,7 @@ set_dummy_rel_pathlist(RelOptInfo *rel) rel->partial_pathlist = NIL; /* Set up the dummy path */ - add_path(rel, (Path *) create_append_path(NULL, rel, NIL, NIL, NIL, + add_path(rel, (Path *) create_append_path(NULL, rel, in, NIL, rel->lateral_relids, 0, false, -1)); diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index e94021b6880..443e2dca7c0 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -1513,6 +1513,7 @@ void mark_dummy_rel(RelOptInfo *rel) { MemoryContext oldcontext; + AppendPathInput in = {0}; /* Already marked? */ if (is_dummy_rel(rel)) @@ -1529,8 +1530,8 @@ mark_dummy_rel(RelOptInfo *rel) rel->partial_pathlist = NIL; /* Set up the dummy path */ - add_path(rel, (Path *) create_append_path(NULL, rel, NIL, NIL, - NIL, NIL, rel->lateral_relids, + add_path(rel, (Path *) create_append_path(NULL, rel, in, + NIL, rel->lateral_relids, 0, false, -1)); /* Set or update cheapest_total_path and related fields */ diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index d905b64b9ca..d4bf8a955d1 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -4062,7 +4062,7 @@ create_degenerate_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, * might get between 0 and N output rows. Offhand I think that's * desired.) */ - List *paths = NIL; + AppendPathInput append = {0}; while (--nrows >= 0) { @@ -4070,14 +4070,12 @@ create_degenerate_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, create_group_result_path(root, grouped_rel, grouped_rel->reltarget, (List *) parse->havingQual); - paths = lappend(paths, path); + append.subpaths = lappend(append.subpaths, path); } path = (Path *) create_append_path(root, grouped_rel, - paths, - NIL, - NIL, + append, NIL, NULL, 0, diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 6e76783126b..f50c296e3d9 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -696,9 +696,9 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, ListCell *lc; ListCell *lc2; ListCell *lc3; - List *cheapest_pathlist = NIL; - List *ordered_pathlist = NIL; - List *partial_pathlist = NIL; + AppendPathInput cheapest = {0}; + AppendPathInput ordered = {0}; + AppendPathInput partial = {0}; bool partial_paths_valid = true; bool consider_parallel = true; List *rellist; @@ -783,7 +783,7 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, if (is_dummy_rel(rel)) continue; - cheapest_pathlist = lappend(cheapest_pathlist, + cheapest.subpaths = lappend(cheapest.subpaths, rel->cheapest_total_path); if (try_sorted) @@ -795,7 +795,7 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, false); if (ordered_path != NULL) - ordered_pathlist = lappend(ordered_pathlist, ordered_path); + ordered.subpaths = lappend(ordered.subpaths, ordered_path); else { /* @@ -818,20 +818,20 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, else if (rel->partial_pathlist == NIL) partial_paths_valid = false; else - partial_pathlist = lappend(partial_pathlist, - linitial(rel->partial_pathlist)); + partial.partial_subpaths = lappend(partial.partial_subpaths, + linitial(rel->partial_pathlist)); } } /* Build result relation. */ result_rel = fetch_upper_rel(root, UPPERREL_SETOP, relids); result_rel->reltarget = create_setop_pathtarget(root, tlist, - cheapest_pathlist); + cheapest.subpaths); result_rel->consider_parallel = consider_parallel; result_rel->consider_startup = (root->tuple_fraction > 0); /* If all UNION children were dummy rels, make the resulting rel dummy */ - if (cheapest_pathlist == NIL) + if (cheapest.subpaths == NIL) { mark_dummy_rel(result_rel); @@ -842,8 +842,8 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, * Append the child results together using the cheapest paths from each * union child. */ - apath = (Path *) create_append_path(root, result_rel, cheapest_pathlist, - NIL, NIL, NIL, NULL, 0, false, -1); + apath = (Path *) create_append_path(root, result_rel, cheapest, + NIL, NULL, 0, false, -1); /* * Estimate number of groups. For now we just assume the output is unique @@ -862,7 +862,7 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, int parallel_workers = 0; /* Find the highest number of workers requested for any subpath. */ - foreach(lc, partial_pathlist) + foreach(lc, partial.partial_subpaths) { Path *subpath = lfirst(lc); @@ -881,15 +881,15 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, if (enable_parallel_append) { parallel_workers = Max(parallel_workers, - pg_leftmost_one_pos32(list_length(partial_pathlist)) + 1); + pg_leftmost_one_pos32(list_length(partial.partial_subpaths)) + 1); parallel_workers = Min(parallel_workers, max_parallel_workers_per_gather); } Assert(parallel_workers > 0); papath = (Path *) - create_append_path(root, result_rel, NIL, partial_pathlist, - NIL, NIL, NULL, parallel_workers, + create_append_path(root, result_rel, partial, + NIL, NULL, parallel_workers, enable_parallel_append, -1); gpath = (Path *) create_gather_path(root, result_rel, papath, @@ -901,7 +901,7 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, double dNumGroups; bool can_sort = grouping_is_sortable(groupList); bool can_hash = grouping_is_hashable(groupList); - Path *first_path = linitial(cheapest_pathlist); + Path *first_path = linitial(cheapest.subpaths); /* * Estimate the number of UNION output rows. In the case when only a @@ -911,7 +911,7 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, * contain Vars with varno==0, which estimate_num_groups() wouldn't * like. */ - if (list_length(cheapest_pathlist) == 1 && + if (list_length(cheapest.subpaths) == 1 && first_path->parent->reloptkind != RELOPT_UPPER_REL) { dNumGroups = estimate_num_groups(root, @@ -1017,7 +1017,7 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, path = (Path *) create_merge_append_path(root, result_rel, - ordered_pathlist, + ordered.subpaths, NIL, union_pathkeys, NULL); @@ -1217,6 +1217,9 @@ generate_nonunion_paths(SetOperationStmt *op, PlannerInfo *root, if (op->all) { Path *apath; + AppendPathInput append = {0}; + + append.subpaths = list_make1(lpath); /* * EXCEPT ALL: If the right-hand input is dummy then we can @@ -1226,8 +1229,7 @@ generate_nonunion_paths(SetOperationStmt *op, PlannerInfo *root, * left input. The Append will be removed in setrefs.c. */ apath = (Path *) create_append_path(root, result_rel, - list_make1(lpath), - NIL, NIL, NIL, NULL, 0, + append, NIL, NULL, 0, false, -1); add_path(result_rel, apath); diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 310175b6b21..dca5459aeab 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -1300,8 +1300,7 @@ create_tidrangescan_path(PlannerInfo *root, RelOptInfo *rel, AppendPath * create_append_path(PlannerInfo *root, RelOptInfo *rel, - List *subpaths, List *partial_subpaths, - List *child_append_relid_sets, + AppendPathInput input, List *pathkeys, Relids required_outer, int parallel_workers, bool parallel_aware, double rows) @@ -1311,7 +1310,7 @@ create_append_path(PlannerInfo *root, Assert(!parallel_aware || parallel_workers > 0); - pathnode->child_append_relid_sets = child_append_relid_sets; + pathnode->child_append_relid_sets = input.child_append_relid_sets; pathnode->path.pathtype = T_Append; pathnode->path.parent = rel; pathnode->path.pathtarget = rel->reltarget; @@ -1327,7 +1326,7 @@ create_append_path(PlannerInfo *root, * on the simpler get_appendrel_parampathinfo. There's no point in doing * the more expensive thing for a dummy path, either. */ - if (rel->reloptkind == RELOPT_BASEREL && root && subpaths != NIL) + if (rel->reloptkind == RELOPT_BASEREL && root && input.subpaths != NIL) pathnode->path.param_info = get_baserel_parampathinfo(root, rel, required_outer); @@ -1358,11 +1357,11 @@ create_append_path(PlannerInfo *root, */ Assert(pathkeys == NIL); - list_sort(subpaths, append_total_cost_compare); - list_sort(partial_subpaths, append_startup_cost_compare); + list_sort(input.subpaths, append_total_cost_compare); + list_sort(input.partial_subpaths, append_startup_cost_compare); } - pathnode->first_partial_path = list_length(subpaths); - pathnode->subpaths = list_concat(subpaths, partial_subpaths); + pathnode->first_partial_path = list_length(input.subpaths); + pathnode->subpaths = list_concat(input.subpaths, input.partial_subpaths); /* * Apply query-wide LIMIT if known and path is for sole base relation. @@ -3938,11 +3937,12 @@ reparameterize_path(PlannerInfo *root, Path *path, case T_Append: { AppendPath *apath = (AppendPath *) path; - List *childpaths = NIL; - List *partialpaths = NIL; + AppendPathInput new_append = {0}; int i; ListCell *lc; + new_append.child_append_relid_sets = apath->child_append_relid_sets; + /* Reparameterize the children */ i = 0; foreach(lc, apath->subpaths) @@ -3956,14 +3956,13 @@ reparameterize_path(PlannerInfo *root, Path *path, return NULL; /* We have to re-split the regular and partial paths */ if (i < apath->first_partial_path) - childpaths = lappend(childpaths, spath); + new_append.subpaths = lappend(new_append.subpaths, spath); else - partialpaths = lappend(partialpaths, spath); + new_append.partial_subpaths = lappend(new_append.partial_subpaths, spath); i++; } return (Path *) - create_append_path(root, rel, childpaths, partialpaths, - apath->child_append_relid_sets, + create_append_path(root, rel, new_append, apath->path.pathkeys, required_outer, apath->path.parallel_workers, apath->path.parallel_aware, diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h index dc8cab2b7e6..8dca0cc67e8 100644 --- a/src/include/optimizer/pathnode.h +++ b/src/include/optimizer/pathnode.h @@ -77,9 +77,15 @@ extern TidRangePath *create_tidrangescan_path(PlannerInfo *root, List *tidrangequals, Relids required_outer, int parallel_workers); + +typedef struct AppendPathInput +{ + List *subpaths; + List *partial_subpaths; + List *child_append_relid_sets; +} AppendPathInput; extern AppendPath *create_append_path(PlannerInfo *root, RelOptInfo *rel, - List *subpaths, List *partial_subpaths, - List *child_append_relid_sets, + AppendPathInput input, List *pathkeys, Relids required_outer, int parallel_workers, bool parallel_aware, double rows); diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 2c4f350bebe..38382b4c91d 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -125,6 +125,7 @@ AnlIndexData AnyArrayType Append AppendPath +AppendPathInput AppendRelInfo AppendState ApplyErrorCallbackArg -- 2.47.1