1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-18 17:42:25 +03:00

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
This commit is contained in:
Alvaro Herrera
2022-12-02 10:35:55 +01:00
parent 40b1491357
commit fb958b5da8
10 changed files with 107 additions and 52 deletions

View File

@ -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;

View File

@ -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 =

View File

@ -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;
}

View File

@ -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;