Commit 321f648a authored by Tom Lane's avatar Tom Lane

Assorted cosmetic cleanup of run-time-partition-pruning code.

Use "subplan" rather than "subnode" to refer to the child plans of
a partitioning Append; this seems a bit more specific and hence
clearer.  Improve assorted comments.  No non-cosmetic changes.

David Rowley and Tom Lane

Discussion: https://postgr.es/m/CAFj8pRBjrufA3ocDm8o4LPGNye9Y+pm1b9kCwode4X04CULG3g@mail.gmail.com
parent 939449de
...@@ -1334,9 +1334,9 @@ adjust_partition_tlist(List *tlist, TupleConversionMap *map) ...@@ -1334,9 +1334,9 @@ adjust_partition_tlist(List *tlist, TupleConversionMap *map)
* Run-Time Partition Pruning Support. * Run-Time Partition Pruning Support.
* *
* The following series of functions exist to support the removal of unneeded * The following series of functions exist to support the removal of unneeded
* subnodes for queries against partitioned tables. The supporting functions * subplans for queries against partitioned tables. The supporting functions
* here are designed to work with any node type which supports an arbitrary * here are designed to work with any plan type which supports an arbitrary
* number of subnodes, e.g. Append, MergeAppend. * number of subplans, e.g. Append, MergeAppend.
* *
* When pruning involves comparison of a partition key to a constant, it's * 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 * 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) ...@@ -1346,73 +1346,72 @@ adjust_partition_tlist(List *tlist, TupleConversionMap *map)
* *
* We must distinguish expressions containing PARAM_EXEC Params from * We must distinguish expressions containing PARAM_EXEC Params from
* expressions that don't contain those. Even though a PARAM_EXEC Param is * 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 * considered to be a stable expression, it can change value from one plan
* scan to the next during query execution. Stable comparison expressions * node scan to the next during query execution. Stable comparison
* that don't involve such Params allow partition pruning to be done once * expressions that don't involve such Params allow partition pruning to be
* during executor startup. Expressions that do involve such Params require * done once during executor startup. Expressions that do involve such Params
* us to prune separately for each scan of the parent plan node. * require us to prune separately for each scan of the parent plan node.
* *
* Note that pruning away unneeded subnodes during executor startup has the * Note that pruning away unneeded subplans during executor startup has the
* added benefit of not having to initialize the unneeded subnodes at all. * added benefit of not having to initialize the unneeded subplans at all.
* *
* *
* Functions: * Functions:
* *
* ExecSetupPartitionPruneState: * ExecSetupPartitionPruneState:
* This must be called by nodes before any partition pruning is * Creates the PartitionPruneState required by each of the two pruning
* attempted. Normally executor startup is a good time. This function * functions. Details stored include how to map the partition index
* creates the PartitionPruneState details which are required by each * returned by the partition pruning code into subplan indexes.
* 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.
* *
* ExecFindInitialMatchingSubPlans: * 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. * without any evaluation of expressions containing PARAM_EXEC Params.
* This function must be called during executor startup for the given * This function must be called during executor startup for the parent
* node before the subnodes themselves are initialized. Subnodes which * plan before the subplans themselves are initialized. Subplans which
* are found not to match by this function must not be included in the * are found not to match by this function must be removed from the
* node's list of subnodes as this function performs a remap of the * plan's list of subplans during execution, as this function performs a
* partition index to subplan index map and the newly created map * remap of the partition index to subplan index map and the newly
* provides indexes only for subnodes which remain after calling this * created map provides indexes only for subplans which remain after
* function. * calling this function.
* *
* ExecFindMatchingSubPlans: * ExecFindMatchingSubPlans:
* Returns indexes of matching subnodes after evaluating all available * Returns indexes of matching subplans after evaluating all available
* expressions. This function can only be called while the executor is * expressions. This function can only be called during execution and
* running. * must be called again each time the value of a Param listed in
* PartitionPruneState's 'execparamids' changes.
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
/* /*
* ExecSetupPartitionPruneState * ExecSetupPartitionPruneState
* Setup the required data structure which is required for calling * Set up the data structure required for calling
* ExecFindInitialMatchingSubPlans and ExecFindMatchingSubPlans. * ExecFindInitialMatchingSubPlans and ExecFindMatchingSubPlans.
* *
* 'planstate' is the parent plan node's execution state.
*
* 'partitionpruneinfo' is a List of PartitionPruneInfos as generated by * 'partitionpruneinfo' is a List of PartitionPruneInfos as generated by
* make_partition_pruneinfo. Here we build a PartitionPruneContext for each * make_partition_pruneinfo. Here we build a PartitionPruneState containing a
* item in the List. These contexts can be re-used each time we re-evaulate * PartitionPruningData for each item in that List. This data can be re-used
* which partitions match the pruning steps provided in each * each time we re-evaluate which partitions match the pruning steps provided
* PartitionPruneInfo. * in each PartitionPruneInfo.
*/ */
PartitionPruneState * PartitionPruneState *
ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo)
{ {
PartitionPruningData *prunedata;
PartitionPruneState *prunestate; PartitionPruneState *prunestate;
PartitionPruningData *prunedata;
ListCell *lc; ListCell *lc;
int i; int i;
Assert(partitionpruneinfo != NIL); Assert(partitionpruneinfo != NIL);
/*
* Allocate the data structure
*/
prunestate = (PartitionPruneState *) palloc(sizeof(PartitionPruneState)); prunestate = (PartitionPruneState *) palloc(sizeof(PartitionPruneState));
prunedata = (PartitionPruningData *) prunedata = (PartitionPruningData *)
palloc(sizeof(PartitionPruningData) * list_length(partitionpruneinfo)); 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->partprunedata = prunedata;
prunestate->num_partprunedata = list_length(partitionpruneinfo); prunestate->num_partprunedata = list_length(partitionpruneinfo);
prunestate->do_initial_prune = false; /* may be set below */ prunestate->do_initial_prune = false; /* may be set below */
...@@ -1420,11 +1419,10 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) ...@@ -1420,11 +1419,10 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo)
prunestate->execparamids = NULL; prunestate->execparamids = NULL;
/* /*
* Create a sub memory context which we'll use when making calls to the * Create a short-term memory context which we'll use when making calls to
* query planner's function to determine which partitions will match. The * the partition pruning functions. This avoids possible memory leaks,
* planner is not too careful about freeing memory, so we'll ensure we * since the pruning functions call comparison functions that aren't under
* call the function in this context to avoid any memory leaking in the * our control.
* executor's memory context.
*/ */
prunestate->prune_context = prunestate->prune_context =
AllocSetContextCreate(CurrentMemoryContext, AllocSetContextCreate(CurrentMemoryContext,
...@@ -1448,8 +1446,8 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) ...@@ -1448,8 +1446,8 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo)
* We must make a copy of this rather than pointing directly to the * 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. * plan's version as we may end up making modifications to it later.
*/ */
pprune->subnode_map = palloc(sizeof(int) * pinfo->nparts); pprune->subplan_map = palloc(sizeof(int) * pinfo->nparts);
memcpy(pprune->subnode_map, pinfo->subnode_map, memcpy(pprune->subplan_map, pinfo->subplan_map,
sizeof(int) * pinfo->nparts); sizeof(int) * pinfo->nparts);
/* We can use the subpart_map verbatim, since we never modify it */ /* We can use the subpart_map verbatim, since we never modify it */
...@@ -1525,7 +1523,7 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) ...@@ -1525,7 +1523,7 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo)
/* /*
* Accumulate the IDs of all PARAM_EXEC Params affecting the * 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, prunestate->execparamids = bms_add_members(prunestate->execparamids,
pinfo->execparamids); pinfo->execparamids);
...@@ -1540,22 +1538,19 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) ...@@ -1540,22 +1538,19 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo)
/* /*
* ExecFindInitialMatchingSubPlans * ExecFindInitialMatchingSubPlans
* Determine which subset of subplan nodes we need to initialize based * Identify the set of subplans that cannot be eliminated by initial
* on the details stored in 'prunestate'. Here we only determine the * pruning (disregarding any pruning constraints involving PARAM_EXEC
* matching partitions using values known during plan startup, which * Params). Also re-map the translation matrix which allows conversion
* excludes any expressions containing PARAM_EXEC Params. * 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 * Must only be called once per 'prunestate', and only if initial pruning
* init plan. The caller must only initialize the subnodes which are returned * is required.
* 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.
* *
* 'nsubnodes' must be passed as the total number of unpruned subnodes. * 'nsubplans' must be passed as the total number of unpruned subplans.
*/ */
Bitmapset * Bitmapset *
ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes) ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubplans)
{ {
PartitionPruningData *pprune; PartitionPruningData *pprune;
MemoryContext oldcontext; MemoryContext oldcontext;
...@@ -1584,33 +1579,33 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes) ...@@ -1584,33 +1579,33 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes)
ResetExprContext(pprune->context.planstate->ps_ExprContext); 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 * 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 i;
int newidx; int newidx;
/* /*
* First we must build an array which we can use to adjust the * 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; newidx = 0;
for (i = 0; i < nsubnodes; i++) for (i = 0; i < nsubplans; i++)
{ {
if (bms_is_member(i, result)) if (bms_is_member(i, result))
new_subnode_indexes[i] = newidx++; new_subplan_indexes[i] = newidx++;
else 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 * Now we can re-sequence each PartitionPruneInfo's subplan_map so
* that they point to the new index of the subnode. * that they point to the new index of the subplan.
*/ */
for (i = 0; i < prunestate->num_partprunedata; i++) for (i = 0; i < prunestate->num_partprunedata; i++)
{ {
...@@ -1622,7 +1617,7 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes) ...@@ -1622,7 +1617,7 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes)
/* /*
* We also need to reset the present_parts field so that it only * 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 * for. It seems easier to build a fresh one, rather than trying
* to update the existing one. * to update the existing one.
*/ */
...@@ -1631,20 +1626,20 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes) ...@@ -1631,20 +1626,20 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes)
for (j = 0; j < nparts; j++) 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 * If this partition existed as a subplan then change the old
* subnode index to the new subnode index. The new index may * subplan index to the new subplan index. The new index may
* become -1 if the partition was pruned above, or it may just * 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. * removed earlier in the list.
*/ */
if (oldidx >= 0) 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 = pprune->present_parts =
bms_add_member(pprune->present_parts, j); bms_add_member(pprune->present_parts, j);
} }
...@@ -1686,7 +1681,7 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes) ...@@ -1686,7 +1681,7 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes)
} }
} }
pfree(new_subnode_indexes); pfree(new_subplan_indexes);
} }
return result; return result;
...@@ -1695,7 +1690,7 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes) ...@@ -1695,7 +1690,7 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubnodes)
/* /*
* ExecFindMatchingSubPlans * ExecFindMatchingSubPlans
* Determine which subplans match the pruning steps detailed in * 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. * Here we assume we may evaluate PARAM_EXEC Params.
*/ */
...@@ -1767,28 +1762,24 @@ find_matching_subplans_recurse(PartitionPruneState *prunestate, ...@@ -1767,28 +1762,24 @@ find_matching_subplans_recurse(PartitionPruneState *prunestate,
partset = pprune->present_parts; partset = pprune->present_parts;
} }
/* Translate partset into subnode indexes */ /* Translate partset into subplan indexes */
i = -1; i = -1;
while ((i = bms_next_member(partset, i)) >= 0) 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, *validsubplans = bms_add_member(*validsubplans,
pprune->subnode_map[i]); pprune->subplan_map[i]);
else else
{ {
int partidx = pprune->subpart_map[i]; int partidx = pprune->subpart_map[i];
if (partidx != -1) if (partidx >= 0)
find_matching_subplans_recurse(prunestate, find_matching_subplans_recurse(prunestate,
&prunestate->partprunedata[partidx], &prunestate->partprunedata[partidx],
initial_prune, validsubplans); initial_prune, validsubplans);
else else
{ {
/* /* Shouldn't happen */
* This could only happen if clauses used in planning where
* more restrictive than those used here, or if the maps are
* somehow corrupt.
*/
elog(ERROR, "partition missing from subplans"); elog(ERROR, "partition missing from subplans");
} }
} }
......
...@@ -1186,7 +1186,7 @@ _copyPartitionPruneInfo(const PartitionPruneInfo *from) ...@@ -1186,7 +1186,7 @@ _copyPartitionPruneInfo(const PartitionPruneInfo *from)
COPY_BITMAPSET_FIELD(present_parts); COPY_BITMAPSET_FIELD(present_parts);
COPY_SCALAR_FIELD(nparts); COPY_SCALAR_FIELD(nparts);
COPY_SCALAR_FIELD(nexprs); COPY_SCALAR_FIELD(nexprs);
COPY_POINTER_FIELD(subnode_map, from->nparts * sizeof(int)); COPY_POINTER_FIELD(subplan_map, from->nparts * sizeof(int));
COPY_POINTER_FIELD(subpart_map, from->nparts * sizeof(int)); COPY_POINTER_FIELD(subpart_map, from->nparts * sizeof(int));
COPY_POINTER_FIELD(hasexecparam, from->nexprs * sizeof(bool)); COPY_POINTER_FIELD(hasexecparam, from->nexprs * sizeof(bool));
COPY_SCALAR_FIELD(do_initial_prune); COPY_SCALAR_FIELD(do_initial_prune);
......
...@@ -1023,9 +1023,9 @@ _outPartitionPruneInfo(StringInfo str, const PartitionPruneInfo *node) ...@@ -1023,9 +1023,9 @@ _outPartitionPruneInfo(StringInfo str, const PartitionPruneInfo *node)
WRITE_INT_FIELD(nparts); WRITE_INT_FIELD(nparts);
WRITE_INT_FIELD(nexprs); WRITE_INT_FIELD(nexprs);
appendStringInfoString(str, " :subnode_map"); appendStringInfoString(str, " :subplan_map");
for (i = 0; i < node->nparts; i++) for (i = 0; i < node->nparts; i++)
appendStringInfo(str, " %d", node->subnode_map[i]); appendStringInfo(str, " %d", node->subplan_map[i]);
appendStringInfoString(str, " :subpart_map"); appendStringInfoString(str, " :subpart_map");
for (i = 0; i < node->nparts; i++) for (i = 0; i < node->nparts; i++)
......
...@@ -2333,7 +2333,7 @@ _readPartitionPruneInfo(void) ...@@ -2333,7 +2333,7 @@ _readPartitionPruneInfo(void)
READ_BITMAPSET_FIELD(present_parts); READ_BITMAPSET_FIELD(present_parts);
READ_INT_FIELD(nparts); READ_INT_FIELD(nparts);
READ_INT_FIELD(nexprs); READ_INT_FIELD(nexprs);
READ_INT_ARRAY(subnode_map, local_node->nparts); READ_INT_ARRAY(subplan_map, local_node->nparts);
READ_INT_ARRAY(subpart_map, local_node->nparts); READ_INT_ARRAY(subpart_map, local_node->nparts);
READ_BOOL_ARRAY(hasexecparam, local_node->nexprs); READ_BOOL_ARRAY(hasexecparam, local_node->nexprs);
READ_BOOL_FIELD(do_initial_prune); READ_BOOL_FIELD(do_initial_prune);
......
...@@ -4,28 +4,24 @@ ...@@ -4,28 +4,24 @@
* Support for partition pruning during query planning and execution * Support for partition pruning during query planning and execution
* *
* This module implements partition pruning using the information contained in * This module implements partition pruning using the information contained in
* table's partition descriptor, query clauses, and run-time parameters. * a table's partition descriptor, query clauses, and run-time parameters.
* *
* During planning, clauses that can be matched to the table's partition key * During planning, clauses that can be matched to the table's partition key
* are turned into a set of "pruning steps", which are then executed to * are turned into a set of "pruning steps", which are then executed to
* produce a set of partitions (as indexes of the RelOptInfo->part_rels array) * identify a set of partitions (as indexes in the RelOptInfo->part_rels
* that satisfy the constraints in the step. Partitions not in the set are said * array) that satisfy the constraints in the step. Partitions not in the set
* to have been pruned. * are said to have been pruned.
* *
* A base pruning step may also consist of expressions whose values are only * A base pruning step may involve expressions whose values are only known
* known during execution, such as Params, in which case pruning cannot occur * during execution, such as Params, in which case pruning cannot occur
* entirely during planning. In that case, such steps are included alongside * entirely during planning. In that case, such steps are included alongside
* the plan, so that they can be used by the executor for further pruning. * the plan, so that they can be used by the executor for further pruning.
* *
* There are two kinds of pruning steps: a "base" pruning step, which contains * There are two kinds of pruning steps. A "base" pruning step represents
* information extracted from one or more clauses that are matched to the * tests on partition key column(s), typically comparisons to expressions.
* (possibly multi-column) partition key, such as the expressions whose values * A "combine" pruning step represents a Boolean connector (AND/OR), and
* to match against partition bounds and operator strategy to associate to * combines the outputs of some previous steps using the appropriate
* each expression. The other kind is a "combine" pruning step, which combines * combination method.
* the outputs of some other steps using the appropriate combination method.
* All steps that are constructed are executed in succession such that for any
* "combine" step, all of the steps whose output it depends on are executed
* first and their ouput preserved.
* *
* See gen_partprune_steps_internal() for more details on step generation. * See gen_partprune_steps_internal() for more details on step generation.
* *
...@@ -66,18 +62,17 @@ ...@@ -66,18 +62,17 @@
typedef struct PartClauseInfo typedef struct PartClauseInfo
{ {
int keyno; /* Partition key number (0 to partnatts - 1) */ int keyno; /* Partition key number (0 to partnatts - 1) */
Oid opno; /* operator used to compare partkey to 'expr' */ Oid opno; /* operator used to compare partkey to expr */
bool op_is_ne; /* is clause's original operator <> ? */ bool op_is_ne; /* is clause's original operator <> ? */
Expr *expr; /* expr the partition key is compared to */ Expr *expr; /* expr the partition key is compared to */
Oid cmpfn; /* Oid of function to compare 'expr' to the Oid cmpfn; /* Oid of function to compare 'expr' to the
* partition key */ * partition key */
int op_strategy; /* cached info. */ int op_strategy; /* btree strategy identifying the operator */
} PartClauseInfo; } PartClauseInfo;
/* /*
* PartClauseMatchStatus * PartClauseMatchStatus
* Describes the result match_clause_to_partition_key produces for a * Describes the result of match_clause_to_partition_key()
* given clause and the partition key to match with that are passed to it
*/ */
typedef enum PartClauseMatchStatus typedef enum PartClauseMatchStatus
{ {
...@@ -177,6 +172,7 @@ static bool match_boolean_partition_clause(Oid partopfamily, Expr *clause, ...@@ -177,6 +172,7 @@ static bool match_boolean_partition_clause(Oid partopfamily, Expr *clause,
static bool partkey_datum_from_expr(PartitionPruneContext *context, static bool partkey_datum_from_expr(PartitionPruneContext *context,
Expr *expr, int stateidx, Datum *value); Expr *expr, int stateidx, Datum *value);
/* /*
* make_partition_pruneinfo * make_partition_pruneinfo
* Build List of PartitionPruneInfos, one for each 'partitioned_rels'. * Build List of PartitionPruneInfos, one for each 'partitioned_rels'.
...@@ -196,18 +192,18 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels, ...@@ -196,18 +192,18 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
List *subpaths, List *prunequal) List *subpaths, List *prunequal)
{ {
RelOptInfo *targetpart = NULL; RelOptInfo *targetpart = NULL;
ListCell *lc;
List *pinfolist = NIL; List *pinfolist = NIL;
int *relid_subnode_map; bool doruntimeprune = false;
int *relid_subplan_map;
int *relid_subpart_map; int *relid_subpart_map;
ListCell *lc;
int i; int i;
bool doruntimeprune = false;
/* /*
* Allocate two arrays to store the 1-based indexes of the 'subpaths' and * Allocate two arrays to store the 1-based indexes of the 'subpaths' and
* 'partitioned_rels' by relid. * 'partitioned_rels' by relid.
*/ */
relid_subnode_map = palloc0(sizeof(int) * root->simple_rel_array_size); relid_subplan_map = palloc0(sizeof(int) * root->simple_rel_array_size);
relid_subpart_map = palloc0(sizeof(int) * root->simple_rel_array_size); relid_subpart_map = palloc0(sizeof(int) * root->simple_rel_array_size);
i = 1; i = 1;
...@@ -219,7 +215,7 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels, ...@@ -219,7 +215,7 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
Assert(IS_SIMPLE_REL(pathrel)); Assert(IS_SIMPLE_REL(pathrel));
Assert(pathrel->relid < root->simple_rel_array_size); Assert(pathrel->relid < root->simple_rel_array_size);
relid_subnode_map[pathrel->relid] = i++; relid_subplan_map[pathrel->relid] = i++;
} }
/* Likewise for the partition_rels */ /* Likewise for the partition_rels */
...@@ -243,7 +239,7 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels, ...@@ -243,7 +239,7 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
Bitmapset *present_parts; Bitmapset *present_parts;
int nparts = subpart->nparts; int nparts = subpart->nparts;
int partnatts = subpart->part_scheme->partnatts; int partnatts = subpart->part_scheme->partnatts;
int *subnode_map; int *subplan_map;
int *subpart_map; int *subpart_map;
List *partprunequal; List *partprunequal;
List *pruning_steps; List *pruning_steps;
...@@ -289,7 +285,7 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels, ...@@ -289,7 +285,7 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
return NIL; return NIL;
} }
subnode_map = (int *) palloc(nparts * sizeof(int)); subplan_map = (int *) palloc(nparts * sizeof(int));
subpart_map = (int *) palloc(nparts * sizeof(int)); subpart_map = (int *) palloc(nparts * sizeof(int));
present_parts = NULL; present_parts = NULL;
...@@ -302,19 +298,18 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels, ...@@ -302,19 +298,18 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
for (i = 0; i < nparts; i++) for (i = 0; i < nparts; i++)
{ {
RelOptInfo *partrel = subpart->part_rels[i]; RelOptInfo *partrel = subpart->part_rels[i];
int subnodeidx = relid_subnode_map[partrel->relid] - 1; int subplanidx = relid_subplan_map[partrel->relid] - 1;
int subpartidx = relid_subpart_map[partrel->relid] - 1; int subpartidx = relid_subpart_map[partrel->relid] - 1;
subnode_map[i] = subnodeidx; subplan_map[i] = subplanidx;
subpart_map[i] = subpartidx; subpart_map[i] = subpartidx;
/* /*
* Record the indexes of all the partition indexes that we have * Record the indexes of all the partition indexes that we have
* subnodes or subparts for. This allows an optimization to skip * subplans or subparts for. This allows an optimization to skip
* attempting any run-time pruning when no Params are found * attempting any run-time pruning when it's irrelevant.
* matching the partition key at this level.
*/ */
if (subnodeidx >= 0 || subpartidx >= 0) if (subplanidx >= 0 || subpartidx >= 0)
present_parts = bms_add_member(present_parts, i); present_parts = bms_add_member(present_parts, i);
} }
...@@ -325,16 +320,17 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels, ...@@ -325,16 +320,17 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
pinfo->pruning_steps = pruning_steps; pinfo->pruning_steps = pruning_steps;
pinfo->present_parts = present_parts; pinfo->present_parts = present_parts;
pinfo->nparts = nparts; pinfo->nparts = nparts;
pinfo->subnode_map = subnode_map; pinfo->subplan_map = subplan_map;
pinfo->subpart_map = subpart_map; pinfo->subpart_map = subpart_map;
/* Determine which pruning types should be enabled at this level */ /* Determine which pruning types should be enabled at this level */
doruntimeprune |= analyze_partkey_exprs(pinfo, pruning_steps, partnatts); doruntimeprune |= analyze_partkey_exprs(pinfo, pruning_steps,
partnatts);
pinfolist = lappend(pinfolist, pinfo); pinfolist = lappend(pinfolist, pinfo);
} }
pfree(relid_subnode_map); pfree(relid_subplan_map);
pfree(relid_subpart_map); pfree(relid_subpart_map);
if (doruntimeprune) if (doruntimeprune)
......
...@@ -114,21 +114,21 @@ typedef struct PartitionTupleRouting ...@@ -114,21 +114,21 @@ typedef struct PartitionTupleRouting
/*----------------------- /*-----------------------
* PartitionPruningData - Encapsulates all information required to support * PartitionPruningData - Encapsulates all information required to support
* elimination of partitions in node types which support arbitrary Lists of * elimination of partitions in plan types which support arbitrary Lists of
* subplans. Information stored here allows the planner's partition pruning * subplans. Information stored here allows the partition pruning functions
* functions to be called and the return value of partition indexes translated * to be called and the return value of partition indexes translated into the
* into the subpath indexes of node types such as Append, thus allowing us to * subpath indexes of plan types such as Append, thus allowing us to bypass a
* bypass certain subnodes when we have proofs that indicate that no tuple * subplan when we can prove that no tuple matching the 'pruning_steps' will
* matching the 'pruning_steps' will be found within. * be found within.
* *
* subnode_map An array containing the subnode index which * subplan_map An array containing the subplan index which
* matches this partition index, or -1 if the * matches this partition index, or -1 if the
* subnode has been pruned already. * subplan has been pruned already.
* subpart_map An array containing the offset into the * subpart_map An array containing the index into the
* 'partprunedata' array in PartitionPruning, or * partprunedata array in PartitionPruneState, or
* -1 if there is no such element in that array. * -1 if there is no such element in that array.
* present_parts A Bitmapset of the partition indexes that we * present_parts A Bitmapset of the partition indexes that we
* have subnodes mapped for. * have subplans mapped for.
* context Contains the context details required to call * context Contains the context details required to call
* the partition pruning code. * the partition pruning code.
* pruning_steps List of PartitionPruneSteps used to * pruning_steps List of PartitionPruneSteps used to
...@@ -141,7 +141,7 @@ typedef struct PartitionTupleRouting ...@@ -141,7 +141,7 @@ typedef struct PartitionTupleRouting
*/ */
typedef struct PartitionPruningData typedef struct PartitionPruningData
{ {
int *subnode_map; int *subplan_map;
int *subpart_map; int *subpart_map;
Bitmapset *present_parts; Bitmapset *present_parts;
PartitionPruneContext context; PartitionPruneContext context;
...@@ -151,15 +151,15 @@ typedef struct PartitionPruningData ...@@ -151,15 +151,15 @@ typedef struct PartitionPruningData
} PartitionPruningData; } PartitionPruningData;
/*----------------------- /*-----------------------
* PartitionPruneState - State object required for executor nodes to perform * PartitionPruneState - State object required for plan nodes to perform
* partition pruning elimination of their subnodes. This encapsulates a * partition pruning elimination of their subplans. This encapsulates a
* flattened hierarchy of PartitionPruningData structs. * flattened hierarchy of PartitionPruningData structs.
* This struct can be attached to node types which support arbitrary Lists of * This struct can be attached to plan types which support arbitrary Lists of
* subnodes containing partitions to allow subnodes to be eliminated due to * subplans containing partitions to allow subplans to be eliminated due to
* the clauses being unable to match to any tuple that the subnode could * the clauses being unable to match to any tuple that the subplan could
* possibly produce. * possibly produce.
* *
* partprunedata Array of PartitionPruningData for the node's target * partprunedata Array of PartitionPruningData for the plan's target
* partitioned relation. First element contains the * partitioned relation. First element contains the
* details for the target partitioned table. * details for the target partitioned table.
* num_partprunedata Number of items in 'partprunedata' array. * num_partprunedata Number of items in 'partprunedata' array.
...@@ -167,10 +167,12 @@ typedef struct PartitionPruningData ...@@ -167,10 +167,12 @@ typedef struct PartitionPruningData
* startup (at any hierarchy level). * startup (at any hierarchy level).
* do_exec_prune true if pruning should be performed during * do_exec_prune true if pruning should be performed during
* executor run (at any hierarchy level). * executor run (at any hierarchy level).
* prune_context A memory context which can be used to call the query
* planner's partition prune functions.
* execparamids Contains paramids of PARAM_EXEC Params found within * execparamids Contains paramids of PARAM_EXEC Params found within
* any of the partprunedata structs. * any of the partprunedata structs. Pruning must be
* done again each time the value of one of these
* parameters changes.
* prune_context A short-lived memory context in which to execute the
* partition pruning functions.
*----------------------- *-----------------------
*/ */
typedef struct PartitionPruneState typedef struct PartitionPruneState
...@@ -179,8 +181,8 @@ typedef struct PartitionPruneState ...@@ -179,8 +181,8 @@ typedef struct PartitionPruneState
int num_partprunedata; int num_partprunedata;
bool do_initial_prune; bool do_initial_prune;
bool do_exec_prune; bool do_exec_prune;
MemoryContext prune_context;
Bitmapset *execparamids; Bitmapset *execparamids;
MemoryContext prune_context;
} PartitionPruneState; } PartitionPruneState;
extern PartitionTupleRouting *ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, extern PartitionTupleRouting *ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
...@@ -211,6 +213,6 @@ extern PartitionPruneState *ExecSetupPartitionPruneState(PlanState *planstate, ...@@ -211,6 +213,6 @@ extern PartitionPruneState *ExecSetupPartitionPruneState(PlanState *planstate,
List *partitionpruneinfo); List *partitionpruneinfo);
extern Bitmapset *ExecFindMatchingSubPlans(PartitionPruneState *prunestate); extern Bitmapset *ExecFindMatchingSubPlans(PartitionPruneState *prunestate);
extern Bitmapset *ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, extern Bitmapset *ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate,
int nsubnodes); int nsubplans);
#endif /* EXECPARTITION_H */ #endif /* EXECPARTITION_H */
...@@ -1055,19 +1055,21 @@ typedef struct PlanRowMark ...@@ -1055,19 +1055,21 @@ typedef struct PlanRowMark
* partitions. * partitions.
* *
* Here we store mapping details to allow translation of a partitioned table's * Here we store mapping details to allow translation of a partitioned table's
* index into subnode indexes for node types which support arbitrary numbers * index as returned by the partition pruning code into subplan indexes for
* of sub nodes, such as Append. * plan types which support arbitrary numbers of subplans, such as Append.
* We also store various details to tell the executor when it should be
* performing partition pruning.
*/ */
typedef struct PartitionPruneInfo typedef struct PartitionPruneInfo
{ {
NodeTag type; NodeTag type;
Oid reloid; /* Oid of partition rel */ Oid reloid; /* Oid of partition rel */
List *pruning_steps; /* List of PartitionPruneStep, see below */ List *pruning_steps; /* List of PartitionPruneStep, see below */
Bitmapset *present_parts; /* Indexes of all partitions which subnodes Bitmapset *present_parts; /* Indexes of all partitions which subplans
* are present for. */ * are present for. */
int nparts; /* Length of subnode_map[] and subpart_map[] */ int nparts; /* Length of subplan_map[] and subpart_map[] */
int nexprs; /* Length of hasexecparam[] */ int nexprs; /* Length of hasexecparam[] */
int *subnode_map; /* subnode index by partition id, or -1 */ int *subplan_map; /* subplan index by partition id, or -1 */
int *subpart_map; /* subpart index by partition id, or -1 */ int *subpart_map; /* subpart index by partition id, or -1 */
bool *hasexecparam; /* true if corresponding pruning_step contains bool *hasexecparam; /* true if corresponding pruning_step contains
* any PARAM_EXEC Params. */ * any PARAM_EXEC Params. */
...@@ -1099,9 +1101,9 @@ typedef struct PartitionPruneStep ...@@ -1099,9 +1101,9 @@ typedef struct PartitionPruneStep
* strategy of the operator in the clause matched to the last partition key. * strategy of the operator in the clause matched to the last partition key.
* 'exprs' contains expressions which comprise the lookup key to be passed to * 'exprs' contains expressions which comprise the lookup key to be passed to
* the partition bound search function. 'cmpfns' contains the OIDs of * the partition bound search function. 'cmpfns' contains the OIDs of
* comparison function used to compare aforementioned expressions with * comparison functions used to compare aforementioned expressions with
* partition bounds. Both 'exprs' and 'cmpfns' contain the same number of * partition bounds. Both 'exprs' and 'cmpfns' contain the same number of
* items up to partnatts items. * items, up to partnatts items.
* *
* Once we find the offset of a partition bound using the lookup key, we * Once we find the offset of a partition bound using the lookup key, we
* determine which partitions to include in the result based on the value of * determine which partitions to include in the result based on the value of
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment