Refactor partition tuple routing code to reduce duplication.

Amit Langote
This commit is contained in:
Robert Haas 2016-12-21 11:36:10 -05:00
parent 3b790d256f
commit 1fc5c49450
4 changed files with 125 additions and 116 deletions

View File

@ -1406,64 +1406,22 @@ BeginCopy(ParseState *pstate,
/* Initialize state for CopyFrom tuple routing. */
if (is_from && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
List *leaf_parts;
ListCell *cell;
int i,
num_parted;
ResultRelInfo *leaf_part_rri;
PartitionDispatch *partition_dispatch_info;
ResultRelInfo *partitions;
TupleConversionMap **partition_tupconv_maps;
int num_parted,
num_partitions;
/* Get the tuple-routing information and lock partitions */
cstate->partition_dispatch_info =
RelationGetPartitionDispatchInfo(rel, RowExclusiveLock,
&num_parted,
&leaf_parts);
ExecSetupPartitionTupleRouting(rel,
&partition_dispatch_info,
&partitions,
&partition_tupconv_maps,
&num_parted, &num_partitions);
cstate->partition_dispatch_info = partition_dispatch_info;
cstate->num_dispatch = num_parted;
cstate->num_partitions = list_length(leaf_parts);
cstate->partitions = (ResultRelInfo *)
palloc(cstate->num_partitions *
sizeof(ResultRelInfo));
cstate->partition_tupconv_maps = (TupleConversionMap **)
palloc0(cstate->num_partitions *
sizeof(TupleConversionMap *));
leaf_part_rri = cstate->partitions;
i = 0;
foreach(cell, leaf_parts)
{
Relation partrel;
/*
* We locked all the partitions above including the leaf
* partitions. Note that each of the relations in
* cstate->partitions will be closed by CopyFrom() after it's
* finished with its processing.
*/
partrel = heap_open(lfirst_oid(cell), NoLock);
/*
* Verify result relation is a valid target for the current
* operation.
*/
CheckValidResultRel(partrel, CMD_INSERT);
InitResultRelInfo(leaf_part_rri,
partrel,
1, /* dummy */
false, /* no partition constraint
* check */
0);
/* Open partition indices */
ExecOpenIndices(leaf_part_rri, false);
if (!equalTupleDescs(tupDesc, RelationGetDescr(partrel)))
cstate->partition_tupconv_maps[i] =
convert_tuples_by_name(tupDesc,
RelationGetDescr(partrel),
gettext_noop("could not convert row type"));
leaf_part_rri++;
i++;
}
cstate->partitions = partitions;
cstate->num_partitions = num_partitions;
cstate->partition_tupconv_maps = partition_tupconv_maps;
}
}
else

View File

@ -51,6 +51,7 @@
#include "miscadmin.h"
#include "optimizer/clauses.h"
#include "parser/parsetree.h"
#include "rewrite/rewriteManip.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "tcop/utility.h"
@ -2998,6 +2999,97 @@ EvalPlanQualEnd(EPQState *epqstate)
epqstate->origslot = NULL;
}
/*
* ExecSetupPartitionTupleRouting - set up information needed during
* tuple routing for partitioned tables
*
* Output arguments:
* 'pd' receives an array of PartitionDispatch objects with one entry for
* every partitioned table in the partition tree
* 'partitions' receives an array of ResultRelInfo objects with one entry for
* every leaf partition in the partition tree
* 'tup_conv_maps' receives an array of TupleConversionMap objects with one
* entry for every leaf partition (required to convert input tuple based
* on the root table's rowtype to a leaf partition's rowtype after tuple
* routing is done
* 'num_parted' receives the number of partitioned tables in the partition
* tree (= the number of entries in the 'pd' output array)
* 'num_partitions' receives the number of leaf partitions in the partition
* tree (= the number of entries in the 'partitions' and 'tup_conv_maps'
* output arrays
*
* Note that all the relations in the partition tree are locked using the
* RowExclusiveLock mode upon return from this function.
*/
void
ExecSetupPartitionTupleRouting(Relation rel,
PartitionDispatch **pd,
ResultRelInfo **partitions,
TupleConversionMap ***tup_conv_maps,
int *num_parted, int *num_partitions)
{
TupleDesc tupDesc = RelationGetDescr(rel);
List *leaf_parts;
ListCell *cell;
int i;
ResultRelInfo *leaf_part_rri;
/* Get the tuple-routing information and lock partitions */
*pd = RelationGetPartitionDispatchInfo(rel, RowExclusiveLock, num_parted,
&leaf_parts);
*num_partitions = list_length(leaf_parts);
*partitions = (ResultRelInfo *) palloc(*num_partitions *
sizeof(ResultRelInfo));
*tup_conv_maps = (TupleConversionMap **) palloc0(*num_partitions *
sizeof(TupleConversionMap *));
leaf_part_rri = *partitions;
i = 0;
foreach(cell, leaf_parts)
{
Relation partrel;
TupleDesc part_tupdesc;
/*
* We locked all the partitions above including the leaf partitions.
* Note that each of the relations in *partitions are eventually
* closed by the caller.
*/
partrel = heap_open(lfirst_oid(cell), NoLock);
part_tupdesc = RelationGetDescr(partrel);
/*
* Verify result relation is a valid target for the current operation.
*/
CheckValidResultRel(partrel, CMD_INSERT);
/*
* Save a tuple conversion map to convert a tuple routed to this
* partition from the parent's type to the partition's.
*/
(*tup_conv_maps)[i] = convert_tuples_by_name(tupDesc, part_tupdesc,
gettext_noop("could not convert row type"));
InitResultRelInfo(leaf_part_rri,
partrel,
1, /* dummy */
false,
0);
/*
* Open partition indices (remember we do not support ON CONFLICT in
* case of partitioned tables, so we do not need support information
* for speculative insertion)
*/
if (leaf_part_rri->ri_RelationDesc->rd_rel->relhasindex &&
leaf_part_rri->ri_IndexRelationDescs == NULL)
ExecOpenIndices(leaf_part_rri, false);
leaf_part_rri++;
i++;
}
}
/*
* ExecFindPartition -- Find a leaf partition in the partition tree rooted
* at parent, for the heap tuple contained in *slot

View File

@ -1718,68 +1718,22 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (operation == CMD_INSERT &&
rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
int i,
j,
num_parted;
List *leaf_parts;
ListCell *cell;
ResultRelInfo *leaf_part_rri;
PartitionDispatch *partition_dispatch_info;
ResultRelInfo *partitions;
TupleConversionMap **partition_tupconv_maps;
int num_parted,
num_partitions;
/* Get the tuple-routing information and lock partitions */
mtstate->mt_partition_dispatch_info =
RelationGetPartitionDispatchInfo(rel, RowExclusiveLock,
&num_parted,
&leaf_parts);
ExecSetupPartitionTupleRouting(rel,
&partition_dispatch_info,
&partitions,
&partition_tupconv_maps,
&num_parted, &num_partitions);
mtstate->mt_partition_dispatch_info = partition_dispatch_info;
mtstate->mt_num_dispatch = num_parted;
mtstate->mt_num_partitions = list_length(leaf_parts);
mtstate->mt_partitions = (ResultRelInfo *)
palloc0(mtstate->mt_num_partitions *
sizeof(ResultRelInfo));
mtstate->mt_partition_tupconv_maps = (TupleConversionMap **)
palloc0(mtstate->mt_num_partitions *
sizeof(TupleConversionMap *));
leaf_part_rri = mtstate->mt_partitions;
i = j = 0;
foreach(cell, leaf_parts)
{
Oid partrelid = lfirst_oid(cell);
Relation partrel;
/*
* We locked all the partitions above including the leaf
* partitions. Note that each of the relations in
* mtstate->mt_partitions will be closed by ExecEndModifyTable().
*/
partrel = heap_open(partrelid, NoLock);
/*
* Verify result relation is a valid target for the current
* operation
*/
CheckValidResultRel(partrel, CMD_INSERT);
InitResultRelInfo(leaf_part_rri,
partrel,
1, /* dummy */
false, /* no partition constraint checks */
eflags);
/* Open partition indices (note: ON CONFLICT unsupported)*/
if (partrel->rd_rel->relhasindex && operation != CMD_DELETE &&
leaf_part_rri->ri_IndexRelationDescs == NULL)
ExecOpenIndices(leaf_part_rri, false);
if (!equalTupleDescs(RelationGetDescr(rel),
RelationGetDescr(partrel)))
mtstate->mt_partition_tupconv_maps[i] =
convert_tuples_by_name(RelationGetDescr(rel),
RelationGetDescr(partrel),
gettext_noop("could not convert row type"));
leaf_part_rri++;
i++;
}
mtstate->mt_partitions = partitions;
mtstate->mt_num_partitions = num_partitions;
mtstate->mt_partition_tupconv_maps = partition_tupconv_maps;
}
/*

View File

@ -213,6 +213,11 @@ extern void EvalPlanQualSetPlan(EPQState *epqstate,
extern void EvalPlanQualSetTuple(EPQState *epqstate, Index rti,
HeapTuple tuple);
extern HeapTuple EvalPlanQualGetTuple(EPQState *epqstate, Index rti);
extern void ExecSetupPartitionTupleRouting(Relation rel,
PartitionDispatch **pd,
ResultRelInfo **partitions,
TupleConversionMap ***tup_conv_maps,
int *num_parted, int *num_partitions);
extern int ExecFindPartition(ResultRelInfo *resultRelInfo,
PartitionDispatch *pd,
TupleTableSlot *slot,