@ -68,7 +68,6 @@ static TupleTableSlot *ExecPrepareTupleRouting(ModifyTableState *mtstate,
ResultRelInfo * targetRelInfo ,
TupleTableSlot * slot ) ;
static ResultRelInfo * getTargetResultRelInfo ( ModifyTableState * node ) ;
static void ExecSetupChildParentMapForTcs ( ModifyTableState * mtstate ) ;
static void ExecSetupChildParentMapForSubplan ( ModifyTableState * mtstate ) ;
static TupleConversionMap * tupconv_map_for_subplan ( ModifyTableState * node ,
int whichplan ) ;
@ -1157,7 +1156,8 @@ lreplace:;
tupconv_map = tupconv_map_for_subplan ( mtstate , map_index ) ;
if ( tupconv_map ! = NULL )
slot = execute_attr_map_slot ( tupconv_map - > attrMap ,
slot , proute - > root_tuple_slot ) ;
slot ,
mtstate - > mt_root_tuple_slot ) ;
/*
* Prepare for tuple routing , making it look like we ' re inserting
@ -1653,7 +1653,7 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
if ( mtstate - > mt_transition_capture ! = NULL | |
mtstate - > mt_oc_transition_capture ! = NULL )
{
ExecSetupChildParentMapForTcs ( mtstate ) ;
ExecSetupChildParentMapForSubplan ( mtstate ) ;
/*
* Install the conversion map for the first plan for UPDATE and DELETE
@ -1686,52 +1686,21 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate,
TupleTableSlot * slot )
{
ModifyTable * node ;
int partidx ;
ResultRelInfo * partrel ;
PartitionRoutingInfo * partrouteinfo ;
HeapTuple tuple ;
TupleConversionMap * map ;
/*
* Determine the target partition . If ExecFindPartition does not find a
* partition after all , it doesn ' t return here ; otherwise , the returned
* value is to be used as an index into the arrays for the ResultRelInfo
* and TupleConversionMap for the partition .
*/
partidx = ExecFindPartition ( targetRelInfo ,
proute - > partition_dispatch_info ,
slot ,
estate ) ;
Assert ( partidx > = 0 & & partidx < proute - > num_partitions ) ;
/*
* Get the ResultRelInfo corresponding to the selected partition ; if not
* yet there , initialize it .
* Lookup the target partition ' s ResultRelInfo . If ExecFindPartition does
* not find a valid partition for the tuple in ' slot ' then an error is
* raised . An error may also be raised if the found partition is not a
* valid target for INSERTs . This is required since a partitioned table
* UPDATE to another partition becomes a DELETE + INSERT .
*/
partrel = proute - > partitions [ partidx ] ;
if ( partrel = = NULL )
partrel = ExecInitPartitionInfo ( mtstate , targetRelInfo ,
proute , estate ,
partidx ) ;
/*
* Check whether the partition is routable if we didn ' t yet
*
* Note : an UPDATE of a partition key invokes an INSERT that moves the
* tuple to a new partition . This check would be applied to a subplan
* partition of such an UPDATE that is chosen as the partition to route
* the tuple to . The reason we do this check here rather than in
* ExecSetupPartitionTupleRouting is to avoid aborting such an UPDATE
* unnecessarily due to non - routable subplan partitions that may not be
* chosen for update tuple movement after all .
*/
if ( ! partrel - > ri_PartitionReadyForRouting )
{
/* Verify the partition is a valid target for INSERT. */
CheckValidResultRel ( partrel , CMD_INSERT ) ;
/* Set up information needed for routing tuples to the partition. */
ExecInitRoutingInfo ( mtstate , estate , proute , partrel , partidx ) ;
}
partrel = ExecFindPartition ( mtstate , targetRelInfo , proute , slot , estate ) ;
partrouteinfo = partrel - > ri_PartitionInfo ;
Assert ( partrouteinfo ! = NULL ) ;
/*
* Make it look like we are inserting into the partition .
@ -1743,7 +1712,7 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate,
/*
* If we ' re capturing transition tuples , we might need to convert from the
* partition rowtype to paren t rowtype .
* partition rowtype to root partition ed table ' s rowtype .
*/
if ( mtstate - > mt_transition_capture ! = NULL )
{
@ -1756,7 +1725,7 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate,
*/
mtstate - > mt_transition_capture - > tcs_original_insert_tuple = NULL ;
mtstate - > mt_transition_capture - > tcs_map =
TupConvMapForLeaf ( proute , targetRelInfo , partidx ) ;
partrouteinfo - > pi_PartitionToRootMap ;
}
else
{
@ -1771,20 +1740,17 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate,
if ( mtstate - > mt_oc_transition_capture ! = NULL )
{
mtstate - > mt_oc_transition_capture - > tcs_map =
TupConvMapForLeaf ( proute , targetRelInfo , partidx ) ;
partrouteinfo - > pi_PartitionToRootMap ;
}
/*
* Convert the tuple , if necessary .
*/
map = proute - > parent_child_tupconv_maps [ partidx ] ;
map = part routeinfo - > pi_RootToPartitionMap ;
if ( map ! = NULL )
{
TupleTableSlot * new_slot ;
TupleTableSlot * new_slot = partrouteinfo - > pi_PartitionTupleSlot ;
Assert ( proute - > partition_tuple_slots ! = NULL & &
proute - > partition_tuple_slots [ partidx ] ! = NULL ) ;
new_slot = proute - > partition_tuple_slots [ partidx ] ;
slot = execute_attr_map_slot ( map - > attrMap , slot , new_slot ) ;
}
@ -1822,17 +1788,6 @@ ExecSetupChildParentMapForSubplan(ModifyTableState *mtstate)
int numResultRelInfos = mtstate - > mt_nplans ;
int i ;
/*
* First check if there is already a per - subplan array allocated . Even if
* there is already a per - leaf map array , we won ' t require a per - subplan
* one , since we will use the subplan offset array to convert the subplan
* index to per - leaf index .
*/
if ( mtstate - > mt_per_subplan_tupconv_maps | |
( mtstate - > mt_partition_tuple_routing & &
mtstate - > mt_partition_tuple_routing - > child_parent_tupconv_maps ) )
return ;
/*
* Build array of conversion maps from each child ' s TupleDesc to the one
* used in the target relation . The map pointers may be NULL when no
@ -1854,79 +1809,18 @@ ExecSetupChildParentMapForSubplan(ModifyTableState *mtstate)
}
}
/*
* Initialize the child - to - root tuple conversion map array required for
* capturing transition tuples .
*
* The map array can be indexed either by subplan index or by leaf - partition
* index . For transition tables , we need a subplan - indexed access to the map ,
* and where tuple - routing is present , we also require a leaf - indexed access .
*/
static void
ExecSetupChildParentMapForTcs ( ModifyTableState * mtstate )
{
PartitionTupleRouting * proute = mtstate - > mt_partition_tuple_routing ;
/*
* If partition tuple routing is set up , we will require partition - indexed
* access . In that case , create the map array indexed by partition ; we
* will still be able to access the maps using a subplan index by
* converting the subplan index to a partition index using
* subplan_partition_offsets . If tuple routing is not set up , it means we
* don ' t require partition - indexed access . In that case , create just a
* subplan - indexed map .
*/
if ( proute )
{
/*
* If a partition - indexed map array is to be created , the subplan map
* array has to be NULL . If the subplan map array is already created ,
* we won ' t be able to access the map using a partition index .
*/
Assert ( mtstate - > mt_per_subplan_tupconv_maps = = NULL ) ;
ExecSetupChildParentMapForLeaf ( proute ) ;
}
else
ExecSetupChildParentMapForSubplan ( mtstate ) ;
}
/*
* For a given subplan index , get the tuple conversion map .
*/
static TupleConversionMap *
tupconv_map_for_subplan ( ModifyTableState * mtstate , int whichplan )
{
/*
* If a partition - index tuple conversion map array is allocated , we need
* to first get the index into the partition array . Exactly * one * of the
* two arrays is allocated . This is because if there is a partition array
* required , we don ' t require subplan - indexed array since we can translate
* subplan index into partition index . And , we create a subplan - indexed
* array * only * if partition - indexed array is not required .
*/
/* If nobody else set the per-subplan array of maps, do so ourselves. */
if ( mtstate - > mt_per_subplan_tupconv_maps = = NULL )
{
int leaf_index ;
PartitionTupleRouting * proute = mtstate - > mt_partition_tuple_routing ;
/*
* If subplan - indexed array is NULL , things should have been arranged
* to convert the subplan index to partition index .
*/
Assert ( proute & & proute - > subplan_partition_offsets ! = NULL & &
whichplan < proute - > num_subplan_partition_offsets ) ;
leaf_index = proute - > subplan_partition_offsets [ whichplan ] ;
ExecSetupChildParentMapForSubplan ( mtstate ) ;
return TupConvMapForLeaf ( proute , getTargetResultRelInfo ( mtstate ) ,
leaf_index ) ;
}
else
{
Assert ( whichplan > = 0 & & whichplan < mtstate - > mt_nplans ) ;
return mtstate - > mt_per_subplan_tupconv_maps [ whichplan ] ;
}
Assert ( whichplan > = 0 & & whichplan < mtstate - > mt_nplans ) ;
return mtstate - > mt_per_subplan_tupconv_maps [ whichplan ] ;
}
/* ----------------------------------------------------------------
@ -2370,10 +2264,15 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
* descriptor of a source partition does not match the root partitioned
* table descriptor . In such a case we need to convert tuples to the root
* tuple descriptor , because the search for destination partition starts
* from the root . Skip this setup if it ' s not a partition key update .
* from the root . We ' ll also need a slot to store these converted tuples .
* We can skip this setup if it ' s not a partition key update .
*/
if ( update_tuple_routing_needed )
{
ExecSetupChildParentMapForSubplan ( mtstate ) ;
mtstate - > mt_root_tuple_slot = MakeTupleTableSlot ( RelationGetDescr ( rel ) ,
& TTSOpsHeapTuple ) ;
}
/*
* Initialize any WITH CHECK OPTION constraints if needed .
@ -2716,10 +2615,18 @@ ExecEndModifyTable(ModifyTableState *node)
resultRelInfo ) ;
}
/* Close all the partitioned tables, leaf partitions, and their indices */
/*
* Close all the partitioned tables , leaf partitions , and their indices
* and release the slot used for tuple routing , if set .
*/
if ( node - > mt_partition_tuple_routing )
{
ExecCleanupTupleRouting ( node , node - > mt_partition_tuple_routing ) ;
if ( node - > mt_root_tuple_slot )
ExecDropSingleTupleTableSlot ( node - > mt_root_tuple_slot ) ;
}
/*
* Free the exprcontext
*/