1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-27 23:21:58 +03:00

Simplify and encapsulate tuple routing support code.

Instead of having ExecSetupPartitionTupleRouting return multiple out
parameters, have it return a pointer to a structure containing all of
those different things.  Also, provide and use a cleanup function,
ExecCleanupTupleRouting, instead of cleaning up all of the resources
allocated by ExecSetupPartitionTupleRouting individually.

Amit Khandekar, reviewed by Amit Langote, David Rowley, and me

Discussion: http://postgr.es/m/CAJ3gD9fWfxgKC+PfJZF3hkgAcNOy-LpfPxVYitDEXKHjeieWQQ@mail.gmail.com
This commit is contained in:
Robert Haas
2018-01-04 15:48:15 -05:00
parent d3fb72ea6d
commit cc6337d2fe
5 changed files with 153 additions and 189 deletions

View File

@ -279,32 +279,33 @@ ExecInsert(ModifyTableState *mtstate,
resultRelInfo = estate->es_result_relation_info;
/* Determine the partition to heap_insert the tuple into */
if (mtstate->mt_partition_dispatch_info)
if (mtstate->mt_partition_tuple_routing)
{
int leaf_part_index;
PartitionTupleRouting *proute = mtstate->mt_partition_tuple_routing;
TupleConversionMap *map;
/*
* Away we go ... If we end up not finding a partition after all,
* ExecFindPartition() does not return and errors out instead.
* Otherwise, the returned value is to be used as an index into arrays
* mt_partitions[] and mt_partition_tupconv_maps[] that will get us
* the ResultRelInfo and TupleConversionMap for the partition,
* proute->partitions[] and proute->partition_tupconv_maps[] that will
* get us the ResultRelInfo and TupleConversionMap for the partition,
* respectively.
*/
leaf_part_index = ExecFindPartition(resultRelInfo,
mtstate->mt_partition_dispatch_info,
proute->partition_dispatch_info,
slot,
estate);
Assert(leaf_part_index >= 0 &&
leaf_part_index < mtstate->mt_num_partitions);
leaf_part_index < proute->num_partitions);
/*
* Save the old ResultRelInfo and switch to the one corresponding to
* the selected partition.
*/
saved_resultRelInfo = resultRelInfo;
resultRelInfo = mtstate->mt_partitions[leaf_part_index];
resultRelInfo = proute->partitions[leaf_part_index];
/* We do not yet have a way to insert into a foreign partition */
if (resultRelInfo->ri_FdwRoutine)
@ -352,7 +353,7 @@ ExecInsert(ModifyTableState *mtstate,
* We might need to convert from the parent rowtype to the partition
* rowtype.
*/
map = mtstate->mt_partition_tupconv_maps[leaf_part_index];
map = proute->partition_tupconv_maps[leaf_part_index];
if (map)
{
Relation partrel = resultRelInfo->ri_RelationDesc;
@ -364,7 +365,7 @@ ExecInsert(ModifyTableState *mtstate,
* on, until we're finished dealing with the partition. Use the
* dedicated slot for that.
*/
slot = mtstate->mt_partition_tuple_slot;
slot = proute->partition_tuple_slot;
Assert(slot != NULL);
ExecSetSlotDescriptor(slot, RelationGetDescr(partrel));
ExecStoreTuple(tuple, slot, InvalidBuffer, true);
@ -1500,9 +1501,10 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
mtstate->mt_oc_transition_capture != NULL)
{
int numResultRelInfos;
PartitionTupleRouting *proute = mtstate->mt_partition_tuple_routing;
numResultRelInfos = (mtstate->mt_partition_tuple_slot != NULL ?
mtstate->mt_num_partitions :
numResultRelInfos = (proute != NULL ?
proute->num_partitions :
mtstate->mt_nplans);
/*
@ -1515,13 +1517,13 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
palloc0(sizeof(TupleConversionMap *) * numResultRelInfos);
/* Choose the right set of partitions */
if (mtstate->mt_partition_dispatch_info != NULL)
if (proute != NULL)
{
/*
* For tuple routing among partitions, we need TupleDescs based on
* the partition routing table.
*/
ResultRelInfo **resultRelInfos = mtstate->mt_partitions;
ResultRelInfo **resultRelInfos = proute->partitions;
for (i = 0; i < numResultRelInfos; ++i)
{
@ -1832,6 +1834,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
ListCell *l;
int i;
Relation rel;
PartitionTupleRouting *proute = NULL;
int num_partitions = 0;
/* check for unsupported flags */
Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
@ -1945,28 +1949,11 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (operation == CMD_INSERT &&
rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
PartitionDispatch *partition_dispatch_info;
ResultRelInfo **partitions;
TupleConversionMap **partition_tupconv_maps;
TupleTableSlot *partition_tuple_slot;
int num_parted,
num_partitions;
ExecSetupPartitionTupleRouting(mtstate,
rel,
node->nominalRelation,
estate,
&partition_dispatch_info,
&partitions,
&partition_tupconv_maps,
&partition_tuple_slot,
&num_parted, &num_partitions);
mtstate->mt_partition_dispatch_info = partition_dispatch_info;
mtstate->mt_num_dispatch = num_parted;
mtstate->mt_partitions = partitions;
mtstate->mt_num_partitions = num_partitions;
mtstate->mt_partition_tupconv_maps = partition_tupconv_maps;
mtstate->mt_partition_tuple_slot = partition_tuple_slot;
proute = mtstate->mt_partition_tuple_routing =
ExecSetupPartitionTupleRouting(mtstate,
rel, node->nominalRelation,
estate);
num_partitions = proute->num_partitions;
}
/*
@ -2009,7 +1996,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
* will suffice. This only occurs for the INSERT case; UPDATE/DELETE
* cases are handled above.
*/
if (node->withCheckOptionLists != NIL && mtstate->mt_num_partitions > 0)
if (node->withCheckOptionLists != NIL && num_partitions > 0)
{
List *wcoList;
PlanState *plan;
@ -2026,14 +2013,14 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_nplans == 1);
wcoList = linitial(node->withCheckOptionLists);
plan = mtstate->mt_plans[0];
for (i = 0; i < mtstate->mt_num_partitions; i++)
for (i = 0; i < num_partitions; i++)
{
Relation partrel;
List *mapped_wcoList;
List *wcoExprs = NIL;
ListCell *ll;
resultRelInfo = mtstate->mt_partitions[i];
resultRelInfo = proute->partitions[i];
partrel = resultRelInfo->ri_RelationDesc;
/* varno = node->nominalRelation */
@ -2101,12 +2088,12 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
* are handled above.
*/
returningList = linitial(node->returningLists);
for (i = 0; i < mtstate->mt_num_partitions; i++)
for (i = 0; i < num_partitions; i++)
{
Relation partrel;
List *rlist;
resultRelInfo = mtstate->mt_partitions[i];
resultRelInfo = proute->partitions[i];
partrel = resultRelInfo->ri_RelationDesc;
/* varno = node->nominalRelation */
@ -2372,32 +2359,9 @@ ExecEndModifyTable(ModifyTableState *node)
resultRelInfo);
}
/*
* Close all the partitioned tables, leaf partitions, and their indices
*
* Remember node->mt_partition_dispatch_info[0] corresponds to the root
* partitioned table, which we must not try to close, because it is the
* main target table of the query that will be closed by ExecEndPlan().
* Also, tupslot is NULL for the root partitioned table.
*/
for (i = 1; i < node->mt_num_dispatch; i++)
{
PartitionDispatch pd = node->mt_partition_dispatch_info[i];
heap_close(pd->reldesc, NoLock);
ExecDropSingleTupleTableSlot(pd->tupslot);
}
for (i = 0; i < node->mt_num_partitions; i++)
{
ResultRelInfo *resultRelInfo = node->mt_partitions[i];
ExecCloseIndices(resultRelInfo);
heap_close(resultRelInfo->ri_RelationDesc, NoLock);
}
/* Release the standalone partition tuple descriptor, if any */
if (node->mt_partition_tuple_slot)
ExecDropSingleTupleTableSlot(node->mt_partition_tuple_slot);
/* Close all the partitioned tables, leaf partitions, and their indices */
if (node->mt_partition_tuple_routing)
ExecCleanupTupleRouting(node->mt_partition_tuple_routing);
/*
* Free the exprcontext