mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03:00
Move PartitionPruneInfo out of plan nodes into PlannedStmt
This moves PartitionPruneInfo from plan nodes to PlannedStmt, simplifying traversal by centralizing all PartitionPruneInfo structures in a single list in it, which holds all instances for the main query and its subqueries. Instead of plan nodes (Append or MergeAppend) storing PartitionPruneInfo pointers, they now reference an index in this list. A bitmapset field is added to PartitionPruneInfo to store the RT indexes corresponding to the apprelids field in Append or MergeAppend. This allows execution pruning logic to verify that it operates on the correct plan node, mainly to facilitate debugging. Duplicated code in set_append_references() and set_mergeappend_references() is refactored into a new function, register_pruneinfo(). This updates RT indexes by applying rtoffet and adds PartitionPruneInfo to the global list in PlannerGlobal. By allowing pruning to be performed without traversing the plan tree, this change lays the groundwork for runtime initial pruning to occur independently of plan tree initialization. Reviewed-by: Alvaro Herrera <alvherre@alvh.no-ip.org> (earlier version) Reviewed-by: Robert Haas <robertmhaas@gmail.com> Reviewed-by: Tomas Vondra <tomas@vondra.me> Discussion: https://postgr.es/m/CA+HiwqFGkMSge6TgC9KQzde0ohpAycLQuV7ooitEEpbKB0O_mg@mail.gmail.com
This commit is contained in:
@@ -1227,7 +1227,6 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
|
||||
ListCell *subpaths;
|
||||
int nasyncplans = 0;
|
||||
RelOptInfo *rel = best_path->path.parent;
|
||||
PartitionPruneInfo *partpruneinfo = NULL;
|
||||
int nodenumsortkeys = 0;
|
||||
AttrNumber *nodeSortColIdx = NULL;
|
||||
Oid *nodeSortOperators = NULL;
|
||||
@@ -1378,6 +1377,9 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
|
||||
subplans = lappend(subplans, subplan);
|
||||
}
|
||||
|
||||
/* Set below if we find quals that we can use to run-time prune */
|
||||
plan->part_prune_index = -1;
|
||||
|
||||
/*
|
||||
* If any quals exist, they may be useful to perform further partition
|
||||
* pruning during execution. Gather information needed by the executor to
|
||||
@@ -1401,16 +1403,14 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
|
||||
}
|
||||
|
||||
if (prunequal != NIL)
|
||||
partpruneinfo =
|
||||
make_partition_pruneinfo(root, rel,
|
||||
best_path->subpaths,
|
||||
prunequal);
|
||||
plan->part_prune_index = make_partition_pruneinfo(root, rel,
|
||||
best_path->subpaths,
|
||||
prunequal);
|
||||
}
|
||||
|
||||
plan->appendplans = subplans;
|
||||
plan->nasyncplans = nasyncplans;
|
||||
plan->first_partial_plan = best_path->first_partial_path;
|
||||
plan->part_prune_info = partpruneinfo;
|
||||
|
||||
copy_generic_path_info(&plan->plan, (Path *) best_path);
|
||||
|
||||
@@ -1449,7 +1449,6 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path,
|
||||
List *subplans = NIL;
|
||||
ListCell *subpaths;
|
||||
RelOptInfo *rel = best_path->path.parent;
|
||||
PartitionPruneInfo *partpruneinfo = NULL;
|
||||
|
||||
/*
|
||||
* We don't have the actual creation of the MergeAppend node split out
|
||||
@@ -1542,6 +1541,9 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path,
|
||||
subplans = lappend(subplans, subplan);
|
||||
}
|
||||
|
||||
/* Set below if we find quals that we can use to run-time prune */
|
||||
node->part_prune_index = -1;
|
||||
|
||||
/*
|
||||
* If any quals exist, they may be useful to perform further partition
|
||||
* pruning during execution. Gather information needed by the executor to
|
||||
@@ -1557,13 +1559,12 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path,
|
||||
Assert(best_path->path.param_info == NULL);
|
||||
|
||||
if (prunequal != NIL)
|
||||
partpruneinfo = make_partition_pruneinfo(root, rel,
|
||||
best_path->subpaths,
|
||||
prunequal);
|
||||
node->part_prune_index = make_partition_pruneinfo(root, rel,
|
||||
best_path->subpaths,
|
||||
prunequal);
|
||||
}
|
||||
|
||||
node->mergeplans = subplans;
|
||||
node->part_prune_info = partpruneinfo;
|
||||
|
||||
/*
|
||||
* If prepare_sort_from_pathkeys added sort columns, but we were told to
|
||||
|
||||
@@ -555,6 +555,7 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions,
|
||||
result->dependsOnRole = glob->dependsOnRole;
|
||||
result->parallelModeNeeded = glob->parallelModeNeeded;
|
||||
result->planTree = top_plan;
|
||||
result->partPruneInfos = glob->partPruneInfos;
|
||||
result->rtable = glob->finalrtable;
|
||||
result->permInfos = glob->finalrteperminfos;
|
||||
result->resultRelations = glob->resultRelations;
|
||||
|
||||
@@ -1731,6 +1731,53 @@ set_customscan_references(PlannerInfo *root,
|
||||
cscan->custom_relids = offset_relid_set(cscan->custom_relids, rtoffset);
|
||||
}
|
||||
|
||||
/*
|
||||
* register_partpruneinfo
|
||||
* Subroutine for set_append_references and set_mergeappend_references
|
||||
*
|
||||
* Add the PartitionPruneInfo from root->partPruneInfos at the given index
|
||||
* into PlannerGlobal->partPruneInfos and return its index there.
|
||||
*
|
||||
* Also update the RT indexes present in PartitionedRelPruneInfos to add the
|
||||
* offset.
|
||||
*/
|
||||
static int
|
||||
register_partpruneinfo(PlannerInfo *root, int part_prune_index, int rtoffset)
|
||||
{
|
||||
PlannerGlobal *glob = root->glob;
|
||||
PartitionPruneInfo *pinfo;
|
||||
ListCell *l;
|
||||
|
||||
Assert(part_prune_index >= 0 &&
|
||||
part_prune_index < list_length(root->partPruneInfos));
|
||||
pinfo = list_nth_node(PartitionPruneInfo, root->partPruneInfos,
|
||||
part_prune_index);
|
||||
|
||||
pinfo->relids = offset_relid_set(pinfo->relids, rtoffset);
|
||||
foreach(l, pinfo->prune_infos)
|
||||
{
|
||||
List *prune_infos = lfirst(l);
|
||||
ListCell *l2;
|
||||
|
||||
foreach(l2, prune_infos)
|
||||
{
|
||||
PartitionedRelPruneInfo *prelinfo = lfirst(l2);
|
||||
|
||||
prelinfo->rtindex += rtoffset;
|
||||
prelinfo->initial_pruning_steps =
|
||||
fix_scan_list(root, prelinfo->initial_pruning_steps,
|
||||
rtoffset, 1);
|
||||
prelinfo->exec_pruning_steps =
|
||||
fix_scan_list(root, prelinfo->exec_pruning_steps,
|
||||
rtoffset, 1);
|
||||
}
|
||||
}
|
||||
|
||||
glob->partPruneInfos = lappend(glob->partPruneInfos, pinfo);
|
||||
|
||||
return list_length(glob->partPruneInfos) - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* set_append_references
|
||||
* Do set_plan_references processing on an Append
|
||||
@@ -1783,27 +1830,13 @@ set_append_references(PlannerInfo *root,
|
||||
|
||||
aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset);
|
||||
|
||||
if (aplan->part_prune_info)
|
||||
{
|
||||
foreach(l, aplan->part_prune_info->prune_infos)
|
||||
{
|
||||
List *prune_infos = lfirst(l);
|
||||
ListCell *l2;
|
||||
|
||||
foreach(l2, prune_infos)
|
||||
{
|
||||
PartitionedRelPruneInfo *pinfo = lfirst(l2);
|
||||
|
||||
pinfo->rtindex += rtoffset;
|
||||
pinfo->initial_pruning_steps =
|
||||
fix_scan_list(root, pinfo->initial_pruning_steps,
|
||||
rtoffset, 1);
|
||||
pinfo->exec_pruning_steps =
|
||||
fix_scan_list(root, pinfo->exec_pruning_steps,
|
||||
rtoffset, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Add PartitionPruneInfo, if any, to PlannerGlobal and update the index.
|
||||
* Also update the RT indexes present in it to add the offset.
|
||||
*/
|
||||
if (aplan->part_prune_index >= 0)
|
||||
aplan->part_prune_index =
|
||||
register_partpruneinfo(root, aplan->part_prune_index, rtoffset);
|
||||
|
||||
/* We don't need to recurse to lefttree or righttree ... */
|
||||
Assert(aplan->plan.lefttree == NULL);
|
||||
@@ -1865,27 +1898,13 @@ set_mergeappend_references(PlannerInfo *root,
|
||||
|
||||
mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset);
|
||||
|
||||
if (mplan->part_prune_info)
|
||||
{
|
||||
foreach(l, mplan->part_prune_info->prune_infos)
|
||||
{
|
||||
List *prune_infos = lfirst(l);
|
||||
ListCell *l2;
|
||||
|
||||
foreach(l2, prune_infos)
|
||||
{
|
||||
PartitionedRelPruneInfo *pinfo = lfirst(l2);
|
||||
|
||||
pinfo->rtindex += rtoffset;
|
||||
pinfo->initial_pruning_steps =
|
||||
fix_scan_list(root, pinfo->initial_pruning_steps,
|
||||
rtoffset, 1);
|
||||
pinfo->exec_pruning_steps =
|
||||
fix_scan_list(root, pinfo->exec_pruning_steps,
|
||||
rtoffset, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Add PartitionPruneInfo, if any, to PlannerGlobal and update the index.
|
||||
* Also update the RT indexes present in it to add the offset.
|
||||
*/
|
||||
if (mplan->part_prune_index >= 0)
|
||||
mplan->part_prune_index =
|
||||
register_partpruneinfo(root, mplan->part_prune_index, rtoffset);
|
||||
|
||||
/* We don't need to recurse to lefttree or righttree ... */
|
||||
Assert(mplan->plan.lefttree == NULL);
|
||||
|
||||
Reference in New Issue
Block a user