aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execPartition.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execPartition.c')
-rw-r--r--src/backend/executor/execPartition.c96
1 files changed, 77 insertions, 19 deletions
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 4491ee69912..aaa81f0620e 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -167,7 +167,8 @@ static void ExecInitRoutingInfo(ModifyTableState *mtstate,
PartitionDispatch dispatch,
ResultRelInfo *partRelInfo,
int partidx);
-static PartitionDispatch ExecInitPartitionDispatchInfo(PartitionTupleRouting *proute,
+static PartitionDispatch ExecInitPartitionDispatchInfo(EState *estate,
+ PartitionTupleRouting *proute,
Oid partoid, PartitionDispatch parent_pd, int partidx);
static void FormPartitionKeyDatum(PartitionDispatch pd,
TupleTableSlot *slot,
@@ -201,7 +202,8 @@ static void find_matching_subplans_recurse(PartitionPruningData *prunedata,
* it should be estate->es_query_cxt.
*/
PartitionTupleRouting *
-ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, Relation rel)
+ExecSetupPartitionTupleRouting(EState *estate, ModifyTableState *mtstate,
+ Relation rel)
{
PartitionTupleRouting *proute;
ModifyTable *node = mtstate ? (ModifyTable *) mtstate->ps.plan : NULL;
@@ -223,7 +225,8 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, Relation rel)
* parent as NULL as we don't need to care about any parent of the target
* partitioned table.
*/
- ExecInitPartitionDispatchInfo(proute, RelationGetRelid(rel), NULL, 0);
+ ExecInitPartitionDispatchInfo(estate, proute, RelationGetRelid(rel),
+ NULL, 0);
/*
* If performing an UPDATE with tuple routing, we can reuse partition
@@ -424,7 +427,8 @@ ExecFindPartition(ModifyTableState *mtstate,
* Create the new PartitionDispatch. We pass the current one
* in as the parent PartitionDispatch
*/
- subdispatch = ExecInitPartitionDispatchInfo(proute,
+ subdispatch = ExecInitPartitionDispatchInfo(mtstate->ps.state,
+ proute,
partdesc->oids[partidx],
dispatch, partidx);
Assert(dispatch->indexes[partidx] >= 0 &&
@@ -988,7 +992,8 @@ ExecInitRoutingInfo(ModifyTableState *mtstate,
* PartitionDispatch later.
*/
static PartitionDispatch
-ExecInitPartitionDispatchInfo(PartitionTupleRouting *proute, Oid partoid,
+ExecInitPartitionDispatchInfo(EState *estate,
+ PartitionTupleRouting *proute, Oid partoid,
PartitionDispatch parent_pd, int partidx)
{
Relation rel;
@@ -997,6 +1002,10 @@ ExecInitPartitionDispatchInfo(PartitionTupleRouting *proute, Oid partoid,
int dispatchidx;
MemoryContext oldcxt;
+ if (estate->es_partition_directory == NULL)
+ estate->es_partition_directory =
+ CreatePartitionDirectory(estate->es_query_cxt);
+
oldcxt = MemoryContextSwitchTo(proute->memcxt);
/*
@@ -1008,7 +1017,7 @@ ExecInitPartitionDispatchInfo(PartitionTupleRouting *proute, Oid partoid,
rel = table_open(partoid, RowExclusiveLock);
else
rel = proute->partition_root;
- partdesc = RelationGetPartitionDesc(rel);
+ partdesc = PartitionDirectoryLookup(estate->es_partition_directory, rel);
pd = (PartitionDispatch) palloc(offsetof(PartitionDispatchData, indexes) +
partdesc->nparts * sizeof(int));
@@ -1554,6 +1563,10 @@ ExecCreatePartitionPruneState(PlanState *planstate,
ListCell *lc;
int i;
+ if (estate->es_partition_directory == NULL)
+ estate->es_partition_directory =
+ CreatePartitionDirectory(estate->es_query_cxt);
+
n_part_hierarchies = list_length(partitionpruneinfo->prune_infos);
Assert(n_part_hierarchies > 0);
@@ -1610,18 +1623,6 @@ ExecCreatePartitionPruneState(PlanState *planstate,
int n_steps;
ListCell *lc3;
- /*
- * 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,
- sizeof(int) * pinfo->nparts);
-
- /* We can use the subpart_map verbatim, since we never modify it */
- pprune->subpart_map = pinfo->subpart_map;
-
/* present_parts is also subject to later modification */
pprune->present_parts = bms_copy(pinfo->present_parts);
@@ -1633,7 +1634,64 @@ ExecCreatePartitionPruneState(PlanState *planstate,
*/
partrel = ExecGetRangeTableRelation(estate, pinfo->rtindex);
partkey = RelationGetPartitionKey(partrel);
- partdesc = RelationGetPartitionDesc(partrel);
+ partdesc = PartitionDirectoryLookup(estate->es_partition_directory,
+ partrel);
+
+ /*
+ * Initialize the subplan_map and subpart_map. Since detaching a
+ * partition requires AccessExclusiveLock, no partitions can have
+ * disappeared, nor can the bounds for any partition have changed.
+ * However, new partitions may have been added.
+ */
+ Assert(partdesc->nparts >= pinfo->nparts);
+ pprune->subplan_map = palloc(sizeof(int) * partdesc->nparts);
+ if (partdesc->nparts == pinfo->nparts)
+ {
+ /*
+ * There are no new partitions, so this is simple. We can
+ * simply point to the subpart_map from the plan, but we must
+ * copy the subplan_map since we may change it later.
+ */
+ pprune->subpart_map = pinfo->subpart_map;
+ memcpy(pprune->subplan_map, pinfo->subplan_map,
+ sizeof(int) * pinfo->nparts);
+
+ /* Double-check that list of relations has not changed. */
+ Assert(memcmp(partdesc->oids, pinfo->relid_map,
+ pinfo->nparts * sizeof(Oid)) == 0);
+ }
+ else
+ {
+ int pd_idx = 0;
+ int pp_idx;
+
+ /*
+ * Some new partitions have appeared since plan time, and
+ * those are reflected in our PartitionDesc but were not
+ * present in the one used to construct subplan_map and
+ * subpart_map. So we must construct new and longer arrays
+ * where the partitions that were originally present map to the
+ * same place, and any added indexes map to -1, as if the
+ * new partitions had been pruned.
+ */
+ pprune->subpart_map = palloc(sizeof(int) * partdesc->nparts);
+ for (pp_idx = 0; pp_idx < partdesc->nparts; ++pp_idx)
+ {
+ if (pinfo->relid_map[pd_idx] != partdesc->oids[pp_idx])
+ {
+ pprune->subplan_map[pp_idx] = -1;
+ pprune->subpart_map[pp_idx] = -1;
+ }
+ else
+ {
+ pprune->subplan_map[pp_idx] =
+ pinfo->subplan_map[pd_idx];
+ pprune->subpart_map[pp_idx] =
+ pinfo->subpart_map[pd_idx++];
+ }
+ }
+ Assert(pd_idx == pinfo->nparts);
+ }
n_steps = list_length(pinfo->pruning_steps);