*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.56 2005/11/22 18:17:06 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.57 2005/12/03 05:50:59 tgl Exp $
*
*
* INTERFACE ROUTINES
/*
* Find the chunks by index
*/
- toastscan = index_beginscan(toastrel, toastidx, SnapshotToast,
- 1, &toastkey);
+ toastscan = index_beginscan(toastrel, toastidx, true,
+ SnapshotToast, 1, &toastkey);
while ((toasttup = index_getnext(toastscan, ForwardScanDirection)) != NULL)
{
/*
*/
nextidx = 0;
- toastscan = index_beginscan(toastrel, toastidx, SnapshotToast,
- 1, &toastkey);
+ toastscan = index_beginscan(toastrel, toastidx, true,
+ SnapshotToast, 1, &toastkey);
while ((ttup = index_getnext(toastscan, ForwardScanDirection)) != NULL)
{
/*
* The index is on (valueid, chunkidx) so they will come in order
*/
nextidx = startchunk;
- toastscan = index_beginscan(toastrel, toastidx, SnapshotToast,
- nscankeys, toastkey);
+ toastscan = index_beginscan(toastrel, toastidx, true,
+ SnapshotToast, nscankeys, toastkey);
while ((ttup = index_getnext(toastscan, ForwardScanDirection)) != NULL)
{
/*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.51 2005/11/22 18:17:06 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.52 2005/12/03 05:51:00 tgl Exp $
*
* NOTES
* many of the old access method routines have been turned into
else
scan->keyData = NULL;
- scan->is_multiscan = false; /* caller may change this */
+ scan->is_multiscan = false; /* caller may change this */
+ scan->have_lock = false; /* ditto */
scan->kill_prior_tuple = false;
scan->ignore_killed_tuples = true; /* default setting */
scan->keys_are_unique = false; /* may be set by index AM */
key[i].sk_attno = i + 1;
}
- sysscan->iscan = index_beginscan(heapRelation, irel, snapshot,
- nkeys, key);
+ sysscan->iscan = index_beginscan(heapRelation, irel, true,
+ snapshot, nkeys, key);
sysscan->scan = NULL;
}
else
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.86 2005/10/15 02:49:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.87 2005/12/03 05:51:00 tgl Exp $
*
* INTERFACE ROUTINES
* index_open - open an index relation by relation OID
} while(0)
static IndexScanDesc index_beginscan_internal(Relation indexRelation,
+ bool need_index_lock,
int nkeys, ScanKey key);
* heapRelation link (nor the snapshot). However, the caller had better
* be holding some kind of lock on the heap relation in any case, to ensure
* no one deletes it (or the index) out from under us.
+ *
+ * Most callers should pass need_index_lock = true to cause the index code
+ * to take AccessShareLock on the index for the duration of the scan. But
+ * if it is known that a lock is already held on the index, pass false to
+ * skip taking an unnecessary lock.
*/
IndexScanDesc
index_beginscan(Relation heapRelation,
Relation indexRelation,
+ bool need_index_lock,
Snapshot snapshot,
int nkeys, ScanKey key)
{
IndexScanDesc scan;
- scan = index_beginscan_internal(indexRelation, nkeys, key);
+ scan = index_beginscan_internal(indexRelation, need_index_lock,
+ nkeys, key);
/*
* Save additional parameters into the scandesc. Everything else was set
*/
IndexScanDesc
index_beginscan_multi(Relation indexRelation,
+ bool need_index_lock,
Snapshot snapshot,
int nkeys, ScanKey key)
{
IndexScanDesc scan;
- scan = index_beginscan_internal(indexRelation, nkeys, key);
+ scan = index_beginscan_internal(indexRelation, need_index_lock,
+ nkeys, key);
/*
* Save additional parameters into the scandesc. Everything else was set
*/
static IndexScanDesc
index_beginscan_internal(Relation indexRelation,
+ bool need_index_lock,
int nkeys, ScanKey key)
{
IndexScanDesc scan;
RelationIncrementReferenceCount(indexRelation);
/*
- * Acquire AccessShareLock for the duration of the scan
+ * Acquire AccessShareLock for the duration of the scan, unless caller
+ * says it already has lock on the index.
*
* Note: we could get an SI inval message here and consequently have to
* rebuild the relcache entry. The refcount increment above ensures that
* we will rebuild it and not just flush it...
*/
- LockRelation(indexRelation, AccessShareLock);
+ if (need_index_lock)
+ LockRelation(indexRelation, AccessShareLock);
/*
* LockRelation can clean rd_aminfo structure, so fill procedure after
Int32GetDatum(nkeys),
PointerGetDatum(key)));
+ /* Save flag to tell index_endscan whether to release lock */
+ scan->have_lock = need_index_lock;
+
return scan;
}
/* Release index lock and refcount acquired by index_beginscan */
- UnlockRelation(scan->indexRelation, AccessShareLock);
+ if (scan->have_lock)
+ UnlockRelation(scan->indexRelation, AccessShareLock);
RelationDecrementReferenceCount(scan->indexRelation);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/catalog.c,v 1.64 2005/10/15 02:49:12 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/catalog.c,v 1.65 2005/12/03 05:51:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
ObjectIdGetDatum(newOid));
/* see notes above about using SnapshotDirty */
- scan = index_beginscan(relation, indexrel, SnapshotDirty, 1, &key);
+ scan = index_beginscan(relation, indexrel, true,
+ SnapshotDirty, 1, &key);
collides = HeapTupleIsValid(index_getnext(scan, ForwardScanDirection));
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.142 2005/11/22 18:17:08 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.143 2005/12/03 05:51:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* Scan through the OldHeap on the OldIndex and copy each tuple into the
* NewHeap.
*/
- scan = index_beginscan(OldHeap, OldIndex, SnapshotNow, 0, (ScanKey) NULL);
+ scan = index_beginscan(OldHeap, OldIndex, true,
+ SnapshotNow, 0, (ScanKey) NULL);
while ((tuple = index_getnext(scan, ForwardScanDirection)) != NULL)
{
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.130 2005/12/02 20:03:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.131 2005/12/03 05:51:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* ----------------------------------------------------------------
*/
+/* ----------------------------------------------------------------
+ * ExecRelationIsTargetRelation
+ *
+ * Detect whether a relation (identified by rangetable index)
+ * is one of the target relations of the query.
+ * ----------------------------------------------------------------
+ */
+bool
+ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
+{
+ ResultRelInfo *resultRelInfos;
+ int i;
+
+ resultRelInfos = estate->es_result_relations;
+ for (i = 0; i < estate->es_num_result_relations; i++)
+ {
+ if (resultRelInfos[i].ri_RangeTableIndex == scanrelid)
+ return true;
+ }
+ return false;
+}
+
/* ----------------------------------------------------------------
* ExecOpenScanRelation
*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.13 2005/12/02 20:03:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.14 2005/12/03 05:51:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate)
{
BitmapIndexScanState *indexstate;
+ bool relistarget;
/*
* create state structure
indexstate->ss.ss_currentScanDesc = NULL;
/*
- * open the index relation and initialize relation and scan descriptors.
+ * Open the index relation and initialize relation and scan descriptors.
* Note we acquire no locks here; the index machinery does its own locks
- * and unlocks.
+ * and unlocks. (We rely on having a lock on the parent table to
+ * ensure the index won't go away!) Furthermore, if the parent table
+ * is one of the target relations of the query, then InitPlan already
+ * opened and write-locked the index, so we can tell the index machinery
+ * not to bother getting an extra lock.
*/
indexstate->biss_RelationDesc = index_open(node->indexid);
+ relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
indexstate->biss_ScanDesc =
index_beginscan_multi(indexstate->biss_RelationDesc,
+ !relistarget,
estate->es_snapshot,
indexstate->biss_NumScanKeys,
indexstate->biss_ScanKeys);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.108 2005/12/02 20:03:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.109 2005/12/03 05:51:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
IndexScanState *indexstate;
Relation currentRelation;
+ bool relistarget;
/*
* create state structure
ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation), false);
/*
- * open the index relation and initialize relation and scan descriptors.
+ * Open the index relation and initialize relation and scan descriptors.
* Note we acquire no locks here; the index machinery does its own locks
* and unlocks. (We rely on having a lock on the parent table to
- * ensure the index won't go away!)
+ * ensure the index won't go away!) Furthermore, if the parent table
+ * is one of the target relations of the query, then InitPlan already
+ * opened and write-locked the index, so we can tell the index machinery
+ * not to bother getting an extra lock.
*/
indexstate->iss_RelationDesc = index_open(node->indexid);
+ relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
indexstate->iss_ScanDesc = index_beginscan(currentRelation,
indexstate->iss_RelationDesc,
+ !relistarget,
estate->es_snapshot,
indexstate->iss_NumScanKeys,
indexstate->iss_ScanKeys);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.113 2005/10/15 02:49:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.114 2005/12/03 05:51:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(obj_desc->id));
- sd = index_beginscan(lo_heap_r, lo_index_r,
+ sd = index_beginscan(lo_heap_r, lo_index_r, true,
obj_desc->snapshot, 1, skey);
/*
BTGreaterEqualStrategyNumber, F_INT4GE,
Int32GetDatum(pageno));
- sd = index_beginscan(lo_heap_r, lo_index_r,
+ sd = index_beginscan(lo_heap_r, lo_index_r, true,
obj_desc->snapshot, 2, skey);
while ((tuple = index_getnext(sd, ForwardScanDirection)) != NULL)
BTGreaterEqualStrategyNumber, F_INT4GE,
Int32GetDatum(pageno));
- sd = index_beginscan(lo_heap_r, lo_index_r,
+ sd = index_beginscan(lo_heap_r, lo_index_r, false /* got lock */,
obj_desc->snapshot, 2, skey);
oldtuple = NULL;
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.53 2005/10/15 02:49:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.54 2005/12/03 05:51:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern IndexScanDesc index_beginscan(Relation heapRelation,
Relation indexRelation,
+ bool need_index_lock,
Snapshot snapshot,
int nkeys, ScanKey key);
extern IndexScanDesc index_beginscan_multi(Relation indexRelation,
+ bool need_index_lock,
Snapshot snapshot,
int nkeys, ScanKey key);
extern void index_rescan(IndexScanDesc scan, ScanKey key);
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.42 2005/11/26 03:03:07 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.43 2005/12/03 05:51:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
int numberOfKeys; /* number of scan keys */
ScanKey keyData; /* array of scan key descriptors */
bool is_multiscan; /* TRUE = using amgetmulti */
+ bool have_lock; /* TRUE = holding AccessShareLock for scan */
/* signaling to index AM about killing index tuples */
bool kill_prior_tuple; /* last-returned tuple is dead */
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.122 2005/12/02 20:03:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.123 2005/12/03 05:51:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
TupleDesc tupDesc, bool shouldFree);
extern void ExecAssignScanTypeFromOuterPlan(ScanState *scanstate);
+extern bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid);
+
extern Relation ExecOpenScanRelation(EState *estate, Index scanrelid);
extern void ExecCloseScanRelation(Relation scanrel);