diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execMain.c | 76 | ||||
-rw-r--r-- | src/backend/executor/execPartition.c | 46 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 60 | ||||
-rw-r--r-- | src/backend/executor/nodeAppend.c | 6 | ||||
-rw-r--r-- | src/backend/executor/nodeBitmapHeapscan.c | 7 | ||||
-rw-r--r-- | src/backend/executor/nodeCustom.c | 4 | ||||
-rw-r--r-- | src/backend/executor/nodeForeignscan.c | 4 | ||||
-rw-r--r-- | src/backend/executor/nodeIndexonlyscan.c | 7 | ||||
-rw-r--r-- | src/backend/executor/nodeIndexscan.c | 11 | ||||
-rw-r--r-- | src/backend/executor/nodeMergeAppend.c | 6 | ||||
-rw-r--r-- | src/backend/executor/nodeSamplescan.c | 9 | ||||
-rw-r--r-- | src/backend/executor/nodeSeqscan.c | 9 | ||||
-rw-r--r-- | src/backend/executor/nodeTidscan.c | 7 |
13 files changed, 92 insertions, 160 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 9569d2fa423..8cbd75ed7aa 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -824,6 +824,15 @@ InitPlan(QueryDesc *queryDesc, int eflags) * initialize the node's execution state */ estate->es_range_table = rangeTable; + + /* + * Allocate an array to store an open Relation corresponding to each + * rangeTable item, and initialize entries to NULL. Relations are opened + * and stored here as needed. + */ + estate->es_relations = (Relation *) palloc0(list_length(rangeTable) * + sizeof(Relation)); + estate->es_plannedstmt = plannedstmt; /* @@ -845,13 +854,10 @@ InitPlan(QueryDesc *queryDesc, int eflags) foreach(l, resultRelations) { Index resultRelationIndex = lfirst_int(l); - Oid resultRelationOid; Relation resultRelation; - resultRelationOid = getrelid(resultRelationIndex, rangeTable); - resultRelation = heap_open(resultRelationOid, NoLock); - Assert(CheckRelationLockedByMe(resultRelation, RowExclusiveLock, true)); - + resultRelation = ExecGetRangeTableRelation(estate, + resultRelationIndex); InitResultRelInfo(resultRelInfo, resultRelation, resultRelationIndex, @@ -886,15 +892,13 @@ InitPlan(QueryDesc *queryDesc, int eflags) foreach(l, plannedstmt->rootResultRelations) { Index resultRelIndex = lfirst_int(l); - Oid resultRelOid; Relation resultRelDesc; - resultRelOid = getrelid(resultRelIndex, rangeTable); - resultRelDesc = heap_open(resultRelOid, NoLock); - Assert(CheckRelationLockedByMe(resultRelDesc, RowExclusiveLock, true)); + resultRelDesc = ExecGetRangeTableRelation(estate, + resultRelIndex); InitResultRelInfo(resultRelInfo, resultRelDesc, - lfirst_int(l), + resultRelIndex, NULL, estate->es_instrument); resultRelInfo++; @@ -967,10 +971,7 @@ InitPlan(QueryDesc *queryDesc, int eflags) case ROW_MARK_SHARE: case ROW_MARK_KEYSHARE: case ROW_MARK_REFERENCE: - relation = heap_open(relid, NoLock); - Assert(CheckRelationLockedByMe(relation, - rt_fetch(rc->rti, rangeTable)->rellockmode, - true)); + relation = ExecGetRangeTableRelation(estate, rc->rti); break; case ROW_MARK_COPY: /* no physical table access is required */ @@ -1483,8 +1484,19 @@ ExecCleanUpTriggerState(EState *estate) { ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l); - /* Close indices and then the relation itself */ - ExecCloseIndices(resultRelInfo); + /* + * Assert this is a "dummy" ResultRelInfo, see above. Otherwise we + * might be issuing a duplicate close against a Relation opened by + * ExecGetRangeTableRelation. + */ + Assert(resultRelInfo->ri_RangeTableIndex == 0); + + /* + * Since ExecGetTriggerResultRel doesn't call ExecOpenIndices for + * these rels, we needn't call ExecCloseIndices either. + */ + Assert(resultRelInfo->ri_NumIndices == 0); + heap_close(resultRelInfo->ri_RelationDesc, NoLock); } } @@ -1607,6 +1619,7 @@ static void ExecEndPlan(PlanState *planstate, EState *estate) { ResultRelInfo *resultRelInfo; + int num_relations; int i; ListCell *l; @@ -1634,39 +1647,29 @@ ExecEndPlan(PlanState *planstate, EState *estate) ExecResetTupleTable(estate->es_tupleTable, false); /* - * close the result relation(s) if any, but hold locks until xact commit. + * close indexes of result relation(s) if any. (Rels themselves get + * closed next.) */ resultRelInfo = estate->es_result_relations; for (i = estate->es_num_result_relations; i > 0; i--) { - /* Close indices and then the relation itself */ ExecCloseIndices(resultRelInfo); - heap_close(resultRelInfo->ri_RelationDesc, NoLock); resultRelInfo++; } - /* Close the root target relation(s). */ - resultRelInfo = estate->es_root_result_relations; - for (i = estate->es_num_root_result_relations; i > 0; i--) + /* + * close whatever rangetable Relations have been opened. We did not + * acquire locks in ExecGetRangeTableRelation, so don't release 'em here. + */ + num_relations = list_length(estate->es_range_table); + for (i = 0; i < num_relations; i++) { - heap_close(resultRelInfo->ri_RelationDesc, NoLock); - resultRelInfo++; + if (estate->es_relations[i]) + heap_close(estate->es_relations[i], NoLock); } /* likewise close any trigger target relations */ ExecCleanUpTriggerState(estate); - - /* - * close any relations selected FOR [KEY] UPDATE/SHARE, again keeping - * locks - */ - foreach(l, estate->es_rowMarks) - { - ExecRowMark *erm = (ExecRowMark *) lfirst(l); - - if (erm->relation) - heap_close(erm->relation, NoLock); - } } /* ---------------------------------------------------------------- @@ -3161,6 +3164,7 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree) estate->es_snapshot = parentestate->es_snapshot; estate->es_crosscheck_snapshot = parentestate->es_crosscheck_snapshot; estate->es_range_table = parentestate->es_range_table; + estate->es_relations = parentestate->es_relations; estate->es_plannedstmt = parentestate->es_plannedstmt; estate->es_junkFilter = parentestate->es_junkFilter; estate->es_output_cid = parentestate->es_output_cid; diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index 832c79b41ea..c7dc9bf1362 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -219,7 +219,7 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd, ExprContext *ecxt = GetPerTupleExprContext(estate); TupleTableSlot *ecxt_scantuple_old = ecxt->ecxt_scantuple; TupleTableSlot *myslot = NULL; - MemoryContext oldcxt; + MemoryContext oldcxt; /* use per-tuple context here to avoid leaking memory */ oldcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); @@ -1389,9 +1389,6 @@ adjust_partition_tlist(List *tlist, TupleConversionMap *map) * functions. Details stored include how to map the partition index * returned by the partition pruning code into subplan indexes. * - * ExecDestroyPartitionPruneState: - * Deletes a PartitionPruneState. Must be called during executor shutdown. - * * ExecFindInitialMatchingSubPlans: * Returns indexes of matching subplans. Partition pruning is attempted * without any evaluation of expressions containing PARAM_EXEC Params. @@ -1433,6 +1430,7 @@ PartitionPruneState * ExecCreatePartitionPruneState(PlanState *planstate, PartitionPruneInfo *partitionpruneinfo) { + EState *estate = planstate->state; PartitionPruneState *prunestate; int n_part_hierarchies; ListCell *lc; @@ -1487,6 +1485,7 @@ ExecCreatePartitionPruneState(PlanState *planstate, PartitionedRelPruneInfo *pinfo = lfirst_node(PartitionedRelPruneInfo, lc2); PartitionedRelPruningData *pprune = &prunedata->partrelprunedata[j]; PartitionPruneContext *context = &pprune->context; + Relation partrel; PartitionDesc partdesc; PartitionKey partkey; int partnatts; @@ -1509,16 +1508,15 @@ ExecCreatePartitionPruneState(PlanState *planstate, pprune->present_parts = bms_copy(pinfo->present_parts); /* - * We need to hold a pin on the partitioned table's relcache entry - * so that we can rely on its copies of the table's partition key - * and partition descriptor. We need not get a lock though; one - * should have been acquired already by InitPlan or - * ExecLockNonLeafAppendTables. + * We can rely on the copies of the partitioned table's partition + * key and partition descriptor appearing in its relcache entry, + * because that entry will be held open and locked for the + * duration of this executor run. */ - context->partrel = relation_open(pinfo->reloid, NoLock); + partrel = ExecGetRangeTableRelation(estate, pinfo->rtindex); + partkey = RelationGetPartitionKey(partrel); + partdesc = RelationGetPartitionDesc(partrel); - partkey = RelationGetPartitionKey(context->partrel); - partdesc = RelationGetPartitionDesc(context->partrel); n_steps = list_length(pinfo->pruning_steps); context->strategy = partkey->strategy; @@ -1596,30 +1594,6 @@ ExecCreatePartitionPruneState(PlanState *planstate, } /* - * ExecDestroyPartitionPruneState - * Release resources at plan shutdown. - * - * We don't bother to free any memory here, since the whole executor context - * will be going away shortly. We do need to release our relcache pins. - */ -void -ExecDestroyPartitionPruneState(PartitionPruneState *prunestate) -{ - PartitionPruningData **partprunedata = prunestate->partprunedata; - int i; - - for (i = 0; i < prunestate->num_partprunedata; i++) - { - PartitionPruningData *prunedata = partprunedata[i]; - PartitionedRelPruningData *pprune = prunedata->partrelprunedata; - int j; - - for (j = 0; j < prunedata->num_partrelprunedata; j++) - relation_close(pprune[j].context.partrel, NoLock); - } -} - -/* * ExecFindInitialMatchingSubPlans * Identify the set of subplans that cannot be eliminated by initial * pruning (disregarding any pruning constraints involving PARAM_EXEC diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index ba93b401046..a89ef2a482f 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -25,7 +25,8 @@ * etc * * ExecOpenScanRelation Common code for scan node init routines. - * ExecCloseScanRelation + * + * ExecGetRangeTableRelation Fetch Relation for a rangetable entry. * * executor_errposition Report syntactic position of an error. * @@ -107,6 +108,7 @@ CreateExecutorState(void) estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */ estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */ estate->es_range_table = NIL; + estate->es_relations = NULL; estate->es_plannedstmt = NULL; estate->es_junkFilter = NULL; @@ -648,15 +650,9 @@ Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags) { Relation rel; - Oid reloid; - /* Open the relation and verify lock was obtained upstream */ - reloid = getrelid(scanrelid, estate->es_range_table); - rel = heap_open(reloid, NoLock); - Assert(IsParallelWorker() || - CheckRelationLockedByMe(rel, - rt_fetch(scanrelid, estate->es_range_table)->rellockmode, - true)); + /* Open the relation. */ + rel = ExecGetRangeTableRelation(estate, scanrelid); /* * Complain if we're attempting a scan of an unscannable relation, except @@ -674,24 +670,40 @@ ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags) return rel; } -/* ---------------------------------------------------------------- - * ExecCloseScanRelation - * - * Close the heap relation scanned by a base-level scan plan node. - * This should be called during the node's ExecEnd routine. - * - * Currently, we do not release the lock acquired by ExecOpenScanRelation. - * This lock should be held till end of transaction. (There is a faction - * that considers this too much locking, however.) +/* + * ExecGetRangeTableRelation + * Open the Relation for a range table entry, if not already done * - * If we did want to release the lock, we'd have to repeat the logic in - * ExecOpenScanRelation in order to figure out what to release. - * ---------------------------------------------------------------- + * The Relations will be closed again in ExecEndPlan(). */ -void -ExecCloseScanRelation(Relation scanrel) +Relation +ExecGetRangeTableRelation(EState *estate, Index rti) { - heap_close(scanrel, NoLock); + Relation rel; + + Assert(rti > 0 && rti <= list_length(estate->es_range_table)); + + rel = estate->es_relations[rti - 1]; + if (rel == NULL) + { + /* First time through, so open the relation */ + RangeTblEntry *rte = rt_fetch(rti, estate->es_range_table); + + Assert(rte->rtekind == RTE_RELATION); + + rel = estate->es_relations[rti - 1] = heap_open(rte->relid, NoLock); + + /* + * Verify that appropriate lock was obtained before execution. + * + * In the case of parallel query, only the leader would've obtained + * the lock (that needs to be fixed, though). + */ + Assert(IsParallelWorker() || + CheckRelationLockedByMe(rel, rte->rellockmode, false)); + } + + return rel; } /* diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index f08dfcbcf01..d44befd44e3 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -335,12 +335,6 @@ ExecEndAppend(AppendState *node) */ for (i = 0; i < nplans; i++) ExecEndNode(appendplans[i]); - - /* - * release any resources associated with run-time pruning - */ - if (node->as_prune_state) - ExecDestroyPartitionPruneState(node->as_prune_state); } void diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index baffae27e3e..5307cd1b870 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -785,13 +785,11 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node) void ExecEndBitmapHeapScan(BitmapHeapScanState *node) { - Relation relation; HeapScanDesc scanDesc; /* * extract information from the node */ - relation = node->ss.ss_currentRelation; scanDesc = node->ss.ss_currentScanDesc; /* @@ -832,11 +830,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node) * close heap scan */ heap_endscan(scanDesc); - - /* - * close the heap relation. - */ - ExecCloseScanRelation(relation); } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c index b816e0b31db..9a33eda6887 100644 --- a/src/backend/executor/nodeCustom.c +++ b/src/backend/executor/nodeCustom.c @@ -126,10 +126,6 @@ ExecEndCustomScan(CustomScanState *node) /* Clean out the tuple table */ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); - - /* Close the heap relation */ - if (node->ss.ss_currentRelation) - ExecCloseScanRelation(node->ss.ss_currentRelation); } void diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c index a2a28b7ec26..cf7df72d8c2 100644 --- a/src/backend/executor/nodeForeignscan.c +++ b/src/backend/executor/nodeForeignscan.c @@ -258,10 +258,6 @@ ExecEndForeignScan(ForeignScanState *node) /* clean out the tuple table */ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); - - /* close the relation. */ - if (node->ss.ss_currentRelation) - ExecCloseScanRelation(node->ss.ss_currentRelation); } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index 4b6d531810c..1b530cea405 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -373,14 +373,12 @@ ExecEndIndexOnlyScan(IndexOnlyScanState *node) { Relation indexRelationDesc; IndexScanDesc indexScanDesc; - Relation relation; /* * extract information from the node */ indexRelationDesc = node->ioss_RelationDesc; indexScanDesc = node->ioss_ScanDesc; - relation = node->ss.ss_currentRelation; /* Release VM buffer pin, if any. */ if (node->ioss_VMBuffer != InvalidBuffer) @@ -411,11 +409,6 @@ ExecEndIndexOnlyScan(IndexOnlyScanState *node) index_endscan(indexScanDesc); if (indexRelationDesc) index_close(indexRelationDesc, NoLock); - - /* - * close the heap relation. - */ - ExecCloseScanRelation(relation); } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 6285a2114e8..d74499fd7c1 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -140,7 +140,7 @@ IndexNext(IndexScanState *node) * Note: we pass 'false' because tuples returned by amgetnext are * pointers onto disk pages and must not be pfree()'d. */ - ExecStoreBufferHeapTuple(tuple, /* tuple to store */ + ExecStoreBufferHeapTuple(tuple, /* tuple to store */ slot, /* slot to store in */ scandesc->xs_cbuf); /* buffer containing * tuple */ @@ -285,7 +285,7 @@ next_indextuple: /* * Store the scanned tuple in the scan tuple slot of the scan state. */ - ExecStoreBufferHeapTuple(tuple, /* tuple to store */ + ExecStoreBufferHeapTuple(tuple, /* tuple to store */ slot, /* slot to store in */ scandesc->xs_cbuf); /* buffer containing * tuple */ @@ -802,14 +802,12 @@ ExecEndIndexScan(IndexScanState *node) { Relation indexRelationDesc; IndexScanDesc indexScanDesc; - Relation relation; /* * extract information from the node */ indexRelationDesc = node->iss_RelationDesc; indexScanDesc = node->iss_ScanDesc; - relation = node->ss.ss_currentRelation; /* * Free the exprcontext(s) ... now dead code, see ExecFreeExprContext @@ -833,11 +831,6 @@ ExecEndIndexScan(IndexScanState *node) index_endscan(indexScanDesc); if (indexRelationDesc) index_close(indexRelationDesc, NoLock); - - /* - * close the heap relation. - */ - ExecCloseScanRelation(relation); } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c index 9a72d3a0ace..6daf60a454d 100644 --- a/src/backend/executor/nodeMergeAppend.c +++ b/src/backend/executor/nodeMergeAppend.c @@ -369,12 +369,6 @@ ExecEndMergeAppend(MergeAppendState *node) */ for (i = 0; i < nplans; i++) ExecEndNode(mergeplans[i]); - - /* - * release any resources associated with run-time pruning - */ - if (node->ms_prune_state) - ExecDestroyPartitionPruneState(node->ms_prune_state); } void diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c index 99528be84a6..70ae1bc7e46 100644 --- a/src/backend/executor/nodeSamplescan.c +++ b/src/backend/executor/nodeSamplescan.c @@ -63,9 +63,9 @@ SampleNext(SampleScanState *node) slot = node->ss.ss_ScanTupleSlot; if (tuple) - ExecStoreBufferHeapTuple(tuple, /* tuple to store */ + ExecStoreBufferHeapTuple(tuple, /* tuple to store */ slot, /* slot to store in */ - node->ss.ss_currentScanDesc->rs_cbuf); /* tuple's buffer */ + node->ss.ss_currentScanDesc->rs_cbuf); /* tuple's buffer */ else ExecClearTuple(slot); @@ -222,11 +222,6 @@ ExecEndSampleScan(SampleScanState *node) */ if (node->ss.ss_currentScanDesc) heap_endscan(node->ss.ss_currentScanDesc); - - /* - * close the heap relation. - */ - ExecCloseScanRelation(node->ss.ss_currentRelation); } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c index cd53491be0a..5dede816c6a 100644 --- a/src/backend/executor/nodeSeqscan.c +++ b/src/backend/executor/nodeSeqscan.c @@ -88,7 +88,7 @@ SeqNext(SeqScanState *node) * refcount will not be dropped until the tuple table slot is cleared. */ if (tuple) - ExecStoreBufferHeapTuple(tuple, /* tuple to store */ + ExecStoreBufferHeapTuple(tuple, /* tuple to store */ slot, /* slot to store in */ scandesc->rs_cbuf); /* buffer associated * with this tuple */ @@ -201,13 +201,11 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags) void ExecEndSeqScan(SeqScanState *node) { - Relation relation; HeapScanDesc scanDesc; /* * get information from node */ - relation = node->ss.ss_currentRelation; scanDesc = node->ss.ss_currentScanDesc; /* @@ -226,11 +224,6 @@ ExecEndSeqScan(SeqScanState *node) */ if (scanDesc != NULL) heap_endscan(scanDesc); - - /* - * close the heap relation. - */ - ExecCloseScanRelation(relation); } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index 0cb1946a3e3..593185f726b 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -380,7 +380,7 @@ TidNext(TidScanState *node) * Store the scanned tuple in the scan tuple slot of the scan * state. Eventually we will only do this and not return a tuple. */ - ExecStoreBufferHeapTuple(tuple, /* tuple to store */ + ExecStoreBufferHeapTuple(tuple, /* tuple to store */ slot, /* slot to store in */ buffer); /* buffer associated with * tuple */ @@ -489,11 +489,6 @@ ExecEndTidScan(TidScanState *node) */ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); - - /* - * close the heap relation. - */ - ExecCloseScanRelation(node->ss.ss_currentRelation); } /* ---------------------------------------------------------------- |