aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2018-06-11 17:35:43 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2018-06-11 17:35:53 -0400
commit69025c5a07a10c842bfbcb62d4af1221e5ce7e85 (patch)
tree876c59e1bc560a06f87e7837fe2015eb77d1000f /src/backend/executor
parent4e23236403336052a000c8bf85720e9d65ba8036 (diff)
downloadpostgresql-69025c5a07a10c842bfbcb62d4af1221e5ce7e85.tar.gz
postgresql-69025c5a07a10c842bfbcb62d4af1221e5ce7e85.zip
Improve ExecFindInitialMatchingSubPlans's subplan renumbering logic.
We don't need two passes if we scan child partitions before parents, as that way the children's present_parts are up to date before they're needed. I (tgl) think there's actually a bug being fixed here, for the case of an intermediate partitioned table with no direct leaf children, but haven't attempted to construct a test case to prove it. David Rowley Discussion: https://postgr.es/m/CAKJS1f-6GODRNgEtdPxCnAPme2h2hTztB6LmtfdmcYAAOE0kQg@mail.gmail.com
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execPartition.c68
1 files changed, 22 insertions, 46 deletions
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 80c12cfcc0d..33513ff1d15 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -1442,8 +1442,8 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo)
int n_steps;
/*
- * 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.
+ * We must copy the subplan_map rather than pointing directly to the
+ * plan's version, as we may end up making modifications to it later.
*/
pprune->subplan_map = palloc(sizeof(int) * pinfo->nparts);
memcpy(pprune->subplan_map, pinfo->subplan_map,
@@ -1589,8 +1589,8 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubplans)
int newidx;
/*
- * First we must build an array which we can use to adjust the
- * existing subplan_map so that it contains the new subplan indexes.
+ * First we must build a temporary array which maps old subplan
+ * indexes to new ones.
*/
new_subplan_indexes = (int *) palloc(sizeof(int) * nsubplans);
newidx = 0;
@@ -1603,79 +1603,55 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubplans)
}
/*
- * Now we can re-sequence each PartitionPruneInfo's subplan_map so
- * that they point to the new index of the subplan.
+ * Now we can update each PartitionPruneInfo's subplan_map with new
+ * subplan indexes. We must also recompute its present_parts bitmap.
+ * We perform this loop in back-to-front order so that we determine
+ * present_parts for the lowest-level partitioned tables first. This
+ * way we can tell whether a sub-partitioned table's partitions were
+ * entirely pruned so we can exclude that from 'present_parts'.
*/
- for (i = 0; i < prunestate->num_partprunedata; i++)
+ for (i = prunestate->num_partprunedata - 1; i >= 0; i--)
{
int nparts;
int j;
pprune = &prunestate->partprunedata[i];
nparts = pprune->context.nparts;
-
- /*
- * We also need to reset the present_parts field so that it only
- * 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.
- */
+ /* We just rebuild present_parts from scratch */
bms_free(pprune->present_parts);
pprune->present_parts = NULL;
for (j = 0; j < nparts; j++)
{
int oldidx = pprune->subplan_map[j];
+ int subidx;
/*
* 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 subplan list due to some subplans being
- * removed earlier in the list.
+ * removed earlier in the list. If it's a subpartition, add
+ * it to present_parts unless it's entirely pruned.
*/
if (oldidx >= 0)
{
+ Assert(oldidx < nsubplans);
pprune->subplan_map[j] = new_subplan_indexes[oldidx];
if (new_subplan_indexes[oldidx] >= 0)
pprune->present_parts =
bms_add_member(pprune->present_parts, j);
}
- }
- }
-
- /*
- * Now we must determine which sub-partitioned tables still have
- * unpruned partitions. The easiest way to do this is to simply loop
- * over each PartitionPruningData again checking if there are any
- * 'present_parts' in the sub-partitioned table. We needn't bother
- * doing this if there are no sub-partitioned tables.
- */
- if (prunestate->num_partprunedata > 1)
- {
- for (i = 0; i < prunestate->num_partprunedata; i++)
- {
- int nparts;
- int j;
-
- pprune = &prunestate->partprunedata[i];
- nparts = pprune->context.nparts;
-
- for (j = 0; j < nparts; j++)
+ else if ((subidx = pprune->subpart_map[j]) >= 0)
{
- int subidx = pprune->subpart_map[j];
-
- if (subidx >= 0)
- {
- PartitionPruningData *subprune;
+ PartitionPruningData *subprune;
- subprune = &prunestate->partprunedata[subidx];
+ subprune = &prunestate->partprunedata[subidx];
- if (!bms_is_empty(subprune->present_parts))
- pprune->present_parts =
- bms_add_member(pprune->present_parts, j);
- }
+ if (!bms_is_empty(subprune->present_parts))
+ pprune->present_parts =
+ bms_add_member(pprune->present_parts, j);
}
}
}