diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-04-12 23:14:21 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-04-12 23:14:21 +0000 |
commit | ec498cdcbb7e7b430acc7236ab19ef70f116441a (patch) | |
tree | 48ab9fa79a3b9ac79f58a6079c28328243312f56 /src/backend/access | |
parent | 00832809a0fe271487d6851af72d0d88246a5d94 (diff) | |
download | postgresql-ec498cdcbb7e7b430acc7236ab19ef70f116441a.tar.gz |
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.
Diffstat (limited to 'src/backend/access')
-rw-r--r-- | src/backend/access/heap/tuptoaster.c | 43 | ||||
-rw-r--r-- | src/backend/access/index/genam.c | 86 | ||||
-rw-r--r-- | src/backend/access/index/indexam.c | 48 |
3 files changed, 110 insertions, 67 deletions
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index bd92b9adfb..cf2edbf31e 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -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); diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c index 8877938322..cafb1e6867 100644 --- a/src/backend/access/index/genam.c +++ b/src/backend/access/index/genam.c @@ -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); +} diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index d59f1529db..7a06d0074e 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -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, @@ -635,45 +630,6 @@ index_getnext(IndexScanDesc scan, ScanDirection direction) } /* ---------------- - * 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 * * Adds the TIDs of all heap tuples satisfying the scan keys to a bitmap. |