mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Replace "amgetmulti" AM functions with "amgetbitmap", in which the whole
indexscan always occurs in one call, and the results are returned in a TIDBitmap instead of a limited-size array of TIDs. This should improve speed a little by reducing AM entry/exit overhead, and it is necessary infrastructure if we are ever to support bitmap indexes. In an only slightly related change, add support for TIDBitmaps to preserve (somewhat lossily) the knowledge that particular TIDs reported by an index need to have their quals rechecked when the heap is visited. This facility is not really used yet; we'll need to extend the forced-recheck feature to plain indexscans before it's useful, and that hasn't been coded yet. The intent is to use it to clean up 8.3's horrid @@@ kluge for text search with weighted queries. There might be other uses in future, but that one alone is sufficient reason. Heikki Linnakangas, with some adjustments by me.
This commit is contained in:
@@ -8,13 +8,15 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/gin/ginget.c,v 1.10 2008/01/01 19:45:46 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/gin/ginget.c,v 1.11 2008/04/10 22:25:25 tgl Exp $
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/gin.h"
|
||||
#include "catalog/index.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/memutils.h"
|
||||
|
||||
static bool
|
||||
@@ -476,34 +478,37 @@ scanGetItem(IndexScanDesc scan, ItemPointerData *item)
|
||||
#define GinIsVoidRes(s) ( ((GinScanOpaque) scan->opaque)->isVoidRes == true )
|
||||
|
||||
Datum
|
||||
gingetmulti(PG_FUNCTION_ARGS)
|
||||
gingetbitmap(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);
|
||||
TIDBitmap *tbm = (TIDBitmap *) PG_GETARG_POINTER(1);
|
||||
int64 ntids;
|
||||
|
||||
if (GinIsNewKey(scan))
|
||||
newScanKey(scan);
|
||||
|
||||
*returned_tids = 0;
|
||||
|
||||
if (GinIsVoidRes(scan))
|
||||
PG_RETURN_BOOL(false);
|
||||
PG_RETURN_INT64(0);
|
||||
|
||||
startScan(scan);
|
||||
|
||||
do
|
||||
ntids = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (scanGetItem(scan, tids + *returned_tids))
|
||||
(*returned_tids)++;
|
||||
else
|
||||
ItemPointerData iptr;
|
||||
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
|
||||
if (!scanGetItem(scan, &iptr))
|
||||
break;
|
||||
} while (*returned_tids < max_tids);
|
||||
|
||||
tbm_add_tuples(tbm, &iptr, 1, false);
|
||||
ntids++;
|
||||
}
|
||||
|
||||
stopScan(scan);
|
||||
|
||||
PG_RETURN_BOOL(*returned_tids == max_tids);
|
||||
PG_RETURN_INT64(ntids);
|
||||
}
|
||||
|
||||
Datum
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.69 2008/01/01 19:45:46 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.70 2008/04/10 22:25:25 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -16,13 +16,16 @@
|
||||
|
||||
#include "access/gist_private.h"
|
||||
#include "executor/execdebug.h"
|
||||
#include "miscadmin.h"
|
||||
#include "pgstat.h"
|
||||
#include "utils/memutils.h"
|
||||
|
||||
|
||||
static OffsetNumber gistfindnext(IndexScanDesc scan, OffsetNumber n,
|
||||
ScanDirection dir);
|
||||
static int gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, bool ignore_killed_tuples);
|
||||
static int64 gistnext(IndexScanDesc scan, ScanDirection dir,
|
||||
ItemPointer tid, TIDBitmap *tbm,
|
||||
bool ignore_killed_tuples);
|
||||
static bool gistindex_keytest(IndexTuple tuple, IndexScanDesc scan,
|
||||
OffsetNumber offset);
|
||||
|
||||
@@ -114,32 +117,37 @@ gistgettuple(PG_FUNCTION_ARGS)
|
||||
* tuples, continue looping until we find a non-killed tuple that matches
|
||||
* the search key.
|
||||
*/
|
||||
res = (gistnext(scan, dir, &tid, 1, scan->ignore_killed_tuples)) ? true : false;
|
||||
res = (gistnext(scan, dir, &tid, NULL, scan->ignore_killed_tuples) > 0) ? true : false;
|
||||
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
|
||||
Datum
|
||||
gistgetmulti(PG_FUNCTION_ARGS)
|
||||
gistgetbitmap(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);
|
||||
TIDBitmap *tbm = (TIDBitmap *) PG_GETARG_POINTER(1);
|
||||
int64 ntids;
|
||||
|
||||
*returned_tids = gistnext(scan, ForwardScanDirection, tids, max_tids, false);
|
||||
ntids = gistnext(scan, ForwardScanDirection, NULL, tbm, false);
|
||||
|
||||
PG_RETURN_BOOL(*returned_tids == max_tids);
|
||||
PG_RETURN_INT64(ntids);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch a tuples that matchs the search key; this can be invoked
|
||||
* either to fetch the first such tuple or subsequent matching
|
||||
* tuples. Returns true iff a matching tuple was found.
|
||||
* Fetch tuple(s) that match the search key; this can be invoked
|
||||
* either to fetch the first such tuple or subsequent matching tuples.
|
||||
*
|
||||
* This function is used by both gistgettuple and gistgetbitmap. When
|
||||
* invoked from gistgettuple, tbm is null and the next matching tuple
|
||||
* is returned in *tid. When invoked from getbitmap, tid is null and
|
||||
* all matching tuples are added to tbm. In both cases, the function
|
||||
* result is the number of returned tuples.
|
||||
*/
|
||||
static int
|
||||
gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids,
|
||||
int maxtids, bool ignore_killed_tuples)
|
||||
static int64
|
||||
gistnext(IndexScanDesc scan, ScanDirection dir,
|
||||
ItemPointer tid, TIDBitmap *tbm,
|
||||
bool ignore_killed_tuples)
|
||||
{
|
||||
Page p;
|
||||
OffsetNumber n;
|
||||
@@ -148,7 +156,7 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids,
|
||||
IndexTuple it;
|
||||
GISTPageOpaque opaque;
|
||||
bool resetoffset = false;
|
||||
int ntids = 0;
|
||||
int64 ntids = 0;
|
||||
|
||||
so = (GISTScanOpaque) scan->opaque;
|
||||
|
||||
@@ -174,6 +182,8 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids,
|
||||
|
||||
for (;;)
|
||||
{
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
|
||||
/* First of all, we need lock buffer */
|
||||
Assert(so->curbuf != InvalidBuffer);
|
||||
LockBuffer(so->curbuf, GIST_SHARE);
|
||||
@@ -285,20 +295,21 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids,
|
||||
* return success. Note that we keep "curbuf" pinned so that
|
||||
* we can efficiently resume the index scan later.
|
||||
*/
|
||||
|
||||
ItemPointerSet(&(so->curpos),
|
||||
BufferGetBlockNumber(so->curbuf), n);
|
||||
|
||||
if (!(ignore_killed_tuples && ItemIdIsDead(PageGetItemId(p, n))))
|
||||
{
|
||||
it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
|
||||
tids[ntids] = scan->xs_ctup.t_self = it->t_tid;
|
||||
ntids++;
|
||||
|
||||
if (ntids == maxtids)
|
||||
if (tbm != NULL)
|
||||
tbm_add_tuples(tbm, &it->t_tid, 1, false);
|
||||
else
|
||||
{
|
||||
*tid = scan->xs_ctup.t_self = it->t_tid;
|
||||
|
||||
LockBuffer(so->curbuf, GIST_UNLOCK);
|
||||
return ntids;
|
||||
return ntids; /* always 1 */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,7 +319,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids,
|
||||
* We've found an entry in an internal node whose key is
|
||||
* consistent with the search key, so push it to stack
|
||||
*/
|
||||
|
||||
stk = (GISTSearchStack *) palloc(sizeof(GISTSearchStack));
|
||||
|
||||
it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
|
||||
@@ -318,7 +328,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids,
|
||||
|
||||
stk->next = so->stack->next;
|
||||
so->stack->next = stk;
|
||||
|
||||
}
|
||||
|
||||
if (ScanDirectionIsBackward(dir))
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.100 2008/03/16 23:15:08 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.101 2008/04/10 22:25:25 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* This file contains only the public interface routines.
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "access/hash.h"
|
||||
#include "catalog/index.h"
|
||||
#include "commands/vacuum.h"
|
||||
#include "miscadmin.h"
|
||||
#include "optimizer/cost.h"
|
||||
#include "optimizer/plancat.h"
|
||||
|
||||
@@ -275,72 +276,51 @@ 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.
|
||||
* hashgetbitmap() -- get all tuples at once
|
||||
*/
|
||||
Datum
|
||||
hashgetmulti(PG_FUNCTION_ARGS)
|
||||
hashgetbitmap(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);
|
||||
TIDBitmap *tbm = (TIDBitmap *) PG_GETARG_POINTER(1);
|
||||
HashScanOpaque so = (HashScanOpaque) scan->opaque;
|
||||
Relation rel = scan->indexRelation;
|
||||
bool res = true;
|
||||
int32 ntids = 0;
|
||||
bool res;
|
||||
int64 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);
|
||||
res = _hash_first(scan, ForwardScanDirection);
|
||||
|
||||
while (ntids < max_tids)
|
||||
while (res)
|
||||
{
|
||||
/*
|
||||
* Start scan, or advance to next tuple.
|
||||
*/
|
||||
if (ItemPointerIsValid(&(so->hashso_curpos)))
|
||||
res = _hash_next(scan, ForwardScanDirection);
|
||||
else
|
||||
res = _hash_first(scan, ForwardScanDirection);
|
||||
bool add_tuple;
|
||||
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
|
||||
/*
|
||||
* Skip killed tuples if asked to.
|
||||
*/
|
||||
if (scan->ignore_killed_tuples)
|
||||
{
|
||||
while (res)
|
||||
{
|
||||
Page page;
|
||||
OffsetNumber offnum;
|
||||
Page page;
|
||||
OffsetNumber offnum;
|
||||
|
||||
offnum = ItemPointerGetOffsetNumber(&(so->hashso_curpos));
|
||||
page = BufferGetPage(so->hashso_curbuf);
|
||||
if (!ItemIdIsDead(PageGetItemId(page, offnum)))
|
||||
break;
|
||||
res = _hash_next(scan, ForwardScanDirection);
|
||||
}
|
||||
offnum = ItemPointerGetOffsetNumber(&(so->hashso_curpos));
|
||||
page = BufferGetPage(so->hashso_curbuf);
|
||||
add_tuple = !ItemIdIsDead(PageGetItemId(page, offnum));
|
||||
}
|
||||
else
|
||||
add_tuple = true;
|
||||
|
||||
/* Save tuple ID, and continue scanning */
|
||||
if (add_tuple)
|
||||
{
|
||||
tbm_add_tuples(tbm, &scan->xs_ctup.t_self, 1, false);
|
||||
ntids++;
|
||||
}
|
||||
|
||||
if (!res)
|
||||
break;
|
||||
/* Save tuple ID, and continue scanning */
|
||||
tids[ntids] = scan->xs_ctup.t_self;
|
||||
ntids++;
|
||||
res = _hash_next(scan, ForwardScanDirection);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
PG_RETURN_INT64(ntids);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.65 2008/03/26 21:10:37 alvherre Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.66 2008/04/10 22:25:25 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* many of the old access method routines have been turned into
|
||||
@@ -88,7 +88,6 @@ RelationGetIndexScan(Relation indexRelation,
|
||||
else
|
||||
scan->keyData = NULL;
|
||||
|
||||
scan->is_multiscan = false; /* caller may change this */
|
||||
scan->kill_prior_tuple = false;
|
||||
scan->ignore_killed_tuples = true; /* default setting */
|
||||
|
||||
|
||||
@@ -8,20 +8,20 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.104 2008/03/26 21:10:37 alvherre Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.105 2008/04/10 22:25:25 tgl Exp $
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
* index_open - open an index relation by relation OID
|
||||
* index_close - close an index relation
|
||||
* index_beginscan - start a scan of an index with amgettuple
|
||||
* index_beginscan_multi - start a scan of an index with amgetmulti
|
||||
* index_beginscan_bitmap - start a scan of an index with amgetbitmap
|
||||
* index_rescan - restart a scan of an index
|
||||
* index_endscan - end a scan
|
||||
* index_insert - insert an index tuple into a relation
|
||||
* index_markpos - mark a scan position
|
||||
* index_restrpos - restore a scan position
|
||||
* index_getnext - get the next tuple from a scan
|
||||
* index_getmulti - get multiple tuples from a scan
|
||||
* index_getbitmap - get all tuples from a scan
|
||||
* index_bulk_delete - bulk deletion of index tuples
|
||||
* index_vacuum_cleanup - post-deletion cleanup of an index
|
||||
* index_getprocid - get a support procedure OID
|
||||
@@ -227,7 +227,6 @@ index_beginscan(Relation heapRelation,
|
||||
* Save additional parameters into the scandesc. Everything else was set
|
||||
* up by RelationGetIndexScan.
|
||||
*/
|
||||
scan->is_multiscan = false;
|
||||
scan->heapRelation = heapRelation;
|
||||
scan->xs_snapshot = snapshot;
|
||||
|
||||
@@ -235,15 +234,15 @@ index_beginscan(Relation heapRelation,
|
||||
}
|
||||
|
||||
/*
|
||||
* index_beginscan_multi - start a scan of an index with amgetmulti
|
||||
* index_beginscan_bitmap - start a scan of an index with amgetbitmap
|
||||
*
|
||||
* As above, caller had better be holding some lock on the parent heap
|
||||
* relation, even though it's not explicitly mentioned here.
|
||||
*/
|
||||
IndexScanDesc
|
||||
index_beginscan_multi(Relation indexRelation,
|
||||
Snapshot snapshot,
|
||||
int nkeys, ScanKey key)
|
||||
index_beginscan_bitmap(Relation indexRelation,
|
||||
Snapshot snapshot,
|
||||
int nkeys, ScanKey key)
|
||||
{
|
||||
IndexScanDesc scan;
|
||||
|
||||
@@ -253,7 +252,6 @@ index_beginscan_multi(Relation indexRelation,
|
||||
* Save additional parameters into the scandesc. Everything else was set
|
||||
* up by RelationGetIndexScan.
|
||||
*/
|
||||
scan->is_multiscan = true;
|
||||
scan->xs_snapshot = snapshot;
|
||||
|
||||
return scan;
|
||||
@@ -676,44 +674,39 @@ index_getnext_indexitem(IndexScanDesc scan,
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* index_getmulti - get multiple tuples from an index scan
|
||||
* index_getbitmap - get all tuples at once from an index scan
|
||||
*
|
||||
* Collects the TIDs of multiple heap tuples satisfying the scan keys.
|
||||
* Adds the TIDs of all heap tuples satisfying the scan keys to a bitmap.
|
||||
* Since there's no interlock between the index scan and the eventual heap
|
||||
* access, this is only safe to use with MVCC-based snapshots: the heap
|
||||
* item slot could have been replaced by a newer tuple by the time we get
|
||||
* to it.
|
||||
*
|
||||
* A TRUE result indicates more calls should occur; a FALSE result says the
|
||||
* scan is done. *returned_tids could be zero or nonzero in either case.
|
||||
* Returns the number of matching tuples found.
|
||||
* ----------------
|
||||
*/
|
||||
bool
|
||||
index_getmulti(IndexScanDesc scan,
|
||||
ItemPointer tids, int32 max_tids,
|
||||
int32 *returned_tids)
|
||||
int64
|
||||
index_getbitmap(IndexScanDesc scan, TIDBitmap *bitmap)
|
||||
{
|
||||
FmgrInfo *procedure;
|
||||
bool found;
|
||||
int64 ntids;
|
||||
|
||||
SCAN_CHECKS;
|
||||
GET_SCAN_PROCEDURE(amgetmulti);
|
||||
GET_SCAN_PROCEDURE(amgetbitmap);
|
||||
|
||||
/* just make sure this is false... */
|
||||
scan->kill_prior_tuple = false;
|
||||
|
||||
/*
|
||||
* have the am's getmulti proc do all the work.
|
||||
* have the am's getbitmap proc do all the work.
|
||||
*/
|
||||
found = DatumGetBool(FunctionCall4(procedure,
|
||||
PointerGetDatum(scan),
|
||||
PointerGetDatum(tids),
|
||||
Int32GetDatum(max_tids),
|
||||
PointerGetDatum(returned_tids)));
|
||||
ntids = DatumGetInt64(FunctionCall2(procedure,
|
||||
PointerGetDatum(scan),
|
||||
PointerGetDatum(bitmap)));
|
||||
|
||||
pgstat_count_index_tuples(scan->indexRelation, *returned_tids);
|
||||
pgstat_count_index_tuples(scan->indexRelation, ntids);
|
||||
|
||||
return found;
|
||||
return ntids;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
|
||||
@@ -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.156 2008/01/01 19:45:46 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.157 2008/04/10 22:25:25 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "access/nbtree.h"
|
||||
#include "catalog/index.h"
|
||||
#include "commands/vacuum.h"
|
||||
#include "miscadmin.h"
|
||||
#include "storage/freespace.h"
|
||||
#include "storage/lmgr.h"
|
||||
#include "utils/memutils.h"
|
||||
@@ -278,42 +279,29 @@ btgettuple(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* btgetmulti() -- get multiple tuples at once
|
||||
*
|
||||
* In the current implementation there seems no strong reason to stop at
|
||||
* index page boundaries; we just press on until we fill the caller's buffer
|
||||
* or run out of matches.
|
||||
* btgetbitmap() -- gets all matching tuples, and adds them to a bitmap
|
||||
*/
|
||||
Datum
|
||||
btgetmulti(PG_FUNCTION_ARGS)
|
||||
btgetbitmap(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);
|
||||
TIDBitmap *tbm = (TIDBitmap *) PG_GETARG_POINTER(1);
|
||||
BTScanOpaque so = (BTScanOpaque) scan->opaque;
|
||||
bool res = true;
|
||||
int32 ntids = 0;
|
||||
int64 ntids = 0;
|
||||
ItemPointer heapTid;
|
||||
|
||||
if (max_tids <= 0) /* behave correctly in boundary case */
|
||||
PG_RETURN_BOOL(true);
|
||||
|
||||
/* If we haven't started the scan yet, fetch the first page & tuple. */
|
||||
if (!BTScanPosIsValid(so->currPos))
|
||||
/* Fetch the first page & tuple. */
|
||||
if (!_bt_first(scan, ForwardScanDirection))
|
||||
{
|
||||
res = _bt_first(scan, ForwardScanDirection);
|
||||
if (!res)
|
||||
{
|
||||
/* empty scan */
|
||||
*returned_tids = ntids;
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
/* Save tuple ID, and continue scanning */
|
||||
tids[ntids] = scan->xs_ctup.t_self;
|
||||
ntids++;
|
||||
/* empty scan */
|
||||
PG_RETURN_INT64(0);
|
||||
}
|
||||
/* Save tuple ID, and continue scanning */
|
||||
heapTid = &scan->xs_ctup.t_self;
|
||||
tbm_add_tuples(tbm, heapTid, 1, false);
|
||||
ntids++;
|
||||
|
||||
while (ntids < max_tids)
|
||||
for (;;)
|
||||
{
|
||||
/*
|
||||
* Advance to next tuple within page. This is the same as the easy
|
||||
@@ -321,19 +309,20 @@ btgetmulti(PG_FUNCTION_ARGS)
|
||||
*/
|
||||
if (++so->currPos.itemIndex > so->currPos.lastItem)
|
||||
{
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
|
||||
/* let _bt_next do the heavy lifting */
|
||||
res = _bt_next(scan, ForwardScanDirection);
|
||||
if (!res)
|
||||
if (!_bt_next(scan, ForwardScanDirection))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Save tuple ID, and continue scanning */
|
||||
tids[ntids] = so->currPos.items[so->currPos.itemIndex].heapTid;
|
||||
heapTid = &so->currPos.items[so->currPos.itemIndex].heapTid;
|
||||
tbm_add_tuples(tbm, heapTid, 1, false);
|
||||
ntids++;
|
||||
}
|
||||
|
||||
*returned_tids = ntids;
|
||||
PG_RETURN_BOOL(res);
|
||||
PG_RETURN_INT64(ntids);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user