mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Create new routines systable_beginscan_ordered, systable_getnext_ordered,
systable_endscan_ordered that have API similar to systable_beginscan etc (in particular, the passed-in scankeys have heap not index attnums), but guarantee ordered output, unlike the existing functions. For the moment these are just very thin wrappers around index_beginscan/index_getnext/etc. Someday they might need to get smarter; but for now this is just a code refactoring exercise to reduce the number of direct callers of index_getnext, in preparation for changing that function's API. In passing, remove index_getnext_indexitem, which has been dead code for quite some time, and will have even less use than that in the presence of run-time-lossy indexes.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.85 2008/03/26 21:10:37 alvherre Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.86 2008/04/12 23:14:21 tgl Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@@ -1184,7 +1184,9 @@ toast_save_datum(Relation rel, Datum value,
|
||||
toast_pointer.va_extsize = data_todo;
|
||||
}
|
||||
|
||||
toast_pointer.va_valueid = GetNewOidWithIndex(toastrel, toastidx);
|
||||
toast_pointer.va_valueid = GetNewOidWithIndex(toastrel,
|
||||
RelationGetRelid(toastidx),
|
||||
(AttrNumber) 1);
|
||||
toast_pointer.va_toastrelid = rel->rd_rel->reltoastrelid;
|
||||
|
||||
/*
|
||||
@@ -1273,7 +1275,7 @@ toast_delete_datum(Relation rel, Datum value)
|
||||
Relation toastrel;
|
||||
Relation toastidx;
|
||||
ScanKeyData toastkey;
|
||||
IndexScanDesc toastscan;
|
||||
SysScanDesc toastscan;
|
||||
HeapTuple toasttup;
|
||||
|
||||
if (!VARATT_IS_EXTERNAL(attr))
|
||||
@@ -1289,8 +1291,7 @@ toast_delete_datum(Relation rel, Datum value)
|
||||
toastidx = index_open(toastrel->rd_rel->reltoastidxid, RowExclusiveLock);
|
||||
|
||||
/*
|
||||
* Setup a scan key to fetch from the index by va_valueid (we don't
|
||||
* particularly care whether we see them in sequence or not)
|
||||
* Setup a scan key to find chunks with matching va_valueid
|
||||
*/
|
||||
ScanKeyInit(&toastkey,
|
||||
(AttrNumber) 1,
|
||||
@@ -1298,11 +1299,13 @@ toast_delete_datum(Relation rel, Datum value)
|
||||
ObjectIdGetDatum(toast_pointer.va_valueid));
|
||||
|
||||
/*
|
||||
* Find the chunks by index
|
||||
* Find all the chunks. (We don't actually care whether we see them in
|
||||
* sequence or not, but since we've already locked the index we might
|
||||
* as well use systable_beginscan_ordered.)
|
||||
*/
|
||||
toastscan = index_beginscan(toastrel, toastidx,
|
||||
SnapshotToast, 1, &toastkey);
|
||||
while ((toasttup = index_getnext(toastscan, ForwardScanDirection)) != NULL)
|
||||
toastscan = systable_beginscan_ordered(toastrel, toastidx,
|
||||
SnapshotToast, 1, &toastkey);
|
||||
while ((toasttup = systable_getnext_ordered(toastscan, ForwardScanDirection)) != NULL)
|
||||
{
|
||||
/*
|
||||
* Have a chunk, delete it
|
||||
@@ -1313,7 +1316,7 @@ toast_delete_datum(Relation rel, Datum value)
|
||||
/*
|
||||
* End scan and close relations
|
||||
*/
|
||||
index_endscan(toastscan);
|
||||
systable_endscan_ordered(toastscan);
|
||||
index_close(toastidx, RowExclusiveLock);
|
||||
heap_close(toastrel, RowExclusiveLock);
|
||||
}
|
||||
@@ -1332,7 +1335,7 @@ toast_fetch_datum(struct varlena * attr)
|
||||
Relation toastrel;
|
||||
Relation toastidx;
|
||||
ScanKeyData toastkey;
|
||||
IndexScanDesc toastscan;
|
||||
SysScanDesc toastscan;
|
||||
HeapTuple ttup;
|
||||
TupleDesc toasttupDesc;
|
||||
struct varlena *result;
|
||||
@@ -1383,9 +1386,9 @@ toast_fetch_datum(struct varlena * attr)
|
||||
*/
|
||||
nextidx = 0;
|
||||
|
||||
toastscan = index_beginscan(toastrel, toastidx,
|
||||
SnapshotToast, 1, &toastkey);
|
||||
while ((ttup = index_getnext(toastscan, ForwardScanDirection)) != NULL)
|
||||
toastscan = systable_beginscan_ordered(toastrel, toastidx,
|
||||
SnapshotToast, 1, &toastkey);
|
||||
while ((ttup = systable_getnext_ordered(toastscan, ForwardScanDirection)) != NULL)
|
||||
{
|
||||
/*
|
||||
* Have a chunk, extract the sequence number and the data
|
||||
@@ -1464,7 +1467,7 @@ toast_fetch_datum(struct varlena * attr)
|
||||
/*
|
||||
* End scan and close relations
|
||||
*/
|
||||
index_endscan(toastscan);
|
||||
systable_endscan_ordered(toastscan);
|
||||
index_close(toastidx, AccessShareLock);
|
||||
heap_close(toastrel, AccessShareLock);
|
||||
|
||||
@@ -1485,7 +1488,7 @@ toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length)
|
||||
Relation toastidx;
|
||||
ScanKeyData toastkey[3];
|
||||
int nscankeys;
|
||||
IndexScanDesc toastscan;
|
||||
SysScanDesc toastscan;
|
||||
HeapTuple ttup;
|
||||
TupleDesc toasttupDesc;
|
||||
struct varlena *result;
|
||||
@@ -1592,9 +1595,9 @@ toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length)
|
||||
* The index is on (valueid, chunkidx) so they will come in order
|
||||
*/
|
||||
nextidx = startchunk;
|
||||
toastscan = index_beginscan(toastrel, toastidx,
|
||||
SnapshotToast, nscankeys, toastkey);
|
||||
while ((ttup = index_getnext(toastscan, ForwardScanDirection)) != NULL)
|
||||
toastscan = systable_beginscan_ordered(toastrel, toastidx,
|
||||
SnapshotToast, nscankeys, toastkey);
|
||||
while ((ttup = systable_getnext_ordered(toastscan, ForwardScanDirection)) != NULL)
|
||||
{
|
||||
/*
|
||||
* Have a chunk, extract the sequence number and the data
|
||||
@@ -1681,7 +1684,7 @@ toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length)
|
||||
/*
|
||||
* End scan and close relations
|
||||
*/
|
||||
index_endscan(toastscan);
|
||||
systable_endscan_ordered(toastscan);
|
||||
index_close(toastidx, AccessShareLock);
|
||||
heap_close(toastrel, AccessShareLock);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.66 2008/04/10 22:25:25 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.67 2008/04/12 23:14:21 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* many of the old access method routines have been turned into
|
||||
@@ -258,3 +258,87 @@ systable_endscan(SysScanDesc sysscan)
|
||||
|
||||
pfree(sysscan);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* systable_beginscan_ordered --- set up for ordered catalog scan
|
||||
*
|
||||
* These routines have essentially the same API as systable_beginscan etc,
|
||||
* except that they guarantee to return multiple matching tuples in
|
||||
* index order. Also, for largely historical reasons, the index to use
|
||||
* is opened and locked by the caller, not here.
|
||||
*
|
||||
* Currently we do not support non-index-based scans here. (In principle
|
||||
* we could do a heapscan and sort, but the uses are in places that
|
||||
* probably don't need to still work with corrupted catalog indexes.)
|
||||
* For the moment, therefore, these functions are merely the thinnest of
|
||||
* wrappers around index_beginscan/index_getnext. The main reason for their
|
||||
* existence is to centralize possible future support of lossy operators
|
||||
* in catalog scans.
|
||||
*/
|
||||
SysScanDesc
|
||||
systable_beginscan_ordered(Relation heapRelation,
|
||||
Relation indexRelation,
|
||||
Snapshot snapshot,
|
||||
int nkeys, ScanKey key)
|
||||
{
|
||||
SysScanDesc sysscan;
|
||||
int i;
|
||||
|
||||
/* REINDEX can probably be a hard error here ... */
|
||||
if (ReindexIsProcessingIndex(RelationGetRelid(indexRelation)))
|
||||
elog(ERROR, "cannot do ordered scan on index \"%s\", because it is the current REINDEX target",
|
||||
RelationGetRelationName(indexRelation));
|
||||
/* ... but we only throw a warning about violating IgnoreSystemIndexes */
|
||||
if (IgnoreSystemIndexes)
|
||||
elog(WARNING, "using index \"%s\" despite IgnoreSystemIndexes",
|
||||
RelationGetRelationName(indexRelation));
|
||||
|
||||
sysscan = (SysScanDesc) palloc(sizeof(SysScanDescData));
|
||||
|
||||
sysscan->heap_rel = heapRelation;
|
||||
sysscan->irel = indexRelation;
|
||||
|
||||
/*
|
||||
* Change attribute numbers to be index column numbers.
|
||||
*
|
||||
* This code could be generalized to search for the index key numbers
|
||||
* to substitute, but for now there's no need.
|
||||
*/
|
||||
for (i = 0; i < nkeys; i++)
|
||||
{
|
||||
Assert(key[i].sk_attno == indexRelation->rd_index->indkey.values[i]);
|
||||
key[i].sk_attno = i + 1;
|
||||
}
|
||||
|
||||
sysscan->iscan = index_beginscan(heapRelation, indexRelation,
|
||||
snapshot, nkeys, key);
|
||||
sysscan->scan = NULL;
|
||||
|
||||
return sysscan;
|
||||
}
|
||||
|
||||
/*
|
||||
* systable_getnext_ordered --- get next tuple in an ordered catalog scan
|
||||
*/
|
||||
HeapTuple
|
||||
systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
|
||||
{
|
||||
HeapTuple htup;
|
||||
|
||||
Assert(sysscan->irel);
|
||||
htup = index_getnext(sysscan->iscan, direction);
|
||||
|
||||
return htup;
|
||||
}
|
||||
|
||||
/*
|
||||
* systable_endscan_ordered --- close scan, release resources
|
||||
*/
|
||||
void
|
||||
systable_endscan_ordered(SysScanDesc sysscan)
|
||||
{
|
||||
Assert(sysscan->irel);
|
||||
index_endscan(sysscan->iscan);
|
||||
pfree(sysscan);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.105 2008/04/10 22:25:25 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.106 2008/04/12 23:14:21 tgl Exp $
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
* index_open - open an index relation by relation OID
|
||||
@@ -206,12 +206,7 @@ index_insert(Relation indexRelation,
|
||||
/*
|
||||
* index_beginscan - start a scan of an index with amgettuple
|
||||
*
|
||||
* 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. Caller must also
|
||||
* be holding a lock on the index.
|
||||
* Caller must be holding suitable locks on the heap and the index.
|
||||
*/
|
||||
IndexScanDesc
|
||||
index_beginscan(Relation heapRelation,
|
||||
@@ -634,45 +629,6 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
|
||||
return NULL; /* failure exit */
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* index_getnext_indexitem - get the next index tuple from a scan
|
||||
*
|
||||
* Finds the next index tuple satisfying the scan keys. Note that the
|
||||
* corresponding heap tuple is not accessed, and thus no time qual (snapshot)
|
||||
* check is done, other than the index AM's internal check for killed tuples
|
||||
* (which most callers of this routine will probably want to suppress by
|
||||
* setting scan->ignore_killed_tuples = false).
|
||||
*
|
||||
* On success (TRUE return), the heap TID of the found index entry is in
|
||||
* scan->xs_ctup.t_self. scan->xs_cbuf is untouched.
|
||||
* ----------------
|
||||
*/
|
||||
bool
|
||||
index_getnext_indexitem(IndexScanDesc scan,
|
||||
ScanDirection direction)
|
||||
{
|
||||
FmgrInfo *procedure;
|
||||
bool found;
|
||||
|
||||
SCAN_CHECKS;
|
||||
GET_SCAN_PROCEDURE(amgettuple);
|
||||
|
||||
/* just make sure this is false... */
|
||||
scan->kill_prior_tuple = false;
|
||||
|
||||
/*
|
||||
* have the am's gettuple proc do all the work.
|
||||
*/
|
||||
found = DatumGetBool(FunctionCall2(procedure,
|
||||
PointerGetDatum(scan),
|
||||
Int32GetDatum(direction)));
|
||||
|
||||
if (found)
|
||||
pgstat_count_index_tuples(scan->indexRelation, 1);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* index_getbitmap - get all tuples at once from an index scan
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user