From 6ce1654aa929c7f8112c430914af7f464474ed31 Mon Sep 17 00:00:00 2001 From: amit Date: Mon, 30 Jul 2018 14:05:17 +0900 Subject: [PATCH 2/2] Some refactoring around child_parent_tupconv_maps Just like parent_child_tupconv_maps, we should allocate it only if needed. Also, if none of the partitions ended up needing a map, we should not have allocated the child_parent_tupconv_maps array, only the child_parent_map_not_required one. So, get rid of ExecSetupChildParentMapForLeaf(), which currently does initial, possibly useless, allocation of both of the above mentioned arrays. Instead, have TupConvMapForLeaf() allocate the needed array, just like ExecInitRoutingInfo does, when it needs to store a parent-to-child map. Finally, rename the function TupConvMapForLeaf to LeafToParentTupConvMapForTC for clarity; TC stands for "Transition Capture". --- src/backend/commands/copy.c | 19 +----- src/backend/executor/execPartition.c | 102 ++++++++++++++++----------------- src/backend/executor/nodeModifyTable.c | 4 +- src/include/executor/execPartition.h | 12 ++-- 4 files changed, 59 insertions(+), 78 deletions(-) diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 6fc1e2b41c..6d0e9229e0 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -2503,22 +2503,9 @@ CopyFrom(CopyState cstate) * CopyFrom tuple routing. */ if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) - { - PartitionTupleRouting *proute; - - proute = cstate->partition_tuple_routing = + cstate->partition_tuple_routing = ExecSetupPartitionTupleRouting(NULL, cstate->rel); - /* - * If we are capturing transition tuples, they may need to be - * converted from partition format back to partitioned table format - * (this is only ever necessary if a BEFORE trigger modifies the - * tuple). - */ - if (cstate->transition_capture != NULL) - ExecSetupChildParentMapForLeaf(proute); - } - /* * It's more efficient to prepare a bunch of tuples for insertion, and * insert them in one heap_multi_insert() call, than call heap_insert() @@ -2666,8 +2653,8 @@ CopyFrom(CopyState cstate) */ cstate->transition_capture->tcs_original_insert_tuple = NULL; cstate->transition_capture->tcs_map = - TupConvMapForLeaf(proute, saved_resultRelInfo, - leaf_part_index); + LeafToParentTupConvMapForTC(proute, saved_resultRelInfo, + leaf_part_index); } else { diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index 2a18a30b3e..d183e8b758 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -400,7 +400,7 @@ ExecExpandRoutingArrays(PartitionTupleRouting *proute) sizeof(TupleConversionMap *) * (new_size - old_size)); } - if (proute->child_parent_map_not_required != NULL) + if (proute->child_parent_tupconv_maps != NULL) { proute->child_parent_tupconv_maps = (TupleConversionMap **) repalloc(proute->child_parent_tupconv_maps, @@ -940,73 +940,67 @@ ExecInitPartitionDispatchInfo(PartitionTupleRouting *proute, Oid partoid, } /* - * ExecSetupChildParentMapForLeaf -- Initialize the per-leaf-partition - * child-to-root tuple conversion map array. - * - * This map is required for capturing transition tuples when the target table - * is a partitioned table. For a tuple that is routed by an INSERT or UPDATE, - * we need to convert it from the leaf partition to the target table - * descriptor. - */ -void -ExecSetupChildParentMapForLeaf(PartitionTupleRouting *proute) -{ - int size; - - Assert(proute != NULL); - - size = proute->partitions_allocsize; - - /* - * These array elements get filled up with maps on an on-demand basis. - * Initially just set all of them to NULL. - */ - proute->child_parent_tupconv_maps = - (TupleConversionMap **) palloc0(sizeof(TupleConversionMap *) * size); - - /* Same is the case for this array. All the values are set to false */ - proute->child_parent_map_not_required = (bool *) palloc0(sizeof(bool) * - size); -} - -/* - * TupConvMapForLeaf -- Get the tuple conversion map for a given leaf partition - * index. + * LeafToParentTupConvMapForTC -- Get the tuple conversion map to convert + * tuples of a leaf partition to the root parent's rowtype for storing in the + * transition capture tuplestore */ TupleConversionMap * -TupConvMapForLeaf(PartitionTupleRouting *proute, - ResultRelInfo *rootRelInfo, int leaf_index) +LeafToParentTupConvMapForTC(PartitionTupleRouting *proute, + ResultRelInfo *rootRelInfo, + int leaf_index) { - TupleConversionMap **map; + TupleConversionMap *map; TupleDesc tupdesc; - /* If nobody else set up the per-leaf maps array, do so ourselves. */ - if (proute->child_parent_tupconv_maps == NULL) - ExecSetupChildParentMapForLeaf(proute); + Assert(leaf_index < proute->partitions_allocsize); - /* If it's already known that we don't need a map, return NULL. */ - else if (proute->child_parent_map_not_required[leaf_index]) + /* Did we already find out that we don't need a map for this partition? */ + if (proute->child_parent_map_not_required && + proute->child_parent_map_not_required[leaf_index]) return NULL; - /* If we've already got a map, return it. */ - map = &proute->child_parent_tupconv_maps[leaf_index]; - if (*map != NULL) - return *map; - - /* No map yet; try to create one. */ tupdesc = RelationGetDescr(proute->partitions[leaf_index]->ri_RelationDesc); - *map = + map = convert_tuples_by_name(tupdesc, RelationGetDescr(rootRelInfo->ri_RelationDesc), gettext_noop("could not convert row type")); - /* - * If it turns out no map is needed, remember that so we don't try making - * one again next time. - */ - proute->child_parent_map_not_required[leaf_index] = (*map == NULL); + if (map) + { + /* If the per-leaf maps array has not been set up, do so ourselves. */ + if (proute->child_parent_tupconv_maps == NULL) + { + int size = proute->partitions_allocsize; - return *map; + /* + * These array elements get filled up with maps on an on-demand + * basis. Initially just set all of them to NULL. + */ + proute->child_parent_tupconv_maps = + (TupleConversionMap **) palloc0(sizeof(TupleConversionMap *) * + size); + } + + proute->child_parent_tupconv_maps[leaf_index] = map; + } + else + { + if (proute->child_parent_map_not_required == NULL) + { + int size = proute->partitions_allocsize; + + /* + * Values for other partitions will be filled whenever they're + * selected by routing. + */ + proute->child_parent_map_not_required = + (bool *) palloc0(sizeof(bool) * size); + } + + proute->child_parent_map_not_required[leaf_index] = true; + } + + return map; } /* diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 4f7cea7668..7d658ddad2 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -1758,7 +1758,7 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate, */ mtstate->mt_transition_capture->tcs_original_insert_tuple = NULL; mtstate->mt_transition_capture->tcs_map = - TupConvMapForLeaf(proute, targetRelInfo, partidx); + LeafToParentTupConvMapForTC(proute, targetRelInfo, partidx); } else { @@ -1773,7 +1773,7 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate, if (mtstate->mt_oc_transition_capture != NULL) { mtstate->mt_oc_transition_capture->tcs_map = - TupConvMapForLeaf(proute, targetRelInfo, partidx); + LeafToParentTupConvMapForTC(proute, targetRelInfo, partidx); } /* diff --git a/src/include/executor/execPartition.h b/src/include/executor/execPartition.h index d921ab6ca0..487a131343 100644 --- a/src/include/executor/execPartition.h +++ b/src/include/executor/execPartition.h @@ -125,9 +125,9 @@ typedef struct PartitionDispatchData *PartitionDispatch; * the same size as 'partitions'. * * child_parent_map_not_required Stores if we don't need a conversion - * map for a partition so that TupConvMapForLeaf - * can return without having to re-check if it needs - * to build a map. + * map for a partition so that + * LeafToParentTupConvMapForTC can return without + * having to re-check if it needs to build a map. * * subplan_resultrel_hash Hash table to store subplan index by Oid. * @@ -244,9 +244,9 @@ extern void ExecInitRoutingInfo(ModifyTableState *mtstate, PartitionTupleRouting *proute, ResultRelInfo *partRelInfo, int partidx); -extern void ExecSetupChildParentMapForLeaf(PartitionTupleRouting *proute); -extern TupleConversionMap *TupConvMapForLeaf(PartitionTupleRouting *proute, - ResultRelInfo *rootRelInfo, int leaf_index); +extern TupleConversionMap *LeafToParentTupConvMapForTC(PartitionTupleRouting *proute, + ResultRelInfo *rootRelInfo, + int leaf_index); extern HeapTuple ConvertPartitionTupleSlot(TupleConversionMap *map, HeapTuple tuple, TupleTableSlot *new_slot, -- 2.11.0