@@ -78,6 +78,10 @@ static char *ExecBuildSlotPartitionKeyDescription(Relation rel,
78
78
bool * isnull ,
79
79
int maxfieldlen );
80
80
static List * adjust_partition_tlist (List * tlist , TupleConversionMap * map );
81
+ static void ExecInitPruningContext (PartitionPruneContext * context ,
82
+ Oid reloid ,
83
+ List * pruning_steps ,
84
+ PlanState * planstate );
81
85
static void find_matching_subplans_recurse (PartitionPruningData * prunedata ,
82
86
PartitionedRelPruningData * pprune ,
83
87
bool initial_prune ,
@@ -1525,18 +1529,13 @@ ExecCreatePartitionPruneState(PlanState *planstate,
1525
1529
{
1526
1530
PartitionedRelPruneInfo * pinfo = lfirst_node (PartitionedRelPruneInfo , lc2 );
1527
1531
PartitionedRelPruningData * pprune = & prunedata -> partrelprunedata [j ];
1528
- PartitionPruneContext * context = & pprune -> context ;
1529
- PartitionDesc partdesc ;
1530
- PartitionKey partkey ;
1531
- int partnatts ;
1532
- int n_steps ;
1533
- ListCell * lc3 ;
1534
1532
1535
1533
/*
1536
1534
* We must copy the subplan_map rather than pointing directly to
1537
1535
* the plan's version, as we may end up making modifications to it
1538
1536
* later.
1539
1537
*/
1538
+ pprune -> nparts = pinfo -> nparts ;
1540
1539
pprune -> subplan_map = palloc (sizeof (int ) * pinfo -> nparts );
1541
1540
memcpy (pprune -> subplan_map , pinfo -> subplan_map ,
1542
1541
sizeof (int ) * pinfo -> nparts );
@@ -1548,76 +1547,28 @@ ExecCreatePartitionPruneState(PlanState *planstate,
1548
1547
pprune -> present_parts = bms_copy (pinfo -> present_parts );
1549
1548
1550
1549
/*
1551
- * We need to hold a pin on the partitioned table's relcache entry
1552
- * so that we can rely on its copies of the table's partition key
1553
- * and partition descriptor. We need not get a lock though; one
1554
- * should have been acquired already by InitPlan or
1555
- * ExecLockNonLeafAppendTables.
1550
+ * Initialize pruning contexts as needed.
1556
1551
*/
1557
- context -> partrel = relation_open (pinfo -> reloid , NoLock );
1558
-
1559
- partkey = RelationGetPartitionKey (context -> partrel );
1560
- partdesc = RelationGetPartitionDesc (context -> partrel );
1561
- n_steps = list_length (pinfo -> pruning_steps );
1562
-
1563
- context -> strategy = partkey -> strategy ;
1564
- context -> partnatts = partnatts = partkey -> partnatts ;
1565
- context -> nparts = pinfo -> nparts ;
1566
- context -> boundinfo = partdesc -> boundinfo ;
1567
- context -> partcollation = partkey -> partcollation ;
1568
- context -> partsupfunc = partkey -> partsupfunc ;
1569
-
1570
- /* We'll look up type-specific support functions as needed */
1571
- context -> stepcmpfuncs = (FmgrInfo * )
1572
- palloc0 (sizeof (FmgrInfo ) * n_steps * partnatts );
1573
-
1574
- context -> ppccontext = CurrentMemoryContext ;
1575
- context -> planstate = planstate ;
1576
-
1577
- /* Initialize expression state for each expression we need */
1578
- context -> exprstates = (ExprState * * )
1579
- palloc0 (sizeof (ExprState * ) * n_steps * partnatts );
1580
- foreach (lc3 , pinfo -> pruning_steps )
1552
+ pprune -> initial_pruning_steps = pinfo -> initial_pruning_steps ;
1553
+ if (pinfo -> initial_pruning_steps )
1581
1554
{
1582
- PartitionPruneStepOp * step = (PartitionPruneStepOp * ) lfirst (lc3 );
1583
- ListCell * lc4 ;
1584
- int keyno ;
1585
-
1586
- /* not needed for other step kinds */
1587
- if (!IsA (step , PartitionPruneStepOp ))
1588
- continue ;
1589
-
1590
- Assert (list_length (step -> exprs ) <= partnatts );
1591
-
1592
- keyno = 0 ;
1593
- foreach (lc4 , step -> exprs )
1594
- {
1595
- Expr * expr = (Expr * ) lfirst (lc4 );
1596
-
1597
- /* not needed for Consts */
1598
- if (!IsA (expr , Const ))
1599
- {
1600
- int stateidx = PruneCxtStateIdx (partnatts ,
1601
- step -> step .step_id ,
1602
- keyno );
1603
-
1604
- context -> exprstates [stateidx ] =
1605
- ExecInitExpr (expr , context -> planstate );
1606
- }
1607
- keyno ++ ;
1608
- }
1555
+ ExecInitPruningContext (& pprune -> initial_context ,
1556
+ pinfo -> reloid ,
1557
+ pinfo -> initial_pruning_steps ,
1558
+ planstate );
1559
+ /* Record whether initial pruning is needed at any level */
1560
+ prunestate -> do_initial_prune = true;
1561
+ }
1562
+ pprune -> exec_pruning_steps = pinfo -> exec_pruning_steps ;
1563
+ if (pinfo -> exec_pruning_steps )
1564
+ {
1565
+ ExecInitPruningContext (& pprune -> exec_context ,
1566
+ pinfo -> reloid ,
1567
+ pinfo -> exec_pruning_steps ,
1568
+ planstate );
1569
+ /* Record whether exec pruning is needed at any level */
1570
+ prunestate -> do_exec_prune = true;
1609
1571
}
1610
-
1611
- /* Array is not modified at runtime, so just point to plan's copy */
1612
- context -> exprhasexecparam = pinfo -> hasexecparam ;
1613
-
1614
- pprune -> pruning_steps = pinfo -> pruning_steps ;
1615
- pprune -> do_initial_prune = pinfo -> do_initial_prune ;
1616
- pprune -> do_exec_prune = pinfo -> do_exec_prune ;
1617
-
1618
- /* Record if pruning would be useful at any level */
1619
- prunestate -> do_initial_prune |= pinfo -> do_initial_prune ;
1620
- prunestate -> do_exec_prune |= pinfo -> do_exec_prune ;
1621
1572
1622
1573
/*
1623
1574
* Accumulate the IDs of all PARAM_EXEC Params affecting the
@@ -1654,7 +1605,90 @@ ExecDestroyPartitionPruneState(PartitionPruneState *prunestate)
1654
1605
int j ;
1655
1606
1656
1607
for (j = 0 ; j < prunedata -> num_partrelprunedata ; j ++ )
1657
- relation_close (pprune [j ].context .partrel , NoLock );
1608
+ {
1609
+ if (pprune [j ].initial_pruning_steps )
1610
+ relation_close (pprune [j ].initial_context .partrel , NoLock );
1611
+ if (pprune [j ].exec_pruning_steps )
1612
+ relation_close (pprune [j ].exec_context .partrel , NoLock );
1613
+ }
1614
+ }
1615
+ }
1616
+
1617
+ /*
1618
+ * Initialize a PartitionPruneContext for the given list of pruning steps.
1619
+ */
1620
+ static void
1621
+ ExecInitPruningContext (PartitionPruneContext * context ,
1622
+ Oid reloid ,
1623
+ List * pruning_steps ,
1624
+ PlanState * planstate )
1625
+ {
1626
+ PartitionKey partkey ;
1627
+ PartitionDesc partdesc ;
1628
+ int n_steps ;
1629
+ int partnatts ;
1630
+ ListCell * lc ;
1631
+
1632
+ /*
1633
+ * We need to hold a pin on the partitioned table's relcache entry
1634
+ * so that we can rely on its copies of the table's partition key
1635
+ * and partition descriptor. We need not get a lock though; one
1636
+ * should have been acquired already by InitPlan or
1637
+ * ExecLockNonLeafAppendTables.
1638
+ */
1639
+ context -> partrel = relation_open (reloid , NoLock );
1640
+
1641
+ partkey = RelationGetPartitionKey (context -> partrel );
1642
+ partdesc = RelationGetPartitionDesc (context -> partrel );
1643
+
1644
+ n_steps = list_length (pruning_steps );
1645
+
1646
+ context -> strategy = partkey -> strategy ;
1647
+ context -> partnatts = partnatts = partkey -> partnatts ;
1648
+ context -> nparts = partdesc -> nparts ;
1649
+ context -> boundinfo = partdesc -> boundinfo ;
1650
+ context -> partcollation = partkey -> partcollation ;
1651
+ context -> partsupfunc = partkey -> partsupfunc ;
1652
+
1653
+ /* We'll look up type-specific support functions as needed */
1654
+ context -> stepcmpfuncs = (FmgrInfo * )
1655
+ palloc0 (sizeof (FmgrInfo ) * n_steps * partnatts );
1656
+
1657
+ context -> ppccontext = CurrentMemoryContext ;
1658
+ context -> planstate = planstate ;
1659
+
1660
+ /* Initialize expression state for each expression we need */
1661
+ context -> exprstates = (ExprState * * )
1662
+ palloc0 (sizeof (ExprState * ) * n_steps * partnatts );
1663
+ foreach (lc , pruning_steps )
1664
+ {
1665
+ PartitionPruneStepOp * step = (PartitionPruneStepOp * ) lfirst (lc );
1666
+ ListCell * lc2 ;
1667
+ int keyno ;
1668
+
1669
+ /* not needed for other step kinds */
1670
+ if (!IsA (step , PartitionPruneStepOp ))
1671
+ continue ;
1672
+
1673
+ Assert (list_length (step -> exprs ) <= partnatts );
1674
+
1675
+ keyno = 0 ;
1676
+ foreach (lc2 , step -> exprs )
1677
+ {
1678
+ Expr * expr = (Expr * ) lfirst (lc2 );
1679
+
1680
+ /* not needed for Consts */
1681
+ if (!IsA (expr , Const ))
1682
+ {
1683
+ int stateidx = PruneCxtStateIdx (partnatts ,
1684
+ step -> step .step_id ,
1685
+ keyno );
1686
+
1687
+ context -> exprstates [stateidx ] =
1688
+ ExecInitExpr (expr , context -> planstate );
1689
+ }
1690
+ keyno ++ ;
1691
+ }
1658
1692
}
1659
1693
}
1660
1694
@@ -1702,7 +1736,8 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubplans)
1702
1736
find_matching_subplans_recurse (prunedata , pprune , true, & result );
1703
1737
1704
1738
/* Expression eval may have used space in node's ps_ExprContext too */
1705
- ResetExprContext (pprune -> context .planstate -> ps_ExprContext );
1739
+ if (pprune -> initial_pruning_steps )
1740
+ ResetExprContext (pprune -> initial_context .planstate -> ps_ExprContext );
1706
1741
}
1707
1742
1708
1743
MemoryContextSwitchTo (oldcontext );
@@ -1769,7 +1804,7 @@ ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate, int nsubplans)
1769
1804
for (j = prunedata -> num_partrelprunedata - 1 ; j >= 0 ; j -- )
1770
1805
{
1771
1806
PartitionedRelPruningData * pprune = & prunedata -> partrelprunedata [j ];
1772
- int nparts = pprune -> context . nparts ;
1807
+ int nparts = pprune -> nparts ;
1773
1808
int k ;
1774
1809
1775
1810
/* We just rebuild present_parts from scratch */
@@ -1854,7 +1889,8 @@ ExecFindMatchingSubPlans(PartitionPruneState *prunestate)
1854
1889
find_matching_subplans_recurse (prunedata , pprune , false, & result );
1855
1890
1856
1891
/* Expression eval may have used space in node's ps_ExprContext too */
1857
- ResetExprContext (pprune -> context .planstate -> ps_ExprContext );
1892
+ if (pprune -> exec_pruning_steps )
1893
+ ResetExprContext (pprune -> exec_context .planstate -> ps_ExprContext );
1858
1894
}
1859
1895
1860
1896
MemoryContextSwitchTo (oldcontext );
@@ -1890,15 +1926,15 @@ find_matching_subplans_recurse(PartitionPruningData *prunedata,
1890
1926
check_stack_depth ();
1891
1927
1892
1928
/* Only prune if pruning would be useful at this level. */
1893
- if (initial_prune ? pprune -> do_initial_prune : pprune -> do_exec_prune )
1929
+ if (initial_prune && pprune -> initial_pruning_steps )
1894
1930
{
1895
- PartitionPruneContext * context = & pprune -> context ;
1896
-
1897
- /* Set whether we can evaluate PARAM_EXEC Params or not */
1898
- context -> evalexecparams = !initial_prune ;
1899
-
1900
- partset = get_matching_partitions (context ,
1901
- pprune -> pruning_steps );
1931
+ partset = get_matching_partitions ( & pprune -> initial_context ,
1932
+ pprune -> initial_pruning_steps );
1933
+ }
1934
+ else if ( !initial_prune && pprune -> exec_pruning_steps )
1935
+ {
1936
+ partset = get_matching_partitions (& pprune -> exec_context ,
1937
+ pprune -> exec_pruning_steps );
1902
1938
}
1903
1939
else
1904
1940
{
0 commit comments