mirror of
https://github.com/postgres/postgres.git
synced 2025-11-07 19:06:32 +03:00
Restructure indexscan API (index_beginscan, index_getnext) per
yesterday's proposal to pghackers. Also remove unnecessary parameters to heap_beginscan, heap_rescan. I modified pg_proc.h to reflect the new numbers of parameters for the AM interface routines, but did not force an initdb because nothing actually looks at those fields.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/index/genam.c,v 1.32 2002/03/29 22:10:32 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/index/genam.c,v 1.33 2002/05/20 23:51:41 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* many of the old access method routines have been turned into
|
||||
@@ -16,34 +16,7 @@
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
/*
|
||||
* OLD COMMENTS
|
||||
* Scans are implemented as follows:
|
||||
*
|
||||
* `0' represents an invalid item pointer.
|
||||
* `-' represents an unknown item pointer.
|
||||
* `X' represents a known item pointers.
|
||||
* `+' represents known or invalid item pointers.
|
||||
* `*' represents any item pointers.
|
||||
*
|
||||
* State is represented by a triple of these symbols in the order of
|
||||
* previous, current, next. Note that the case of reverse scans works
|
||||
* identically.
|
||||
*
|
||||
* State Result
|
||||
* (1) + + - + 0 0 (if the next item pointer is invalid)
|
||||
* (2) + X - (otherwise)
|
||||
* (3) * 0 0 * 0 0 (no change)
|
||||
* (4) + X 0 X 0 0 (shift)
|
||||
* (5) * + X + X - (shift, add unknown)
|
||||
*
|
||||
* All other states cannot occur.
|
||||
*
|
||||
* Note:
|
||||
* It would be possible to cache the status of the previous and
|
||||
* next item pointer using the flags.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/genam.h"
|
||||
@@ -83,50 +56,58 @@
|
||||
* the passed key.
|
||||
*
|
||||
* Parameters:
|
||||
* relation -- index relation for scan.
|
||||
* scanFromEnd -- if true, begin scan at one of the index's
|
||||
* endpoints.
|
||||
* numberOfKeys -- count of scan keys.
|
||||
* key -- the ScanKey for the starting position of the scan.
|
||||
* indexRelation -- index relation for scan.
|
||||
* nkeys -- count of scan keys.
|
||||
* key -- array of scan keys to restrict the index scan.
|
||||
*
|
||||
* Returns:
|
||||
* An initialized IndexScanDesc.
|
||||
* ----------------
|
||||
*/
|
||||
IndexScanDesc
|
||||
RelationGetIndexScan(Relation relation,
|
||||
bool scanFromEnd,
|
||||
uint16 numberOfKeys,
|
||||
ScanKey key)
|
||||
RelationGetIndexScan(Relation indexRelation,
|
||||
int nkeys, ScanKey key)
|
||||
{
|
||||
IndexScanDesc scan;
|
||||
|
||||
if (!RelationIsValid(relation))
|
||||
if (!RelationIsValid(indexRelation))
|
||||
elog(ERROR, "RelationGetIndexScan: relation invalid");
|
||||
|
||||
scan = (IndexScanDesc) palloc(sizeof(IndexScanDescData));
|
||||
|
||||
scan->relation = relation;
|
||||
scan->heapRelation = NULL; /* may be set later */
|
||||
scan->indexRelation = indexRelation;
|
||||
scan->xs_snapshot = SnapshotNow; /* may be set later */
|
||||
scan->numberOfKeys = nkeys;
|
||||
|
||||
/*
|
||||
* We allocate the key space here, but the AM is responsible for
|
||||
* actually filling it from the passed key array.
|
||||
*/
|
||||
if (nkeys > 0)
|
||||
scan->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);
|
||||
else
|
||||
scan->keyData = NULL;
|
||||
|
||||
scan->opaque = NULL;
|
||||
scan->numberOfKeys = numberOfKeys;
|
||||
|
||||
ItemPointerSetInvalid(&scan->currentItemData);
|
||||
ItemPointerSetInvalid(&scan->currentMarkData);
|
||||
|
||||
pgstat_initstats(&scan->xs_pgstat_info, relation);
|
||||
ItemPointerSetInvalid(&scan->xs_ctup.t_self);
|
||||
scan->xs_ctup.t_datamcxt = NULL;
|
||||
scan->xs_ctup.t_data = NULL;
|
||||
scan->xs_cbuf = InvalidBuffer;
|
||||
|
||||
/*
|
||||
* mark cached function lookup data invalid; it will be set on first
|
||||
* use
|
||||
*/
|
||||
/* mark cached function lookup data invalid; it will be set later */
|
||||
scan->fn_getnext.fn_oid = InvalidOid;
|
||||
|
||||
if (numberOfKeys > 0)
|
||||
scan->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * numberOfKeys);
|
||||
else
|
||||
scan->keyData = NULL;
|
||||
pgstat_initstats(&scan->xs_pgstat_info, indexRelation);
|
||||
|
||||
index_rescan(scan, scanFromEnd, key);
|
||||
/*
|
||||
* Let the AM fill in the key and any opaque data it wants.
|
||||
*/
|
||||
index_rescan(scan, key);
|
||||
|
||||
return scan;
|
||||
}
|
||||
@@ -155,113 +136,21 @@ IndexScanEnd(IndexScanDesc scan)
|
||||
pfree(scan);
|
||||
}
|
||||
|
||||
#ifdef NOT_USED
|
||||
/* ----------------
|
||||
* IndexScanRestart -- Restart an index scan.
|
||||
*
|
||||
* This routine isn't used by any existing access method. It's
|
||||
* appropriate if relation level locks are what you want.
|
||||
*
|
||||
* Returns:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
IndexScanRestart(IndexScanDesc scan,
|
||||
bool scanFromEnd,
|
||||
ScanKey key)
|
||||
{
|
||||
if (!IndexScanIsValid(scan))
|
||||
elog(ERROR, "IndexScanRestart: invalid scan");
|
||||
|
||||
ItemPointerSetInvalid(&scan->currentItemData);
|
||||
|
||||
if (RelationGetNumberOfBlocks(scan->relation) == 0)
|
||||
scan->flags = ScanUnmarked;
|
||||
else if (scanFromEnd)
|
||||
scan->flags = ScanUnmarked | ScanUncheckedPrevious;
|
||||
else
|
||||
scan->flags = ScanUnmarked | ScanUncheckedNext;
|
||||
|
||||
scan->scanFromEnd = (bool) scanFromEnd;
|
||||
|
||||
if (scan->numberOfKeys > 0)
|
||||
memmove(scan->keyData,
|
||||
key,
|
||||
scan->numberOfKeys * sizeof(ScanKeyData));
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* IndexScanMarkPosition -- Mark current position in a scan.
|
||||
*
|
||||
* This routine isn't used by any existing access method, but is the
|
||||
* one that AM implementors should use, if they don't want to do any
|
||||
* special locking. If relation-level locking is sufficient, this is
|
||||
* the routine for you.
|
||||
*
|
||||
* Returns:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
IndexScanMarkPosition(IndexScanDesc scan)
|
||||
{
|
||||
scan->currentMarkData = scan->currentItemData;
|
||||
|
||||
scan->flags = 0x0; /* XXX should have a symbolic name */
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* IndexScanRestorePosition -- Restore position on a marked scan.
|
||||
*
|
||||
* This routine isn't used by any existing access method, but is the
|
||||
* one that AM implementors should use if they don't want to do any
|
||||
* special locking. If relation-level locking is sufficient, then
|
||||
* this is the one you want.
|
||||
*
|
||||
* Returns:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
IndexScanRestorePosition(IndexScanDesc scan)
|
||||
{
|
||||
if (scan->flags & ScanUnmarked)
|
||||
elog(ERROR, "IndexScanRestorePosition: no mark to restore");
|
||||
|
||||
scan->currentItemData = scan->currentMarkData;
|
||||
|
||||
scan->flags = 0x0; /* XXX should have a symbolic name */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* heap-or-index-scan access to system catalogs
|
||||
*
|
||||
* These functions support system catalog accesses that normally use
|
||||
* an index but need to be capable of being switched to heap scans
|
||||
* if the system indexes are unavailable. The interface is
|
||||
* as easy to use as a heap scan, and hides all the extra cruft of
|
||||
* the present indexscan API.
|
||||
* if the system indexes are unavailable.
|
||||
*
|
||||
* The specified scan keys must be compatible with the named index.
|
||||
* Generally this means that they must constrain either all columns
|
||||
* of the index, or the first K columns of an N-column index.
|
||||
*
|
||||
* These routines would work fine with non-system tables, actually,
|
||||
* These routines could work with non-system tables, actually,
|
||||
* but they're only useful when there is a known index to use with
|
||||
* the given scan keys, so in practice they're only good for
|
||||
* the given scan keys; so in practice they're only good for
|
||||
* predetermined types of scans of system catalogs.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
@@ -286,27 +175,24 @@ IndexScanRestorePosition(IndexScanDesc scan)
|
||||
* In standard case indexOK can simply be constant TRUE.
|
||||
*/
|
||||
SysScanDesc
|
||||
systable_beginscan(Relation rel,
|
||||
systable_beginscan(Relation heapRelation,
|
||||
const char *indexRelname,
|
||||
bool indexOK,
|
||||
Snapshot snapshot,
|
||||
unsigned nkeys, ScanKey key)
|
||||
int nkeys, ScanKey key)
|
||||
{
|
||||
SysScanDesc sysscan;
|
||||
|
||||
sysscan = (SysScanDesc) palloc(sizeof(SysScanDescData));
|
||||
sysscan->heap_rel = rel;
|
||||
sysscan->snapshot = snapshot;
|
||||
sysscan->tuple.t_datamcxt = NULL;
|
||||
sysscan->tuple.t_data = NULL;
|
||||
sysscan->buffer = InvalidBuffer;
|
||||
|
||||
sysscan->heap_rel = heapRelation;
|
||||
|
||||
if (indexOK &&
|
||||
rel->rd_rel->relhasindex &&
|
||||
heapRelation->rd_rel->relhasindex &&
|
||||
!IsIgnoringSystemIndexes())
|
||||
{
|
||||
Relation irel;
|
||||
unsigned i;
|
||||
int i;
|
||||
|
||||
/* We assume it's a system index, so index_openr is OK */
|
||||
sysscan->irel = irel = index_openr(indexRelname);
|
||||
@@ -321,13 +207,14 @@ systable_beginscan(Relation rel,
|
||||
Assert(key[i].sk_attno == irel->rd_index->indkey[i]);
|
||||
key[i].sk_attno = i+1;
|
||||
}
|
||||
sysscan->iscan = index_beginscan(irel, false, nkeys, key);
|
||||
sysscan->iscan = index_beginscan(heapRelation, irel, snapshot,
|
||||
nkeys, key);
|
||||
sysscan->scan = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
sysscan->irel = (Relation) NULL;
|
||||
sysscan->scan = heap_beginscan(rel, false, snapshot, nkeys, key);
|
||||
sysscan->irel = NULL;
|
||||
sysscan->scan = heap_beginscan(heapRelation, snapshot, nkeys, key);
|
||||
sysscan->iscan = NULL;
|
||||
}
|
||||
|
||||
@@ -346,34 +233,12 @@ systable_beginscan(Relation rel,
|
||||
HeapTuple
|
||||
systable_getnext(SysScanDesc sysscan)
|
||||
{
|
||||
HeapTuple htup = (HeapTuple) NULL;
|
||||
HeapTuple htup;
|
||||
|
||||
if (sysscan->irel)
|
||||
{
|
||||
RetrieveIndexResult indexRes;
|
||||
|
||||
if (BufferIsValid(sysscan->buffer))
|
||||
{
|
||||
ReleaseBuffer(sysscan->buffer);
|
||||
sysscan->buffer = InvalidBuffer;
|
||||
}
|
||||
|
||||
while ((indexRes = index_getnext(sysscan->iscan, ForwardScanDirection)) != NULL)
|
||||
{
|
||||
sysscan->tuple.t_self = indexRes->heap_iptr;
|
||||
pfree(indexRes);
|
||||
heap_fetch(sysscan->heap_rel, sysscan->snapshot,
|
||||
&sysscan->tuple, &sysscan->buffer,
|
||||
sysscan->iscan);
|
||||
if (sysscan->tuple.t_data != NULL)
|
||||
{
|
||||
htup = &sysscan->tuple;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
htup = index_getnext(sysscan->iscan, ForwardScanDirection);
|
||||
else
|
||||
htup = heap_getnext(sysscan->scan, 0);
|
||||
htup = heap_getnext(sysscan->scan, ForwardScanDirection);
|
||||
|
||||
return htup;
|
||||
}
|
||||
@@ -388,8 +253,6 @@ systable_endscan(SysScanDesc sysscan)
|
||||
{
|
||||
if (sysscan->irel)
|
||||
{
|
||||
if (BufferIsValid(sysscan->buffer))
|
||||
ReleaseBuffer(sysscan->buffer);
|
||||
index_endscan(sysscan->iscan);
|
||||
index_close(sysscan->irel);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.57 2002/04/17 20:57:56 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.58 2002/05/20 23:51:41 tgl Exp $
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
* index_open - open an index relation by relation OID
|
||||
@@ -73,20 +73,20 @@
|
||||
*/
|
||||
#define RELATION_CHECKS \
|
||||
( \
|
||||
AssertMacro(RelationIsValid(relation)), \
|
||||
AssertMacro(PointerIsValid(relation->rd_am)) \
|
||||
AssertMacro(RelationIsValid(indexRelation)), \
|
||||
AssertMacro(PointerIsValid(indexRelation->rd_am)) \
|
||||
)
|
||||
|
||||
#define SCAN_CHECKS \
|
||||
( \
|
||||
AssertMacro(IndexScanIsValid(scan)), \
|
||||
AssertMacro(RelationIsValid(scan->relation)), \
|
||||
AssertMacro(PointerIsValid(scan->relation->rd_am)) \
|
||||
AssertMacro(RelationIsValid(scan->indexRelation)), \
|
||||
AssertMacro(PointerIsValid(scan->indexRelation->rd_am)) \
|
||||
)
|
||||
|
||||
#define GET_REL_PROCEDURE(x,y) \
|
||||
( \
|
||||
procedure = relation->rd_am->y, \
|
||||
procedure = indexRelation->rd_am->y, \
|
||||
(!RegProcedureIsValid(procedure)) ? \
|
||||
elog(ERROR, "index_%s: invalid %s regproc", \
|
||||
CppAsString(x), CppAsString(y)) \
|
||||
@@ -95,7 +95,7 @@
|
||||
|
||||
#define GET_SCAN_PROCEDURE(x,y) \
|
||||
( \
|
||||
procedure = scan->relation->rd_am->y, \
|
||||
procedure = scan->indexRelation->rd_am->y, \
|
||||
(!RegProcedureIsValid(procedure)) ? \
|
||||
elog(ERROR, "index_%s: invalid %s regproc", \
|
||||
CppAsString(x), CppAsString(y)) \
|
||||
@@ -200,11 +200,11 @@ index_close(Relation relation)
|
||||
* ----------------
|
||||
*/
|
||||
InsertIndexResult
|
||||
index_insert(Relation relation,
|
||||
Datum *datum,
|
||||
index_insert(Relation indexRelation,
|
||||
Datum *datums,
|
||||
char *nulls,
|
||||
ItemPointer heap_t_ctid,
|
||||
Relation heapRel)
|
||||
Relation heapRelation)
|
||||
{
|
||||
RegProcedure procedure;
|
||||
InsertIndexResult specificResult;
|
||||
@@ -217,11 +217,11 @@ index_insert(Relation relation,
|
||||
*/
|
||||
specificResult = (InsertIndexResult)
|
||||
DatumGetPointer(OidFunctionCall5(procedure,
|
||||
PointerGetDatum(relation),
|
||||
PointerGetDatum(datum),
|
||||
PointerGetDatum(indexRelation),
|
||||
PointerGetDatum(datums),
|
||||
PointerGetDatum(nulls),
|
||||
PointerGetDatum(heap_t_ctid),
|
||||
PointerGetDatum(heapRel)));
|
||||
PointerGetDatum(heapRelation)));
|
||||
|
||||
/* must be pfree'ed */
|
||||
return specificResult;
|
||||
@@ -229,13 +229,19 @@ index_insert(Relation relation,
|
||||
|
||||
/* ----------------
|
||||
* index_beginscan - start a scan of an index
|
||||
*
|
||||
* Note: heapRelation may be NULL if there is no intention of calling
|
||||
* index_getnext on this scan; index_getnext_indexitem will not use the
|
||||
* heapRelation link (nor the snapshot). However, the caller had better
|
||||
* be holding some kind of lock on the heap relation in any case, to ensure
|
||||
* no one deletes it (or the index) out from under us.
|
||||
* ----------------
|
||||
*/
|
||||
IndexScanDesc
|
||||
index_beginscan(Relation relation,
|
||||
bool scanFromEnd,
|
||||
uint16 numberOfKeys,
|
||||
ScanKey key)
|
||||
index_beginscan(Relation heapRelation,
|
||||
Relation indexRelation,
|
||||
Snapshot snapshot,
|
||||
int nkeys, ScanKey key)
|
||||
{
|
||||
IndexScanDesc scan;
|
||||
RegProcedure procedure;
|
||||
@@ -243,7 +249,7 @@ index_beginscan(Relation relation,
|
||||
RELATION_CHECKS;
|
||||
GET_REL_PROCEDURE(beginscan, ambeginscan);
|
||||
|
||||
RelationIncrementReferenceCount(relation);
|
||||
RelationIncrementReferenceCount(indexRelation);
|
||||
|
||||
/*
|
||||
* Acquire AccessShareLock for the duration of the scan
|
||||
@@ -252,16 +258,23 @@ index_beginscan(Relation relation,
|
||||
* rebuild the relcache entry. The refcount increment above ensures
|
||||
* that we will rebuild it and not just flush it...
|
||||
*/
|
||||
LockRelation(relation, AccessShareLock);
|
||||
LockRelation(indexRelation, AccessShareLock);
|
||||
|
||||
/*
|
||||
* Tell the AM to open a scan.
|
||||
*/
|
||||
scan = (IndexScanDesc)
|
||||
DatumGetPointer(OidFunctionCall4(procedure,
|
||||
PointerGetDatum(relation),
|
||||
BoolGetDatum(scanFromEnd),
|
||||
UInt16GetDatum(numberOfKeys),
|
||||
DatumGetPointer(OidFunctionCall3(procedure,
|
||||
PointerGetDatum(indexRelation),
|
||||
Int32GetDatum(nkeys),
|
||||
PointerGetDatum(key)));
|
||||
|
||||
pgstat_initstats(&scan->xs_pgstat_info, relation);
|
||||
/*
|
||||
* Save additional parameters into the scandesc. Everything else
|
||||
* was set up by RelationGetIndexScan.
|
||||
*/
|
||||
scan->heapRelation = heapRelation;
|
||||
scan->xs_snapshot = snapshot;
|
||||
|
||||
/*
|
||||
* We want to look up the amgettuple procedure just once per scan, not
|
||||
@@ -275,20 +288,23 @@ index_beginscan(Relation relation,
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* index_rescan - restart a scan of an index
|
||||
* index_rescan - (re)start a scan of an index
|
||||
*
|
||||
* The caller may specify a new set of scankeys (but the number of keys
|
||||
* cannot change). Note that this is also called when first starting
|
||||
* an indexscan; see RelationGetIndexScan.
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
index_rescan(IndexScanDesc scan, bool scanFromEnd, ScanKey key)
|
||||
index_rescan(IndexScanDesc scan, ScanKey key)
|
||||
{
|
||||
RegProcedure procedure;
|
||||
|
||||
SCAN_CHECKS;
|
||||
GET_SCAN_PROCEDURE(rescan, amrescan);
|
||||
|
||||
OidFunctionCall3(procedure,
|
||||
OidFunctionCall2(procedure,
|
||||
PointerGetDatum(scan),
|
||||
BoolGetDatum(scanFromEnd),
|
||||
PointerGetDatum(key));
|
||||
|
||||
pgstat_reset_index_scan(&scan->xs_pgstat_info);
|
||||
@@ -306,13 +322,21 @@ index_endscan(IndexScanDesc scan)
|
||||
SCAN_CHECKS;
|
||||
GET_SCAN_PROCEDURE(endscan, amendscan);
|
||||
|
||||
/* Release any held pin on a heap page */
|
||||
if (BufferIsValid(scan->xs_cbuf))
|
||||
{
|
||||
ReleaseBuffer(scan->xs_cbuf);
|
||||
scan->xs_cbuf = InvalidBuffer;
|
||||
}
|
||||
|
||||
/* End the AM's scan */
|
||||
OidFunctionCall1(procedure, PointerGetDatum(scan));
|
||||
|
||||
/* Release lock and refcount acquired by index_beginscan */
|
||||
/* Release index lock and refcount acquired by index_beginscan */
|
||||
|
||||
UnlockRelation(scan->relation, AccessShareLock);
|
||||
UnlockRelation(scan->indexRelation, AccessShareLock);
|
||||
|
||||
RelationDecrementReferenceCount(scan->relation);
|
||||
RelationDecrementReferenceCount(scan->indexRelation);
|
||||
|
||||
/* Release the scan data structure itself */
|
||||
IndexScanEnd(scan);
|
||||
@@ -349,33 +373,87 @@ index_restrpos(IndexScanDesc scan)
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* index_getnext - get the next tuple from a scan
|
||||
* index_getnext - get the next heap tuple from a scan
|
||||
*
|
||||
* A RetrieveIndexResult is a index tuple/heap tuple pair
|
||||
* The result is the next heap tuple satisfying the scan keys and the
|
||||
* snapshot, or NULL if no more matching tuples exist. On success,
|
||||
* the buffer containing the heap tuple is pinned (the pin will be dropped
|
||||
* at the next index_getnext or index_endscan). The index TID corresponding
|
||||
* to the heap tuple can be obtained if needed from scan->currentItemData.
|
||||
* ----------------
|
||||
*/
|
||||
RetrieveIndexResult
|
||||
index_getnext(IndexScanDesc scan,
|
||||
ScanDirection direction)
|
||||
HeapTuple
|
||||
index_getnext(IndexScanDesc scan, ScanDirection direction)
|
||||
{
|
||||
RetrieveIndexResult result;
|
||||
bool found;
|
||||
|
||||
SCAN_CHECKS;
|
||||
|
||||
pgstat_count_index_scan(&scan->xs_pgstat_info);
|
||||
/* Release any previously held pin */
|
||||
if (BufferIsValid(scan->xs_cbuf))
|
||||
{
|
||||
ReleaseBuffer(scan->xs_cbuf);
|
||||
scan->xs_cbuf = InvalidBuffer;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
pgstat_count_index_scan(&scan->xs_pgstat_info);
|
||||
|
||||
/*
|
||||
* The AM's gettuple proc finds the next tuple matching the scan
|
||||
* keys. index_beginscan already set up fn_getnext.
|
||||
*/
|
||||
found = DatumGetBool(FunctionCall2(&scan->fn_getnext,
|
||||
PointerGetDatum(scan),
|
||||
Int32GetDatum(direction)));
|
||||
if (!found)
|
||||
return NULL; /* failure exit */
|
||||
/*
|
||||
* Fetch the heap tuple and see if it matches the snapshot.
|
||||
*/
|
||||
heap_fetch(scan->heapRelation, scan->xs_snapshot,
|
||||
&scan->xs_ctup, &scan->xs_cbuf,
|
||||
&scan->xs_pgstat_info);
|
||||
if (scan->xs_ctup.t_data != NULL)
|
||||
break;
|
||||
/*
|
||||
* XXX here, consider whether we can kill the index tuple.
|
||||
*/
|
||||
}
|
||||
|
||||
/* Success exit */
|
||||
pgstat_count_index_getnext(&scan->xs_pgstat_info);
|
||||
|
||||
return &scan->xs_ctup;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* index_getnext_indexitem - get the next index tuple from a scan
|
||||
*
|
||||
* Finds the next index tuple satisfying the scan keys. Note that no
|
||||
* time qual (snapshot) check is done; indeed the heap tuple is not accessed.
|
||||
* On success (TRUE return), the found index TID is in scan->currentItemData,
|
||||
* and its heap TID is in scan->xs_ctup.t_self. scan->xs_cbuf is untouched.
|
||||
* ----------------
|
||||
*/
|
||||
bool
|
||||
index_getnext_indexitem(IndexScanDesc scan,
|
||||
ScanDirection direction)
|
||||
{
|
||||
bool found;
|
||||
|
||||
SCAN_CHECKS;
|
||||
|
||||
/*
|
||||
* have the am's gettuple proc do all the work. index_beginscan
|
||||
* already set up fn_getnext.
|
||||
*/
|
||||
result = (RetrieveIndexResult)
|
||||
DatumGetPointer(FunctionCall2(&scan->fn_getnext,
|
||||
PointerGetDatum(scan),
|
||||
Int32GetDatum(direction)));
|
||||
found = DatumGetBool(FunctionCall2(&scan->fn_getnext,
|
||||
PointerGetDatum(scan),
|
||||
Int32GetDatum(direction)));
|
||||
|
||||
if (result != NULL)
|
||||
pgstat_count_index_getnext(&scan->xs_pgstat_info);
|
||||
return result;
|
||||
return found;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
@@ -388,7 +466,7 @@ index_getnext(IndexScanDesc scan,
|
||||
* ----------------
|
||||
*/
|
||||
IndexBulkDeleteResult *
|
||||
index_bulk_delete(Relation relation,
|
||||
index_bulk_delete(Relation indexRelation,
|
||||
IndexBulkDeleteCallback callback,
|
||||
void *callback_state)
|
||||
{
|
||||
@@ -400,7 +478,7 @@ index_bulk_delete(Relation relation,
|
||||
|
||||
result = (IndexBulkDeleteResult *)
|
||||
DatumGetPointer(OidFunctionCall3(procedure,
|
||||
PointerGetDatum(relation),
|
||||
PointerGetDatum(indexRelation),
|
||||
PointerGetDatum((Pointer) callback),
|
||||
PointerGetDatum(callback_state)));
|
||||
|
||||
@@ -418,7 +496,7 @@ index_bulk_delete(Relation relation,
|
||||
* ----------------
|
||||
*/
|
||||
RegProcedure
|
||||
index_cost_estimator(Relation relation)
|
||||
index_cost_estimator(Relation indexRelation)
|
||||
{
|
||||
RegProcedure procedure;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user