@ -184,11 +184,17 @@ static char *ExecBuildSlotPartitionKeyDescription(Relation rel,
int maxfieldlen ) ;
static List * adjust_partition_colnos ( List * colnos , ResultRelInfo * leaf_part_rri ) ;
static List * adjust_partition_colnos_using_map ( List * colnos , AttrMap * attrMap ) ;
static void ExecInitPruningContext ( PartitionPruneContext * context ,
List * pruning_steps ,
PartitionDesc partdesc ,
PartitionKey partkey ,
PlanState * planstate ) ;
static PartitionPruneState * CreatePartitionPruneState ( PlanState * planstate ,
PartitionPruneInfo * pruneinfo ) ;
static void InitPartitionPruneContext ( PartitionPruneContext * context ,
List * pruning_steps ,
PartitionDesc partdesc ,
PartitionKey partkey ,
PlanState * planstate ,
ExprContext * econtext ) ;
static void PartitionPruneFixSubPlanMap ( PartitionPruneState * prunestate ,
Bitmapset * initially_valid_subplans ,
int n_total_subplans ) ;
static void find_matching_subplans_recurse ( PartitionPruningData * prunedata ,
PartitionedRelPruningData * pprune ,
bool initial_prune ,
@ -1590,64 +1596,121 @@ adjust_partition_colnos_using_map(List *colnos, AttrMap *attrMap)
*
* Functions :
*
* ExecCreatePartitionPruneState :
* Creates the PartitionPruneState required by each of the two pruning
* functions . Details stored include how to map the partition index
* returned by the partition pruning code into subplan indexes .
*
* ExecFindInitialMatchingSubPlans :
* Returns indexes of matching subplans . Partition pruning is attempted
* without any evaluation of expressions containing PARAM_EXEC Params .
* This function must be called during executor startup for the parent
* plan before the subplans themselves are initialized . Subplans which
* are found not to match by this function must be removed from the
* plan ' s list of subplans during execution , as this function performs a
* remap of the partition index to subplan index map and the newly
* created map provides indexes only for subplans which remain after
* calling this function .
* ExecInitPartitionPruning :
* Creates the PartitionPruneState required by ExecFindMatchingSubPlans .
* Details stored include how to map the partition index returned by the
* partition pruning code into subplan indexes . Also determines the set
* of subplans to initialize considering the result of performing initial
* pruning steps if any . Maps in PartitionPruneState are updated to
* account for initial pruning possibly having eliminated some of the
* subplans .
*
* ExecFindMatchingSubPlans :
* Returns indexes of matching subplans after evaluating all available
* expressions . This function can only be called during execution and
* must be called again each time the value of a Param listed in
* Returns indexes of matching subplans after evaluating the expressions
* that are safe to evaluate at a given point . This function is first
* called during ExecInitPartitionPruning ( ) to find the initially
* matching subplans based on performing the initial pruning steps and
* then must be called again each time the value of a Param listed in
* PartitionPruneState ' s ' execparamids ' changes .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
/*
* ExecCreatePartitionPruneState
* Build the data structure required for calling
* ExecFindInitialMatchingSubPlans and ExecFindMatchingSubPlans .
* ExecInitPartitionPruning
* Initialize data structure needed for run - time partition pruning and
* do initial pruning if needed
*
* On return , * initially_valid_subplans is assigned the set of indexes of
* child subplans that must be initialized along with the parent plan node .
* Initial pruning is performed here if needed and in that case only the
* surviving subplans ' indexes are added .
*
* If subplans are indeed pruned , subplan_map arrays contained in the returned
* PartitionPruneState are re - sequenced to not count those , though only if the
* maps will be needed for subsequent execution pruning passes .
*/
PartitionPruneState *
ExecInitPartitionPruning ( PlanState * planstate ,
int n_total_subplans ,
PartitionPruneInfo * pruneinfo ,
Bitmapset * * initially_valid_subplans )
{
PartitionPruneState * prunestate ;
EState * estate = planstate - > state ;
/* We may need an expression context to evaluate partition exprs */
ExecAssignExprContext ( estate , planstate ) ;
/* Create the working data structure for pruning */
prunestate = CreatePartitionPruneState ( planstate , pruneinfo ) ;
/*
* Perform an initial partition prune pass , if required .
*/
if ( prunestate - > do_initial_prune )
* initially_valid_subplans = ExecFindMatchingSubPlans ( prunestate , true ) ;
else
{
/* No pruning, so we'll need to initialize all subplans */
Assert ( n_total_subplans > 0 ) ;
* initially_valid_subplans = bms_add_range ( NULL , 0 ,
n_total_subplans - 1 ) ;
}
/*
* Re - sequence subplan indexes contained in prunestate to account for any
* that were removed above due to initial pruning . No need to do this if
* no steps were removed .
*/
if ( bms_num_members ( * initially_valid_subplans ) < n_total_subplans )
{
/*
* We can safely skip this when ! do_exec_prune , even though that
* leaves invalid data in prunestate , because that data won ' t be
* consulted again ( cf initial Assert in ExecFindMatchingSubPlans ) .
*/
if ( prunestate - > do_exec_prune )
PartitionPruneFixSubPlanMap ( prunestate ,
* initially_valid_subplans ,
n_total_subplans ) ;
}
return prunestate ;
}
/*
* CreatePartitionPruneState
* Build the data structure required for calling ExecFindMatchingSubPlans
*
* ' planstate ' is the parent plan node ' s execution state .
*
* ' partitionpruneinfo ' is a PartitionPruneInfo as generated by
* ' pruneinfo ' is a PartitionPruneInfo as generated by
* make_partition_pruneinfo . Here we build a PartitionPruneState containing a
* PartitionPruningData for each partitioning hierarchy ( i . e . , each sublist of
* partitionpruneinfo - > prune_infos ) , each of which contains a
* PartitionedRelPruningData for each PartitionedRelPruneInfo appearing in
* that sublist . This two - level system is needed to keep from confusing the
* different hierarchies when a UNION ALL contains multiple partitioned tables
* as children . The data stored in each PartitionedRelPruningData can be
* re - used each time we re - evaluate which partitions match the pruning steps
* provided in each PartitionedRelPruneInfo .
* pruneinfo - > prune_infos ) , each of which contains a PartitionedRelPruningDat a
* for each PartitionedRelPruneInfo appearing in that sublist . This two - level
* system is needed to keep from confusing the different hierarchies when a
* UNION ALL contains multiple partitioned tables as children . The data
* stored in each PartitionedRelPruningData can be re - used each time w e
* re - evaluate which partitions match the pruning steps provided in each
* PartitionedRelPruneInfo .
*/
PartitionPruneState *
ExecCreatePartitionPruneState ( PlanState * planstate ,
PartitionPruneInfo * partitionpruneinfo )
static PartitionPruneState *
CreatePartitionPruneState ( PlanState * planstate , PartitionPruneInfo * pruneinfo )
{
EState * estate = planstate - > state ;
PartitionPruneState * prunestate ;
int n_part_hierarchies ;
ListCell * lc ;
int i ;
ExprContext * econtext = planstate - > ps_ExprContext ;
/* For data reading, executor always omits detached partitions */
if ( estate - > es_partition_directory = = NULL )
estate - > es_partition_directory =
CreatePartitionDirectory ( estate - > es_query_cxt , false ) ;
n_part_hierarchies = list_length ( partitionpruneinfo - > prune_infos ) ;
n_part_hierarchies = list_length ( pruneinfo - > prune_infos ) ;
Assert ( n_part_hierarchies > 0 ) ;
/*
@ -1659,7 +1722,7 @@ ExecCreatePartitionPruneState(PlanState *planstate,
prunestate - > execparamids = NULL ;
/* other_subplans can change at runtime, so we need our own copy */
prunestate - > other_subplans = bms_copy ( partitionp runeinfo - > other_subplans ) ;
prunestate - > other_subplans = bms_copy ( pruneinfo - > other_subplans ) ;
prunestate - > do_initial_prune = false ; /* may be set below */
prunestate - > do_exec_prune = false ; /* may be set below */
prunestate - > num_partprunedata = n_part_hierarchies ;
@ -1676,7 +1739,7 @@ ExecCreatePartitionPruneState(PlanState *planstate,
ALLOCSET_DEFAULT_SIZES ) ;
i = 0 ;
foreach ( lc , partitionp runeinfo - > prune_infos )
foreach ( lc , pruneinfo - > prune_infos )
{
List * partrelpruneinfos = lfirst_node ( List , lc ) ;
int npartrelpruneinfos = list_length ( partrelpruneinfos ) ;
@ -1812,18 +1875,20 @@ ExecCreatePartitionPruneState(PlanState *planstate,
pprune - > initial_pruning_steps = pinfo - > initial_pruning_steps ;
if ( pinfo - > initial_pruning_steps )
{
ExecInitPruningContext ( & pprune - > initial_context ,
pinfo - > initial_pruning_steps ,
partdesc , partkey , planstate ) ;
InitPartitionPruneContext ( & pprune - > initial_context ,
pinfo - > initial_pruning_steps ,
partdesc , partkey , planstate ,
econtext ) ;
/* Record whether initial pruning is needed at any level */
prunestate - > do_initial_prune = true ;
}
pprune - > exec_pruning_steps = pinfo - > exec_pruning_steps ;
if ( pinfo - > exec_pruning_steps )
{
ExecInitPruningContext ( & pprune - > exec_context ,
pinfo - > exec_pruning_steps ,
partdesc , partkey , planstate ) ;
InitPartitionPruneContext ( & pprune - > exec_context ,
pinfo - > exec_pruning_steps ,
partdesc , partkey , planstate ,
econtext ) ;
/* Record whether exec pruning is needed at any level */
prunestate - > do_exec_prune = true ;
}
@ -1847,11 +1912,12 @@ ExecCreatePartitionPruneState(PlanState *planstate,
* Initialize a PartitionPruneContext for the given list of pruning steps .
*/
static void
ExecInitPruningContext ( PartitionPruneContext * context ,
List * pruning_steps ,
PartitionDesc partdesc ,
PartitionKey partkey ,
PlanState * planstate )
InitPartitionPruneContext ( PartitionPruneContext * context ,
List * pruning_steps ,
PartitionDesc partdesc ,
PartitionKey partkey ,
PlanState * planstate ,
ExprContext * econtext )
{
int n_steps ;
int partnatts ;
@ -1872,6 +1938,7 @@ ExecInitPruningContext(PartitionPruneContext *context,
context - > ppccontext = CurrentMemoryContext ;
context - > planstate = planstate ;
context - > exprcontext = econtext ;
/* Initialize expression state for each expression we need */
context - > exprstates = ( ExprState * * )
@ -1900,8 +1967,20 @@ ExecInitPruningContext(PartitionPruneContext *context,
step - > step . step_id ,
keyno ) ;
context - > exprstates [ stateidx ] =
ExecInitExpr ( expr , context - > planstate ) ;
/*
* When planstate is NULL , pruning_steps is known not to
* contain any expressions that depend on the parent plan .
* Information of any available EXTERN parameters must be
* passed explicitly in that case , which the caller must have
* made available via econtext .
*/
if ( planstate = = NULL )
context - > exprstates [ stateidx ] =
ExecInitExprWithParams ( expr ,
econtext - > ecxt_param_list_info ) ;
else
context - > exprstates [ stateidx ] =
ExecInitExpr ( expr , context - > planstate ) ;
}
keyno + + ;
}
@ -1909,179 +1988,119 @@ ExecInitPruningContext(PartitionPruneContext *context,
}
/*
* ExecFindInitialMatchingSubPlans
* Identify the set of subplans that cannot be eliminated by initial
* pruning , disregarding any pruning constraints involving PARAM_EXEC
* Params .
* PartitionPruneFixSubPlanMap
* Fix mapping of partition indexes to subplan indexes contained in
* prunestate by considering the new list of subplans that survived
* initial pruning
*
* If additional pruning passes will be required ( because of PARAM_EXEC
* Params ) , we must also update the translation data that allows conversion
* of partition indexes into subplan indexes to account for the unneeded
* subplans having been removed .
*
* Must only be called once per ' prunestate ' , and only if initial pruning
* is required .
*
* ' nsubplans ' must be passed as the total number of unpruned subplans .
* Current values of the indexes present in PartitionPruneState count all the
* subplans that would be present before initial pruning was done . If initial
* pruning got rid of some of the subplans , any subsequent pruning passes will
* will be looking at a different set of target subplans to choose from than
* those in the pre - initial - pruning set , so the maps in PartitionPruneState
* containing those indexes must be updated to reflect the new indexes of
* subplans in the post - initial - pruning set .
*/
Bitmapset *
ExecFindInitialMatchingSubPlans ( PartitionPruneState * prunestate , int nsubplans )
static void
PartitionPruneFixSubPlanMap ( PartitionPruneState * prunestate ,
Bitmapset * initially_valid_subplans ,
int n_total_subplans )
{
Bitmapset * result = NULL ;
MemoryContext oldcontext ;
int * new_subplan_indexes ;
Bitmapset * new_other_subplans ;
int i ;
/* Caller error if we get here without do_initial_prune */
Assert ( prunestate - > do_initial_prune ) ;
int newidx ;
/*
* Switch to a temp context to avoid leaking memory in the executor ' s
* query - lifespan memory context .
* First we must build a temporary array which maps old subplan indexes to
* new ones . For convenience of initialization , we use 1 - based indexes in
* this array and leave pruned items as 0.
*/
oldcontext = MemoryContextSwitchTo ( prunestate - > prune_context ) ;
/*
* For each hierarchy , do the pruning tests , and add nondeletable
* subplans ' indexes to " result " .
*/
for ( i = 0 ; i < prunestate - > num_partprunedata ; i + + )
new_subplan_indexes = ( int * ) palloc0 ( sizeof ( int ) * n_total_subplans ) ;
newidx = 1 ;
i = - 1 ;
while ( ( i = bms_next_member ( initially_valid_subplans , i ) ) > = 0 )
{
PartitionPruningData * prunedata ;
PartitionedRelPruningData * pprune ;
prunedata = prunestate - > partprunedata [ i ] ;
pprune = & prunedata - > partrelprunedata [ 0 ] ;
/* Perform pruning without using PARAM_EXEC Params */
find_matching_subplans_recurse ( prunedata , pprune , true , & result ) ;
/* Expression eval may have used space in node's ps_ExprContext too */
if ( pprune - > initial_pruning_steps )
ResetExprContext ( pprune - > initial_context . planstate - > ps_ExprContext ) ;
Assert ( i < n_total_subplans ) ;
new_subplan_indexes [ i ] = newidx + + ;
}
/* Add in any subplans that partition pruning didn't account for */
result = bms_add_members ( result , prunestate - > other_subplans ) ;
MemoryContextSwitchTo ( oldcontext ) ;
/* Copy result out of the temp context before we reset it */
result = bms_copy ( result ) ;
MemoryContextReset ( prunestate - > prune_context ) ;
/*
* If exec - time pruning is required and we pruned subplans above , then we
* must re - sequence the subplan indexes so that ExecFindMatchingSubPlans
* properly returns the indexes from the subplans which will remain after
* execution of this function .
*
* We can safely skip this when ! do_exec_prune , even though that leaves
* invalid data in prunestate , because that data won ' t be consulted again
* ( cf initial Assert in ExecFindMatchingSubPlans ) .
* Now we can update each PartitionedRelPruneInfo ' s subplan_map with new
* subplan indexes . We must also recompute its present_parts bitmap .
*/
if ( prunestate - > do_exec_prune & & bms_num_members ( result ) < nsubplans )
for ( i = 0 ; i < prunestate - > num_partprunedata ; i + + )
{
int * new_subplan_indexes ;
Bitmapset * new_other_subplans ;
int i ;
int newidx ;
PartitionPruningData * prunedata = prunestate - > partprunedata [ i ] ;
int j ;
/*
* First we must build a temporary array which maps old subplan
* indexes to new ones . For convenience of initialization , we use
* 1 - based indexes in this array and leave pruned items as 0.
* Within each hierarchy , we perform this loop in back - to - front order
* so that we determine present_parts for the lowest - level partitioned
* tables first . This way we can tell whether a sub - partitioned
* table ' s partitions were entirely pruned so we can exclude it from
* the current level ' s present_parts .
*/
new_subplan_indexes = ( int * ) palloc0 ( sizeof ( int ) * nsubplans ) ;
newidx = 1 ;
i = - 1 ;
while ( ( i = bms_next_member ( result , i ) ) > = 0 )
for ( j = prunedata - > num_partrelprunedata - 1 ; j > = 0 ; j - - )
{
Assert ( i < nsubplans ) ;
new_subplan_indexes [ i ] = newidx + + ;
}
PartitionedRelPruningData * pprune = & prunedata - > partrelprunedata [ j ] ;
int nparts = pprune - > nparts ;
int k ;
/*
* Now we can update each PartitionedRelPruneInfo ' s subplan_map with
* new subplan indexes . We must also recompute its present_parts
* bitmap .
*/
for ( i = 0 ; i < prunestate - > num_partprunedata ; i + + )
{
PartitionPruningData * prunedata = prunestate - > partprunedata [ i ] ;
int j ;
/* We just rebuild present_parts from scratch */
bms_free ( pprune - > present_parts ) ;
pprune - > present_parts = NULL ;
/*
* Within each hierarchy , we perform this loop in back - to - front
* order so that we determine present_parts for the lowest - level
* partitioned tables first . This way we can tell whether a
* sub - partitioned table ' s partitions were entirely pruned so we
* can exclude it from the current level ' s present_parts .
*/
for ( j = prunedata - > num_partrelprunedata - 1 ; j > = 0 ; j - - )
for ( k = 0 ; k < nparts ; k + + )
{
PartitionedRelPruningData * pprune = & prunedata - > partrelprunedata [ j ] ;
int nparts = pprune - > nparts ;
int k ;
/* We just rebuild present_parts from scratch */
bms_free ( pprune - > present_parts ) ;
pprune - > present_parts = NULL ;
int oldidx = pprune - > subplan_map [ k ] ;
int subidx ;
for ( k = 0 ; k < nparts ; k + + )
/*
* If this partition existed as a subplan then change the old
* subplan index to the new subplan index . The new index may
* become - 1 if the partition was pruned above , or it may just
* come earlier in the subplan list due to some subplans being
* removed earlier in the list . If it ' s a subpartition , add
* it to present_parts unless it ' s entirely pruned .
*/
if ( oldidx > = 0 )
{
int oldidx = pprune - > subplan_map [ k ] ;
int subidx ;
Assert ( oldidx < n_total_subplans ) ;
pprune - > subplan_map [ k ] = new_subplan_indexes [ oldidx ] - 1 ;
/*
* If this partition existed as a subplan then change the
* old subplan index to the new subplan index . The new
* index may become - 1 if the partition was pruned above ,
* or it may just come earlier in the subplan list due to
* some subplans being removed earlier in the list . If
* it ' s a subpartition , add it to present_parts unless
* it ' s entirely pruned .
*/
if ( oldidx > = 0 )
{
Assert ( oldidx < nsubplans ) ;
pprune - > subplan_map [ k ] = new_subplan_indexes [ oldidx ] - 1 ;
if ( new_subplan_indexes [ oldidx ] > 0 )
pprune - > present_parts =
bms_add_member ( pprune - > present_parts , k ) ;
}
else if ( ( subidx = pprune - > subpart_map [ k ] ) > = 0 )
{
PartitionedRelPruningData * subprune ;
if ( new_subplan_indexes [ oldidx ] > 0 )
pprune - > present_parts =
bms_add_member ( pprune - > present_parts , k ) ;
}
else if ( ( subidx = pprune - > subpart_map [ k ] ) > = 0 )
{
PartitionedRelPruningData * subprune ;
subprune = & prunedata - > partrelprunedata [ subidx ] ;
subprune = & prunedata - > partrelprunedata [ subidx ] ;
if ( ! bms_is_empty ( subprune - > present_parts ) )
pprune - > present_parts =
bms_add_member ( pprune - > present_parts , k ) ;
}
if ( ! bms_is_empty ( subprune - > present_parts ) )
pprune - > present_parts =
bms_add_member ( pprune - > present_parts , k ) ;
}
}
}
}
/*
* We must also recompute the other_subplans set , since indexes in it
* may change .
*/
new_other_subplans = NULL ;
i = - 1 ;
while ( ( i = bms_next_member ( prunestate - > other_subplans , i ) ) > = 0 )
new_other_subplans = bms_add_member ( new_other_subplans ,
new_subplan_indexes [ i ] - 1 ) ;
bms_free ( prunestate - > other_subplans ) ;
prunestate - > other_subplans = new_other_subplans ;
/*
* We must also recompute the other_subplans set , since indexes in it may
* change .
*/
new_other_subplans = NULL ;
i = - 1 ;
while ( ( i = bms_next_member ( prunestate - > other_subplans , i ) ) > = 0 )
new_other_subplans = bms_add_member ( new_other_subplans ,
new_subplan_indexes [ i ] - 1 ) ;
pfree ( new_subplan_indexe s ) ;
}
bms_free ( prunestate - > other_subplans ) ;
prunestate - > other_subplans = new_other_subplans ;
return result ;
pfree ( new_subplan_indexes ) ;
}
/*
@ -2089,21 +2108,24 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubplans)
* Determine which subplans match the pruning steps detailed in
* ' prunestate ' for the current comparison expression values .
*
* Here we assume we may evaluate PARAM_EXEC Params .
* Pass initial_prune if PARAM_EXEC Params cannot yet be evaluated . This
* differentiates the initial executor - time pruning step from later
* runtime pruning .
*/
Bitmapset *
ExecFindMatchingSubPlans ( PartitionPruneState * prunestate )
ExecFindMatchingSubPlans ( PartitionPruneState * prunestate ,
bool initial_prune )
{
Bitmapset * result = NULL ;
MemoryContext oldcontext ;
int i ;
/*
* If ! do_exec_prune , we ' ve got problems because
* ExecFindInitialMatchingSubPlans will not have bothered to updat e
* prunestate for whatever pruning it did .
* Either we ' re here on the initial prune done during pruning
* initialization , or we ' re at a point where PARAM_EXEC Params can b e
* evaluated * and * there are steps in which to do so .
*/
Assert ( prunestate - > do_exec_prune ) ;
Assert ( initial_prune | | prunestate - > do_exec_prune ) ;
/*
* Switch to a temp context to avoid leaking memory in the executor ' s
@ -2117,17 +2139,21 @@ ExecFindMatchingSubPlans(PartitionPruneState *prunestate)
*/
for ( i = 0 ; i < prunestate - > num_partprunedata ; i + + )
{
PartitionPruningData * prunedata ;
PartitionPruningData * prunedata = prunestate - > partprunedata [ i ] ;
PartitionedRelPruningData * pprune ;
prunedata = prunestate - > partprunedata [ i ] ;
/*
* We pass the zeroth item , belonging to the root table of the
* hierarchy , and find_matching_subplans_recurse ( ) takes care of
* recursing to other ( lower - level ) parents as needed .
*/
pprune = & prunedata - > partrelprunedata [ 0 ] ;
find_matching_subplans_recurse ( prunedata , pprune , initial_prune ,
& result ) ;
find_matching_subplans_recurse ( prunedata , pprune , false , & result ) ;
/* Expression eval may have used space in node's ps_ExprContext too */
/* Expression eval may have used space in ExprContext too */
if ( pprune - > exec_pruning_steps )
ResetExprContext ( pprune - > exec_context . planstate - > ps_ExprC ontext) ;
ResetExprContext ( pprune - > exec_context . exprcontext ) ;
}
/* Add in any subplans that partition pruning didn't account for */
@ -2145,8 +2171,7 @@ ExecFindMatchingSubPlans(PartitionPruneState *prunestate)
/*
* find_matching_subplans_recurse
* Recursive worker function for ExecFindMatchingSubPlans and
* ExecFindInitialMatchingSubPlans
* Recursive worker function for ExecFindMatchingSubPlans
*
* Adds valid ( non - prunable ) subplan IDs to * validsubplans
*/
@ -2162,25 +2187,19 @@ find_matching_subplans_recurse(PartitionPruningData *prunedata,
/* Guard against stack overflow due to overly deep partition hierarchy. */
check_stack_depth ( ) ;
/* Only prune if pruning would be useful at this level. */
/*
* Prune as appropriate , if we have pruning steps matching the current
* execution context . Otherwise just include all partitions at this
* level .
*/
if ( initial_prune & & pprune - > initial_pruning_steps )
{
partset = get_matching_partitions ( & pprune - > initial_context ,
pprune - > initial_pruning_steps ) ;
}
else if ( ! initial_prune & & pprune - > exec_pruning_steps )
{
partset = get_matching_partitions ( & pprune - > exec_context ,
pprune - > exec_pruning_steps ) ;
}
else
{
/*
* If no pruning is to be done , just include all partitions at this
* level .
*/
partset = pprune - > present_parts ;
}
/* Translate partset into subplan indexes */
i = - 1 ;