summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/pathnode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/pathnode.c')
-rw-r--r--src/backend/optimizer/util/pathnode.c212
1 files changed, 158 insertions, 54 deletions
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 54e042a8a59..fc97bf6ee26 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -68,6 +68,15 @@ static bool pathlist_is_reparameterizable_by_child(List *pathlist,
int
compare_path_costs(Path *path1, Path *path2, CostSelector criterion)
{
+ /* Number of disabled nodes, if different, trumps all else. */
+ if (unlikely(path1->disabled_nodes != path2->disabled_nodes))
+ {
+ if (path1->disabled_nodes < path2->disabled_nodes)
+ return -1;
+ else
+ return +1;
+ }
+
if (criterion == STARTUP_COST)
{
if (path1->startup_cost < path2->startup_cost)
@@ -118,6 +127,15 @@ compare_fractional_path_costs(Path *path1, Path *path2,
Cost cost1,
cost2;
+ /* Number of disabled nodes, if different, trumps all else. */
+ if (unlikely(path1->disabled_nodes != path2->disabled_nodes))
+ {
+ if (path1->disabled_nodes < path2->disabled_nodes)
+ return -1;
+ else
+ return +1;
+ }
+
if (fraction <= 0.0 || fraction >= 1.0)
return compare_path_costs(path1, path2, TOTAL_COST);
cost1 = path1->startup_cost +
@@ -166,6 +184,15 @@ compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor)
#define CONSIDER_PATH_STARTUP_COST(p) \
((p)->param_info == NULL ? (p)->parent->consider_startup : (p)->parent->consider_param_startup)
+ /* Number of disabled nodes, if different, trumps all else. */
+ if (unlikely(path1->disabled_nodes != path2->disabled_nodes))
+ {
+ if (path1->disabled_nodes < path2->disabled_nodes)
+ return COSTS_BETTER1;
+ else
+ return COSTS_BETTER2;
+ }
+
/*
* Check total cost first since it's more likely to be different; many
* paths have zero startup cost.
@@ -362,15 +389,29 @@ set_cheapest(RelOptInfo *parent_rel)
* add_path
* Consider a potential implementation path for the specified parent rel,
* and add it to the rel's pathlist if it is worthy of consideration.
+ *
* A path is worthy if it has a better sort order (better pathkeys) or
- * cheaper cost (on either dimension), or generates fewer rows, than any
- * existing path that has the same or superset parameterization rels.
- * We also consider parallel-safe paths more worthy than others.
+ * cheaper cost (as defined below), or generates fewer rows, than any
+ * existing path that has the same or superset parameterization rels. We
+ * also consider parallel-safe paths more worthy than others.
+ *
+ * Cheaper cost can mean either a cheaper total cost or a cheaper startup
+ * cost; if one path is cheaper in one of these aspects and another is
+ * cheaper in the other, we keep both. However, when some path type is
+ * disabled (e.g. due to enable_seqscan=false), the number of times that
+ * a disabled path type is used is considered to be a higher-order
+ * component of the cost. Hence, if path A uses no disabled path type,
+ * and path B uses 1 or more disabled path types, A is cheaper, no matter
+ * what we estimate for the startup and total costs. The startup and total
+ * cost essentially act as a tiebreak when comparing paths that use equal
+ * numbers of disabled path nodes; but in practice this tiebreak is almost
+ * always used, since normally no path types are disabled.
*
- * We also remove from the rel's pathlist any old paths that are dominated
- * by new_path --- that is, new_path is cheaper, at least as well ordered,
- * generates no more rows, requires no outer rels not required by the old
- * path, and is no less parallel-safe.
+ * In addition to possibly adding new_path, we also remove from the rel's
+ * pathlist any old paths that are dominated by new_path --- that is,
+ * new_path is cheaper, at least as well ordered, generates no more rows,
+ * requires no outer rels not required by the old path, and is no less
+ * parallel-safe.
*
* In most cases, a path with a superset parameterization will generate
* fewer rows (since it has more join clauses to apply), so that those two
@@ -389,10 +430,10 @@ set_cheapest(RelOptInfo *parent_rel)
* parent_rel->consider_param_startup is true for a parameterized one.
* Again, this allows discarding useless paths sooner.
*
- * The pathlist is kept sorted by total_cost, with cheaper paths
- * at the front. Within this routine, that's simply a speed hack:
- * doing it that way makes it more likely that we will reject an inferior
- * path after a few comparisons, rather than many comparisons.
+ * The pathlist is kept sorted by disabled_nodes and then by total_cost,
+ * with cheaper paths at the front. Within this routine, that's simply a
+ * speed hack: doing it that way makes it more likely that we will reject
+ * an inferior path after a few comparisons, rather than many comparisons.
* However, add_path_precheck relies on this ordering to exit early
* when possible.
*
@@ -593,8 +634,13 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
}
else
{
- /* new belongs after this old path if it has cost >= old's */
- if (new_path->total_cost >= old_path->total_cost)
+ /*
+ * new belongs after this old path if it has more disabled nodes
+ * or if it has the same number of nodes but a greater total cost
+ */
+ if (new_path->disabled_nodes > old_path->disabled_nodes ||
+ (new_path->disabled_nodes == old_path->disabled_nodes &&
+ new_path->total_cost >= old_path->total_cost))
insert_at = foreach_current_index(p1) + 1;
}
@@ -639,7 +685,7 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
* so the required information has to be passed piecemeal.
*/
bool
-add_path_precheck(RelOptInfo *parent_rel,
+add_path_precheck(RelOptInfo *parent_rel, int disabled_nodes,
Cost startup_cost, Cost total_cost,
List *pathkeys, Relids required_outer)
{
@@ -659,6 +705,20 @@ add_path_precheck(RelOptInfo *parent_rel,
PathKeysComparison keyscmp;
/*
+ * Since the pathlist is sorted by disabled_nodes and then by
+ * total_cost, we can stop looking once we reach a path with more
+ * disabled nodes, or the same number of disabled nodes plus a
+ * total_cost larger than the new path's.
+ */
+ if (unlikely(old_path->disabled_nodes != disabled_nodes))
+ {
+ if (disabled_nodes < old_path->disabled_nodes)
+ break;
+ }
+ else if (total_cost <= old_path->total_cost * STD_FUZZ_FACTOR)
+ break;
+
+ /*
* We are looking for an old_path with the same parameterization (and
* by assumption the same rowcount) that dominates the new path on
* pathkeys as well as both cost metrics. If we find one, we can
@@ -666,39 +726,27 @@ add_path_precheck(RelOptInfo *parent_rel,
*
* Cost comparisons here should match compare_path_costs_fuzzily.
*/
- if (total_cost > old_path->total_cost * STD_FUZZ_FACTOR)
+ /* new path can win on startup cost only if consider_startup */
+ if (startup_cost > old_path->startup_cost * STD_FUZZ_FACTOR ||
+ !consider_startup)
{
- /* new path can win on startup cost only if consider_startup */
- if (startup_cost > old_path->startup_cost * STD_FUZZ_FACTOR ||
- !consider_startup)
+ /* new path loses on cost, so check pathkeys... */
+ List *old_path_pathkeys;
+
+ old_path_pathkeys = old_path->param_info ? NIL : old_path->pathkeys;
+ keyscmp = compare_pathkeys(new_path_pathkeys,
+ old_path_pathkeys);
+ if (keyscmp == PATHKEYS_EQUAL ||
+ keyscmp == PATHKEYS_BETTER2)
{
- /* new path loses on cost, so check pathkeys... */
- List *old_path_pathkeys;
-
- old_path_pathkeys = old_path->param_info ? NIL : old_path->pathkeys;
- keyscmp = compare_pathkeys(new_path_pathkeys,
- old_path_pathkeys);
- if (keyscmp == PATHKEYS_EQUAL ||
- keyscmp == PATHKEYS_BETTER2)
+ /* new path does not win on pathkeys... */
+ if (bms_equal(required_outer, PATH_REQ_OUTER(old_path)))
{
- /* new path does not win on pathkeys... */
- if (bms_equal(required_outer, PATH_REQ_OUTER(old_path)))
- {
- /* Found an old path that dominates the new one */
- return false;
- }
+ /* Found an old path that dominates the new one */
+ return false;
}
}
}
- else
- {
- /*
- * Since the pathlist is sorted by total_cost, we can stop looking
- * once we reach a path with a total_cost larger than the new
- * path's.
- */
- break;
- }
}
return true;
@@ -734,7 +782,7 @@ add_path_precheck(RelOptInfo *parent_rel,
* produce the same number of rows. Neither do we need to consider startup
* costs: parallelism is only used for plans that will be run to completion.
* Therefore, this routine is much simpler than add_path: it needs to
- * consider only pathkeys and total cost.
+ * consider only disabled nodes, pathkeys and total cost.
*
* As with add_path, we pfree paths that are found to be dominated by
* another partial path; this requires that there be no other references to
@@ -775,7 +823,15 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path)
/* Unless pathkeys are incompatible, keep just one of the two paths. */
if (keyscmp != PATHKEYS_DIFFERENT)
{
- if (new_path->total_cost > old_path->total_cost * STD_FUZZ_FACTOR)
+ if (unlikely(new_path->disabled_nodes != old_path->disabled_nodes))
+ {
+ if (new_path->disabled_nodes > old_path->disabled_nodes)
+ accept_new = false;
+ else
+ remove_old = true;
+ }
+ else if (new_path->total_cost > old_path->total_cost
+ * STD_FUZZ_FACTOR)
{
/* New path costs more; keep it only if pathkeys are better. */
if (keyscmp != PATHKEYS_BETTER1)
@@ -862,8 +918,8 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path)
* is surely a loser.
*/
bool
-add_partial_path_precheck(RelOptInfo *parent_rel, Cost total_cost,
- List *pathkeys)
+add_partial_path_precheck(RelOptInfo *parent_rel, int disabled_nodes,
+ Cost total_cost, List *pathkeys)
{
ListCell *p1;
@@ -906,8 +962,8 @@ add_partial_path_precheck(RelOptInfo *parent_rel, Cost total_cost,
* partial path; the resulting plans, if run in parallel, will be run to
* completion.
*/
- if (!add_path_precheck(parent_rel, total_cost, total_cost, pathkeys,
- NULL))
+ if (!add_path_precheck(parent_rel, disabled_nodes, total_cost, total_cost,
+ pathkeys, NULL))
return false;
return true;
@@ -1419,6 +1475,7 @@ create_merge_append_path(PlannerInfo *root,
Relids required_outer)
{
MergeAppendPath *pathnode = makeNode(MergeAppendPath);
+ int input_disabled_nodes;
Cost input_startup_cost;
Cost input_total_cost;
ListCell *l;
@@ -1452,6 +1509,7 @@ create_merge_append_path(PlannerInfo *root,
* Add up the sizes and costs of the input paths.
*/
pathnode->path.rows = 0;
+ input_disabled_nodes = 0;
input_startup_cost = 0;
input_total_cost = 0;
foreach(l, subpaths)
@@ -1468,6 +1526,7 @@ create_merge_append_path(PlannerInfo *root,
if (pathkeys_contained_in(pathkeys, subpath->pathkeys))
{
/* Subpath is adequately ordered, we won't need to sort it */
+ input_disabled_nodes += subpath->disabled_nodes;
input_startup_cost += subpath->startup_cost;
input_total_cost += subpath->total_cost;
}
@@ -1479,12 +1538,14 @@ create_merge_append_path(PlannerInfo *root,
cost_sort(&sort_path,
root,
pathkeys,
+ subpath->disabled_nodes,
subpath->total_cost,
subpath->rows,
subpath->pathtarget->width,
0.0,
work_mem,
pathnode->limit_tuples);
+ input_disabled_nodes += sort_path.disabled_nodes;
input_startup_cost += sort_path.startup_cost;
input_total_cost += sort_path.total_cost;
}
@@ -1500,12 +1561,14 @@ create_merge_append_path(PlannerInfo *root,
((Path *) linitial(subpaths))->parallel_aware ==
pathnode->path.parallel_aware)
{
+ pathnode->path.disabled_nodes = input_disabled_nodes;
pathnode->path.startup_cost = input_startup_cost;
pathnode->path.total_cost = input_total_cost;
}
else
cost_merge_append(&pathnode->path, root,
pathkeys, list_length(subpaths),
+ input_disabled_nodes,
input_startup_cost, input_total_cost,
pathnode->path.rows);
@@ -1587,6 +1650,7 @@ create_material_path(RelOptInfo *rel, Path *subpath)
pathnode->subpath = subpath;
cost_material(&pathnode->path,
+ subpath->disabled_nodes,
subpath->startup_cost,
subpath->total_cost,
subpath->rows,
@@ -1633,6 +1697,10 @@ create_memoize_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
*/
pathnode->est_entries = 0;
+ /* we should not generate this path type when enable_memoize=false */
+ Assert(enable_memoize);
+ pathnode->path.disabled_nodes = subpath->disabled_nodes;
+
/*
* Add a small additional charge for caching the first entry. All the
* harder calculations for rescans are performed in cost_memoize_rescan().
@@ -1732,6 +1800,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
{
pathnode->umethod = UNIQUE_PATH_NOOP;
pathnode->path.rows = rel->rows;
+ pathnode->path.disabled_nodes = subpath->disabled_nodes;
pathnode->path.startup_cost = subpath->startup_cost;
pathnode->path.total_cost = subpath->total_cost;
pathnode->path.pathkeys = subpath->pathkeys;
@@ -1770,6 +1839,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
{
pathnode->umethod = UNIQUE_PATH_NOOP;
pathnode->path.rows = rel->rows;
+ pathnode->path.disabled_nodes = subpath->disabled_nodes;
pathnode->path.startup_cost = subpath->startup_cost;
pathnode->path.total_cost = subpath->total_cost;
pathnode->path.pathkeys = subpath->pathkeys;
@@ -1797,6 +1867,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
* Estimate cost for sort+unique implementation
*/
cost_sort(&sort_path, root, NIL,
+ subpath->disabled_nodes,
subpath->total_cost,
rel->rows,
subpath->pathtarget->width,
@@ -1834,6 +1905,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
AGG_HASHED, NULL,
numCols, pathnode->path.rows,
NIL,
+ subpath->disabled_nodes,
subpath->startup_cost,
subpath->total_cost,
rel->rows,
@@ -1842,7 +1914,9 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
if (sjinfo->semi_can_btree && sjinfo->semi_can_hash)
{
- if (agg_path.total_cost < sort_path.total_cost)
+ if (agg_path.disabled_nodes < sort_path.disabled_nodes ||
+ (agg_path.disabled_nodes == sort_path.disabled_nodes &&
+ agg_path.total_cost < sort_path.total_cost))
pathnode->umethod = UNIQUE_PATH_HASH;
else
pathnode->umethod = UNIQUE_PATH_SORT;
@@ -1860,11 +1934,13 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
if (pathnode->umethod == UNIQUE_PATH_HASH)
{
+ pathnode->path.disabled_nodes = agg_path.disabled_nodes;
pathnode->path.startup_cost = agg_path.startup_cost;
pathnode->path.total_cost = agg_path.total_cost;
}
else
{
+ pathnode->path.disabled_nodes = sort_path.disabled_nodes;
pathnode->path.startup_cost = sort_path.startup_cost;
pathnode->path.total_cost = sort_path.total_cost;
}
@@ -1888,6 +1964,7 @@ create_gather_merge_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
Relids required_outer, double *rows)
{
GatherMergePath *pathnode = makeNode(GatherMergePath);
+ int input_disabled_nodes = 0;
Cost input_startup_cost = 0;
Cost input_total_cost = 0;
@@ -1915,11 +1992,13 @@ create_gather_merge_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
pathnode->path.pathkeys = pathkeys;
pathnode->path.pathtarget = target ? target : rel->reltarget;
+ input_disabled_nodes += subpath->disabled_nodes;
input_startup_cost += subpath->startup_cost;
input_total_cost += subpath->total_cost;
cost_gather_merge(pathnode, root, rel, pathnode->path.param_info,
- input_startup_cost, input_total_cost, rows);
+ input_disabled_nodes, input_startup_cost,
+ input_total_cost, rows);
return pathnode;
}
@@ -2227,7 +2306,8 @@ create_worktablescan_path(PlannerInfo *root, RelOptInfo *rel,
ForeignPath *
create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
PathTarget *target,
- double rows, Cost startup_cost, Cost total_cost,
+ double rows, int disabled_nodes,
+ Cost startup_cost, Cost total_cost,
List *pathkeys,
Relids required_outer,
Path *fdw_outerpath,
@@ -2248,6 +2328,7 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
pathnode->path.parallel_safe = rel->consider_parallel;
pathnode->path.parallel_workers = 0;
pathnode->path.rows = rows;
+ pathnode->path.disabled_nodes = disabled_nodes;
pathnode->path.startup_cost = startup_cost;
pathnode->path.total_cost = total_cost;
pathnode->path.pathkeys = pathkeys;
@@ -2273,7 +2354,8 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
ForeignPath *
create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel,
PathTarget *target,
- double rows, Cost startup_cost, Cost total_cost,
+ double rows, int disabled_nodes,
+ Cost startup_cost, Cost total_cost,
List *pathkeys,
Relids required_outer,
Path *fdw_outerpath,
@@ -2300,6 +2382,7 @@ create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel,
pathnode->path.parallel_safe = rel->consider_parallel;
pathnode->path.parallel_workers = 0;
pathnode->path.rows = rows;
+ pathnode->path.disabled_nodes = disabled_nodes;
pathnode->path.startup_cost = startup_cost;
pathnode->path.total_cost = total_cost;
pathnode->path.pathkeys = pathkeys;
@@ -2325,7 +2408,8 @@ create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel,
ForeignPath *
create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel,
PathTarget *target,
- double rows, Cost startup_cost, Cost total_cost,
+ double rows, int disabled_nodes,
+ Cost startup_cost, Cost total_cost,
List *pathkeys,
Path *fdw_outerpath,
List *fdw_restrictinfo,
@@ -2347,6 +2431,7 @@ create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel,
pathnode->path.parallel_safe = rel->consider_parallel;
pathnode->path.parallel_workers = 0;
pathnode->path.rows = rows;
+ pathnode->path.disabled_nodes = disabled_nodes;
pathnode->path.startup_cost = startup_cost;
pathnode->path.total_cost = total_cost;
pathnode->path.pathkeys = pathkeys;
@@ -2734,6 +2819,7 @@ create_projection_path(PlannerInfo *root,
* Set cost of plan as subpath's cost, adjusted for tlist replacement.
*/
pathnode->path.rows = subpath->rows;
+ pathnode->path.disabled_nodes = subpath->disabled_nodes;
pathnode->path.startup_cost = subpath->startup_cost +
(target->cost.startup - oldtarget->cost.startup);
pathnode->path.total_cost = subpath->total_cost +
@@ -2750,6 +2836,7 @@ create_projection_path(PlannerInfo *root,
* evaluating the tlist. There is no qual to worry about.
*/
pathnode->path.rows = subpath->rows;
+ pathnode->path.disabled_nodes = subpath->disabled_nodes;
pathnode->path.startup_cost = subpath->startup_cost +
target->cost.startup;
pathnode->path.total_cost = subpath->total_cost +
@@ -2917,6 +3004,7 @@ create_set_projection_path(PlannerInfo *root,
* This is slightly bizarre maybe, but it's what 9.6 did; we may revisit
* this estimate later.
*/
+ pathnode->path.disabled_nodes = subpath->disabled_nodes;
pathnode->path.rows = subpath->rows * tlist_rows;
pathnode->path.startup_cost = subpath->startup_cost +
target->cost.startup;
@@ -2967,6 +3055,7 @@ create_incremental_sort_path(PlannerInfo *root,
cost_incremental_sort(&pathnode->path,
root, pathkeys, presorted_keys,
+ subpath->disabled_nodes,
subpath->startup_cost,
subpath->total_cost,
subpath->rows,
@@ -3013,6 +3102,7 @@ create_sort_path(PlannerInfo *root,
pathnode->subpath = subpath;
cost_sort(&pathnode->path, root, pathkeys,
+ subpath->disabled_nodes,
subpath->total_cost,
subpath->rows,
subpath->pathtarget->width,
@@ -3065,6 +3155,7 @@ create_group_path(PlannerInfo *root,
list_length(groupClause),
numGroups,
qual,
+ subpath->disabled_nodes,
subpath->startup_cost, subpath->total_cost,
subpath->rows);
@@ -3122,6 +3213,7 @@ create_upper_unique_path(PlannerInfo *root,
* all columns get compared at most of the tuples. (XXX probably this is
* an overestimate.)
*/
+ pathnode->path.disabled_nodes = subpath->disabled_nodes;
pathnode->path.startup_cost = subpath->startup_cost;
pathnode->path.total_cost = subpath->total_cost +
cpu_operator_cost * subpath->rows * numCols;
@@ -3200,6 +3292,7 @@ create_agg_path(PlannerInfo *root,
aggstrategy, aggcosts,
list_length(groupClause), numGroups,
qual,
+ subpath->disabled_nodes,
subpath->startup_cost, subpath->total_cost,
subpath->rows, subpath->pathtarget->width);
@@ -3308,6 +3401,7 @@ create_groupingsets_path(PlannerInfo *root,
numGroupCols,
rollup->numGroups,
having_qual,
+ subpath->disabled_nodes,
subpath->startup_cost,
subpath->total_cost,
subpath->rows,
@@ -3333,7 +3427,7 @@ create_groupingsets_path(PlannerInfo *root,
numGroupCols,
rollup->numGroups,
having_qual,
- 0.0, 0.0,
+ 0, 0.0, 0.0,
subpath->rows,
subpath->pathtarget->width);
if (!rollup->is_hashed)
@@ -3342,7 +3436,7 @@ create_groupingsets_path(PlannerInfo *root,
else
{
/* Account for cost of sort, but don't charge input cost again */
- cost_sort(&sort_path, root, NIL,
+ cost_sort(&sort_path, root, NIL, 0,
0.0,
subpath->rows,
subpath->pathtarget->width,
@@ -3358,12 +3452,14 @@ create_groupingsets_path(PlannerInfo *root,
numGroupCols,
rollup->numGroups,
having_qual,
+ sort_path.disabled_nodes,
sort_path.startup_cost,
sort_path.total_cost,
sort_path.rows,
subpath->pathtarget->width);
}
+ pathnode->path.disabled_nodes += agg_path.disabled_nodes;
pathnode->path.total_cost += agg_path.total_cost;
pathnode->path.rows += agg_path.rows;
}
@@ -3395,6 +3491,7 @@ create_minmaxagg_path(PlannerInfo *root,
{
MinMaxAggPath *pathnode = makeNode(MinMaxAggPath);
Cost initplan_cost;
+ int initplan_disabled_nodes = 0;
ListCell *lc;
/* The topmost generated Plan node will be a Result */
@@ -3419,12 +3516,14 @@ create_minmaxagg_path(PlannerInfo *root,
{
MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
+ initplan_disabled_nodes += mminfo->path->disabled_nodes;
initplan_cost += mminfo->pathcost;
if (!mminfo->path->parallel_safe)
pathnode->path.parallel_safe = false;
}
/* add tlist eval cost for each output row, plus cpu_tuple_cost */
+ pathnode->path.disabled_nodes = initplan_disabled_nodes;
pathnode->path.startup_cost = initplan_cost + target->cost.startup;
pathnode->path.total_cost = initplan_cost + target->cost.startup +
target->cost.per_tuple + cpu_tuple_cost;
@@ -3517,6 +3616,7 @@ create_windowagg_path(PlannerInfo *root,
cost_windowagg(&pathnode->path, root,
windowFuncs,
winclause,
+ subpath->disabled_nodes,
subpath->startup_cost,
subpath->total_cost,
subpath->rows);
@@ -3584,6 +3684,7 @@ create_setop_path(PlannerInfo *root,
* Charge one cpu_operator_cost per comparison per input tuple. We assume
* all columns get compared at most of the tuples.
*/
+ pathnode->path.disabled_nodes = subpath->disabled_nodes;
pathnode->path.startup_cost = subpath->startup_cost;
pathnode->path.total_cost = subpath->total_cost +
cpu_operator_cost * subpath->rows * list_length(distinctList);
@@ -3683,6 +3784,7 @@ create_lockrows_path(PlannerInfo *root, RelOptInfo *rel,
* possible refetches, but it's hard to say how much. For now, use
* cpu_tuple_cost per row.
*/
+ pathnode->path.disabled_nodes = subpath->disabled_nodes;
pathnode->path.startup_cost = subpath->startup_cost;
pathnode->path.total_cost = subpath->total_cost +
cpu_tuple_cost * subpath->rows;
@@ -3759,6 +3861,7 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel,
* costs to change any higher-level planning choices. But we might want
* to make it look better sometime.
*/
+ pathnode->path.disabled_nodes = subpath->disabled_nodes;
pathnode->path.startup_cost = subpath->startup_cost;
pathnode->path.total_cost = subpath->total_cost;
if (returningLists != NIL)
@@ -3835,6 +3938,7 @@ create_limit_path(PlannerInfo *root, RelOptInfo *rel,
subpath->parallel_safe;
pathnode->path.parallel_workers = subpath->parallel_workers;
pathnode->path.rows = subpath->rows;
+ pathnode->path.disabled_nodes = subpath->disabled_nodes;
pathnode->path.startup_cost = subpath->startup_cost;
pathnode->path.total_cost = subpath->total_cost;
pathnode->path.pathkeys = subpath->pathkeys;