ExecInitRangeTable(estate, rangeTable, plannedstmt->permInfos);
estate->es_plannedstmt = plannedstmt;
- estate->es_part_prune_infos = plannedstmt->partPruneInfos;
/*
* Next, build the ExecRowMark array from the PlanRowMark(s), if any.
pstmt->dependsOnRole = false;
pstmt->parallelModeNeeded = false;
pstmt->planTree = plan;
- pstmt->partPruneInfos = estate->es_part_prune_infos;
pstmt->rtable = estate->es_range_table;
pstmt->permInfos = estate->es_rteperminfos;
pstmt->resultRelations = NIL;
* Initialize data structure needed for run-time partition pruning and
* do initial pruning if needed
*
- * 'root_parent_relids' identifies the relation to which both the parent plan
- * and the PartitionPruneInfo given by 'part_prune_index' belong.
- *
* On return, *initially_valid_subplans is assigned the set of indexes of
* child subplans that must be initialized along with the parent plan node.
* Initial pruning is performed here if needed and in that case only the
PartitionPruneState *
ExecInitPartitionPruning(PlanState *planstate,
int n_total_subplans,
- int part_prune_index,
- Bitmapset *root_parent_relids,
+ PartitionPruneInfo *pruneinfo,
Bitmapset **initially_valid_subplans)
{
PartitionPruneState *prunestate;
EState *estate = planstate->state;
- PartitionPruneInfo *pruneinfo;
-
- /* Obtain the pruneinfo we need, and make sure it's the right one */
- pruneinfo = list_nth(estate->es_part_prune_infos, part_prune_index);
- if (!bms_equal(root_parent_relids, pruneinfo->root_parent_relids))
- ereport(ERROR,
- errcode(ERRCODE_INTERNAL_ERROR),
- errmsg_internal("mismatching PartitionPruneInfo found at part_prune_index %d",
- part_prune_index),
- errdetail_internal("plan node relids %s, pruneinfo relids %s",
- bmsToString(root_parent_relids),
- bmsToString(pruneinfo->root_parent_relids)));
/* We may need an expression context to evaluate partition exprs */
ExecAssignExprContext(estate, planstate);
estate->es_rowmarks = NULL;
estate->es_rteperminfos = NIL;
estate->es_plannedstmt = NULL;
- estate->es_part_prune_infos = NIL;
estate->es_junkFilter = NULL;
appendstate->as_begun = false;
/* If run-time partition pruning is enabled, then set that up now */
- if (node->part_prune_index >= 0)
+ if (node->part_prune_info != NULL)
{
PartitionPruneState *prunestate;
*/
prunestate = ExecInitPartitionPruning(&appendstate->ps,
list_length(node->appendplans),
- node->part_prune_index,
- node->apprelids,
+ node->part_prune_info,
&validsubplans);
appendstate->as_prune_state = prunestate;
nplans = bms_num_members(validsubplans);
mergestate->ps.ExecProcNode = ExecMergeAppend;
/* If run-time partition pruning is enabled, then set that up now */
- if (node->part_prune_index >= 0)
+ if (node->part_prune_info != NULL)
{
PartitionPruneState *prunestate;
*/
prunestate = ExecInitPartitionPruning(&mergestate->ps,
list_length(node->mergeplans),
- node->part_prune_index,
- node->apprelids,
+ node->part_prune_info,
&validsubplans);
mergestate->ms_prune_state = prunestate;
nplans = bms_num_members(validsubplans);
ListCell *subpaths;
int nasyncplans = 0;
RelOptInfo *rel = best_path->path.parent;
+ PartitionPruneInfo *partpruneinfo = NULL;
int nodenumsortkeys = 0;
AttrNumber *nodeSortColIdx = NULL;
Oid *nodeSortOperators = NULL;
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
}
if (prunequal != NIL)
- plan->part_prune_index = make_partition_pruneinfo(root, rel,
- best_path->subpaths,
- prunequal);
+ partpruneinfo =
+ 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);
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
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
Assert(best_path->path.param_info == NULL);
if (prunequal != NIL)
- node->part_prune_index = make_partition_pruneinfo(root, rel,
- best_path->subpaths,
- prunequal);
+ partpruneinfo = 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
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;
palloc0(list_length(glob->subplans) * sizeof(bool));
}
- /* Also fix up the information in PartitionPruneInfos. */
- foreach(lc, root->partPruneInfos)
- {
- PartitionPruneInfo *pruneinfo = lfirst(lc);
- ListCell *l;
-
- pruneinfo->root_parent_relids =
- offset_relid_set(pruneinfo->root_parent_relids, rtoffset);
- foreach(l, pruneinfo->prune_infos)
- {
- List *prune_infos = lfirst(l);
- ListCell *l2;
-
- foreach(l2, prune_infos)
- {
- PartitionedRelPruneInfo *pinfo = lfirst(l2);
-
- /* RT index of the table to which the pinfo belongs. */
- pinfo->rtindex += rtoffset;
- }
- }
- }
-
/* Now fix the Plan tree */
result = set_plan_refs(root, plan, rtoffset);
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.
- */
-static int
-register_partpruneinfo(PlannerInfo *root, int part_prune_index)
-{
- PlannerGlobal *glob = root->glob;
- PartitionPruneInfo *pruneinfo;
-
- Assert(part_prune_index >= 0 &&
- part_prune_index < list_length(root->partPruneInfos));
- pruneinfo = list_nth_node(PartitionPruneInfo, root->partPruneInfos,
- part_prune_index);
-
- glob->partPruneInfos = lappend(glob->partPruneInfos, pruneinfo);
-
- return list_length(glob->partPruneInfos) - 1;
-}
-
/*
* set_append_references
* Do set_plan_references processing on an Append
aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset);
- /*
- * Add PartitionPruneInfo, if any, to PlannerGlobal and update the index.
- */
- if (aplan->part_prune_index >= 0)
- aplan->part_prune_index =
- register_partpruneinfo(root, aplan->part_prune_index);
+ 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;
+ }
+ }
+ }
/* We don't need to recurse to lefttree or righttree ... */
Assert(aplan->plan.lefttree == NULL);
mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset);
- /*
- * Add PartitionPruneInfo, if any, to PlannerGlobal and update the index.
- */
- if (mplan->part_prune_index >= 0)
- mplan->part_prune_index =
- register_partpruneinfo(root, mplan->part_prune_index);
+ 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;
+ }
+ }
+ }
/* We don't need to recurse to lefttree or righttree ... */
Assert(mplan->plan.lefttree == NULL);
/*
* make_partition_pruneinfo
- * Checks if the given set of quals can be used to build pruning steps
- * that the executor can use to prune away unneeded partitions. If
- * suitable quals are found then a PartitionPruneInfo is built and tagged
- * onto the PlannerInfo's partPruneInfos list.
- *
- * The return value is the 0-based index of the item added to the
- * partPruneInfos list or -1 if nothing was added.
+ * Builds a PartitionPruneInfo which can be used in the executor to allow
+ * additional partition pruning to take place. Returns NULL when
+ * partition pruning would be useless.
*
* 'parentrel' is the RelOptInfo for an appendrel, and 'subpaths' is the list
* of scan paths for its child rels.
* 'prunequal' is a list of potential pruning quals (i.e., restriction
* clauses that are applicable to the appendrel).
*/
-int
+PartitionPruneInfo *
make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
List *subpaths,
List *prunequal)
* quals, then we can just not bother with run-time pruning.
*/
if (prunerelinfos == NIL)
- return -1;
+ return NULL;
/* Else build the result data structure */
pruneinfo = makeNode(PartitionPruneInfo);
- pruneinfo->root_parent_relids = parentrel->relids;
pruneinfo->prune_infos = prunerelinfos;
/*
else
pruneinfo->other_subplans = NULL;
- root->partPruneInfos = lappend(root->partPruneInfos, pruneinfo);
-
- return list_length(root->partPruneInfos) - 1;
+ return pruneinfo;
}
/*
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202304211
+#define CATALOG_VERSION_NO 202305041
#endif
extern PartitionPruneState *ExecInitPartitionPruning(PlanState *planstate,
int n_total_subplans,
- int part_prune_index,
- Bitmapset *root_parent_relids,
+ PartitionPruneInfo *pruneinfo,
Bitmapset **initially_valid_subplans);
extern Bitmapset *ExecFindMatchingSubPlans(PartitionPruneState *prunestate,
bool initial_prune);
+
#endif /* EXECPARTITION_H */
* ExecRowMarks, or NULL if none */
List *es_rteperminfos; /* List of RTEPermissionInfo */
PlannedStmt *es_plannedstmt; /* link to top of plan tree */
- List *es_part_prune_infos; /* PlannedStmt.partPruneInfos */
const char *es_sourceText; /* Source text from QueryDesc */
JunkFilter *es_junkFilter; /* top-level junk filter, if any */
/* "flat" list of AppendRelInfos */
List *appendRelations;
- /* List of PartitionPruneInfo contained in the plan */
- List *partPruneInfos;
-
/* OIDs of relations the plan depends on */
List *relationOids;
/* Does this query modify any partition key columns? */
bool partColsUpdated;
-
- /* PartitionPruneInfos added in this query's plan. */
- List *partPruneInfos;
};
struct Plan *planTree; /* tree of Plan nodes */
- List *partPruneInfos; /* List of PartitionPruneInfo contained in the
- * plan */
-
List *rtable; /* list of RangeTblEntry nodes */
List *permInfos; /* list of RTEPermissionInfo nodes for rtable
*/
int first_partial_plan;
- /* Index to PlannerInfo.partPruneInfos or -1 if no run-time pruning */
- int part_prune_index;
+ /* Info for run-time subplan pruning; NULL if we're not doing that */
+ struct PartitionPruneInfo *part_prune_info;
} Append;
/* ----------------
/* NULLS FIRST/LAST directions */
bool *nullsFirst pg_node_attr(array_size(numCols));
- /* Index to PlannerInfo.partPruneInfos or -1 if no run-time pruning */
- int part_prune_index;
+ /* Info for run-time subplan pruning; NULL if we're not doing that */
+ struct PartitionPruneInfo *part_prune_info;
} MergeAppend;
/* ----------------
* Then, since an Append-type node could have multiple partitioning
* hierarchies among its children, we have an unordered List of those Lists.
*
- * root_parent_relids RelOptInfo.relids of the relation to which the parent
- * plan node and this PartitionPruneInfo node belong
* prune_infos List of Lists containing PartitionedRelPruneInfo nodes,
* one sublist per run-time-prunable partition hierarchy
* appearing in the parent plan node's subplans.
pg_node_attr(no_equal, no_query_jumble)
NodeTag type;
- Bitmapset *root_parent_relids;
List *prune_infos;
Bitmapset *other_subplans;
} PartitionPruneInfo;
#define PruneCxtStateIdx(partnatts, step_id, keyno) \
((partnatts) * (step_id) + (keyno))
-extern int make_partition_pruneinfo(struct PlannerInfo *root,
- struct RelOptInfo *parentrel,
- List *subpaths,
- List *prunequal);
+extern PartitionPruneInfo *make_partition_pruneinfo(struct PlannerInfo *root,
+ struct RelOptInfo *parentrel,
+ List *subpaths,
+ List *prunequal);
extern Bitmapset *prune_append_rel_partitions(struct RelOptInfo *rel);
extern Bitmapset *get_matching_partitions(PartitionPruneContext *context,
List *pruning_steps);