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:
@ -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
|
||||
|
Reference in New Issue
Block a user