diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2022-12-02 10:35:55 +0100 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2022-12-02 10:35:55 +0100 |
commit | fb958b5da86da69651f6fb9f540c2cfb1346cdc5 (patch) | |
tree | a059d6e4ceab797bc94f2212a5d748f5e1b3fa6d /src/backend/executor | |
parent | 40b1491357a4a092ea054176944cf76e2fe3eff8 (diff) | |
download | postgresql-fb958b5da86da69651f6fb9f540c2cfb1346cdc5.tar.gz postgresql-fb958b5da86da69651f6fb9f540c2cfb1346cdc5.zip |
Generalize ri_RootToPartitionMap to use for non-partition children
ri_RootToPartitionMap is currently only initialized for tuple routing
target partitions, though a future commit will need the ability to use
it even for the non-partition child tables, so make adjustments to the
decouple it from the partitioning code.
Also, make it lazily initialized via ExecGetRootToChildMap(), making
that function its preferred access path. Existing third-party code
accessing it directly should no longer do so; consequently, it's been
renamed to ri_RootToChildMap, which also makes it consistent with
ri_ChildToRootMap.
ExecGetRootToChildMap() houses the logic of setting the map appropriately
depending on whether a given child relation is partition or not.
To support this, also add a separate entry point for TupleConversionMap
creation that receives an AttrMap. No new code here, just split an
existing function in two.
Author: Amit Langote <amitlangote09@gmail.com>
Discussion: https://postgr.es/m/CA+HiwqEYUhDXSK5BTvG_xk=eaAEJCD4GS3C6uH7ybBvv+Z_Tmg@mail.gmail.com
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execMain.c | 8 | ||||
-rw-r--r-- | src/backend/executor/execPartition.c | 27 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 57 | ||||
-rw-r--r-- | src/backend/executor/nodeModifyTable.c | 2 |
4 files changed, 63 insertions, 31 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index b6751da5743..12ff4f3de58 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -1256,9 +1256,11 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo, * this field is filled in ExecInitModifyTable(). */ resultRelInfo->ri_RootResultRelInfo = partition_root_rri; - resultRelInfo->ri_RootToPartitionMap = NULL; /* set by - * ExecInitRoutingInfo */ - resultRelInfo->ri_PartitionTupleSlot = NULL; /* ditto */ + /* Set by ExecGetRootToChildMap */ + resultRelInfo->ri_RootToChildMap = NULL; + resultRelInfo->ri_RootToChildMapValid = false; + /* Set by ExecInitRoutingInfo */ + resultRelInfo->ri_PartitionTupleSlot = NULL; resultRelInfo->ri_ChildToRootMap = NULL; resultRelInfo->ri_ChildToRootMapValid = false; resultRelInfo->ri_CopyMultiInsertBuffer = NULL; diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index 8e6453aec2a..88d0ea3adb1 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -463,7 +463,7 @@ ExecFindPartition(ModifyTableState *mtstate, */ if (is_leaf) { - TupleConversionMap *map = rri->ri_RootToPartitionMap; + TupleConversionMap *map = ExecGetRootToChildMap(rri, estate); if (map) slot = execute_attr_map_slot(map->attrMap, rootslot, @@ -727,7 +727,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, OnConflictSetState *onconfl = makeNode(OnConflictSetState); TupleConversionMap *map; - map = leaf_part_rri->ri_RootToPartitionMap; + map = ExecGetRootToChildMap(leaf_part_rri, estate); Assert(node->onConflictSet != NIL); Assert(rootResultRelInfo->ri_onConflict != NULL); @@ -977,33 +977,24 @@ ExecInitRoutingInfo(ModifyTableState *mtstate, int partidx, bool is_borrowed_rel) { - ResultRelInfo *rootRelInfo = partRelInfo->ri_RootResultRelInfo; MemoryContext oldcxt; int rri_index; oldcxt = MemoryContextSwitchTo(proute->memcxt); /* - * Set up a tuple conversion map to convert a tuple routed to the - * partition from the parent's type to the partition's. + * Set up tuple conversion between root parent and the partition if the + * two have different rowtypes. If conversion is indeed required, also + * initialize a slot dedicated to storing this partition's converted + * tuples. Various operations that are applied to tuples after routing, + * such as checking constraints, will refer to this slot. */ - partRelInfo->ri_RootToPartitionMap = - convert_tuples_by_name(RelationGetDescr(rootRelInfo->ri_RelationDesc), - RelationGetDescr(partRelInfo->ri_RelationDesc)); - - /* - * If a partition has a different rowtype than the root parent, initialize - * a slot dedicated to storing this partition's tuples. The slot is used - * for various operations that are applied to tuples after routing, such - * as checking constraints. - */ - if (partRelInfo->ri_RootToPartitionMap != NULL) + if (ExecGetRootToChildMap(partRelInfo, estate) != NULL) { Relation partrel = partRelInfo->ri_RelationDesc; /* - * Initialize the slot itself setting its descriptor to this - * partition's TupleDesc; TupleDesc reference will be released at the + * This pins the partition's TupleDesc, which will be released at the * end of the command. */ partRelInfo->ri_PartitionTupleSlot = diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 9695de85b9a..572c87e4536 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -1253,6 +1253,45 @@ ExecGetChildToRootMap(ResultRelInfo *resultRelInfo) return resultRelInfo->ri_ChildToRootMap; } +/* + * Returns the map needed to convert given root result relation's tuples to + * the rowtype of the given child relation. Note that a NULL result is valid + * and means that no conversion is needed. + */ +TupleConversionMap * +ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate) +{ + /* Mustn't get called for a non-child result relation. */ + Assert(resultRelInfo->ri_RootResultRelInfo); + + /* If we didn't already do so, compute the map for this child. */ + if (!resultRelInfo->ri_RootToChildMapValid) + { + ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo; + TupleDesc indesc = RelationGetDescr(rootRelInfo->ri_RelationDesc); + TupleDesc outdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc); + Relation childrel = resultRelInfo->ri_RelationDesc; + AttrMap *attrMap; + MemoryContext oldcontext; + + /* + * When this child table is not a partition (!relispartition), it may + * have columns that are not present in the root table, which we ask + * to ignore by passing true for missing_ok. + */ + oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); + attrMap = build_attrmap_by_name_if_req(indesc, outdesc, + !childrel->rd_rel->relispartition); + if (attrMap) + resultRelInfo->ri_RootToChildMap = + convert_tuples_by_name_attrmap(indesc, outdesc, attrMap); + MemoryContextSwitchTo(oldcontext); + resultRelInfo->ri_RootToChildMapValid = true; + } + + return resultRelInfo->ri_RootToChildMap; +} + /* Return a bitmap representing columns being inserted */ Bitmapset * ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate) @@ -1273,10 +1312,10 @@ ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate) { ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo; RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate); + TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate); - if (relinfo->ri_RootToPartitionMap != NULL) - return execute_attr_map_cols(relinfo->ri_RootToPartitionMap->attrMap, - rte->insertedCols); + if (map != NULL) + return execute_attr_map_cols(map->attrMap, rte->insertedCols); else return rte->insertedCols; } @@ -1307,10 +1346,10 @@ ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate) { ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo; RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate); + TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate); - if (relinfo->ri_RootToPartitionMap != NULL) - return execute_attr_map_cols(relinfo->ri_RootToPartitionMap->attrMap, - rte->updatedCols); + if (map != NULL) + return execute_attr_map_cols(map->attrMap, rte->updatedCols); else return rte->updatedCols; } @@ -1333,10 +1372,10 @@ ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate) { ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo; RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate); + TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate); - if (relinfo->ri_RootToPartitionMap != NULL) - return execute_attr_map_cols(relinfo->ri_RootToPartitionMap->attrMap, - rte->extraUpdatedCols); + if (map != NULL) + return execute_attr_map_cols(map->attrMap, rte->extraUpdatedCols); else return rte->extraUpdatedCols; } diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 271ff2be8ef..a3988b11754 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -3481,7 +3481,7 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate, /* * Convert the tuple, if necessary. */ - map = partrel->ri_RootToPartitionMap; + map = ExecGetRootToChildMap(partrel, estate); if (map != NULL) { TupleTableSlot *new_slot = partrel->ri_PartitionTupleSlot; |