diff options
Diffstat (limited to 'src/backend/access/hash/hash.c')
-rw-r--r-- | src/backend/access/hash/hash.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index 1fd901e96a3..7b15937766e 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.77 2005/03/21 01:23:57 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.78 2005/03/27 23:52:57 tgl Exp $ * * NOTES * This file contains only the public interface routines. @@ -265,6 +265,75 @@ hashgettuple(PG_FUNCTION_ARGS) /* + * hashgetmulti() -- get multiple tuples at once + * + * This is a somewhat generic implementation: it avoids lock reacquisition + * overhead, but there's no smarts about picking especially good stopping + * points such as index page boundaries. + */ +Datum +hashgetmulti(PG_FUNCTION_ARGS) +{ + IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); + ItemPointer tids = (ItemPointer) PG_GETARG_POINTER(1); + int32 max_tids = PG_GETARG_INT32(2); + int32 *returned_tids = (int32 *) PG_GETARG_POINTER(3); + HashScanOpaque so = (HashScanOpaque) scan->opaque; + Relation rel = scan->indexRelation; + bool res = true; + int32 ntids = 0; + + /* + * We hold pin but not lock on current buffer while outside the hash + * AM. Reacquire the read lock here. + */ + if (BufferIsValid(so->hashso_curbuf)) + _hash_chgbufaccess(rel, so->hashso_curbuf, HASH_NOLOCK, HASH_READ); + + while (ntids < max_tids) + { + /* + * Start scan, or advance to next tuple. + */ + if (ItemPointerIsValid(&(scan->currentItemData))) + res = _hash_next(scan, ForwardScanDirection); + else + res = _hash_first(scan, ForwardScanDirection); + /* + * Skip killed tuples if asked to. + */ + if (scan->ignore_killed_tuples) + { + while (res) + { + Page page; + OffsetNumber offnum; + + offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData)); + page = BufferGetPage(so->hashso_curbuf); + if (!ItemIdDeleted(PageGetItemId(page, offnum))) + break; + res = _hash_next(scan, ForwardScanDirection); + } + } + + if (!res) + break; + /* Save tuple ID, and continue scanning */ + tids[ntids] = scan->xs_ctup.t_self; + ntids++; + } + + /* Release read lock on current buffer, but keep it pinned */ + if (BufferIsValid(so->hashso_curbuf)) + _hash_chgbufaccess(rel, so->hashso_curbuf, HASH_READ, HASH_NOLOCK); + + *returned_tids = ntids; + PG_RETURN_BOOL(res); +} + + +/* * hashbeginscan() -- start a scan on a hash index */ Datum |