aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/postgres_fdw/postgres_fdw.c4
-rw-r--r--src/backend/catalog/indexing.c2
-rw-r--r--src/backend/commands/copy.c4
-rw-r--r--src/backend/executor/execMain.c76
-rw-r--r--src/backend/executor/execPartition.c46
-rw-r--r--src/backend/executor/execUtils.c60
-rw-r--r--src/backend/executor/nodeAppend.c6
-rw-r--r--src/backend/executor/nodeBitmapHeapscan.c7
-rw-r--r--src/backend/executor/nodeCustom.c4
-rw-r--r--src/backend/executor/nodeForeignscan.c4
-rw-r--r--src/backend/executor/nodeIndexonlyscan.c7
-rw-r--r--src/backend/executor/nodeIndexscan.c11
-rw-r--r--src/backend/executor/nodeMergeAppend.c6
-rw-r--r--src/backend/executor/nodeSamplescan.c9
-rw-r--r--src/backend/executor/nodeSeqscan.c9
-rw-r--r--src/backend/executor/nodeTidscan.c7
-rw-r--r--src/backend/nodes/copyfuncs.c2
-rw-r--r--src/backend/nodes/outfuncs.c2
-rw-r--r--src/backend/nodes/readfuncs.c2
-rw-r--r--src/backend/optimizer/plan/setrefs.c30
-rw-r--r--src/backend/partitioning/partprune.c6
-rw-r--r--src/backend/replication/logical/worker.c1
-rw-r--r--src/include/executor/execPartition.h1
-rw-r--r--src/include/executor/executor.h3
-rw-r--r--src/include/nodes/execnodes.h11
-rw-r--r--src/include/nodes/plannodes.h2
-rw-r--r--src/include/partitioning/partprune.h3
27 files changed, 144 insertions, 181 deletions
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 6cbba97c223..c02287a55ca 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -2546,10 +2546,6 @@ postgresEndDirectModify(ForeignScanState *node)
ReleaseConnection(dmstate->conn);
dmstate->conn = NULL;
- /* close the target relation. */
- if (dmstate->resultRel)
- ExecCloseScanRelation(dmstate->resultRel);
-
/* MemoryContext will be deleted automatically. */
}
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 4674beaf3e7..daf7ae2eb2b 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -42,7 +42,7 @@ CatalogOpenIndexes(Relation heapRel)
ResultRelInfo *resultRelInfo;
resultRelInfo = makeNode(ResultRelInfo);
- resultRelInfo->ri_RangeTableIndex = 1; /* dummy */
+ resultRelInfo->ri_RangeTableIndex = 0; /* dummy */
resultRelInfo->ri_RelationDesc = heapRel;
resultRelInfo->ri_TrigDesc = NULL; /* we don't fire triggers */
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 32706fad90f..df98e4ac626 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2471,7 +2471,7 @@ CopyFrom(CopyState cstate)
resultRelInfo = makeNode(ResultRelInfo);
InitResultRelInfo(resultRelInfo,
cstate->rel,
- 1, /* dummy rangetable index */
+ 1, /* must match rel's position in range_table */
NULL,
0);
target_resultRelInfo = resultRelInfo;
@@ -2485,6 +2485,8 @@ CopyFrom(CopyState cstate)
estate->es_num_result_relations = 1;
estate->es_result_relation_info = resultRelInfo;
estate->es_range_table = cstate->range_table;
+ estate->es_relations = (Relation *) palloc0(list_length(cstate->range_table) *
+ sizeof(Relation));
/* Set up a tuple slot too */
myslot = ExecInitExtraTupleSlot(estate, tupDesc);
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);
}
/* ----------------------------------------------------------------
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 925cb8f3800..3b690b55b38 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -1193,7 +1193,7 @@ _copyPartitionedRelPruneInfo(const PartitionedRelPruneInfo *from)
{
PartitionedRelPruneInfo *newnode = makeNode(PartitionedRelPruneInfo);
- COPY_SCALAR_FIELD(reloid);
+ COPY_SCALAR_FIELD(rtindex);
COPY_NODE_FIELD(pruning_steps);
COPY_BITMAPSET_FIELD(present_parts);
COPY_SCALAR_FIELD(nparts);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 22dbae15d3b..863d29cc57d 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -1032,7 +1032,7 @@ _outPartitionedRelPruneInfo(StringInfo str, const PartitionedRelPruneInfo *node)
WRITE_NODE_TYPE("PARTITIONEDRELPRUNEINFO");
- WRITE_OID_FIELD(reloid);
+ WRITE_UINT_FIELD(rtindex);
WRITE_NODE_FIELD(pruning_steps);
WRITE_BITMAPSET_FIELD(present_parts);
WRITE_INT_FIELD(nparts);
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index ce556580a5f..73ffa9714c6 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -2376,7 +2376,7 @@ _readPartitionedRelPruneInfo(void)
{
READ_LOCALS(PartitionedRelPruneInfo);
- READ_OID_FIELD(reloid);
+ READ_UINT_FIELD(rtindex);
READ_NODE_FIELD(pruning_steps);
READ_BITMAPSET_FIELD(present_parts);
READ_INT_FIELD(nparts);
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index f66f39d8c68..54293e25aff 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -925,6 +925,21 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
(Plan *) lfirst(l),
rtoffset);
}
+ if (splan->part_prune_info)
+ {
+ foreach(l, splan->part_prune_info->prune_infos)
+ {
+ List *prune_infos = lfirst(l);
+ ListCell *l2;
+
+ foreach(l2, prune_infos)
+ {
+ PartitionedRelPruneInfo *pinfo = lfirst(l2);
+
+ pinfo->rtindex += rtoffset;
+ }
+ }
+ }
}
break;
case T_MergeAppend:
@@ -947,6 +962,21 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
(Plan *) lfirst(l),
rtoffset);
}
+ if (splan->part_prune_info)
+ {
+ foreach(l, splan->part_prune_info->prune_infos)
+ {
+ List *prune_infos = lfirst(l);
+ ListCell *l2;
+
+ foreach(l2, prune_infos)
+ {
+ PartitionedRelPruneInfo *pinfo = lfirst(l2);
+
+ pinfo->rtindex += rtoffset;
+ }
+ }
+ }
}
break;
case T_RecursiveUnion:
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index e1ce8b4ddcb..d6ca03de4a3 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -357,7 +357,6 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
Index rti = lfirst_int(lc);
RelOptInfo *subpart = find_base_rel(root, rti);
PartitionedRelPruneInfo *pinfo;
- RangeTblEntry *rte;
Bitmapset *present_parts;
int nparts = subpart->nparts;
int partnatts = subpart->part_scheme->partnatts;
@@ -459,10 +458,8 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
present_parts = bms_add_member(present_parts, i);
}
- rte = root->simple_rte_array[subpart->relid];
-
pinfo = makeNode(PartitionedRelPruneInfo);
- pinfo->reloid = rte->relid;
+ pinfo->rtindex = rti;
pinfo->pruning_steps = pruning_steps;
pinfo->present_parts = present_parts;
pinfo->nparts = nparts;
@@ -587,7 +584,6 @@ prune_append_rel_partitions(RelOptInfo *rel)
context.ppccontext = CurrentMemoryContext;
/* These are not valid when being called from the planner */
- context.partrel = NULL;
context.planstate = NULL;
context.exprstates = NULL;
context.exprhasexecparam = NULL;
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index e247539d7b1..c3443c5a2ce 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -201,6 +201,7 @@ create_estate_for_relation(LogicalRepRelMapEntry *rel)
rte->relkind = rel->localrel->rd_rel->relkind;
rte->rellockmode = AccessShareLock;
estate->es_range_table = list_make1(rte);
+ estate->es_relations = (Relation *) palloc0(1 * sizeof(Relation));
resultRelInfo = makeNode(ResultRelInfo);
InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0);
diff --git a/src/include/executor/execPartition.h b/src/include/executor/execPartition.h
index 8b4a9ca0447..3e08104ea42 100644
--- a/src/include/executor/execPartition.h
+++ b/src/include/executor/execPartition.h
@@ -195,7 +195,6 @@ extern void ExecCleanupTupleRouting(ModifyTableState *mtstate,
PartitionTupleRouting *proute);
extern PartitionPruneState *ExecCreatePartitionPruneState(PlanState *planstate,
PartitionPruneInfo *partitionpruneinfo);
-extern void ExecDestroyPartitionPruneState(PartitionPruneState *prunestate);
extern Bitmapset *ExecFindMatchingSubPlans(PartitionPruneState *prunestate);
extern Bitmapset *ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate,
int nsubplans);
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index f82b51667f4..83ce989e3a3 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -513,7 +513,8 @@ extern void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate
extern bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid);
extern Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags);
-extern void ExecCloseScanRelation(Relation scanrel);
+
+extern Relation ExecGetRangeTableRelation(EState *estate, Index rti);
extern int executor_errposition(EState *estate, int location);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 020ecdcd404..35646231a4c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -386,12 +386,19 @@ typedef struct OnConflictSetState
* Whenever we update an existing relation, we have to update indexes on the
* relation, and perhaps also fire triggers. ResultRelInfo holds all the
* information needed about a result relation, including indexes.
+ *
+ * Normally, a ResultRelInfo refers to a table that is in the query's
+ * range table; then ri_RangeTableIndex is the RT index and ri_RelationDesc
+ * is just a copy of the relevant es_relations[] entry. But sometimes,
+ * in ResultRelInfos used only for triggers, ri_RangeTableIndex is zero
+ * and ri_RelationDesc is a separately-opened relcache pointer that needs
+ * to be separately closed. See ExecGetTriggerResultRel.
*/
typedef struct ResultRelInfo
{
NodeTag type;
- /* result relation's range table index */
+ /* result relation's range table index, or 0 if not in range table */
Index ri_RangeTableIndex;
/* relation descriptor for result relation */
@@ -479,6 +486,8 @@ typedef struct EState
Snapshot es_snapshot; /* time qual to use */
Snapshot es_crosscheck_snapshot; /* crosscheck time qual for RI */
List *es_range_table; /* List of RangeTblEntry */
+ Relation *es_relations; /* Array of per-es_range_table-entry Relation
+ * pointers, or NULL if not yet opened */
PlannedStmt *es_plannedstmt; /* link to top of plan tree */
const char *es_sourceText; /* Source text from QueryDesc */
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 7c2abbd03a6..8b374370576 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -1105,7 +1105,7 @@ typedef struct PartitionPruneInfo
typedef struct PartitionedRelPruneInfo
{
NodeTag type;
- Oid reloid; /* OID of partition rel for this level */
+ Index rtindex; /* RT index of partition rel for this level */
List *pruning_steps; /* List of PartitionPruneStep, see below */
Bitmapset *present_parts; /* Indexes of all partitions which subplans or
* subparts are present for. */
diff --git a/src/include/partitioning/partprune.h b/src/include/partitioning/partprune.h
index b95c346bab0..e07aaaf798b 100644
--- a/src/include/partitioning/partprune.h
+++ b/src/include/partitioning/partprune.h
@@ -23,8 +23,6 @@
* Stores information needed at runtime for pruning computations
* related to a single partitioned table.
*
- * partrel Relcache pointer for the partitioned table,
- * if we have it open (else NULL).
* strategy Partition strategy, e.g. LIST, RANGE, HASH.
* partnatts Number of columns in the partition key.
* nparts Number of partitions in this partitioned table.
@@ -50,7 +48,6 @@
*/
typedef struct PartitionPruneContext
{
- Relation partrel;
char strategy;
int partnatts;
int nparts;