@@ -1596,10 +1596,13 @@ ExecCreatePartitionPruneState(PlanState *planstate,
15961596/*
15971597 * ExecFindInitialMatchingSubPlans
15981598 * Identify the set of subplans that cannot be eliminated by initial
1599- * pruning (disregarding any pruning constraints involving PARAM_EXEC
1600- * Params). Also re-map the translation matrix which allows conversion
1601- * of partition indexes into subplan indexes to account for the unneeded
1602- * subplans having been removed.
1599+ * pruning, disregarding any pruning constraints involving PARAM_EXEC
1600+ * Params.
1601+ *
1602+ * If additional pruning passes will be required (because of PARAM_EXEC
1603+ * Params), we must also update the translation data that allows conversion
1604+ * of partition indexes into subplan indexes to account for the unneeded
1605+ * subplans having been removed.
16031606 *
16041607 * Must only be called once per 'prunestate', and only if initial pruning
16051608 * is required.
@@ -1613,17 +1616,18 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubplans)
16131616 MemoryContext oldcontext ;
16141617 int i ;
16151618
1619+ /* Caller error if we get here without do_initial_prune */
16161620 Assert (prunestate -> do_initial_prune );
16171621
16181622 /*
16191623 * Switch to a temp context to avoid leaking memory in the executor's
1620- * memory context.
1624+ * query-lifespan memory context.
16211625 */
16221626 oldcontext = MemoryContextSwitchTo (prunestate -> prune_context );
16231627
16241628 /*
1625- * For each hierarchy, do the pruning tests, and add deletable subplans'
1626- * indexes to "result".
1629+ * For each hierarchy, do the pruning tests, and add nondeletable
1630+ * subplans' indexes to "result".
16271631 */
16281632 for (i = 0 ; i < prunestate -> num_partprunedata ; i ++ )
16291633 {
@@ -1640,22 +1644,27 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubplans)
16401644 ResetExprContext (pprune -> context .planstate -> ps_ExprContext );
16411645 }
16421646
1647+ /* Add in any subplans that partition pruning didn't account for */
1648+ result = bms_add_members (result , prunestate -> other_subplans );
1649+
16431650 MemoryContextSwitchTo (oldcontext );
16441651
16451652 /* Copy result out of the temp context before we reset it */
16461653 result = bms_copy (result );
16471654
1648- /* Add in any subplans that partition pruning didn't account for */
1649- result = bms_add_members (result , prunestate -> other_subplans );
1650-
16511655 MemoryContextReset (prunestate -> prune_context );
16521656
16531657 /*
1654- * If any subplans were pruned, we must re-sequence the subplan indexes so
1655- * that ExecFindMatchingSubPlans properly returns the indexes from the
1656- * subplans which will remain after execution of this function.
1658+ * If exec-time pruning is required and we pruned subplans above, then we
1659+ * must re-sequence the subplan indexes so that ExecFindMatchingSubPlans
1660+ * properly returns the indexes from the subplans which will remain after
1661+ * execution of this function.
1662+ *
1663+ * We can safely skip this when !do_exec_prune, even though that leaves
1664+ * invalid data in prunestate, because that data won't be consulted again
1665+ * (cf initial Assert in ExecFindMatchingSubPlans).
16571666 */
1658- if (bms_num_members (result ) < nsubplans )
1667+ if (prunestate -> do_exec_prune && bms_num_members (result ) < nsubplans )
16591668 {
16601669 int * new_subplan_indexes ;
16611670 Bitmapset * new_other_subplans ;
@@ -1664,25 +1673,17 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubplans)
16641673
16651674 /*
16661675 * First we must build a temporary array which maps old subplan
1667- * indexes to new ones. While we're at it, also recompute the
1668- * other_subplans set, since indexes in it may change .
1676+ * indexes to new ones. For convenience of initialization, we use
1677+ * 1-based indexes in this array and leave pruned items as 0 .
16691678 */
1670- new_subplan_indexes = (int * ) palloc (sizeof (int ) * nsubplans );
1671- new_other_subplans = NULL ;
1672- newidx = 0 ;
1673- for ( i = 0 ; i < nsubplans ; i ++ )
1679+ new_subplan_indexes = (int * ) palloc0 (sizeof (int ) * nsubplans );
1680+ newidx = 1 ;
1681+ i = -1 ;
1682+ while (( i = bms_next_member ( result , i )) >= 0 )
16741683 {
1675- if (bms_is_member (i , result ))
1676- new_subplan_indexes [i ] = newidx ++ ;
1677- else
1678- new_subplan_indexes [i ] = -1 ; /* Newly pruned */
1679-
1680- if (bms_is_member (i , prunestate -> other_subplans ))
1681- new_other_subplans = bms_add_member (new_other_subplans ,
1682- new_subplan_indexes [i ]);
1684+ Assert (i < nsubplans );
1685+ new_subplan_indexes [i ] = newidx ++ ;
16831686 }
1684- bms_free (prunestate -> other_subplans );
1685- prunestate -> other_subplans = new_other_subplans ;
16861687
16871688 /*
16881689 * Now we can update each PartitionedRelPruneInfo's subplan_map with
@@ -1699,7 +1700,7 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubplans)
16991700 * order so that we determine present_parts for the lowest-level
17001701 * partitioned tables first. This way we can tell whether a
17011702 * sub-partitioned table's partitions were entirely pruned so we
1702- * can exclude that from ' present_parts' .
1703+ * can exclude it from the current level's present_parts.
17031704 */
17041705 for (j = prunedata -> num_partrelprunedata - 1 ; j >= 0 ; j -- )
17051706 {
@@ -1728,9 +1729,9 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubplans)
17281729 if (oldidx >= 0 )
17291730 {
17301731 Assert (oldidx < nsubplans );
1731- pprune -> subplan_map [k ] = new_subplan_indexes [oldidx ];
1732+ pprune -> subplan_map [k ] = new_subplan_indexes [oldidx ] - 1 ;
17321733
1733- if (new_subplan_indexes [oldidx ] >= 0 )
1734+ if (new_subplan_indexes [oldidx ] > 0 )
17341735 pprune -> present_parts =
17351736 bms_add_member (pprune -> present_parts , k );
17361737 }
@@ -1748,6 +1749,19 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubplans)
17481749 }
17491750 }
17501751
1752+ /*
1753+ * We must also recompute the other_subplans set, since indexes in it
1754+ * may change.
1755+ */
1756+ new_other_subplans = NULL ;
1757+ i = -1 ;
1758+ while ((i = bms_next_member (prunestate -> other_subplans , i )) >= 0 )
1759+ new_other_subplans = bms_add_member (new_other_subplans ,
1760+ new_subplan_indexes [i ] - 1 );
1761+
1762+ bms_free (prunestate -> other_subplans );
1763+ prunestate -> other_subplans = new_other_subplans ;
1764+
17511765 pfree (new_subplan_indexes );
17521766 }
17531767
@@ -1768,15 +1782,22 @@ ExecFindMatchingSubPlans(PartitionPruneState *prunestate)
17681782 MemoryContext oldcontext ;
17691783 int i ;
17701784
1785+ /*
1786+ * If !do_exec_prune, we've got problems because
1787+ * ExecFindInitialMatchingSubPlans will not have bothered to update
1788+ * prunestate for whatever pruning it did.
1789+ */
1790+ Assert (prunestate -> do_exec_prune );
1791+
17711792 /*
17721793 * Switch to a temp context to avoid leaking memory in the executor's
1773- * memory context.
1794+ * query-lifespan memory context.
17741795 */
17751796 oldcontext = MemoryContextSwitchTo (prunestate -> prune_context );
17761797
17771798 /*
1778- * For each hierarchy, do the pruning tests, and add deletable subplans'
1779- * indexes to "result".
1799+ * For each hierarchy, do the pruning tests, and add nondeletable
1800+ * subplans' indexes to "result".
17801801 */
17811802 for (i = 0 ; i < prunestate -> num_partprunedata ; i ++ )
17821803 {
@@ -1792,14 +1813,14 @@ ExecFindMatchingSubPlans(PartitionPruneState *prunestate)
17921813 ResetExprContext (pprune -> context .planstate -> ps_ExprContext );
17931814 }
17941815
1816+ /* Add in any subplans that partition pruning didn't account for */
1817+ result = bms_add_members (result , prunestate -> other_subplans );
1818+
17951819 MemoryContextSwitchTo (oldcontext );
17961820
17971821 /* Copy result out of the temp context before we reset it */
17981822 result = bms_copy (result );
17991823
1800- /* Add in any subplans that partition pruning didn't account for */
1801- result = bms_add_members (result , prunestate -> other_subplans );
1802-
18031824 MemoryContextReset (prunestate -> prune_context );
18041825
18051826 return result ;
0 commit comments