aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/hash/hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/hash/hash.c')
-rw-r--r--src/backend/access/hash/hash.c71
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