Hi hackers,

I have write an initial patch to retire the disable_cost​ GUC, which labeled a 
flag on the Path struct instead of adding up a big cost which is hard to 
estimate. Though it involved in tons of plan changes in regression tests, I 
have tested on some simple test cases such as eagerly generate a two-stage agg 
plans and it worked. Could someone help to review?


regards,

Jian
________________________________
From: Euler Taveira <eu...@timbira.com.br>
Sent: Friday, November 1, 2019 22:48
To: Zhenghua Lyu <z...@vmware.com>
Cc: PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Subject: Re: On disable_cost

!! External Email

Em sex, 1 de nov de 2019 às 03:42, Zhenghua Lyu <z...@pivotal.io> escreveu:
>
>     My issue: I did some spikes and tests on TPCDS 1TB Bytes data. For query 
> 104, it generates
>  nestloop join even with enable_nestloop set off. And the final plan's total 
> cost is very huge (about 1e24). But If I enlarge the disable_cost to 1e30, 
> then, planner will generate hash join.
>
>     So I guess that disable_cost is not large enough for huge amount of data.
>
>     It is tricky to set disable_cost a huge number. Can we come up with 
> better solution?
>
Isn't it a case for a GUC disable_cost? As Thomas suggested, DBL_MAX
upper limit should be sufficient.

>     The following thoughts are from Heikki:
>>
>>     Aside from not having a large enough disable cost, there's also the fact 
>> that the high cost might affect the rest of the plan, if we have to use a 
>> plan type that's disabled. For example, if a table doesn't have any indexes, 
>> but enable_seqscan is off, we might put the unavoidable Seq Scan on 
>> different side of a join than we we would with enable_seqscan=on, because of 
>> the high cost estimate.
>
>
>>
>> I think a more robust way to disable forbidden plan types would be to handle 
>> the disabling in add_path(). Instead of having a high disable cost on the 
>> Path itself, the comparison add_path() would always consider disabled paths 
>> as more expensive than others, regardless of the cost.
>
I'm afraid it is not as cheap as using diable_cost as a node cost. Are
you proposing to add a new boolean variable in Path struct to handle
those cases in compare_path_costs_fuzzily?


--
   Euler Taveira                                   Timbira -
https://nam04.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.timbira.com.br%2F&data=05%7C01%7Cgjian%40vmware.com%7C12a30b2852dd4651667608db9401d056%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C0%7C0%7C638266507757076648%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=v54JhsW8FX4mSmjgt2yP59t7xtv1mZvC%2BBhtKrfp%2FBY%3D&reserved=0<http://www.timbira.com.br/>
   PostgreSQL: Consultoria, Desenvolvimento, Suporte 24x7 e Treinamento





!! External Email: This email originated from outside of the organization. Do 
not click links or open attachments unless you recognize the sender.
From baf0143438a91c8739534c7d85b9d121a7bb560e Mon Sep 17 00:00:00 2001
From: Jian Guo <gj...@vmware.com>
Date: Thu, 3 Aug 2023 17:03:49 +0800
Subject: [PATCH] Retire disable_cost, introduce new flag is_disabled into Path
 struct.

Signed-off-by: Jian Guo <gj...@vmware.com>
---
 src/backend/optimizer/path/costsize.c | 30 +++++++-------
 src/backend/optimizer/util/pathnode.c | 58 +++++++++++++++++++++++++++
 src/include/nodes/pathnodes.h         |  1 +
 3 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index ef475d95a1..0814604c49 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -274,7 +274,7 @@ cost_seqscan(Path *path, PlannerInfo *root,
 		path->rows = baserel->rows;
 
 	if (!enable_seqscan)
-		startup_cost += disable_cost;
+		path->is_disabled = true;
 
 	/* fetch estimated page cost for tablespace containing table */
 	get_tablespace_page_costs(baserel->reltablespace,
@@ -463,7 +463,7 @@ cost_gather_merge(GatherMergePath *path, PlannerInfo *root,
 		path->path.rows = rel->rows;
 
 	if (!enable_gathermerge)
-		startup_cost += disable_cost;
+		path->path.is_disabled = true;
 
 	/*
 	 * Add one to the number of workers to account for the leader.  This might
@@ -576,7 +576,7 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count,
 	}
 
 	if (!enable_indexscan)
-		startup_cost += disable_cost;
+		path->path.is_disabled = true;
 	/* we don't need to check enable_indexonlyscan; indxpath.c does that */
 
 	/*
@@ -1011,7 +1011,7 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
 		path->rows = baserel->rows;
 
 	if (!enable_bitmapscan)
-		startup_cost += disable_cost;
+		path->is_disabled = true;
 
 	pages_fetched = compute_bitmap_pages(root, baserel, bitmapqual,
 										 loop_count, &indexTotalCost,
@@ -1279,11 +1279,10 @@ cost_tidscan(Path *path, PlannerInfo *root,
 	 */
 	if (isCurrentOf)
 	{
-		Assert(baserel->baserestrictcost.startup >= disable_cost);
-		startup_cost -= disable_cost;
+		path->is_disabled = false;
 	}
 	else if (!enable_tidscan)
-		startup_cost += disable_cost;
+		path->is_disabled = true;
 
 	/*
 	 * The TID qual expressions will be computed once, any other baserestrict
@@ -1372,7 +1371,7 @@ cost_tidrangescan(Path *path, PlannerInfo *root,
 	nseqpages = pages - 1.0;
 
 	if (!enable_tidscan)
-		startup_cost += disable_cost;
+		path->is_disabled = true;
 
 	/*
 	 * The TID qual expressions will be computed once, any other baserestrict
@@ -2108,7 +2107,7 @@ cost_sort(Path *path, PlannerInfo *root,
 				   limit_tuples);
 
 	if (!enable_sort)
-		startup_cost += disable_cost;
+		path->is_disabled = true;
 
 	startup_cost += input_cost;
 
@@ -2679,8 +2678,7 @@ cost_agg(Path *path, PlannerInfo *root,
 		total_cost = input_total_cost;
 		if (aggstrategy == AGG_MIXED && !enable_hashagg)
 		{
-			startup_cost += disable_cost;
-			total_cost += disable_cost;
+			path->is_disabled = true;
 		}
 		/* calcs phrased this way to match HASHED case, see note above */
 		total_cost += aggcosts->transCost.startup;
@@ -2696,7 +2694,7 @@ cost_agg(Path *path, PlannerInfo *root,
 		/* must be AGG_HASHED */
 		startup_cost = input_total_cost;
 		if (!enable_hashagg)
-			startup_cost += disable_cost;
+			path->is_disabled = true;
 		startup_cost += aggcosts->transCost.startup;
 		startup_cost += aggcosts->transCost.per_tuple * input_tuples;
 		/* cost of computing hash value */
@@ -3076,7 +3074,7 @@ final_cost_nestloop(PlannerInfo *root, NestPath *path,
 	 * disabled, which doesn't seem like the way to bet.
 	 */
 	if (!enable_nestloop)
-		startup_cost += disable_cost;
+		path->jpath.path.is_disabled = true;
 
 	/* cost of inner-relation source data (we already dealt with outer rel) */
 
@@ -3523,7 +3521,7 @@ final_cost_mergejoin(PlannerInfo *root, MergePath *path,
 	 * disabled, which doesn't seem like the way to bet.
 	 */
 	if (!enable_mergejoin)
-		startup_cost += disable_cost;
+		path->jpath.path.is_disabled = true;
 
 	/*
 	 * Compute cost of the mergequals and qpquals (other restriction clauses)
@@ -3953,7 +3951,7 @@ final_cost_hashjoin(PlannerInfo *root, HashPath *path,
 	 * disabled, which doesn't seem like the way to bet.
 	 */
 	if (!enable_hashjoin)
-		startup_cost += disable_cost;
+		path->jpath.path.is_disabled = true;
 
 	/* mark the path with estimated # of batches */
 	path->num_batches = numbatches;
@@ -4050,7 +4048,7 @@ final_cost_hashjoin(PlannerInfo *root, HashPath *path,
 	 */
 	if (relation_byte_size(clamp_row_est(inner_path_rows * innermcvfreq),
 						   inner_path->pathtarget->width) > get_hash_memory_limit())
-		startup_cost += disable_cost;
+		path->jpath.path.is_disabled = true;
 
 	/*
 	 * Compute cost of the hashquals and qpquals (other restriction clauses)
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index f123fcb41e..42d72cb1d5 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -165,6 +165,19 @@ compare_fractional_path_costs(Path *path1, Path *path2,
 static PathCostComparison
 compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor)
 {
+	if (path1->is_disabled && path2->is_disabled)
+	{
+		return COSTS_EQUAL;
+	}
+	else if (path1->is_disabled)
+	{
+		return COSTS_BETTER2;
+	}
+	else if (path2->is_disabled)
+	{
+		return COSTS_BETTER1;
+	}
+
 #define CONSIDER_PATH_STARTUP_COST(p)  \
 	((p)->param_info == NULL ? (p)->parent->consider_startup : (p)->parent->consider_param_startup)
 
@@ -940,6 +953,7 @@ create_seqscan_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->parallel_safe = rel->consider_parallel;
 	pathnode->parallel_workers = parallel_workers;
 	pathnode->pathkeys = NIL;	/* seqscan has unordered result */
+	pathnode->is_disabled = false;
 
 	cost_seqscan(pathnode, root, rel, pathnode->param_info);
 
@@ -964,6 +978,7 @@ create_samplescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer
 	pathnode->parallel_safe = rel->consider_parallel;
 	pathnode->parallel_workers = 0;
 	pathnode->pathkeys = NIL;	/* samplescan has unordered result */
+	pathnode->is_disabled = false;
 
 	cost_samplescan(pathnode, root, rel, pathnode->param_info);
 
@@ -1016,6 +1031,7 @@ create_index_path(PlannerInfo *root,
 	pathnode->path.parallel_safe = rel->consider_parallel;
 	pathnode->path.parallel_workers = 0;
 	pathnode->path.pathkeys = pathkeys;
+	pathnode->path.is_disabled = false;
 
 	pathnode->indexinfo = index;
 	pathnode->indexclauses = indexclauses;
@@ -1059,6 +1075,7 @@ create_bitmap_heap_path(PlannerInfo *root,
 	pathnode->path.parallel_safe = rel->consider_parallel;
 	pathnode->path.parallel_workers = parallel_degree;
 	pathnode->path.pathkeys = NIL;	/* always unordered */
+	pathnode->path.is_disabled = false;
 
 	pathnode->bitmapqual = bitmapqual;
 
@@ -1112,6 +1129,7 @@ create_bitmap_and_path(PlannerInfo *root,
 	pathnode->path.parallel_workers = 0;
 
 	pathnode->path.pathkeys = NIL;	/* always unordered */
+	pathnode->path.is_disabled = false;
 
 	pathnode->bitmapquals = bitmapquals;
 
@@ -1164,6 +1182,7 @@ create_bitmap_or_path(PlannerInfo *root,
 	pathnode->path.parallel_workers = 0;
 
 	pathnode->path.pathkeys = NIL;	/* always unordered */
+	pathnode->path.is_disabled = false;
 
 	pathnode->bitmapquals = bitmapquals;
 
@@ -1192,6 +1211,7 @@ create_tidscan_path(PlannerInfo *root, RelOptInfo *rel, List *tidquals,
 	pathnode->path.parallel_safe = rel->consider_parallel;
 	pathnode->path.parallel_workers = 0;
 	pathnode->path.pathkeys = NIL;	/* always unordered */
+	pathnode->path.is_disabled = false;
 
 	pathnode->tidquals = tidquals;
 
@@ -1221,6 +1241,7 @@ create_tidrangescan_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->path.parallel_safe = rel->consider_parallel;
 	pathnode->path.parallel_workers = 0;
 	pathnode->path.pathkeys = NIL;	/* always unordered */
+	pathnode->path.is_disabled = false;
 
 	pathnode->tidrangequals = tidrangequals;
 
@@ -1278,6 +1299,7 @@ create_append_path(PlannerInfo *root,
 	pathnode->path.parallel_safe = rel->consider_parallel;
 	pathnode->path.parallel_workers = parallel_workers;
 	pathnode->path.pathkeys = pathkeys;
+	pathnode->path.is_disabled = false;
 
 	/*
 	 * For parallel append, non-partial paths are sorted by descending total
@@ -1430,6 +1452,7 @@ create_merge_append_path(PlannerInfo *root,
 	pathnode->path.parallel_safe = rel->consider_parallel;
 	pathnode->path.parallel_workers = 0;
 	pathnode->path.pathkeys = pathkeys;
+	pathnode->path.is_disabled = false;
 	pathnode->subpaths = subpaths;
 
 	/*
@@ -1537,6 +1560,7 @@ create_group_result_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->path.startup_cost = target->cost.startup;
 	pathnode->path.total_cost = target->cost.startup +
 		cpu_tuple_cost + target->cost.per_tuple;
+	pathnode->path.is_disabled = false;
 
 	/*
 	 * Add cost of qual, if any --- but we ignore its selectivity, since our
@@ -1576,6 +1600,7 @@ create_material_path(RelOptInfo *rel, Path *subpath)
 		subpath->parallel_safe;
 	pathnode->path.parallel_workers = subpath->parallel_workers;
 	pathnode->path.pathkeys = subpath->pathkeys;
+	pathnode->path.is_disabled = false;
 
 	pathnode->subpath = subpath;
 
@@ -1610,6 +1635,7 @@ create_memoize_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
 		subpath->parallel_safe;
 	pathnode->path.parallel_workers = subpath->parallel_workers;
 	pathnode->path.pathkeys = subpath->pathkeys;
+	pathnode->path.is_disabled = false;
 
 	pathnode->subpath = subpath;
 	pathnode->hash_operators = hash_operators;
@@ -1701,6 +1727,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
 	 * to represent it.  (This might get overridden below.)
 	 */
 	pathnode->path.pathkeys = NIL;
+	pathnode->path.is_disabled = false;
 
 	pathnode->subpath = subpath;
 	pathnode->in_operators = sjinfo->semi_operators;
@@ -1892,6 +1919,7 @@ create_gather_merge_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
 	pathnode->path.pathkeys = pathkeys;
 	pathnode->path.pathtarget = target ? target : rel->reltarget;
 	pathnode->path.rows += subpath->rows;
+	pathnode->path.is_disabled = false;
 
 	if (pathkeys_contained_in(pathkeys, subpath->pathkeys))
 	{
@@ -1977,6 +2005,7 @@ create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
 	pathnode->path.parallel_safe = false;
 	pathnode->path.parallel_workers = 0;
 	pathnode->path.pathkeys = NIL;	/* Gather has unordered result */
+	pathnode->path.is_disabled = false;
 
 	pathnode->subpath = subpath;
 	pathnode->num_workers = subpath->parallel_workers;
@@ -2021,6 +2050,7 @@ create_subqueryscan_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
 		subpath->parallel_safe;
 	pathnode->path.parallel_workers = subpath->parallel_workers;
 	pathnode->path.pathkeys = pathkeys;
+	pathnode->path.is_disabled = false;
 	pathnode->subpath = subpath;
 
 	cost_subqueryscan(pathnode, root, rel, pathnode->path.param_info,
@@ -2049,6 +2079,7 @@ create_functionscan_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->parallel_safe = rel->consider_parallel;
 	pathnode->parallel_workers = 0;
 	pathnode->pathkeys = pathkeys;
+	pathnode->is_disabled = false;
 
 	cost_functionscan(pathnode, root, rel, pathnode->param_info);
 
@@ -2075,6 +2106,7 @@ create_tablefuncscan_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->parallel_safe = rel->consider_parallel;
 	pathnode->parallel_workers = 0;
 	pathnode->pathkeys = NIL;	/* result is always unordered */
+	pathnode->is_disabled = false;
 
 	cost_tablefuncscan(pathnode, root, rel, pathnode->param_info);
 
@@ -2101,6 +2133,7 @@ create_valuesscan_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->parallel_safe = rel->consider_parallel;
 	pathnode->parallel_workers = 0;
 	pathnode->pathkeys = NIL;	/* result is always unordered */
+	pathnode->is_disabled = false;
 
 	cost_valuesscan(pathnode, root, rel, pathnode->param_info);
 
@@ -2126,6 +2159,7 @@ create_ctescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
 	pathnode->parallel_safe = rel->consider_parallel;
 	pathnode->parallel_workers = 0;
 	pathnode->pathkeys = NIL;	/* XXX for now, result is always unordered */
+	pathnode->is_disabled = false;
 
 	cost_ctescan(pathnode, root, rel, pathnode->param_info);
 
@@ -2152,6 +2186,7 @@ create_namedtuplestorescan_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->parallel_safe = rel->consider_parallel;
 	pathnode->parallel_workers = 0;
 	pathnode->pathkeys = NIL;	/* result is always unordered */
+	pathnode->is_disabled = false;
 
 	cost_namedtuplestorescan(pathnode, root, rel, pathnode->param_info);
 
@@ -2178,6 +2213,7 @@ create_resultscan_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->parallel_safe = rel->consider_parallel;
 	pathnode->parallel_workers = 0;
 	pathnode->pathkeys = NIL;	/* result is always unordered */
+	pathnode->is_disabled = false;
 
 	cost_resultscan(pathnode, root, rel, pathnode->param_info);
 
@@ -2204,6 +2240,7 @@ create_worktablescan_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->parallel_safe = rel->consider_parallel;
 	pathnode->parallel_workers = 0;
 	pathnode->pathkeys = NIL;	/* result is always unordered */
+	pathnode->is_disabled = false;
 
 	/* Cost is the same as for a regular CTE scan */
 	cost_ctescan(pathnode, root, rel, pathnode->param_info);
@@ -2248,6 +2285,7 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->path.startup_cost = startup_cost;
 	pathnode->path.total_cost = total_cost;
 	pathnode->path.pathkeys = pathkeys;
+	pathnode->path.is_disabled = false;
 
 	pathnode->fdw_outerpath = fdw_outerpath;
 	pathnode->fdw_private = fdw_private;
@@ -2298,6 +2336,7 @@ create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->path.startup_cost = startup_cost;
 	pathnode->path.total_cost = total_cost;
 	pathnode->path.pathkeys = pathkeys;
+	pathnode->path.is_disabled = false;
 
 	pathnode->fdw_outerpath = fdw_outerpath;
 	pathnode->fdw_private = fdw_private;
@@ -2343,6 +2382,7 @@ create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->path.startup_cost = startup_cost;
 	pathnode->path.total_cost = total_cost;
 	pathnode->path.pathkeys = pathkeys;
+	pathnode->path.is_disabled = false;
 
 	pathnode->fdw_outerpath = fdw_outerpath;
 	pathnode->fdw_private = fdw_private;
@@ -2472,6 +2512,7 @@ create_nestloop_path(PlannerInfo *root,
 	/* This is a foolish way to estimate parallel_workers, but for now... */
 	pathnode->jpath.path.parallel_workers = outer_path->parallel_workers;
 	pathnode->jpath.path.pathkeys = pathkeys;
+	pathnode->jpath.path.is_disabled = false;
 	pathnode->jpath.jointype = jointype;
 	pathnode->jpath.inner_unique = extra->inner_unique;
 	pathnode->jpath.outerjoinpath = outer_path;
@@ -2536,6 +2577,7 @@ create_mergejoin_path(PlannerInfo *root,
 	/* This is a foolish way to estimate parallel_workers, but for now... */
 	pathnode->jpath.path.parallel_workers = outer_path->parallel_workers;
 	pathnode->jpath.path.pathkeys = pathkeys;
+	pathnode->jpath.path.is_disabled = false;
 	pathnode->jpath.jointype = jointype;
 	pathnode->jpath.inner_unique = extra->inner_unique;
 	pathnode->jpath.outerjoinpath = outer_path;
@@ -2613,6 +2655,7 @@ create_hashjoin_path(PlannerInfo *root,
 	 * outer rel than it does now.)
 	 */
 	pathnode->jpath.path.pathkeys = NIL;
+	pathnode->jpath.path.is_disabled = false;
 	pathnode->jpath.jointype = jointype;
 	pathnode->jpath.inner_unique = extra->inner_unique;
 	pathnode->jpath.outerjoinpath = outer_path;
@@ -2671,6 +2714,7 @@ create_projection_path(PlannerInfo *root,
 	pathnode->path.parallel_workers = subpath->parallel_workers;
 	/* Projection does not change the sort order */
 	pathnode->path.pathkeys = subpath->pathkeys;
+	pathnode->path.is_disabled = false;
 
 	pathnode->subpath = subpath;
 
@@ -2853,6 +2897,7 @@ create_set_projection_path(PlannerInfo *root,
 	pathnode->path.parallel_workers = subpath->parallel_workers;
 	/* Projection does not change the sort order XXX? */
 	pathnode->path.pathkeys = subpath->pathkeys;
+	pathnode->path.is_disabled = false;
 
 	pathnode->subpath = subpath;
 
@@ -2922,6 +2967,7 @@ create_incremental_sort_path(PlannerInfo *root,
 		subpath->parallel_safe;
 	pathnode->path.parallel_workers = subpath->parallel_workers;
 	pathnode->path.pathkeys = pathkeys;
+	pathnode->path.is_disabled = false;
 
 	pathnode->subpath = subpath;
 
@@ -2969,6 +3015,7 @@ create_sort_path(PlannerInfo *root,
 		subpath->parallel_safe;
 	pathnode->path.parallel_workers = subpath->parallel_workers;
 	pathnode->path.pathkeys = pathkeys;
+	pathnode->path.is_disabled = false;
 
 	pathnode->subpath = subpath;
 
@@ -3015,6 +3062,7 @@ create_group_path(PlannerInfo *root,
 	pathnode->path.parallel_workers = subpath->parallel_workers;
 	/* Group doesn't change sort ordering */
 	pathnode->path.pathkeys = subpath->pathkeys;
+	pathnode->path.is_disabled = false;
 
 	pathnode->subpath = subpath;
 
@@ -3073,6 +3121,7 @@ create_upper_unique_path(PlannerInfo *root,
 	pathnode->path.parallel_workers = subpath->parallel_workers;
 	/* Unique doesn't change the input ordering */
 	pathnode->path.pathkeys = subpath->pathkeys;
+	pathnode->path.is_disabled = false;
 
 	pathnode->subpath = subpath;
 	pathnode->numkeys = numCols;
@@ -3151,6 +3200,7 @@ create_agg_path(PlannerInfo *root,
 	pathnode->path.startup_cost += target->cost.startup;
 	pathnode->path.total_cost += target->cost.startup +
 		target->cost.per_tuple * pathnode->path.rows;
+	pathnode->path.is_disabled = false;
 
 	return pathnode;
 }
@@ -3194,6 +3244,7 @@ create_groupingsets_path(PlannerInfo *root,
 	pathnode->path.parallel_safe = rel->consider_parallel &&
 		subpath->parallel_safe;
 	pathnode->path.parallel_workers = subpath->parallel_workers;
+	pathnode->path.is_disabled = false;
 	pathnode->subpath = subpath;
 
 	/*
@@ -3353,6 +3404,7 @@ create_minmaxagg_path(PlannerInfo *root,
 	/* Result is one unordered row */
 	pathnode->path.rows = 1;
 	pathnode->path.pathkeys = NIL;
+	pathnode->path.is_disabled = false;
 
 	pathnode->mmaggregates = mmaggregates;
 	pathnode->quals = quals;
@@ -3443,6 +3495,7 @@ create_windowagg_path(PlannerInfo *root,
 	pathnode->path.parallel_workers = subpath->parallel_workers;
 	/* WindowAgg preserves the input sort order */
 	pathnode->path.pathkeys = subpath->pathkeys;
+	pathnode->path.is_disabled = false;
 
 	pathnode->subpath = subpath;
 	pathnode->winclause = winclause;
@@ -3513,6 +3566,7 @@ create_setop_path(PlannerInfo *root,
 	/* SetOp preserves the input sort order if in sort mode */
 	pathnode->path.pathkeys =
 		(strategy == SETOP_SORTED) ? subpath->pathkeys : NIL;
+	pathnode->path.is_disabled = false;
 
 	pathnode->subpath = subpath;
 	pathnode->cmd = cmd;
@@ -3572,6 +3626,7 @@ create_recursiveunion_path(PlannerInfo *root,
 	pathnode->path.parallel_workers = leftpath->parallel_workers;
 	/* RecursiveUnion result is always unsorted */
 	pathnode->path.pathkeys = NIL;
+	pathnode->path.is_disabled = false;
 
 	pathnode->leftpath = leftpath;
 	pathnode->rightpath = rightpath;
@@ -3628,6 +3683,7 @@ create_lockrows_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->path.startup_cost = subpath->startup_cost;
 	pathnode->path.total_cost = subpath->total_cost +
 		cpu_tuple_cost * subpath->rows;
+	pathnode->path.is_disabled = false;
 
 	return pathnode;
 }
@@ -3688,6 +3744,7 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->path.parallel_safe = false;
 	pathnode->path.parallel_workers = 0;
 	pathnode->path.pathkeys = NIL;
+	pathnode->path.is_disabled = false;
 
 	/*
 	 * Compute cost & rowcount as subpath cost & rowcount (if RETURNING)
@@ -3777,6 +3834,7 @@ create_limit_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->path.startup_cost = subpath->startup_cost;
 	pathnode->path.total_cost = subpath->total_cost;
 	pathnode->path.pathkeys = subpath->pathkeys;
+	pathnode->path.is_disabled = false;
 	pathnode->subpath = subpath;
 	pathnode->limitOffset = limitOffset;
 	pathnode->limitCount = limitCount;
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index a1dc1d07e1..50c5b65bde 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -1631,6 +1631,7 @@ typedef struct Path
 
 	/* sort ordering of path's output; a List of PathKey nodes; see above */
 	List	   *pathkeys;
+	bool		is_disabled;
 } Path;
 
 /* Macro for extracting a path's parameterization relids; beware double eval */
-- 
2.41.0

Reply via email to