diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c index 31e0164ea9..c7f3ca2a20 100644 --- a/src/backend/partitioning/partprune.c +++ b/src/backend/partitioning/partprune.c @@ -326,46 +326,43 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, int i; /* - * Construct a temporary array to map from planner relids to index of the - * partitioned_rel. For convenience, we use 1-based indexes here, so that - * zero can represent an un-filled array entry. + * Examine each partitioned rel, constructing a temporary array to map + * from planner relids to index of the partitioned rel, and building a + * PartitionedRelPruneInfo for each partitioned rel. + * + * In this phase we discover whether runtime pruning is needed at all; if + * not, we can avoid doing further work. */ relid_subpart_map = palloc0(sizeof(int) * root->simple_rel_array_size); - /* - * relid_subpart_map maps relid of a non-leaf partition to the index in - * 'partitioned_rels' of that rel (which will also be the index in the - * returned PartitionedRelPruneInfo list of the info for that partition). - */ i = 1; foreach(lc, partitioned_rels) - { - Index rti = lfirst_int(lc); - - Assert(rti < root->simple_rel_array_size); - /* No duplicates please */ - Assert(relid_subpart_map[rti] == 0); - - relid_subpart_map[rti] = i++; - } - - /* We now build a PartitionedRelPruneInfo for each partitioned rel */ - foreach(lc, partitioned_rels) { Index rti = lfirst_int(lc); RelOptInfo *subpart = find_base_rel(root, rti); PartitionedRelPruneInfo *pinfo; - Bitmapset *present_parts; - int nparts = subpart->nparts; int partnatts = subpart->part_scheme->partnatts; - int *subplan_map; - int *subpart_map; - Oid *relid_map; List *partprunequal; List *pruning_steps; bool contradictory; /* + * Fill the mapping array. + * + * relid_subpart_map maps relid of a non-leaf partition to the index + * in 'partitioned_rels' of that rel (which will also be the index in + * the returned PartitionedRelPruneInfo list of the info for that + * partition). We use 1-based indexes here, so that zero can + * represent an un-filled array entry. + */ + Assert(rti < root->simple_rel_array_size); + /* No duplicates please */ + Assert(relid_subpart_map[rti] == 0); + relid_subpart_map[rti] = i++; + + /* + * Translate pruning qual, if necessary, for this partition. + * * The first item in the list is the target partitioned relation. */ if (!targetpart) @@ -411,6 +408,7 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, targetpart->relids); } + /* Convert pruning qual to pruning steps. */ pruning_steps = gen_partprune_steps(subpart, partprunequal, &contradictory); @@ -428,6 +426,47 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, return NIL; } + /* Begin constructing the PartitionedRelPruneInfo for this rel */ + pinfo = makeNode(PartitionedRelPruneInfo); + pinfo->rtindex = rti; + pinfo->pruning_steps = pruning_steps; + /* Remaining fields will be filled in the next loop */ + + pinfolist = lappend(pinfolist, pinfo); + + /* + * Determine which pruning types should be enabled at this level. This + * also records paramids relevant to pruning steps in 'pinfo'. + */ + doruntimeprune |= analyze_partkey_exprs(pinfo, pruning_steps, + partnatts); + } + + if (!doruntimeprune) + { + /* No run-time pruning required. */ + pfree(relid_subpart_map); + return NIL; + } + + /* + * Run-time pruning will be required, so initialize other information. + * That includes two maps -- one needed to convert partition indexes of + * leaf partitions to the indexes of their subplans in the subplan list, + * another needed to convert partition indexes of sub-partitioned + * partitions to the indexes of their PartitionedRelPruneInfo in the + * PartitionedRelPruneInfo list. + */ + foreach(lc, pinfolist) + { + PartitionedRelPruneInfo *pinfo = lfirst(lc); + RelOptInfo *subpart = find_base_rel(root, pinfo->rtindex); + Bitmapset *present_parts; + int nparts = subpart->nparts; + int *subplan_map; + int *subpart_map; + Oid *relid_map; + /* * Construct the subplan and subpart maps for this partitioning level. * Here we convert to zero-based indexes, with -1 for empty entries. @@ -459,30 +498,16 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, present_parts = bms_add_member(present_parts, i); } - pinfo = makeNode(PartitionedRelPruneInfo); - pinfo->rtindex = rti; - pinfo->pruning_steps = pruning_steps; + /* Record the maps and other information. */ pinfo->present_parts = present_parts; pinfo->nparts = nparts; pinfo->subplan_map = subplan_map; pinfo->subpart_map = subpart_map; pinfo->relid_map = relid_map; - - /* Determine which pruning types should be enabled at this level */ - doruntimeprune |= analyze_partkey_exprs(pinfo, pruning_steps, - partnatts); - - pinfolist = lappend(pinfolist, pinfo); } pfree(relid_subpart_map); - if (!doruntimeprune) - { - /* No run-time pruning required. */ - return NIL; - } - *matchedsubplans = subplansfound; return pinfolist; @@ -2907,6 +2932,9 @@ pull_exec_paramids_walker(Node *node, Bitmapset **context) * * Returns true if any executor partition pruning should be attempted at this * level. Also fills fields of *pinfo to record how to process each step. + * + * Note: when this is called, not much of *pinfo is valid; but that's OK + * since we only use it as an output area. */ static bool analyze_partkey_exprs(PartitionedRelPruneInfo *pinfo, List *steps,