diff options
Diffstat (limited to 'src/backend/executor/execPartition.c')
-rw-r--r-- | src/backend/executor/execPartition.c | 183 |
1 files changed, 48 insertions, 135 deletions
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index 558060e080f..99780ebb961 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -66,11 +66,17 @@ * * partitions * Array of 'max_partitions' elements containing a pointer to a - * ResultRelInfo for every leaf partitions touched by tuple routing. + * ResultRelInfo for every leaf partition touched by tuple routing. * Some of these are pointers to ResultRelInfos which are borrowed out of - * 'subplan_resultrel_htab'. The remainder have been built especially - * for tuple routing. See comment for PartitionDispatchData->indexes for - * details on how this array is indexed. + * the owning ModifyTableState node. The remainder have been built + * especially for tuple routing. See comment for + * PartitionDispatchData->indexes for details on how this array is + * indexed. + * + * is_borrowed_rel + * Array of 'max_partitions' booleans recording whether a given entry + * in 'partitions' is a ResultRelInfo pointer borrowed from the owning + * ModifyTableState node, rather than being built here. * * num_partitions * The current number of items stored in the 'partitions' array. Also @@ -80,12 +86,6 @@ * max_partitions * The current allocated size of the 'partitions' array. * - * subplan_resultrel_htab - * Hash table to store subplan ResultRelInfos by Oid. This is used to - * cache ResultRelInfos from targets of an UPDATE ModifyTable node; - * NULL in other cases. Some of these may be useful for tuple routing - * to save having to build duplicates. - * * memcxt * Memory context used to allocate subsidiary structs. *----------------------- @@ -98,9 +98,9 @@ struct PartitionTupleRouting int num_dispatch; int max_dispatch; ResultRelInfo **partitions; + bool *is_borrowed_rel; int num_partitions; int max_partitions; - HTAB *subplan_resultrel_htab; MemoryContext memcxt; }; @@ -153,16 +153,7 @@ typedef struct PartitionDispatchData int indexes[FLEXIBLE_ARRAY_MEMBER]; } PartitionDispatchData; -/* struct to hold result relations coming from UPDATE subplans */ -typedef struct SubplanResultRelHashElem -{ - Oid relid; /* hash key -- must be first */ - ResultRelInfo *rri; -} SubplanResultRelHashElem; - -static void ExecHashSubPlanResultRelsByOid(ModifyTableState *mtstate, - PartitionTupleRouting *proute); static ResultRelInfo *ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, PartitionTupleRouting *proute, PartitionDispatch dispatch, @@ -173,7 +164,8 @@ static void ExecInitRoutingInfo(ModifyTableState *mtstate, PartitionTupleRouting *proute, PartitionDispatch dispatch, ResultRelInfo *partRelInfo, - int partidx); + int partidx, + bool is_borrowed_rel); static PartitionDispatch ExecInitPartitionDispatchInfo(EState *estate, PartitionTupleRouting *proute, Oid partoid, PartitionDispatch parent_pd, @@ -215,11 +207,9 @@ static void find_matching_subplans_recurse(PartitionPruningData *prunedata, * it should be estate->es_query_cxt. */ PartitionTupleRouting * -ExecSetupPartitionTupleRouting(EState *estate, ModifyTableState *mtstate, - Relation rel) +ExecSetupPartitionTupleRouting(EState *estate, Relation rel) { PartitionTupleRouting *proute; - ModifyTable *node = mtstate ? (ModifyTable *) mtstate->ps.plan : NULL; /* * Here we attempt to expend as little effort as possible in setting up @@ -241,17 +231,6 @@ ExecSetupPartitionTupleRouting(EState *estate, ModifyTableState *mtstate, ExecInitPartitionDispatchInfo(estate, proute, RelationGetRelid(rel), NULL, 0, NULL); - /* - * If performing an UPDATE with tuple routing, we can reuse partition - * sub-plan result rels. We build a hash table to map the OIDs of - * partitions present in mtstate->resultRelInfo to their ResultRelInfos. - * Every time a tuple is routed to a partition that we've yet to set the - * ResultRelInfo for, before we go to the trouble of making one, we check - * for a pre-made one in the hash table. - */ - if (node && node->operation == CMD_UPDATE) - ExecHashSubPlanResultRelsByOid(mtstate, proute); - return proute; } @@ -351,7 +330,6 @@ ExecFindPartition(ModifyTableState *mtstate, is_leaf = partdesc->is_leaf[partidx]; if (is_leaf) { - /* * We've reached the leaf -- hurray, we're done. Look to see if * we've already got a ResultRelInfo for this partition. @@ -364,42 +342,33 @@ ExecFindPartition(ModifyTableState *mtstate, } else { - bool found = false; - /* - * We have not yet set up a ResultRelInfo for this partition, - * but if we have a subplan hash table, we might have one - * there. If not, we'll have to create one. + * If the partition is known in the owning ModifyTableState + * node, we can re-use that ResultRelInfo instead of creating + * a new one with ExecInitPartitionInfo(). */ - if (proute->subplan_resultrel_htab) + rri = ExecLookupResultRelByOid(mtstate, + partdesc->oids[partidx], + true, false); + if (rri) { - Oid partoid = partdesc->oids[partidx]; - SubplanResultRelHashElem *elem; + /* Verify this ResultRelInfo allows INSERTs */ + CheckValidResultRel(rri, CMD_INSERT); - elem = hash_search(proute->subplan_resultrel_htab, - &partoid, HASH_FIND, NULL); - if (elem) - { - found = true; - rri = elem->rri; - - /* Verify this ResultRelInfo allows INSERTs */ - CheckValidResultRel(rri, CMD_INSERT); - - /* - * Initialize information needed to insert this and - * subsequent tuples routed to this partition. - */ - ExecInitRoutingInfo(mtstate, estate, proute, dispatch, - rri, partidx); - } + /* + * Initialize information needed to insert this and + * subsequent tuples routed to this partition. + */ + ExecInitRoutingInfo(mtstate, estate, proute, dispatch, + rri, partidx, true); } - - /* We need to create a new one. */ - if (!found) + else + { + /* We need to create a new one. */ rri = ExecInitPartitionInfo(mtstate, estate, proute, dispatch, rootResultRelInfo, partidx); + } } Assert(rri != NULL); @@ -510,50 +479,6 @@ ExecFindPartition(ModifyTableState *mtstate, } /* - * ExecHashSubPlanResultRelsByOid - * Build a hash table to allow fast lookups of subplan ResultRelInfos by - * partition Oid. We also populate the subplan ResultRelInfo with an - * ri_PartitionRoot. - */ -static void -ExecHashSubPlanResultRelsByOid(ModifyTableState *mtstate, - PartitionTupleRouting *proute) -{ - HASHCTL ctl; - HTAB *htab; - int i; - - ctl.keysize = sizeof(Oid); - ctl.entrysize = sizeof(SubplanResultRelHashElem); - ctl.hcxt = CurrentMemoryContext; - - htab = hash_create("PartitionTupleRouting table", mtstate->mt_nrels, - &ctl, HASH_ELEM | HASH_BLOBS | HASH_CONTEXT); - proute->subplan_resultrel_htab = htab; - - /* Hash all subplans by their Oid */ - for (i = 0; i < mtstate->mt_nrels; i++) - { - ResultRelInfo *rri = &mtstate->resultRelInfo[i]; - bool found; - Oid partoid = RelationGetRelid(rri->ri_RelationDesc); - SubplanResultRelHashElem *elem; - - elem = (SubplanResultRelHashElem *) - hash_search(htab, &partoid, HASH_ENTER, &found); - Assert(!found); - elem->rri = rri; - - /* - * This is required in order to convert the partition's tuple to be - * compatible with the root partitioned table's tuple descriptor. When - * generating the per-subplan result rels, this was not set. - */ - rri->ri_RootResultRelInfo = mtstate->rootResultRelInfo; - } -} - -/* * ExecInitPartitionInfo * Lock the partition and initialize ResultRelInfo. Also setup other * information for the partition and store it in the next empty slot in @@ -613,7 +538,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, * didn't build the withCheckOptionList for partitions within the planner, * but simple translation of varattnos will suffice. This only occurs for * the INSERT case or in the case of UPDATE tuple routing where we didn't - * find a result rel to reuse in ExecSetupPartitionTupleRouting(). + * find a result rel to reuse. */ if (node && node->withCheckOptionLists != NIL) { @@ -676,7 +601,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, * build the returningList for partitions within the planner, but simple * translation of varattnos will suffice. This only occurs for the INSERT * case or in the case of UPDATE tuple routing where we didn't find a - * result rel to reuse in ExecSetupPartitionTupleRouting(). + * result rel to reuse. */ if (node && node->returningLists != NIL) { @@ -734,7 +659,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, /* Set up information needed for routing tuples to the partition. */ ExecInitRoutingInfo(mtstate, estate, proute, dispatch, - leaf_part_rri, partidx); + leaf_part_rri, partidx, false); /* * If there is an ON CONFLICT clause, initialize state for it. @@ -911,15 +836,6 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, } /* - * Also, if transition capture is required, store a map to convert tuples - * from partition's rowtype to the root partition table's. - */ - if (mtstate->mt_transition_capture || mtstate->mt_oc_transition_capture) - leaf_part_rri->ri_ChildToRootMap = - convert_tuples_by_name(RelationGetDescr(leaf_part_rri->ri_RelationDesc), - RelationGetDescr(rootResultRelInfo->ri_RelationDesc)); - - /* * Since we've just initialized this ResultRelInfo, it's not in any list * attached to the estate as yet. Add it, so that it can be found later. * @@ -949,7 +865,8 @@ ExecInitRoutingInfo(ModifyTableState *mtstate, PartitionTupleRouting *proute, PartitionDispatch dispatch, ResultRelInfo *partRelInfo, - int partidx) + int partidx, + bool is_borrowed_rel) { ResultRelInfo *rootRelInfo = partRelInfo->ri_RootResultRelInfo; MemoryContext oldcxt; @@ -1029,6 +946,8 @@ ExecInitRoutingInfo(ModifyTableState *mtstate, proute->max_partitions = 8; proute->partitions = (ResultRelInfo **) palloc(sizeof(ResultRelInfo *) * proute->max_partitions); + proute->is_borrowed_rel = (bool *) + palloc(sizeof(bool) * proute->max_partitions); } else { @@ -1036,10 +955,14 @@ ExecInitRoutingInfo(ModifyTableState *mtstate, proute->partitions = (ResultRelInfo **) repalloc(proute->partitions, sizeof(ResultRelInfo *) * proute->max_partitions); + proute->is_borrowed_rel = (bool *) + repalloc(proute->is_borrowed_rel, sizeof(bool) * + proute->max_partitions); } } proute->partitions[rri_index] = partRelInfo; + proute->is_borrowed_rel[rri_index] = is_borrowed_rel; dispatch->indexes[partidx] = rri_index; MemoryContextSwitchTo(oldcxt); @@ -1199,7 +1122,6 @@ void ExecCleanupTupleRouting(ModifyTableState *mtstate, PartitionTupleRouting *proute) { - HTAB *htab = proute->subplan_resultrel_htab; int i; /* @@ -1230,20 +1152,11 @@ ExecCleanupTupleRouting(ModifyTableState *mtstate, resultRelInfo); /* - * Check if this result rel is one belonging to the node's subplans, - * if so, let ExecEndPlan() clean it up. + * Close it if it's not one of the result relations borrowed from the + * owning ModifyTableState; those will be closed by ExecEndPlan(). */ - if (htab) - { - Oid partoid; - bool found; - - partoid = RelationGetRelid(resultRelInfo->ri_RelationDesc); - - (void) hash_search(htab, &partoid, HASH_FIND, &found); - if (found) - continue; - } + if (proute->is_borrowed_rel[i]) + continue; ExecCloseIndices(resultRelInfo); table_close(resultRelInfo->ri_RelationDesc, NoLock); |