88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.86 2005/10/15 02:49:09 momjian Exp $
11+ * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.87 2005/12/03 05:51:00 tgl Exp $
1212 *
1313 * INTERFACE ROUTINES
1414 * index_open - open an index relation by relation OID
@@ -111,6 +111,7 @@ do { \
111111} while(0)
112112
113113static IndexScanDesc index_beginscan_internal (Relation indexRelation ,
114+ bool need_index_lock ,
114115 int nkeys , ScanKey key );
115116
116117
@@ -229,16 +230,23 @@ index_insert(Relation indexRelation,
229230 * heapRelation link (nor the snapshot). However, the caller had better
230231 * be holding some kind of lock on the heap relation in any case, to ensure
231232 * no one deletes it (or the index) out from under us.
233+ *
234+ * Most callers should pass need_index_lock = true to cause the index code
235+ * to take AccessShareLock on the index for the duration of the scan. But
236+ * if it is known that a lock is already held on the index, pass false to
237+ * skip taking an unnecessary lock.
232238 */
233239IndexScanDesc
234240index_beginscan (Relation heapRelation ,
235241 Relation indexRelation ,
242+ bool need_index_lock ,
236243 Snapshot snapshot ,
237244 int nkeys , ScanKey key )
238245{
239246 IndexScanDesc scan ;
240247
241- scan = index_beginscan_internal (indexRelation , nkeys , key );
248+ scan = index_beginscan_internal (indexRelation , need_index_lock ,
249+ nkeys , key );
242250
243251 /*
244252 * Save additional parameters into the scandesc. Everything else was set
@@ -259,12 +267,14 @@ index_beginscan(Relation heapRelation,
259267 */
260268IndexScanDesc
261269index_beginscan_multi (Relation indexRelation ,
270+ bool need_index_lock ,
262271 Snapshot snapshot ,
263272 int nkeys , ScanKey key )
264273{
265274 IndexScanDesc scan ;
266275
267- scan = index_beginscan_internal (indexRelation , nkeys , key );
276+ scan = index_beginscan_internal (indexRelation , need_index_lock ,
277+ nkeys , key );
268278
269279 /*
270280 * Save additional parameters into the scandesc. Everything else was set
@@ -281,6 +291,7 @@ index_beginscan_multi(Relation indexRelation,
281291 */
282292static IndexScanDesc
283293index_beginscan_internal (Relation indexRelation ,
294+ bool need_index_lock ,
284295 int nkeys , ScanKey key )
285296{
286297 IndexScanDesc scan ;
@@ -291,13 +302,15 @@ index_beginscan_internal(Relation indexRelation,
291302 RelationIncrementReferenceCount (indexRelation );
292303
293304 /*
294- * Acquire AccessShareLock for the duration of the scan
305+ * Acquire AccessShareLock for the duration of the scan, unless caller
306+ * says it already has lock on the index.
295307 *
296308 * Note: we could get an SI inval message here and consequently have to
297309 * rebuild the relcache entry. The refcount increment above ensures that
298310 * we will rebuild it and not just flush it...
299311 */
300- LockRelation (indexRelation , AccessShareLock );
312+ if (need_index_lock )
313+ LockRelation (indexRelation , AccessShareLock );
301314
302315 /*
303316 * LockRelation can clean rd_aminfo structure, so fill procedure after
@@ -315,6 +328,9 @@ index_beginscan_internal(Relation indexRelation,
315328 Int32GetDatum (nkeys ),
316329 PointerGetDatum (key )));
317330
331+ /* Save flag to tell index_endscan whether to release lock */
332+ scan -> have_lock = need_index_lock ;
333+
318334 return scan ;
319335}
320336
@@ -380,7 +396,8 @@ index_endscan(IndexScanDesc scan)
380396
381397 /* Release index lock and refcount acquired by index_beginscan */
382398
383- UnlockRelation (scan -> indexRelation , AccessShareLock );
399+ if (scan -> have_lock )
400+ UnlockRelation (scan -> indexRelation , AccessShareLock );
384401
385402 RelationDecrementReferenceCount (scan -> indexRelation );
386403
0 commit comments