diff options
Diffstat (limited to 'src/backend/executor/execPartition.c')
-rw-r--r-- | src/backend/executor/execPartition.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index b6e89d0620d..432eeaf9034 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -26,6 +26,7 @@ #include "partitioning/partdesc.h" #include "partitioning/partprune.h" #include "rewrite/rewriteManip.h" +#include "storage/lmgr.h" #include "utils/acl.h" #include "utils/lsyscache.h" #include "utils/partcache.h" @@ -1768,7 +1769,8 @@ adjust_partition_colnos_using_map(List *colnos, AttrMap *attrMap) * ExecDoInitialPruning: * Perform runtime "initial" pruning, if necessary, to determine the set * of child subnodes that need to be initialized during ExecInitNode() for - * all plan nodes that contain a PartitionPruneInfo. + * all plan nodes that contain a PartitionPruneInfo. This also locks the + * leaf partitions whose subnodes will be initialized if needed. * * ExecInitPartitionExecPruning: * Updates the PartitionPruneState found at given part_prune_index in @@ -1789,11 +1791,13 @@ adjust_partition_colnos_using_map(List *colnos, AttrMap *attrMap) *------------------------------------------------------------------------- */ + /* * ExecDoInitialPruning * Perform runtime "initial" pruning, if necessary, to determine the set * of child subnodes that need to be initialized during ExecInitNode() for - * plan nodes that support partition pruning. + * plan nodes that support partition pruning. This also locks the leaf + * partitions whose subnodes will be initialized if needed. * * This function iterates over each PartitionPruneInfo entry in * estate->es_part_prune_infos. For each entry, it creates a PartitionPruneState @@ -1816,6 +1820,7 @@ void ExecDoInitialPruning(EState *estate) { ListCell *lc; + List *locked_relids = NIL; foreach(lc, estate->es_part_prune_infos) { @@ -1841,11 +1846,40 @@ ExecDoInitialPruning(EState *estate) else validsubplan_rtis = all_leafpart_rtis; + if (ExecShouldLockRelations(estate)) + { + int rtindex = -1; + + while ((rtindex = bms_next_member(validsubplan_rtis, + rtindex)) >= 0) + { + RangeTblEntry *rte = exec_rt_fetch(rtindex, estate); + + Assert(rte->rtekind == RTE_RELATION && + rte->rellockmode != NoLock); + LockRelationOid(rte->relid, rte->rellockmode); + locked_relids = lappend_int(locked_relids, rtindex); + } + } estate->es_unpruned_relids = bms_add_members(estate->es_unpruned_relids, validsubplan_rtis); estate->es_part_prune_results = lappend(estate->es_part_prune_results, validsubplans); } + + /* + * Release the useless locks if the plan won't be executed. This is the + * same as what CheckCachedPlan() in plancache.c does. + */ + if (!ExecPlanStillValid(estate)) + { + foreach(lc, locked_relids) + { + RangeTblEntry *rte = exec_rt_fetch(lfirst_int(lc), estate); + + UnlockRelationOid(rte->relid, rte->rellockmode); + } + } } /* |