diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 48202d2232..87561cbb6f 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -2386,6 +2386,7 @@ _outRelOptInfo(StringInfo str, const RelOptInfo *node) WRITE_BOOL_FIELD(consider_partitionwise_join); WRITE_BITMAPSET_FIELD(top_parent_relids); WRITE_BOOL_FIELD(partbounds_merged); + WRITE_BITMAPSET_FIELD(live_parts); WRITE_BITMAPSET_FIELD(all_partrels); } diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 0dbe2ac726..8b69870cf4 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -1539,6 +1539,7 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, child_sjinfo, child_sjinfo->jointype); joinrel->part_rels[cnt_parts] = child_joinrel; + joinrel->live_parts = bms_add_member(joinrel->live_parts, cnt_parts); joinrel->all_partrels = bms_add_members(joinrel->all_partrels, child_joinrel->relids); } diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 86816ffe19..2cd691191c 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -6989,19 +6989,22 @@ apply_scanjoin_target_to_paths(PlannerInfo *root, if (rel_is_partitioned) { List *live_children = NIL; - int partition_idx; + int i; /* Adjust each partition. */ - for (partition_idx = 0; partition_idx < rel->nparts; partition_idx++) + i = -1; + while ((i = bms_next_member(rel->live_parts, i)) >= 0) { - RelOptInfo *child_rel = rel->part_rels[partition_idx]; + RelOptInfo *child_rel = rel->part_rels[i]; AppendRelInfo **appinfos; int nappinfos; List *child_scanjoin_targets = NIL; ListCell *lc; - /* Pruned or dummy children can be ignored. */ - if (child_rel == NULL || IS_DUMMY_REL(child_rel)) + Assert(child_rel != NULL); + + /* Dummy children can be ignored. */ + if (IS_DUMMY_REL(child_rel)) continue; /* Translate scan/join targets for this child. */ @@ -7082,32 +7085,36 @@ create_partitionwise_grouping_paths(PlannerInfo *root, PartitionwiseAggregateType patype, GroupPathExtraData *extra) { - int nparts = input_rel->nparts; - int cnt_parts; List *grouped_live_children = NIL; List *partially_grouped_live_children = NIL; PathTarget *target = grouped_rel->reltarget; bool partial_grouping_valid = true; + int i; Assert(patype != PARTITIONWISE_AGGREGATE_NONE); Assert(patype != PARTITIONWISE_AGGREGATE_PARTIAL || partially_grouped_rel != NULL); /* Add paths for partitionwise aggregation/grouping. */ - for (cnt_parts = 0; cnt_parts < nparts; cnt_parts++) + i = -1; + while ((i = bms_next_member(input_rel->live_parts, i)) >= 0) { - RelOptInfo *child_input_rel = input_rel->part_rels[cnt_parts]; - PathTarget *child_target = copy_pathtarget(target); + RelOptInfo *child_input_rel = input_rel->part_rels[i]; + PathTarget *child_target; AppendRelInfo **appinfos; int nappinfos; GroupPathExtraData child_extra; RelOptInfo *child_grouped_rel; RelOptInfo *child_partially_grouped_rel; - /* Pruned or dummy children can be ignored. */ - if (child_input_rel == NULL || IS_DUMMY_REL(child_input_rel)) + Assert(child_input_rel != NULL); + + /* Dummy children can be ignored. */ + if (IS_DUMMY_REL(child_input_rel)) continue; + child_target = copy_pathtarget(target); + /* * Copy the given "extra" structure as is and then override the * members specific to this child. diff --git a/src/backend/optimizer/util/inherit.c b/src/backend/optimizer/util/inherit.c index 992ef87b9d..c758172efa 100644 --- a/src/backend/optimizer/util/inherit.c +++ b/src/backend/optimizer/util/inherit.c @@ -348,7 +348,7 @@ expand_partitioned_rtentry(PlannerInfo *root, RelOptInfo *relinfo, * that survive pruning. Below, we will initialize child objects for the * surviving partitions. */ - live_parts = prune_append_rel_partitions(relinfo); + relinfo->live_parts = live_parts = prune_append_rel_partitions(relinfo); /* Expand simple_rel_array and friends to hold child objects. */ num_live_parts = bms_num_members(live_parts); diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index e105a4d5f1..47769cea45 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -255,6 +255,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent) rel->partbounds_merged = false; rel->partition_qual = NIL; rel->part_rels = NULL; + rel->live_parts = NULL; rel->all_partrels = NULL; rel->partexprs = NULL; rel->nullable_partexprs = NULL; @@ -669,6 +670,7 @@ build_join_rel(PlannerInfo *root, joinrel->partbounds_merged = false; joinrel->partition_qual = NIL; joinrel->part_rels = NULL; + joinrel->live_parts = NULL; joinrel->all_partrels = NULL; joinrel->partexprs = NULL; joinrel->nullable_partexprs = NULL; @@ -847,6 +849,7 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, joinrel->partbounds_merged = false; joinrel->partition_qual = NIL; joinrel->part_rels = NULL; + joinrel->live_parts = NULL; joinrel->all_partrels = NULL; joinrel->partexprs = NULL; joinrel->nullable_partexprs = NULL; diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c index c79374265c..e00edbe5c8 100644 --- a/src/backend/partitioning/partprune.c +++ b/src/backend/partitioning/partprune.c @@ -654,15 +654,14 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, relid_map = (Oid *) palloc0(nparts * sizeof(Oid)); present_parts = NULL; - for (i = 0; i < nparts; i++) + i = -1; + while ((i = bms_next_member(subpart->live_parts, i)) >= 0) { RelOptInfo *partrel = subpart->part_rels[i]; int subplanidx; int subpartidx; - /* Skip processing pruned partitions. */ - if (partrel == NULL) - continue; + Assert(partrel != NULL); subplan_map[i] = subplanidx = relid_subplan_map[partrel->relid] - 1; subpart_map[i] = subpartidx = relid_subpart_map[partrel->relid] - 1; diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index e20c245f98..ce7908c326 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -762,6 +762,9 @@ typedef struct RelOptInfo List *partition_qual; /* Partition constraint, if not the root */ struct RelOptInfo **part_rels; /* Array of RelOptInfos of partitions, * stored in the same order as bounds */ + Bitmapset *live_parts; /* Bitmap with members acting as indexes into + * the part_rels[] array to indicate which + * partitions survived partition pruning. */ Relids all_partrels; /* Relids set of all partition relids */ List **partexprs; /* Non-nullable partition key expressions */ List **nullable_partexprs; /* Nullable partition key expressions */