Skip to content

Commit fb958b5

Browse files
committed
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 <[email protected]> Discussion: https://postgr.es/m/CA+HiwqEYUhDXSK5BTvG_xk=eaAEJCD4GS3C6uH7ybBvv+Z_Tmg@mail.gmail.com
1 parent 40b1491 commit fb958b5

File tree

10 files changed

+104
-49
lines changed

10 files changed

+104
-49
lines changed

src/backend/access/common/tupconvert.c

+17-2
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,7 @@ TupleConversionMap *
102102
convert_tuples_by_name(TupleDesc indesc,
103103
TupleDesc outdesc)
104104
{
105-
TupleConversionMap *map;
106105
AttrMap *attrMap;
107-
int n = outdesc->natts;
108106

109107
/* Verify compatibility and prepare attribute-number map */
110108
attrMap = build_attrmap_by_name_if_req(indesc, outdesc, false);
@@ -115,6 +113,23 @@ convert_tuples_by_name(TupleDesc indesc,
115113
return NULL;
116114
}
117115

116+
return convert_tuples_by_name_attrmap(indesc, outdesc, attrMap);
117+
}
118+
119+
/*
120+
* Set up tuple conversion for input and output TupleDescs using the given
121+
* AttrMap.
122+
*/
123+
TupleConversionMap *
124+
convert_tuples_by_name_attrmap(TupleDesc indesc,
125+
TupleDesc outdesc,
126+
AttrMap *attrMap)
127+
{
128+
int n = outdesc->natts;
129+
TupleConversionMap *map;
130+
131+
Assert(attrMap != NULL);
132+
118133
/* Prepare the map structure */
119134
map = (TupleConversionMap *) palloc(sizeof(TupleConversionMap));
120135
map->indesc = indesc;

src/backend/commands/copyfrom.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1088,7 +1088,7 @@ CopyFrom(CopyFromState cstate)
10881088
* We might need to convert from the root rowtype to the partition
10891089
* rowtype.
10901090
*/
1091-
map = resultRelInfo->ri_RootToPartitionMap;
1091+
map = ExecGetRootToChildMap(resultRelInfo, estate);
10921092
if (insertMethod == CIM_SINGLE || !leafpart_use_multi_insert)
10931093
{
10941094
/* non batch insert */

src/backend/executor/execMain.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -1256,9 +1256,11 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
12561256
* this field is filled in ExecInitModifyTable().
12571257
*/
12581258
resultRelInfo->ri_RootResultRelInfo = partition_root_rri;
1259-
resultRelInfo->ri_RootToPartitionMap = NULL; /* set by
1260-
* ExecInitRoutingInfo */
1261-
resultRelInfo->ri_PartitionTupleSlot = NULL; /* ditto */
1259+
/* Set by ExecGetRootToChildMap */
1260+
resultRelInfo->ri_RootToChildMap = NULL;
1261+
resultRelInfo->ri_RootToChildMapValid = false;
1262+
/* Set by ExecInitRoutingInfo */
1263+
resultRelInfo->ri_PartitionTupleSlot = NULL;
12621264
resultRelInfo->ri_ChildToRootMap = NULL;
12631265
resultRelInfo->ri_ChildToRootMapValid = false;
12641266
resultRelInfo->ri_CopyMultiInsertBuffer = NULL;

src/backend/executor/execPartition.c

+9-18
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ ExecFindPartition(ModifyTableState *mtstate,
463463
*/
464464
if (is_leaf)
465465
{
466-
TupleConversionMap *map = rri->ri_RootToPartitionMap;
466+
TupleConversionMap *map = ExecGetRootToChildMap(rri, estate);
467467

468468
if (map)
469469
slot = execute_attr_map_slot(map->attrMap, rootslot,
@@ -727,7 +727,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
727727
OnConflictSetState *onconfl = makeNode(OnConflictSetState);
728728
TupleConversionMap *map;
729729

730-
map = leaf_part_rri->ri_RootToPartitionMap;
730+
map = ExecGetRootToChildMap(leaf_part_rri, estate);
731731

732732
Assert(node->onConflictSet != NIL);
733733
Assert(rootResultRelInfo->ri_onConflict != NULL);
@@ -977,33 +977,24 @@ ExecInitRoutingInfo(ModifyTableState *mtstate,
977977
int partidx,
978978
bool is_borrowed_rel)
979979
{
980-
ResultRelInfo *rootRelInfo = partRelInfo->ri_RootResultRelInfo;
981980
MemoryContext oldcxt;
982981
int rri_index;
983982

984983
oldcxt = MemoryContextSwitchTo(proute->memcxt);
985984

986985
/*
987-
* Set up a tuple conversion map to convert a tuple routed to the
988-
* partition from the parent's type to the partition's.
986+
* Set up tuple conversion between root parent and the partition if the
987+
* two have different rowtypes. If conversion is indeed required, also
988+
* initialize a slot dedicated to storing this partition's converted
989+
* tuples. Various operations that are applied to tuples after routing,
990+
* such as checking constraints, will refer to this slot.
989991
*/
990-
partRelInfo->ri_RootToPartitionMap =
991-
convert_tuples_by_name(RelationGetDescr(rootRelInfo->ri_RelationDesc),
992-
RelationGetDescr(partRelInfo->ri_RelationDesc));
993-
994-
/*
995-
* If a partition has a different rowtype than the root parent, initialize
996-
* a slot dedicated to storing this partition's tuples. The slot is used
997-
* for various operations that are applied to tuples after routing, such
998-
* as checking constraints.
999-
*/
1000-
if (partRelInfo->ri_RootToPartitionMap != NULL)
992+
if (ExecGetRootToChildMap(partRelInfo, estate) != NULL)
1001993
{
1002994
Relation partrel = partRelInfo->ri_RelationDesc;
1003995

1004996
/*
1005-
* Initialize the slot itself setting its descriptor to this
1006-
* partition's TupleDesc; TupleDesc reference will be released at the
997+
* This pins the partition's TupleDesc, which will be released at the
1007998
* end of the command.
1008999
*/
10091000
partRelInfo->ri_PartitionTupleSlot =

src/backend/executor/execUtils.c

+48-9
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,45 @@ ExecGetChildToRootMap(ResultRelInfo *resultRelInfo)
12531253
return resultRelInfo->ri_ChildToRootMap;
12541254
}
12551255

1256+
/*
1257+
* Returns the map needed to convert given root result relation's tuples to
1258+
* the rowtype of the given child relation. Note that a NULL result is valid
1259+
* and means that no conversion is needed.
1260+
*/
1261+
TupleConversionMap *
1262+
ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
1263+
{
1264+
/* Mustn't get called for a non-child result relation. */
1265+
Assert(resultRelInfo->ri_RootResultRelInfo);
1266+
1267+
/* If we didn't already do so, compute the map for this child. */
1268+
if (!resultRelInfo->ri_RootToChildMapValid)
1269+
{
1270+
ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
1271+
TupleDesc indesc = RelationGetDescr(rootRelInfo->ri_RelationDesc);
1272+
TupleDesc outdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1273+
Relation childrel = resultRelInfo->ri_RelationDesc;
1274+
AttrMap *attrMap;
1275+
MemoryContext oldcontext;
1276+
1277+
/*
1278+
* When this child table is not a partition (!relispartition), it may
1279+
* have columns that are not present in the root table, which we ask
1280+
* to ignore by passing true for missing_ok.
1281+
*/
1282+
oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1283+
attrMap = build_attrmap_by_name_if_req(indesc, outdesc,
1284+
!childrel->rd_rel->relispartition);
1285+
if (attrMap)
1286+
resultRelInfo->ri_RootToChildMap =
1287+
convert_tuples_by_name_attrmap(indesc, outdesc, attrMap);
1288+
MemoryContextSwitchTo(oldcontext);
1289+
resultRelInfo->ri_RootToChildMapValid = true;
1290+
}
1291+
1292+
return resultRelInfo->ri_RootToChildMap;
1293+
}
1294+
12561295
/* Return a bitmap representing columns being inserted */
12571296
Bitmapset *
12581297
ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
@@ -1273,10 +1312,10 @@ ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
12731312
{
12741313
ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
12751314
RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
1315+
TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
12761316

1277-
if (relinfo->ri_RootToPartitionMap != NULL)
1278-
return execute_attr_map_cols(relinfo->ri_RootToPartitionMap->attrMap,
1279-
rte->insertedCols);
1317+
if (map != NULL)
1318+
return execute_attr_map_cols(map->attrMap, rte->insertedCols);
12801319
else
12811320
return rte->insertedCols;
12821321
}
@@ -1307,10 +1346,10 @@ ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
13071346
{
13081347
ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
13091348
RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
1349+
TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
13101350

1311-
if (relinfo->ri_RootToPartitionMap != NULL)
1312-
return execute_attr_map_cols(relinfo->ri_RootToPartitionMap->attrMap,
1313-
rte->updatedCols);
1351+
if (map != NULL)
1352+
return execute_attr_map_cols(map->attrMap, rte->updatedCols);
13141353
else
13151354
return rte->updatedCols;
13161355
}
@@ -1333,10 +1372,10 @@ ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
13331372
{
13341373
ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
13351374
RangeTblEntry *rte = exec_rt_fetch(rootRelInfo->ri_RangeTableIndex, estate);
1375+
TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
13361376

1337-
if (relinfo->ri_RootToPartitionMap != NULL)
1338-
return execute_attr_map_cols(relinfo->ri_RootToPartitionMap->attrMap,
1339-
rte->extraUpdatedCols);
1377+
if (map != NULL)
1378+
return execute_attr_map_cols(map->attrMap, rte->extraUpdatedCols);
13401379
else
13411380
return rte->extraUpdatedCols;
13421381
}

src/backend/executor/nodeModifyTable.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -3481,7 +3481,7 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate,
34813481
/*
34823482
* Convert the tuple, if necessary.
34833483
*/
3484-
map = partrel->ri_RootToPartitionMap;
3484+
map = ExecGetRootToChildMap(partrel, estate);
34853485
if (map != NULL)
34863486
{
34873487
TupleTableSlot *new_slot = partrel->ri_PartitionTupleSlot;

src/backend/replication/logical/worker.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -2193,7 +2193,7 @@ apply_handle_tuple_routing(ApplyExecutionData *edata,
21932193
remoteslot_part = partrelinfo->ri_PartitionTupleSlot;
21942194
if (remoteslot_part == NULL)
21952195
remoteslot_part = table_slot_create(partrel, &estate->es_tupleTable);
2196-
map = partrelinfo->ri_RootToPartitionMap;
2196+
map = ExecGetRootToChildMap(partrelinfo, estate);
21972197
if (map != NULL)
21982198
{
21992199
attrmap = map->attrMap;
@@ -2353,7 +2353,7 @@ apply_handle_tuple_routing(ApplyExecutionData *edata,
23532353
if (remoteslot_part == NULL)
23542354
remoteslot_part = table_slot_create(partrel_new,
23552355
&estate->es_tupleTable);
2356-
map = partrelinfo_new->ri_RootToPartitionMap;
2356+
map = ExecGetRootToChildMap(partrelinfo_new, estate);
23572357
if (map != NULL)
23582358
{
23592359
remoteslot_part = execute_attr_map_slot(map->attrMap,

src/include/access/tupconvert.h

+3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ extern TupleConversionMap *convert_tuples_by_position(TupleDesc indesc,
3939

4040
extern TupleConversionMap *convert_tuples_by_name(TupleDesc indesc,
4141
TupleDesc outdesc);
42+
extern TupleConversionMap *convert_tuples_by_name_attrmap(TupleDesc indesc,
43+
TupleDesc outdesc,
44+
AttrMap *attrMap);
4245

4346
extern HeapTuple execute_attr_map_tuple(HeapTuple tuple, TupleConversionMap *map);
4447
extern TupleTableSlot *execute_attr_map_slot(AttrMap *attrMap,

src/include/executor/executor.h

+1
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ extern TupleTableSlot *ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relI
600600
extern TupleTableSlot *ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo);
601601
extern TupleTableSlot *ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo);
602602
extern TupleConversionMap *ExecGetChildToRootMap(ResultRelInfo *resultRelInfo);
603+
extern TupleConversionMap *ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate);
603604

604605
extern Bitmapset *ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate);
605606
extern Bitmapset *ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate);

src/include/nodes/execnodes.h

+17-13
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,21 @@ typedef struct ResultRelInfo
538538
/* partition check expression state (NULL if not set up yet) */
539539
ExprState *ri_PartitionCheckExpr;
540540

541+
/*
542+
* Map to convert child result relation tuples to the format of the table
543+
* actually mentioned in the query (called "root"). Computed only if
544+
* needed. A NULL map value indicates that no conversion is needed, so we
545+
* must have a separate flag to show if the map has been computed.
546+
*/
547+
TupleConversionMap *ri_ChildToRootMap;
548+
bool ri_ChildToRootMapValid;
549+
550+
/*
551+
* As above, but in the other direction.
552+
*/
553+
TupleConversionMap *ri_RootToChildMap;
554+
bool ri_RootToChildMapValid;
555+
541556
/*
542557
* Information needed by tuple routing target relations
543558
*
@@ -546,23 +561,12 @@ typedef struct ResultRelInfo
546561
* mentioned in the query is an inherited table, nor when tuple routing is
547562
* not needed.
548563
*
549-
* RootToPartitionMap and PartitionTupleSlot, initialized by
550-
* ExecInitRoutingInfo, are non-NULL if partition has a different tuple
551-
* format than the root table.
564+
* PartitionTupleSlot is non-NULL if RootToChild conversion is needed and
565+
* the relation is a partition.
552566
*/
553567
struct ResultRelInfo *ri_RootResultRelInfo;
554-
TupleConversionMap *ri_RootToPartitionMap;
555568
TupleTableSlot *ri_PartitionTupleSlot;
556569

557-
/*
558-
* Map to convert child result relation tuples to the format of the table
559-
* actually mentioned in the query (called "root"). Computed only if
560-
* needed. A NULL map value indicates that no conversion is needed, so we
561-
* must have a separate flag to show if the map has been computed.
562-
*/
563-
TupleConversionMap *ri_ChildToRootMap;
564-
bool ri_ChildToRootMapValid;
565-
566570
/* for use by copyfrom.c when performing multi-inserts */
567571
struct CopyMultiInsertBuffer *ri_CopyMultiInsertBuffer;
568572

0 commit comments

Comments
 (0)