mirror of
https://github.com/postgres/postgres.git
synced 2025-07-15 19:21:59 +03:00
Make sequential scans parallel-aware.
In addition, this path fills in a number of missing bits and pieces in the parallel infrastructure. Paths and plans now have a parallel_aware flag indicating whether whatever parallel-aware logic they have should be engaged. It is believed that we will need this flag for a number of path/plan types, not just sequential scans, which is why the flag is generic rather than part of the SeqScan structures specifically. Also, execParallel.c now gives parallel nodes a chance to initialize their PlanState nodes from the DSM during parallel worker startup. Amit Kapila, with a fair amount of adjustment by me. Review of previous patch versions by Haribabu Kommi and others.
This commit is contained in:
@ -475,7 +475,7 @@ set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
|
||||
required_outer = rel->lateral_relids;
|
||||
|
||||
/* Consider sequential scan */
|
||||
add_path(rel, create_seqscan_path(root, rel, required_outer));
|
||||
add_path(rel, create_seqscan_path(root, rel, required_outer, 0));
|
||||
|
||||
/* Consider index scans */
|
||||
create_index_paths(root, rel);
|
||||
|
@ -181,10 +181,13 @@ clamp_row_est(double nrows)
|
||||
*
|
||||
* 'baserel' is the relation to be scanned
|
||||
* 'param_info' is the ParamPathInfo if this is a parameterized path, else NULL
|
||||
* 'nworkers' are the number of workers among which the work will be
|
||||
* distributed if the scan is parallel scan
|
||||
*/
|
||||
void
|
||||
cost_seqscan(Path *path, PlannerInfo *root,
|
||||
RelOptInfo *baserel, ParamPathInfo *param_info)
|
||||
RelOptInfo *baserel, ParamPathInfo *param_info,
|
||||
int nworkers)
|
||||
{
|
||||
Cost startup_cost = 0;
|
||||
Cost run_cost = 0;
|
||||
@ -222,6 +225,16 @@ cost_seqscan(Path *path, PlannerInfo *root,
|
||||
cpu_per_tuple = cpu_tuple_cost + qpqual_cost.per_tuple;
|
||||
run_cost += cpu_per_tuple * baserel->tuples;
|
||||
|
||||
/*
|
||||
* Primitive parallel cost model. Assume the leader will do half as much
|
||||
* work as a regular worker, because it will also need to read the tuples
|
||||
* returned by the workers when they percolate up to the gather ndoe.
|
||||
* This is almost certainly not exactly the right way to model this, so
|
||||
* this will probably need to be changed at some point...
|
||||
*/
|
||||
if (nworkers > 0)
|
||||
run_cost = run_cost / (nworkers + 0.5);
|
||||
|
||||
path->startup_cost = startup_cost;
|
||||
path->total_cost = startup_cost + run_cost;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ static List *fix_indexorderby_references(PlannerInfo *root, IndexPath *index_pat
|
||||
static Node *fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol);
|
||||
static List *get_switched_clauses(List *clauses, Relids outerrelids);
|
||||
static List *order_qual_clauses(PlannerInfo *root, List *clauses);
|
||||
static void copy_path_costsize(Plan *dest, Path *src);
|
||||
static void copy_generic_path_info(Plan *dest, Path *src);
|
||||
static void copy_plan_costsize(Plan *dest, Plan *src);
|
||||
static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
|
||||
static SampleScan *make_samplescan(List *qptlist, List *qpqual, Index scanrelid,
|
||||
@ -779,7 +779,7 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path)
|
||||
* prepare_sort_from_pathkeys on it before we do so on the individual
|
||||
* child plans, to make cross-checking the sort info easier.
|
||||
*/
|
||||
copy_path_costsize(plan, (Path *) best_path);
|
||||
copy_generic_path_info(plan, (Path *) best_path);
|
||||
plan->targetlist = tlist;
|
||||
plan->qual = NIL;
|
||||
plan->lefttree = NULL;
|
||||
@ -901,7 +901,7 @@ create_material_plan(PlannerInfo *root, MaterialPath *best_path)
|
||||
|
||||
plan = make_material(subplan);
|
||||
|
||||
copy_path_costsize(&plan->plan, (Path *) best_path);
|
||||
copy_generic_path_info(&plan->plan, (Path *) best_path);
|
||||
|
||||
return plan;
|
||||
}
|
||||
@ -1129,7 +1129,7 @@ create_gather_plan(PlannerInfo *root, GatherPath *best_path)
|
||||
best_path->single_copy,
|
||||
subplan);
|
||||
|
||||
copy_path_costsize(&gather_plan->plan, &best_path->path);
|
||||
copy_generic_path_info(&gather_plan->plan, &best_path->path);
|
||||
|
||||
/* use parallel mode for parallel plans. */
|
||||
root->glob->parallelModeNeeded = true;
|
||||
@ -1178,7 +1178,7 @@ create_seqscan_plan(PlannerInfo *root, Path *best_path,
|
||||
scan_clauses,
|
||||
scan_relid);
|
||||
|
||||
copy_path_costsize(&scan_plan->plan, best_path);
|
||||
copy_generic_path_info(&scan_plan->plan, best_path);
|
||||
|
||||
return scan_plan;
|
||||
}
|
||||
@ -1224,7 +1224,7 @@ create_samplescan_plan(PlannerInfo *root, Path *best_path,
|
||||
scan_relid,
|
||||
tsc);
|
||||
|
||||
copy_path_costsize(&scan_plan->scan.plan, best_path);
|
||||
copy_generic_path_info(&scan_plan->scan.plan, best_path);
|
||||
|
||||
return scan_plan;
|
||||
}
|
||||
@ -1422,7 +1422,7 @@ create_indexscan_plan(PlannerInfo *root,
|
||||
indexorderbyops,
|
||||
best_path->indexscandir);
|
||||
|
||||
copy_path_costsize(&scan_plan->plan, &best_path->path);
|
||||
copy_generic_path_info(&scan_plan->plan, &best_path->path);
|
||||
|
||||
return scan_plan;
|
||||
}
|
||||
@ -1538,7 +1538,7 @@ create_bitmap_scan_plan(PlannerInfo *root,
|
||||
bitmapqualorig,
|
||||
baserelid);
|
||||
|
||||
copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
|
||||
copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
|
||||
|
||||
return scan_plan;
|
||||
}
|
||||
@ -1795,7 +1795,7 @@ create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
|
||||
scan_relid,
|
||||
tidquals);
|
||||
|
||||
copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
|
||||
copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
|
||||
|
||||
return scan_plan;
|
||||
}
|
||||
@ -1836,7 +1836,7 @@ create_subqueryscan_plan(PlannerInfo *root, Path *best_path,
|
||||
scan_relid,
|
||||
best_path->parent->subplan);
|
||||
|
||||
copy_path_costsize(&scan_plan->scan.plan, best_path);
|
||||
copy_generic_path_info(&scan_plan->scan.plan, best_path);
|
||||
|
||||
return scan_plan;
|
||||
}
|
||||
@ -1879,7 +1879,7 @@ create_functionscan_plan(PlannerInfo *root, Path *best_path,
|
||||
scan_plan = make_functionscan(tlist, scan_clauses, scan_relid,
|
||||
functions, rte->funcordinality);
|
||||
|
||||
copy_path_costsize(&scan_plan->scan.plan, best_path);
|
||||
copy_generic_path_info(&scan_plan->scan.plan, best_path);
|
||||
|
||||
return scan_plan;
|
||||
}
|
||||
@ -1923,7 +1923,7 @@ create_valuesscan_plan(PlannerInfo *root, Path *best_path,
|
||||
scan_plan = make_valuesscan(tlist, scan_clauses, scan_relid,
|
||||
values_lists);
|
||||
|
||||
copy_path_costsize(&scan_plan->scan.plan, best_path);
|
||||
copy_generic_path_info(&scan_plan->scan.plan, best_path);
|
||||
|
||||
return scan_plan;
|
||||
}
|
||||
@ -2016,7 +2016,7 @@ create_ctescan_plan(PlannerInfo *root, Path *best_path,
|
||||
scan_plan = make_ctescan(tlist, scan_clauses, scan_relid,
|
||||
plan_id, cte_param_id);
|
||||
|
||||
copy_path_costsize(&scan_plan->scan.plan, best_path);
|
||||
copy_generic_path_info(&scan_plan->scan.plan, best_path);
|
||||
|
||||
return scan_plan;
|
||||
}
|
||||
@ -2076,7 +2076,7 @@ create_worktablescan_plan(PlannerInfo *root, Path *best_path,
|
||||
scan_plan = make_worktablescan(tlist, scan_clauses, scan_relid,
|
||||
cteroot->wt_param_id);
|
||||
|
||||
copy_path_costsize(&scan_plan->scan.plan, best_path);
|
||||
copy_generic_path_info(&scan_plan->scan.plan, best_path);
|
||||
|
||||
return scan_plan;
|
||||
}
|
||||
@ -2132,7 +2132,7 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
|
||||
tlist, scan_clauses);
|
||||
|
||||
/* Copy cost data from Path to Plan; no need to make FDW do this */
|
||||
copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
|
||||
copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
|
||||
|
||||
/* Copy foreign server OID; likewise, no need to make FDW do this */
|
||||
scan_plan->fs_server = rel->serverid;
|
||||
@ -2238,7 +2238,7 @@ create_customscan_plan(PlannerInfo *root, CustomPath *best_path,
|
||||
* Copy cost data from Path to Plan; no need to make custom-plan providers
|
||||
* do this
|
||||
*/
|
||||
copy_path_costsize(&cplan->scan.plan, &best_path->path);
|
||||
copy_generic_path_info(&cplan->scan.plan, &best_path->path);
|
||||
|
||||
/* Likewise, copy the relids that are represented by this custom scan */
|
||||
cplan->custom_relids = best_path->path.parent->relids;
|
||||
@ -2355,7 +2355,7 @@ create_nestloop_plan(PlannerInfo *root,
|
||||
inner_plan,
|
||||
best_path->jointype);
|
||||
|
||||
copy_path_costsize(&join_plan->join.plan, &best_path->path);
|
||||
copy_generic_path_info(&join_plan->join.plan, &best_path->path);
|
||||
|
||||
return join_plan;
|
||||
}
|
||||
@ -2650,7 +2650,7 @@ create_mergejoin_plan(PlannerInfo *root,
|
||||
best_path->jpath.jointype);
|
||||
|
||||
/* Costs of sort and material steps are included in path cost already */
|
||||
copy_path_costsize(&join_plan->join.plan, &best_path->jpath.path);
|
||||
copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
|
||||
|
||||
return join_plan;
|
||||
}
|
||||
@ -2775,7 +2775,7 @@ create_hashjoin_plan(PlannerInfo *root,
|
||||
(Plan *) hash_plan,
|
||||
best_path->jpath.jointype);
|
||||
|
||||
copy_path_costsize(&join_plan->join.plan, &best_path->jpath.path);
|
||||
copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
|
||||
|
||||
return join_plan;
|
||||
}
|
||||
@ -3411,9 +3411,11 @@ order_qual_clauses(PlannerInfo *root, List *clauses)
|
||||
/*
|
||||
* Copy cost and size info from a Path node to the Plan node created from it.
|
||||
* The executor usually won't use this info, but it's needed by EXPLAIN.
|
||||
*
|
||||
* Also copy the parallel-aware flag, which the executor will use.
|
||||
*/
|
||||
static void
|
||||
copy_path_costsize(Plan *dest, Path *src)
|
||||
copy_generic_path_info(Plan *dest, Path *src)
|
||||
{
|
||||
if (src)
|
||||
{
|
||||
@ -3421,6 +3423,7 @@ copy_path_costsize(Plan *dest, Path *src)
|
||||
dest->total_cost = src->total_cost;
|
||||
dest->plan_rows = src->rows;
|
||||
dest->plan_width = src->parent->width;
|
||||
dest->parallel_aware = src->parallel_aware;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3428,6 +3431,7 @@ copy_path_costsize(Plan *dest, Path *src)
|
||||
dest->total_cost = 0;
|
||||
dest->plan_rows = 0;
|
||||
dest->plan_width = 0;
|
||||
dest->parallel_aware = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4690,7 +4690,7 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid)
|
||||
comparisonCost = 2.0 * (indexExprCost.startup + indexExprCost.per_tuple);
|
||||
|
||||
/* Estimate the cost of seq scan + sort */
|
||||
seqScanPath = create_seqscan_path(root, rel, NULL);
|
||||
seqScanPath = create_seqscan_path(root, rel, NULL, 0);
|
||||
cost_sort(&seqScanAndSortPath, root, NIL,
|
||||
seqScanPath->total_cost, rel->tuples, rel->width,
|
||||
comparisonCost, maintenance_work_mem, -1.0);
|
||||
|
@ -696,7 +696,8 @@ add_path_precheck(RelOptInfo *parent_rel,
|
||||
* pathnode.
|
||||
*/
|
||||
Path *
|
||||
create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
|
||||
create_seqscan_path(PlannerInfo *root, RelOptInfo *rel,
|
||||
Relids required_outer, int nworkers)
|
||||
{
|
||||
Path *pathnode = makeNode(Path);
|
||||
|
||||
@ -704,9 +705,10 @@ create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
|
||||
pathnode->parent = rel;
|
||||
pathnode->param_info = get_baserel_parampathinfo(root, rel,
|
||||
required_outer);
|
||||
pathnode->parallel_aware = nworkers > 0 ? true : false;
|
||||
pathnode->pathkeys = NIL; /* seqscan has unordered result */
|
||||
|
||||
cost_seqscan(pathnode, root, rel, pathnode->param_info);
|
||||
cost_seqscan(pathnode, root, rel, pathnode->param_info, nworkers);
|
||||
|
||||
return pathnode;
|
||||
}
|
||||
@ -724,6 +726,7 @@ create_samplescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer
|
||||
pathnode->parent = rel;
|
||||
pathnode->param_info = get_baserel_parampathinfo(root, rel,
|
||||
required_outer);
|
||||
pathnode->parallel_aware = false;
|
||||
pathnode->pathkeys = NIL; /* samplescan has unordered result */
|
||||
|
||||
cost_samplescan(pathnode, root, rel, pathnode->param_info);
|
||||
@ -777,6 +780,7 @@ create_index_path(PlannerInfo *root,
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
|
||||
required_outer);
|
||||
pathnode->path.parallel_aware = false;
|
||||
pathnode->path.pathkeys = pathkeys;
|
||||
|
||||
/* Convert clauses to indexquals the executor can handle */
|
||||
@ -822,6 +826,7 @@ create_bitmap_heap_path(PlannerInfo *root,
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
|
||||
required_outer);
|
||||
pathnode->path.parallel_aware = false;
|
||||
pathnode->path.pathkeys = NIL; /* always unordered */
|
||||
|
||||
pathnode->bitmapqual = bitmapqual;
|
||||
@ -847,6 +852,7 @@ create_bitmap_and_path(PlannerInfo *root,
|
||||
pathnode->path.pathtype = T_BitmapAnd;
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.param_info = NULL; /* not used in bitmap trees */
|
||||
pathnode->path.parallel_aware = false;
|
||||
pathnode->path.pathkeys = NIL; /* always unordered */
|
||||
|
||||
pathnode->bitmapquals = bitmapquals;
|
||||
@ -871,6 +877,7 @@ create_bitmap_or_path(PlannerInfo *root,
|
||||
pathnode->path.pathtype = T_BitmapOr;
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.param_info = NULL; /* not used in bitmap trees */
|
||||
pathnode->path.parallel_aware = false;
|
||||
pathnode->path.pathkeys = NIL; /* always unordered */
|
||||
|
||||
pathnode->bitmapquals = bitmapquals;
|
||||
@ -895,6 +902,7 @@ create_tidscan_path(PlannerInfo *root, RelOptInfo *rel, List *tidquals,
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
|
||||
required_outer);
|
||||
pathnode->path.parallel_aware = false;
|
||||
pathnode->path.pathkeys = NIL; /* always unordered */
|
||||
|
||||
pathnode->tidquals = tidquals;
|
||||
@ -922,6 +930,7 @@ create_append_path(RelOptInfo *rel, List *subpaths, Relids required_outer)
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.param_info = get_appendrel_parampathinfo(rel,
|
||||
required_outer);
|
||||
pathnode->path.parallel_aware = false;
|
||||
pathnode->path.pathkeys = NIL; /* result is always considered
|
||||
* unsorted */
|
||||
pathnode->subpaths = subpaths;
|
||||
@ -975,6 +984,7 @@ create_merge_append_path(PlannerInfo *root,
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.param_info = get_appendrel_parampathinfo(rel,
|
||||
required_outer);
|
||||
pathnode->path.parallel_aware = false;
|
||||
pathnode->path.pathkeys = pathkeys;
|
||||
pathnode->subpaths = subpaths;
|
||||
|
||||
@ -1049,6 +1059,7 @@ create_result_path(List *quals)
|
||||
pathnode->path.pathtype = T_Result;
|
||||
pathnode->path.parent = NULL;
|
||||
pathnode->path.param_info = NULL; /* there are no other rels... */
|
||||
pathnode->path.parallel_aware = false;
|
||||
pathnode->path.pathkeys = NIL;
|
||||
pathnode->quals = quals;
|
||||
|
||||
@ -1082,6 +1093,7 @@ create_material_path(RelOptInfo *rel, Path *subpath)
|
||||
pathnode->path.pathtype = T_Material;
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.param_info = subpath->param_info;
|
||||
pathnode->path.parallel_aware = false;
|
||||
pathnode->path.pathkeys = subpath->pathkeys;
|
||||
|
||||
pathnode->subpath = subpath;
|
||||
@ -1142,6 +1154,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
|
||||
pathnode->path.pathtype = T_Unique;
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.param_info = subpath->param_info;
|
||||
pathnode->path.parallel_aware = false;
|
||||
|
||||
/*
|
||||
* Assume the output is unsorted, since we don't necessarily have pathkeys
|
||||
@ -1323,6 +1336,7 @@ create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
|
||||
required_outer);
|
||||
pathnode->path.parallel_aware = false;
|
||||
pathnode->path.pathkeys = NIL; /* Gather has unordered result */
|
||||
|
||||
pathnode->subpath = subpath;
|
||||
@ -1378,6 +1392,7 @@ create_subqueryscan_path(PlannerInfo *root, RelOptInfo *rel,
|
||||
pathnode->parent = rel;
|
||||
pathnode->param_info = get_baserel_parampathinfo(root, rel,
|
||||
required_outer);
|
||||
pathnode->parallel_aware = false;
|
||||
pathnode->pathkeys = pathkeys;
|
||||
|
||||
cost_subqueryscan(pathnode, root, rel, pathnode->param_info);
|
||||
@ -1400,6 +1415,7 @@ create_functionscan_path(PlannerInfo *root, RelOptInfo *rel,
|
||||
pathnode->parent = rel;
|
||||
pathnode->param_info = get_baserel_parampathinfo(root, rel,
|
||||
required_outer);
|
||||
pathnode->parallel_aware = false;
|
||||
pathnode->pathkeys = pathkeys;
|
||||
|
||||
cost_functionscan(pathnode, root, rel, pathnode->param_info);
|
||||
@ -1422,6 +1438,7 @@ create_valuesscan_path(PlannerInfo *root, RelOptInfo *rel,
|
||||
pathnode->parent = rel;
|
||||
pathnode->param_info = get_baserel_parampathinfo(root, rel,
|
||||
required_outer);
|
||||
pathnode->parallel_aware = false;
|
||||
pathnode->pathkeys = NIL; /* result is always unordered */
|
||||
|
||||
cost_valuesscan(pathnode, root, rel, pathnode->param_info);
|
||||
@ -1443,6 +1460,7 @@ create_ctescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
|
||||
pathnode->parent = rel;
|
||||
pathnode->param_info = get_baserel_parampathinfo(root, rel,
|
||||
required_outer);
|
||||
pathnode->parallel_aware = false;
|
||||
pathnode->pathkeys = NIL; /* XXX for now, result is always unordered */
|
||||
|
||||
cost_ctescan(pathnode, root, rel, pathnode->param_info);
|
||||
@ -1465,6 +1483,7 @@ create_worktablescan_path(PlannerInfo *root, RelOptInfo *rel,
|
||||
pathnode->parent = rel;
|
||||
pathnode->param_info = get_baserel_parampathinfo(root, rel,
|
||||
required_outer);
|
||||
pathnode->parallel_aware = false;
|
||||
pathnode->pathkeys = NIL; /* result is always unordered */
|
||||
|
||||
/* Cost is the same as for a regular CTE scan */
|
||||
@ -1496,6 +1515,7 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
|
||||
required_outer);
|
||||
pathnode->path.parallel_aware = false;
|
||||
pathnode->path.rows = rows;
|
||||
pathnode->path.startup_cost = startup_cost;
|
||||
pathnode->path.total_cost = total_cost;
|
||||
@ -1630,6 +1650,7 @@ create_nestloop_path(PlannerInfo *root,
|
||||
sjinfo,
|
||||
required_outer,
|
||||
&restrict_clauses);
|
||||
pathnode->path.parallel_aware = false;
|
||||
pathnode->path.pathkeys = pathkeys;
|
||||
pathnode->jointype = jointype;
|
||||
pathnode->outerjoinpath = outer_path;
|
||||
@ -1687,6 +1708,7 @@ create_mergejoin_path(PlannerInfo *root,
|
||||
sjinfo,
|
||||
required_outer,
|
||||
&restrict_clauses);
|
||||
pathnode->jpath.path.parallel_aware = false;
|
||||
pathnode->jpath.path.pathkeys = pathkeys;
|
||||
pathnode->jpath.jointype = jointype;
|
||||
pathnode->jpath.outerjoinpath = outer_path;
|
||||
@ -1743,6 +1765,7 @@ create_hashjoin_path(PlannerInfo *root,
|
||||
sjinfo,
|
||||
required_outer,
|
||||
&restrict_clauses);
|
||||
pathnode->jpath.path.parallel_aware = false;
|
||||
|
||||
/*
|
||||
* A hashjoin never has pathkeys, since its output ordering is
|
||||
@ -1798,7 +1821,7 @@ reparameterize_path(PlannerInfo *root, Path *path,
|
||||
switch (path->pathtype)
|
||||
{
|
||||
case T_SeqScan:
|
||||
return create_seqscan_path(root, rel, required_outer);
|
||||
return create_seqscan_path(root, rel, required_outer, 0);
|
||||
case T_SampleScan:
|
||||
return (Path *) create_samplescan_path(root, rel, required_outer);
|
||||
case T_IndexScan:
|
||||
|
Reference in New Issue
Block a user