aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/nbtree/nbtree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/nbtree/nbtree.c')
-rw-r--r--src/backend/access/nbtree/nbtree.c75
1 files changed, 74 insertions, 1 deletions
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 1fc26ea8958..82f9051de79 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.126 2005/03/21 01:23:59 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.127 2005/03/27 23:53:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -341,6 +341,79 @@ btgettuple(PG_FUNCTION_ARGS)
}
/*
+ * btgetmulti() -- get multiple tuples at once
+ *
+ * This is a somewhat generic implementation: it avoids the _bt_restscan
+ * overhead, but there's no smarts about picking especially good stopping
+ * points such as index page boundaries.
+ */
+Datum
+btgetmulti(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);
+ BTScanOpaque so = (BTScanOpaque) scan->opaque;
+ bool res = true;
+ int32 ntids = 0;
+
+ /*
+ * Restore prior state if we were already called at least once.
+ */
+ if (ItemPointerIsValid(&(scan->currentItemData)))
+ _bt_restscan(scan);
+
+ while (ntids < max_tids)
+ {
+ /*
+ * Start scan, or advance to next tuple.
+ */
+ if (ItemPointerIsValid(&(scan->currentItemData)))
+ res = _bt_next(scan, ForwardScanDirection);
+ else
+ res = _bt_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->btso_curbuf);
+ if (!ItemIdDeleted(PageGetItemId(page, offnum)))
+ break;
+ res = _bt_next(scan, ForwardScanDirection);
+ }
+ }
+
+ if (!res)
+ break;
+ /* Save tuple ID, and continue scanning */
+ tids[ntids] = scan->xs_ctup.t_self;
+ ntids++;
+ }
+
+ /*
+ * Save heap TID to use it in _bt_restscan. Then release the read
+ * lock on the buffer so that we aren't blocking other backends.
+ */
+ if (res)
+ {
+ ((BTScanOpaque) scan->opaque)->curHeapIptr = scan->xs_ctup.t_self;
+ LockBuffer(((BTScanOpaque) scan->opaque)->btso_curbuf,
+ BUFFER_LOCK_UNLOCK);
+ }
+
+ *returned_tids = ntids;
+ PG_RETURN_BOOL(res);
+}
+
+/*
* btbeginscan() -- start a scan on a btree index
*/
Datum