mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
A bunch of changes aimed at reducing backend startup time...
Improve 'pg_internal.init' relcache entry preload mechanism so that it is safe to use for all system catalogs, and arrange to preload a realistic set of system-catalog entries instead of only the three nailed-in-cache indexes that were formerly loaded this way. Fix mechanism for deleting out-of-date pg_internal.init files: this must be synchronized with transaction commit, not just done at random times within transactions. Drive it off relcache invalidation mechanism so that no special-case tests are needed. Cache additional information in relcache entries for indexes (their pg_index tuples and index-operator OIDs) to eliminate repeated lookups. Also cache index opclass info at the per-opclass level to avoid repeated lookups during relcache load. Generalize 'systable scan' utilities originally developed by Hiroshi, move them into genam.c, use in a number of places where there was formerly ugly code for choosing either heap or index scan. In particular this allows simplification of the logic that prevents infinite recursion between syscache and relcache during startup: we can easily switch to heapscans in relcache.c when and where needed to avoid recursion, so IndexScanOK becomes simpler and does not need any expensive initialization. Eliminate useless opening of a heapscan data structure while doing an indexscan (this saves an mdnblocks call and thus at least one kernel call).
This commit is contained in:
@ -6,25 +6,12 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: execAmi.c,v 1.60 2001/10/25 05:49:27 momjian Exp $
|
||||
* $Id: execAmi.c,v 1.61 2002/02/19 20:11:13 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
/*
|
||||
* INTERFACE ROUTINES
|
||||
*
|
||||
* ExecOpenScanR \ / amopen
|
||||
* ExecBeginScan \ / ambeginscan
|
||||
* ExecCloseR \ / amclose
|
||||
* ExecInsert \ executor interface / aminsert
|
||||
* ExecReScanR / to access methods \ amrescan
|
||||
* ExecMarkPos / \ ammarkpos
|
||||
* ExecRestrPos / \ amrestpos
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
|
||||
#include "access/genam.h"
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/heap.h"
|
||||
@ -50,202 +37,6 @@
|
||||
#include "executor/nodeSubqueryscan.h"
|
||||
#include "executor/nodeUnique.h"
|
||||
|
||||
static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
|
||||
bool isindex, ScanDirection dir, Snapshot snapshot);
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecOpenScanR
|
||||
*
|
||||
* old comments:
|
||||
* Parameters:
|
||||
* relation -- relation to be opened and scanned.
|
||||
* nkeys -- number of keys
|
||||
* skeys -- keys to restrict scanning
|
||||
* isindex -- if this is true, the relation is the relid of
|
||||
* an index relation, else it is a heap relation.
|
||||
* Returns the relation as(relDesc scanDesc)
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecOpenScanR(Oid relOid,
|
||||
int nkeys,
|
||||
ScanKey skeys,
|
||||
bool isindex,
|
||||
ScanDirection dir,
|
||||
Snapshot snapshot,
|
||||
Relation *returnRelation, /* return */
|
||||
Pointer *returnScanDesc) /* return */
|
||||
{
|
||||
Relation relation;
|
||||
Pointer scanDesc;
|
||||
|
||||
/*
|
||||
* note: scanDesc returned by ExecBeginScan can be either a
|
||||
* HeapScanDesc or an IndexScanDesc so for now we make it a Pointer.
|
||||
* There should be a better scan abstraction someday -cim 9/9/89
|
||||
*/
|
||||
|
||||
/*
|
||||
* Open the relation with the correct call depending on whether this
|
||||
* is a heap relation or an index relation.
|
||||
*
|
||||
* For a table, acquire AccessShareLock for the duration of the query
|
||||
* execution. For indexes, acquire no lock here; the index machinery
|
||||
* does its own locks and unlocks. (We rely on having some kind of
|
||||
* lock on the parent table to ensure the index won't go away!)
|
||||
*/
|
||||
if (isindex)
|
||||
relation = index_open(relOid);
|
||||
else
|
||||
relation = heap_open(relOid, AccessShareLock);
|
||||
|
||||
scanDesc = ExecBeginScan(relation,
|
||||
nkeys,
|
||||
skeys,
|
||||
isindex,
|
||||
dir,
|
||||
snapshot);
|
||||
|
||||
if (returnRelation != NULL)
|
||||
*returnRelation = relation;
|
||||
if (scanDesc != NULL)
|
||||
*returnScanDesc = scanDesc;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecBeginScan
|
||||
*
|
||||
* beginscans a relation in current direction.
|
||||
*
|
||||
* XXX fix parameters to AMbeginscan (and btbeginscan)
|
||||
* currently we need to pass a flag stating whether
|
||||
* or not the scan should begin at an endpoint of
|
||||
* the relation.. Right now we always pass false
|
||||
* -cim 9/14/89
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
static Pointer
|
||||
ExecBeginScan(Relation relation,
|
||||
int nkeys,
|
||||
ScanKey skeys,
|
||||
bool isindex,
|
||||
ScanDirection dir,
|
||||
Snapshot snapshot)
|
||||
{
|
||||
Pointer scanDesc;
|
||||
|
||||
/*
|
||||
* open the appropriate type of scan.
|
||||
*
|
||||
* Note: ambeginscan()'s second arg is a boolean indicating that the scan
|
||||
* should be done in reverse.. That is, if you pass it true, then the
|
||||
* scan is backward.
|
||||
*/
|
||||
if (isindex)
|
||||
{
|
||||
scanDesc = (Pointer) index_beginscan(relation,
|
||||
false, /* see above comment */
|
||||
nkeys,
|
||||
skeys);
|
||||
}
|
||||
else
|
||||
{
|
||||
scanDesc = (Pointer) heap_beginscan(relation,
|
||||
ScanDirectionIsBackward(dir),
|
||||
snapshot,
|
||||
nkeys,
|
||||
skeys);
|
||||
}
|
||||
|
||||
if (scanDesc == NULL)
|
||||
elog(DEBUG, "ExecBeginScan: scanDesc = NULL, heap_beginscan failed.");
|
||||
|
||||
return scanDesc;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecCloseR
|
||||
*
|
||||
* closes the relation and scan descriptor for a scan node.
|
||||
* Also closes index relations and scans for index scans.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecCloseR(Plan *node)
|
||||
{
|
||||
CommonScanState *state;
|
||||
Relation relation;
|
||||
HeapScanDesc scanDesc;
|
||||
|
||||
/*
|
||||
* get state for node and shut down the heap scan, if any
|
||||
*/
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_SeqScan:
|
||||
state = ((SeqScan *) node)->scanstate;
|
||||
break;
|
||||
|
||||
case T_IndexScan:
|
||||
state = ((IndexScan *) node)->scan.scanstate;
|
||||
break;
|
||||
|
||||
case T_TidScan:
|
||||
state = ((TidScan *) node)->scan.scanstate;
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(DEBUG, "ExecCloseR: not a scan node!");
|
||||
return;
|
||||
}
|
||||
|
||||
relation = state->css_currentRelation;
|
||||
scanDesc = state->css_currentScanDesc;
|
||||
|
||||
if (scanDesc != NULL)
|
||||
heap_endscan(scanDesc);
|
||||
|
||||
/*
|
||||
* if this is an index scan then we have to take care of the index
|
||||
* relations as well.
|
||||
*/
|
||||
if (IsA(node, IndexScan))
|
||||
{
|
||||
IndexScan *iscan = (IndexScan *) node;
|
||||
IndexScanState *indexstate = iscan->indxstate;
|
||||
int numIndices;
|
||||
RelationPtr indexRelationDescs;
|
||||
IndexScanDescPtr indexScanDescs;
|
||||
int i;
|
||||
|
||||
numIndices = indexstate->iss_NumIndices;
|
||||
indexRelationDescs = indexstate->iss_RelationDescs;
|
||||
indexScanDescs = indexstate->iss_ScanDescs;
|
||||
|
||||
for (i = 0; i < numIndices; i++)
|
||||
{
|
||||
/*
|
||||
* shut down each of the index scans and close each of the
|
||||
* index relations
|
||||
*/
|
||||
if (indexScanDescs[i] != NULL)
|
||||
index_endscan(indexScanDescs[i]);
|
||||
|
||||
if (indexRelationDescs[i] != NULL)
|
||||
index_close(indexRelationDescs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, close the heap relation.
|
||||
*
|
||||
* Currently, we do not release the AccessShareLock acquired by
|
||||
* ExecOpenScanR. This lock should be held till end of transaction.
|
||||
* (There is a faction that considers this too much locking, however.)
|
||||
*/
|
||||
if (relation != NULL)
|
||||
heap_close(relation, NoLock);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecReScan
|
||||
@ -374,27 +165,6 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecReScanR
|
||||
*
|
||||
* XXX this does not do the right thing with indices yet.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
HeapScanDesc
|
||||
ExecReScanR(Relation relDesc, /* LLL relDesc unused */
|
||||
HeapScanDesc scanDesc,
|
||||
ScanDirection direction,
|
||||
int nkeys, /* LLL nkeys unused */
|
||||
ScanKey skeys)
|
||||
{
|
||||
if (scanDesc != NULL)
|
||||
heap_rescan(scanDesc, /* scan desc */
|
||||
ScanDirectionIsBackward(direction), /* backward flag */
|
||||
skeys); /* scan keys */
|
||||
|
||||
return scanDesc;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecMarkPos
|
||||
*
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.78 2001/10/25 05:49:27 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.79 2002/02/19 20:11:13 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -496,7 +496,6 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo)
|
||||
{
|
||||
Oid indexOid = lfirsti(indexoidscan);
|
||||
Relation indexDesc;
|
||||
HeapTuple indexTuple;
|
||||
IndexInfo *ii;
|
||||
|
||||
/*
|
||||
@ -525,20 +524,9 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo)
|
||||
LockRelation(indexDesc, AccessExclusiveLock);
|
||||
|
||||
/*
|
||||
* Get the pg_index tuple for the index
|
||||
* extract index key information from the index's pg_index tuple
|
||||
*/
|
||||
indexTuple = SearchSysCache(INDEXRELID,
|
||||
ObjectIdGetDatum(indexOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(indexTuple))
|
||||
elog(ERROR, "ExecOpenIndices: index %u not found", indexOid);
|
||||
|
||||
/*
|
||||
* extract the index key information from the tuple
|
||||
*/
|
||||
ii = BuildIndexInfo(indexTuple);
|
||||
|
||||
ReleaseSysCache(indexTuple);
|
||||
ii = BuildIndexInfo(indexDesc->rd_index);
|
||||
|
||||
relationDescs[i] = indexDesc;
|
||||
indexInfoArray[i] = ii;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.66 2002/02/11 20:10:48 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.67 2002/02/19 20:11:13 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -359,14 +359,20 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
|
||||
int n_keys;
|
||||
ScanKey scan_keys;
|
||||
int *run_keys;
|
||||
List *listscan;
|
||||
|
||||
indxqual = lnext(indxqual);
|
||||
n_keys = numScanKeys[i];
|
||||
scan_keys = scanKeys[i];
|
||||
run_keys = runtimeKeyInfo[i];
|
||||
|
||||
listscan = qual;
|
||||
for (j = 0; j < n_keys; j++)
|
||||
{
|
||||
Expr *clause = lfirst(listscan);
|
||||
|
||||
listscan = lnext(listscan);
|
||||
|
||||
/*
|
||||
* If we have a run-time key, then extract the run-time
|
||||
* expression and evaluate it with respect to the current
|
||||
@ -382,7 +388,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
|
||||
*/
|
||||
if (run_keys[j] != NO_OP)
|
||||
{
|
||||
Expr *clause = nth(j, qual);
|
||||
Node *scanexpr;
|
||||
Datum scanvalue;
|
||||
bool isNull;
|
||||
@ -448,6 +453,9 @@ ExecEndIndexScan(IndexScan *node)
|
||||
List *indxqual;
|
||||
int *numScanKeys;
|
||||
int numIndices;
|
||||
Relation relation;
|
||||
RelationPtr indexRelationDescs;
|
||||
IndexScanDescPtr indexScanDescs;
|
||||
int i;
|
||||
|
||||
scanstate = node->scan.scanstate;
|
||||
@ -461,6 +469,9 @@ ExecEndIndexScan(IndexScan *node)
|
||||
numIndices = indexstate->iss_NumIndices;
|
||||
scanKeys = indexstate->iss_ScanKeys;
|
||||
numScanKeys = indexstate->iss_NumScanKeys;
|
||||
indexRelationDescs = indexstate->iss_RelationDescs;
|
||||
indexScanDescs = indexstate->iss_ScanDescs;
|
||||
relation = scanstate->css_currentRelation;
|
||||
|
||||
/*
|
||||
* Free the projection info and the scan attribute info
|
||||
@ -475,9 +486,25 @@ ExecEndIndexScan(IndexScan *node)
|
||||
FreeExprContext(indexstate->iss_RuntimeContext);
|
||||
|
||||
/*
|
||||
* close the heap and index relations
|
||||
* close the index relations
|
||||
*/
|
||||
ExecCloseR((Plan *) node);
|
||||
for (i = 0; i < numIndices; i++)
|
||||
{
|
||||
if (indexScanDescs[i] != NULL)
|
||||
index_endscan(indexScanDescs[i]);
|
||||
|
||||
if (indexRelationDescs[i] != NULL)
|
||||
index_close(indexRelationDescs[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* close the heap relation.
|
||||
*
|
||||
* Currently, we do not release the AccessShareLock acquired by
|
||||
* ExecInitIndexScan. This lock should be held till end of transaction.
|
||||
* (There is a faction that considers this too much locking, however.)
|
||||
*/
|
||||
heap_close(relation, NoLock);
|
||||
|
||||
/*
|
||||
* free the scan keys used in scanning the indices
|
||||
@ -589,6 +616,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
CommonScanState *scanstate;
|
||||
List *indxqual;
|
||||
List *indxid;
|
||||
List *listscan;
|
||||
int i;
|
||||
int numIndices;
|
||||
int indexPtr;
|
||||
@ -603,7 +631,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
Index relid;
|
||||
Oid reloid;
|
||||
Relation currentRelation;
|
||||
HeapScanDesc currentScanDesc;
|
||||
ScanDirection direction;
|
||||
|
||||
/*
|
||||
@ -709,6 +736,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
* for each opclause in the given qual, convert each qual's
|
||||
* opclause into a single scan key
|
||||
*/
|
||||
listscan = qual;
|
||||
for (j = 0; j < n_keys; j++)
|
||||
{
|
||||
Expr *clause; /* one clause of index qual */
|
||||
@ -725,7 +753,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
/*
|
||||
* extract clause information from the qualification
|
||||
*/
|
||||
clause = nth(j, qual);
|
||||
clause = lfirst(listscan);
|
||||
listscan = lnext(listscan);
|
||||
|
||||
op = (Oper *) clause->oper;
|
||||
if (!IsA(clause, Expr) ||!IsA(op, Oper))
|
||||
@ -989,25 +1018,19 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
direction = estate->es_direction;
|
||||
|
||||
/*
|
||||
* open the base relation
|
||||
* open the base relation and acquire AccessShareLock on it.
|
||||
*/
|
||||
relid = node->scan.scanrelid;
|
||||
rtentry = rt_fetch(relid, rangeTable);
|
||||
reloid = rtentry->relid;
|
||||
|
||||
ExecOpenScanR(reloid, /* relation */
|
||||
0, /* nkeys */
|
||||
(ScanKey) NULL, /* scan key */
|
||||
false, /* is index */
|
||||
direction, /* scan direction */
|
||||
estate->es_snapshot, /* */
|
||||
¤tRelation, /* return: rel desc */
|
||||
(Pointer *) ¤tScanDesc); /* return: scan desc */
|
||||
currentRelation = heap_open(reloid, AccessShareLock);
|
||||
|
||||
if (!RelationGetForm(currentRelation)->relhasindex)
|
||||
elog(ERROR, "indexes of the relation %u was inactivated", reloid);
|
||||
|
||||
scanstate->css_currentRelation = currentRelation;
|
||||
scanstate->css_currentScanDesc = currentScanDesc;
|
||||
scanstate->css_currentScanDesc = NULL; /* no heap scan here */
|
||||
|
||||
/*
|
||||
* get the scan type from the relation descriptor.
|
||||
@ -1017,24 +1040,30 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
|
||||
/*
|
||||
* open the index relations and initialize relation and scan
|
||||
* descriptors.
|
||||
* descriptors. Note we acquire no locks here; the index machinery
|
||||
* does its own locks and unlocks. (We rely on having AccessShareLock
|
||||
* on the parent table to ensure the index won't go away!)
|
||||
*/
|
||||
listscan = indxid;
|
||||
for (i = 0; i < numIndices; i++)
|
||||
{
|
||||
Oid indexOid = (Oid) nthi(i, indxid);
|
||||
Oid indexOid = (Oid) lfirsti(listscan);
|
||||
|
||||
if (indexOid != 0)
|
||||
{
|
||||
ExecOpenScanR(indexOid, /* relation */
|
||||
numScanKeys[i], /* nkeys */
|
||||
scanKeys[i], /* scan key */
|
||||
true, /* is index */
|
||||
direction, /* scan direction */
|
||||
estate->es_snapshot,
|
||||
&(relationDescs[i]), /* return: rel desc */
|
||||
(Pointer *) &(scanDescs[i]));
|
||||
/* return: scan desc */
|
||||
relationDescs[i] = index_open(indexOid);
|
||||
|
||||
/*
|
||||
* Note: index_beginscan()'s second arg is a boolean indicating
|
||||
* that the scan should be done in reverse. That is, if you pass
|
||||
* it true, then the scan is backward.
|
||||
*/
|
||||
scanDescs[i] = index_beginscan(relationDescs[i],
|
||||
false, /* see above comment */
|
||||
numScanKeys[i],
|
||||
scanKeys[i]);
|
||||
}
|
||||
listscan = lnext(listscan);
|
||||
}
|
||||
|
||||
indexstate->iss_RelationDescs = relationDescs;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.33 2001/10/28 06:25:43 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.34 2002/02/19 20:11:14 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -154,7 +154,9 @@ InitScanRelation(SeqScan *node, EState *estate,
|
||||
|
||||
/*
|
||||
* get the relation object id from the relid'th entry in the range
|
||||
* table, open that relation and initialize the scan state...
|
||||
* table, open that relation and initialize the scan state.
|
||||
*
|
||||
* We acquire AccessShareLock for the duration of the scan.
|
||||
*/
|
||||
relid = node->scanrelid;
|
||||
rangeTable = estate->es_range_table;
|
||||
@ -162,14 +164,13 @@ InitScanRelation(SeqScan *node, EState *estate,
|
||||
reloid = rtentry->relid;
|
||||
direction = estate->es_direction;
|
||||
|
||||
ExecOpenScanR(reloid, /* relation */
|
||||
0, /* nkeys */
|
||||
NULL, /* scan key */
|
||||
false, /* is index */
|
||||
direction, /* scan direction */
|
||||
estate->es_snapshot,
|
||||
¤tRelation, /* return: rel desc */
|
||||
(Pointer *) ¤tScanDesc); /* return: scan desc */
|
||||
currentRelation = heap_open(reloid, AccessShareLock);
|
||||
|
||||
currentScanDesc = heap_beginscan(currentRelation,
|
||||
ScanDirectionIsBackward(direction),
|
||||
estate->es_snapshot,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
scanstate->css_currentRelation = currentRelation;
|
||||
scanstate->css_currentScanDesc = currentScanDesc;
|
||||
@ -189,7 +190,6 @@ ExecInitSeqScan(SeqScan *node, EState *estate, Plan *parent)
|
||||
{
|
||||
CommonScanState *scanstate;
|
||||
Oid reloid;
|
||||
HeapScanDesc scandesc;
|
||||
|
||||
/*
|
||||
* Once upon a time it was possible to have an outerPlan of a SeqScan,
|
||||
@ -229,7 +229,6 @@ ExecInitSeqScan(SeqScan *node, EState *estate, Plan *parent)
|
||||
*/
|
||||
reloid = InitScanRelation(node, estate, scanstate);
|
||||
|
||||
scandesc = scanstate->css_currentScanDesc;
|
||||
scanstate->cstate.cs_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
@ -259,11 +258,15 @@ void
|
||||
ExecEndSeqScan(SeqScan *node)
|
||||
{
|
||||
CommonScanState *scanstate;
|
||||
Relation relation;
|
||||
HeapScanDesc scanDesc;
|
||||
|
||||
/*
|
||||
* get information from node
|
||||
*/
|
||||
scanstate = node->scanstate;
|
||||
relation = scanstate->css_currentRelation;
|
||||
scanDesc = scanstate->css_currentScanDesc;
|
||||
|
||||
/*
|
||||
* Free the projection info and the scan attribute info
|
||||
@ -276,9 +279,18 @@ ExecEndSeqScan(SeqScan *node)
|
||||
ExecFreeExprContext(&scanstate->cstate);
|
||||
|
||||
/*
|
||||
* close scan relation
|
||||
* close heap scan
|
||||
*/
|
||||
ExecCloseR((Plan *) node);
|
||||
heap_endscan(scanDesc);
|
||||
|
||||
/*
|
||||
* close the heap relation.
|
||||
*
|
||||
* Currently, we do not release the AccessShareLock acquired by
|
||||
* InitScanRelation. This lock should be held till end of transaction.
|
||||
* (There is a faction that considers this too much locking, however.)
|
||||
*/
|
||||
heap_close(relation, NoLock);
|
||||
|
||||
/*
|
||||
* clean out the tuple table
|
||||
@ -303,7 +315,6 @@ ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent)
|
||||
{
|
||||
CommonScanState *scanstate;
|
||||
EState *estate;
|
||||
Relation rel;
|
||||
HeapScanDesc scan;
|
||||
ScanDirection direction;
|
||||
|
||||
@ -317,11 +328,13 @@ ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent)
|
||||
estate->es_evTupleNull[node->scanrelid - 1] = false;
|
||||
return;
|
||||
}
|
||||
rel = scanstate->css_currentRelation;
|
||||
|
||||
scan = scanstate->css_currentScanDesc;
|
||||
direction = estate->es_direction;
|
||||
scan = ExecReScanR(rel, scan, direction, 0, NULL);
|
||||
scanstate->css_currentScanDesc = scan;
|
||||
|
||||
heap_rescan(scan, /* scan desc */
|
||||
ScanDirectionIsBackward(direction), /* backward flag */
|
||||
NULL); /* new scan keys */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.22 2002/02/11 20:10:50 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.23 2002/02/19 20:11:14 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -300,15 +300,14 @@ ExecEndTidScan(TidScan *node)
|
||||
CommonScanState *scanstate;
|
||||
TidScanState *tidstate;
|
||||
|
||||
/*
|
||||
* extract information from the node
|
||||
*/
|
||||
scanstate = node->scan.scanstate;
|
||||
tidstate = node->tidstate;
|
||||
if (tidstate && tidstate->tss_TidList)
|
||||
pfree(tidstate->tss_TidList);
|
||||
|
||||
/*
|
||||
* extract information from the node
|
||||
*/
|
||||
|
||||
/*
|
||||
* Free the projection info and the scan attribute info
|
||||
*
|
||||
@ -320,9 +319,13 @@ ExecEndTidScan(TidScan *node)
|
||||
ExecFreeExprContext(&scanstate->cstate);
|
||||
|
||||
/*
|
||||
* close the heap and tid relations
|
||||
* close the heap relation.
|
||||
*
|
||||
* Currently, we do not release the AccessShareLock acquired by
|
||||
* ExecInitTidScan. This lock should be held till end of transaction.
|
||||
* (There is a faction that considers this too much locking, however.)
|
||||
*/
|
||||
ExecCloseR((Plan *) node);
|
||||
heap_close(scanstate->css_currentRelation, NoLock);
|
||||
|
||||
/*
|
||||
* clear out tuple table slots
|
||||
@ -460,14 +463,17 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
|
||||
|
||||
/*
|
||||
* open the base relation
|
||||
*
|
||||
* We acquire AccessShareLock for the duration of the scan.
|
||||
*/
|
||||
relid = node->scan.scanrelid;
|
||||
rtentry = rt_fetch(relid, rangeTable);
|
||||
reloid = rtentry->relid;
|
||||
|
||||
currentRelation = heap_open(reloid, AccessShareLock);
|
||||
|
||||
scanstate->css_currentRelation = currentRelation;
|
||||
scanstate->css_currentScanDesc = 0;
|
||||
scanstate->css_currentScanDesc = NULL; /* no heap scan here */
|
||||
|
||||
/*
|
||||
* get the scan type from the relation descriptor.
|
||||
|
Reference in New Issue
Block a user