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 <amitlangote09@gmail.com> 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

Lines changed: 17 additions & 2 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 5 additions & 3 deletions
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

Lines changed: 9 additions & 18 deletions
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

Lines changed: 48 additions & 9 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 17 additions & 13 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy