diff options
Diffstat (limited to 'src/backend/executor/execPartition.c')
-rw-r--r-- | src/backend/executor/execPartition.c | 163 |
1 files changed, 77 insertions, 86 deletions
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index 5a04b3524d0..0a003d99351 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -1334,9 +1334,9 @@ adjust_partition_tlist(List *tlist, TupleConversionMap *map) * Run-Time Partition Pruning Support. * * The following series of functions exist to support the removal of unneeded - * subnodes for queries against partitioned tables. The supporting functions - * here are designed to work with any node type which supports an arbitrary - * number of subnodes, e.g. Append, MergeAppend. + * subplans for queries against partitioned tables. The supporting functions + * here are designed to work with any plan type which supports an arbitrary + * number of subplans, e.g. Append, MergeAppend. * * When pruning involves comparison of a partition key to a constant, it's * done by the planner. However, if we have a comparison to a non-constant @@ -1346,73 +1346,72 @@ adjust_partition_tlist(List *tlist, TupleConversionMap *map) * * We must distinguish expressions containing PARAM_EXEC Params from * expressions that don't contain those. Even though a PARAM_EXEC Param is - * considered to be a stable expression, it can change value from one node - * scan to the next during query execution. Stable comparison expressions - * that don't involve such Params allow partition pruning to be done once - * during executor startup. Expressions that do involve such Params require - * us to prune separately for each scan of the parent plan node. + * considered to be a stable expression, it can change value from one plan + * node scan to the next during query execution. Stable comparison + * expressions that don't involve such Params allow partition pruning to be + * done once during executor startup. Expressions that do involve such Params + * require us to prune separately for each scan of the parent plan node. * - * Note that pruning away unneeded subnodes during executor startup has the - * added benefit of not having to initialize the unneeded subnodes at all. + * Note that pruning away unneeded subplans during executor startup has the + * added benefit of not having to initialize the unneeded subplans at all. * * * Functions: * * ExecSetupPartitionPruneState: - * This must be called by nodes before any partition pruning is - * attempted. Normally executor startup is a good time. This function - * creates the PartitionPruneState details which are required by each - * of the two pruning functions, details include information about - * how to map the partition index details which are returned by the - * planner's partition prune function into subnode indexes. + * Creates the PartitionPruneState required by each of the two pruning + * functions. Details stored include how to map the partition index + * returned by the partition pruning code into subplan indexes. * * ExecFindInitialMatchingSubPlans: - * Returns indexes of matching subnodes. Partition pruning is attempted + * Returns indexes of matching subplans. Partition pruning is attempted * without any evaluation of expressions containing PARAM_EXEC Params. - * This function must be called during executor startup for the given - * node before the subnodes themselves are initialized. Subnodes which - * are found not to match by this function must not be included in the - * node's list of subnodes as this function performs a remap of the - * partition index to subplan index map and the newly created map - * provides indexes only for subnodes which remain after calling this - * function. + * This function must be called during executor startup for the parent + * plan before the subplans themselves are initialized. Subplans which + * are found not to match by this function must be removed from the + * plan's list of subplans during execution, as this function performs a + * remap of the partition index to subplan index map and the newly + * created map provides indexes only for subplans which remain after + * calling this function. * * ExecFindMatchingSubPlans: - * Returns indexes of matching subnodes after evaluating all available - * expressions. This function can only be called while the executor is - * running. + * Returns indexes of matching subplans after evaluating all available + * expressions. This function can only be called during execution and + * must be called again each time the value of a Param listed in + * PartitionPruneState's 'execparamids' changes. *------------------------------------------------------------------------- */ /* * ExecSetupPartitionPruneState - * Setup the required data structure which is required for calling + * Set up the data structure required for calling * ExecFindInitialMatchingSubPlans and ExecFindMatchingSubPlans. * + * 'planstate' is the parent plan node's execution state. + * * 'partitionpruneinfo' is a List of PartitionPruneInfos as generated by - * make_partition_pruneinfo. Here we build a PartitionPruneContext for each - * item in the List. These contexts can be re-used each time we re-evaulate - * which partitions match the pruning steps provided in each - * PartitionPruneInfo. + * make_partition_pruneinfo. Here we build a PartitionPruneState containing a + * PartitionPruningData for each item in that List. This data can be re-used + * each time we re-evaluate which partitions match the pruning steps provided + * in each PartitionPruneInfo. */ PartitionPruneState * ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) { - PartitionPruningData *prunedata; PartitionPruneState *prunestate; + PartitionPruningData *prunedata; ListCell *lc; int i; Assert(partitionpruneinfo != NIL); + /* + * Allocate the data structure + */ prunestate = (PartitionPruneState *) palloc(sizeof(PartitionPruneState)); prunedata = (PartitionPruningData *) palloc(sizeof(PartitionPruningData) * list_length(partitionpruneinfo)); - /* - * The first item in the array contains the details for the query's target - * partition, so record that as the root of the partition hierarchy. - */ prunestate->partprunedata = prunedata; prunestate->num_partprunedata = list_length(partitionpruneinfo); prunestate->do_initial_prune = false; /* may be set below */ @@ -1420,11 +1419,10 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) prunestate->execparamids = NULL; /* - * Create a sub memory context which we'll use when making calls to the - * query planner's function to determine which partitions will match. The - * planner is not too careful about freeing memory, so we'll ensure we - * call the function in this context to avoid any memory leaking in the - * executor's memory context. + * Create a short-term memory context which we'll use when making calls to + * the partition pruning functions. This avoids possible memory leaks, + * since the pruning functions call comparison functions that aren't under + * our control. */ prunestate->prune_context = AllocSetContextCreate(CurrentMemoryContext, @@ -1448,8 +1446,8 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) * We must make a copy of this rather than pointing directly to the * plan's version as we may end up making modifications to it later. */ - pprune->subnode_map = palloc(sizeof(int) * pinfo->nparts); - memcpy(pprune->subnode_map, pinfo->subnode_map, + pprune->subplan_map = palloc(sizeof(int) * pinfo->nparts); + memcpy(pprune->subplan_map, pinfo->subplan_map, sizeof(int) * pinfo->nparts); /* We can use the subpart_map verbatim, since we never modify it */ @@ -1525,7 +1523,7 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) /* * Accumulate the IDs of all PARAM_EXEC Params affecting the - * partitioning decisions at this node. + * partitioning decisions at this plan node. */ prunestate->execparamids = bms_add_members(prunestate->execparamids, pinfo->execparamids); @@ -1540,22 +1538,19 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) /* * ExecFindInitialMatchingSubPlans - * Determine which subset of subplan nodes we need to initialize based - * on the details stored in 'prunestate'. Here we only determine the - * matching partitions using values known during plan startup, which - * excludes any expressions containing PARAM_EXEC Params. + * Identify the set of subplans that cannot be eliminated by initial + * pruning (disregarding any pruning constraints involving PARAM_EXEC + * Params). Also re-map the translation matrix which allows conversion + * of partition indexes into subplan indexes to account for the unneeded + * subplans having been removed. * - * It is expected that callers of this function do so only once during their - * init plan. The caller must only initialize the subnodes which are returned - * by this function. The remaining subnodes should be discarded. Once this - * function has been called, future calls to ExecFindMatchingSubPlans will - * return its matching subnode indexes assuming that the caller discarded - * the original non-matching subnodes. + * Must only be called once per 'prunestate', and only if initial pruning + * is required. * - * 'nsubnodes' must be passed as the total number of unpruned subnodes. + * 'nsubplans' must be passed as the total number of unpruned subplans. */ Bitmapset * -ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes) +ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubplans) { PartitionPruningData *pprune; MemoryContext oldcontext; @@ -1584,33 +1579,33 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes) ResetExprContext(pprune->context.planstate->ps_ExprContext); /* - * If any subnodes were pruned, we must re-sequence the subnode indexes so + * If any subplans were pruned, we must re-sequence the subplan indexes so * that ExecFindMatchingSubPlans properly returns the indexes from the - * subnodes which will remain after execution of this function. + * subplans which will remain after execution of this function. */ - if (bms_num_members(result) < nsubnodes) + if (bms_num_members(result) < nsubplans) { - int *new_subnode_indexes; + int *new_subplan_indexes; int i; int newidx; /* * First we must build an array which we can use to adjust the - * existing subnode_map so that it contains the new subnode indexes. + * existing subplan_map so that it contains the new subplan indexes. */ - new_subnode_indexes = (int *) palloc(sizeof(int) * nsubnodes); + new_subplan_indexes = (int *) palloc(sizeof(int) * nsubplans); newidx = 0; - for (i = 0; i < nsubnodes; i++) + for (i = 0; i < nsubplans; i++) { if (bms_is_member(i, result)) - new_subnode_indexes[i] = newidx++; + new_subplan_indexes[i] = newidx++; else - new_subnode_indexes[i] = -1; /* Newly pruned */ + new_subplan_indexes[i] = -1; /* Newly pruned */ } /* - * Now we can re-sequence each PartitionPruneInfo's subnode_map so - * that they point to the new index of the subnode. + * Now we can re-sequence each PartitionPruneInfo's subplan_map so + * that they point to the new index of the subplan. */ for (i = 0; i < prunestate->num_partprunedata; i++) { @@ -1622,7 +1617,7 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes) /* * We also need to reset the present_parts field so that it only - * contains partition indexes that we actually still have subnodes + * contains partition indexes that we actually still have subplans * for. It seems easier to build a fresh one, rather than trying * to update the existing one. */ @@ -1631,20 +1626,20 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes) for (j = 0; j < nparts; j++) { - int oldidx = pprune->subnode_map[j]; + int oldidx = pprune->subplan_map[j]; /* - * If this partition existed as a subnode then change the old - * subnode index to the new subnode index. The new index may + * If this partition existed as a subplan then change the old + * subplan index to the new subplan index. The new index may * become -1 if the partition was pruned above, or it may just - * come earlier in the subnode list due to some subnodes being + * come earlier in the subplan list due to some subplans being * removed earlier in the list. */ if (oldidx >= 0) { - pprune->subnode_map[j] = new_subnode_indexes[oldidx]; + pprune->subplan_map[j] = new_subplan_indexes[oldidx]; - if (new_subnode_indexes[oldidx] >= 0) + if (new_subplan_indexes[oldidx] >= 0) pprune->present_parts = bms_add_member(pprune->present_parts, j); } @@ -1686,7 +1681,7 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes) } } - pfree(new_subnode_indexes); + pfree(new_subplan_indexes); } return result; @@ -1695,7 +1690,7 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes) /* * ExecFindMatchingSubPlans * Determine which subplans match the pruning steps detailed in - * 'pprune' for the current comparison expression values. + * 'prunestate' for the current comparison expression values. * * Here we assume we may evaluate PARAM_EXEC Params. */ @@ -1767,28 +1762,24 @@ find_matching_subplans_recurse(PartitionPruneState *prunestate, partset = pprune->present_parts; } - /* Translate partset into subnode indexes */ + /* Translate partset into subplan indexes */ i = -1; while ((i = bms_next_member(partset, i)) >= 0) { - if (pprune->subnode_map[i] >= 0) + if (pprune->subplan_map[i] >= 0) *validsubplans = bms_add_member(*validsubplans, - pprune->subnode_map[i]); + pprune->subplan_map[i]); else { int partidx = pprune->subpart_map[i]; - if (partidx != -1) + if (partidx >= 0) find_matching_subplans_recurse(prunestate, &prunestate->partprunedata[partidx], initial_prune, validsubplans); else { - /* - * This could only happen if clauses used in planning where - * more restrictive than those used here, or if the maps are - * somehow corrupt. - */ + /* Shouldn't happen */ elog(ERROR, "partition missing from subplans"); } } |