From ec498cdcbb7e7b430acc7236ab19ef70f116441a Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 12 Apr 2008 23:14:21 +0000 Subject: [PATCH] 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. --- src/backend/access/heap/tuptoaster.c | 43 ++++++----- src/backend/access/index/genam.c | 86 +++++++++++++++++++++- src/backend/access/index/indexam.c | 48 +----------- src/backend/catalog/catalog.c | 27 +++---- src/backend/storage/large_object/inv_api.c | 51 ++++++------- src/backend/utils/cache/ts_cache.c | 11 +-- src/include/access/genam.h | 11 ++- src/include/access/relscan.h | 10 +-- src/include/catalog/catalog.h | 5 +- 9 files changed, 168 insertions(+), 124 deletions(-) diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index bd92b9adfbb..cf2edbf31ee 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 8877938322d..cafb1e6867a 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 d59f1529db1..7a06d0074e8 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, @@ -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 * diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c index b23c8b36ab3..314b75a7b07 100644 --- a/src/backend/catalog/catalog.c +++ b/src/backend/catalog/catalog.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/catalog.c,v 1.74 2008/03/26 16:20:46 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/catalog.c,v 1.75 2008/04/12 23:14:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -312,9 +312,7 @@ IsSharedRelation(Oid relationId) Oid GetNewOid(Relation relation) { - Oid newOid; Oid oidIndex; - Relation indexrel; /* If relation doesn't have OIDs at all, caller is confused */ Assert(relation->rd_rel->relhasoids); @@ -342,11 +340,7 @@ GetNewOid(Relation relation) } /* Otherwise, use the index to find a nonconflicting OID */ - indexrel = index_open(oidIndex, AccessShareLock); - newOid = GetNewOidWithIndex(relation, indexrel); - index_close(indexrel, AccessShareLock); - - return newOid; + return GetNewOidWithIndex(relation, oidIndex, ObjectIdAttributeNumber); } /* @@ -357,16 +351,17 @@ GetNewOid(Relation relation) * an index that will not be recognized by RelationGetOidIndex: TOAST tables * and pg_largeobject have indexes that are usable, but have multiple columns * and are on ordinary columns rather than a true OID column. This code - * will work anyway, so long as the OID is the index's first column. + * will work anyway, so long as the OID is the index's first column. The + * caller must pass in the actual heap attnum of the OID column, however. * * Caller must have a suitable lock on the relation. */ Oid -GetNewOidWithIndex(Relation relation, Relation indexrel) +GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn) { Oid newOid; SnapshotData SnapshotDirty; - IndexScanDesc scan; + SysScanDesc scan; ScanKeyData key; bool collides; @@ -380,17 +375,17 @@ GetNewOidWithIndex(Relation relation, Relation indexrel) newOid = GetNewObjectId(); ScanKeyInit(&key, - (AttrNumber) 1, + oidcolumn, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(newOid)); /* see notes above about using SnapshotDirty */ - scan = index_beginscan(relation, indexrel, - &SnapshotDirty, 1, &key); + scan = systable_beginscan(relation, indexId, true, + &SnapshotDirty, 1, &key); - collides = HeapTupleIsValid(index_getnext(scan, ForwardScanDirection)); + collides = HeapTupleIsValid(systable_getnext(scan)); - index_endscan(scan); + systable_endscan(scan); } while (collides); return newOid; diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index 16ad2b03495..00fbfd89ed6 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -24,7 +24,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.131 2008/03/26 21:10:38 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.132 2008/04/12 23:14:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -201,7 +201,8 @@ inv_create(Oid lobjId) { open_lo_relation(); - lobjId = GetNewOidWithIndex(lo_heap_r, lo_index_r); + lobjId = GetNewOidWithIndex(lo_heap_r, LargeObjectLOidPNIndexId, + Anum_pg_largeobject_loid); } /* @@ -311,7 +312,7 @@ inv_getsize(LargeObjectDesc *obj_desc) bool found = false; uint32 lastbyte = 0; ScanKeyData skey[1]; - IndexScanDesc sd; + SysScanDesc sd; HeapTuple tuple; Assert(PointerIsValid(obj_desc)); @@ -323,8 +324,8 @@ inv_getsize(LargeObjectDesc *obj_desc) BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(obj_desc->id)); - sd = index_beginscan(lo_heap_r, lo_index_r, - obj_desc->snapshot, 1, skey); + sd = systable_beginscan_ordered(lo_heap_r, lo_index_r, + obj_desc->snapshot, 1, skey); /* * Because the pg_largeobject index is on both loid and pageno, but we @@ -332,7 +333,7 @@ inv_getsize(LargeObjectDesc *obj_desc) * large object in reverse pageno order. So, it's sufficient to examine * the first valid tuple (== last valid page). */ - while ((tuple = index_getnext(sd, BackwardScanDirection)) != NULL) + while ((tuple = systable_getnext_ordered(sd, BackwardScanDirection)) != NULL) { Form_pg_largeobject data; bytea *datafield; @@ -356,7 +357,7 @@ inv_getsize(LargeObjectDesc *obj_desc) break; } - index_endscan(sd); + systable_endscan_ordered(sd); if (!found) ereport(ERROR, @@ -415,7 +416,7 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes) int32 pageno = (int32) (obj_desc->offset / LOBLKSIZE); uint32 pageoff; ScanKeyData skey[2]; - IndexScanDesc sd; + SysScanDesc sd; HeapTuple tuple; Assert(PointerIsValid(obj_desc)); @@ -436,10 +437,10 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes) BTGreaterEqualStrategyNumber, F_INT4GE, Int32GetDatum(pageno)); - sd = index_beginscan(lo_heap_r, lo_index_r, - obj_desc->snapshot, 2, skey); + sd = systable_beginscan_ordered(lo_heap_r, lo_index_r, + obj_desc->snapshot, 2, skey); - while ((tuple = index_getnext(sd, ForwardScanDirection)) != NULL) + while ((tuple = systable_getnext_ordered(sd, ForwardScanDirection)) != NULL) { Form_pg_largeobject data; bytea *datafield; @@ -450,7 +451,7 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes) data = (Form_pg_largeobject) GETSTRUCT(tuple); /* - * We assume the indexscan will deliver pages in order. However, + * We expect the indexscan will deliver pages in order. However, * there may be missing pages if the LO contains unwritten "holes". We * want missing sections to read out as zeroes. */ @@ -495,7 +496,7 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes) break; } - index_endscan(sd); + systable_endscan_ordered(sd); return nread; } @@ -509,7 +510,7 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) int len; int32 pageno = (int32) (obj_desc->offset / LOBLKSIZE); ScanKeyData skey[2]; - IndexScanDesc sd; + SysScanDesc sd; HeapTuple oldtuple; Form_pg_largeobject olddata; bool neednextpage; @@ -555,8 +556,8 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) BTGreaterEqualStrategyNumber, F_INT4GE, Int32GetDatum(pageno)); - sd = index_beginscan(lo_heap_r, lo_index_r, - obj_desc->snapshot, 2, skey); + sd = systable_beginscan_ordered(lo_heap_r, lo_index_r, + obj_desc->snapshot, 2, skey); oldtuple = NULL; olddata = NULL; @@ -565,12 +566,12 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) while (nwritten < nbytes) { /* - * If possible, get next pre-existing page of the LO. We assume the + * If possible, get next pre-existing page of the LO. We expect the * indexscan will deliver these in order --- but there may be holes. */ if (neednextpage) { - if ((oldtuple = index_getnext(sd, ForwardScanDirection)) != NULL) + if ((oldtuple = systable_getnext_ordered(sd, ForwardScanDirection)) != NULL) { if (HeapTupleHasNulls(oldtuple)) /* paranoia */ elog(ERROR, "null field found in pg_largeobject"); @@ -685,7 +686,7 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) pageno++; } - index_endscan(sd); + systable_endscan_ordered(sd); CatalogCloseIndexes(indstate); @@ -704,7 +705,7 @@ inv_truncate(LargeObjectDesc *obj_desc, int len) int32 pageno = (int32) (len / LOBLKSIZE); int off; ScanKeyData skey[2]; - IndexScanDesc sd; + SysScanDesc sd; HeapTuple oldtuple; Form_pg_largeobject olddata; struct @@ -743,15 +744,15 @@ inv_truncate(LargeObjectDesc *obj_desc, int len) BTGreaterEqualStrategyNumber, F_INT4GE, Int32GetDatum(pageno)); - sd = index_beginscan(lo_heap_r, lo_index_r, - obj_desc->snapshot, 2, skey); + sd = systable_beginscan_ordered(lo_heap_r, lo_index_r, + obj_desc->snapshot, 2, skey); /* * If possible, get the page the truncation point is in. The truncation * point may be beyond the end of the LO or in a hole. */ olddata = NULL; - if ((oldtuple = index_getnext(sd, ForwardScanDirection)) != NULL) + if ((oldtuple = systable_getnext_ordered(sd, ForwardScanDirection)) != NULL) { if (HeapTupleHasNulls(oldtuple)) /* paranoia */ elog(ERROR, "null field found in pg_largeobject"); @@ -846,12 +847,12 @@ inv_truncate(LargeObjectDesc *obj_desc, int len) /* * Delete any pages after the truncation point */ - while ((oldtuple = index_getnext(sd, ForwardScanDirection)) != NULL) + while ((oldtuple = systable_getnext_ordered(sd, ForwardScanDirection)) != NULL) { simple_heap_delete(lo_heap_r, &oldtuple->t_self); } - index_endscan(sd); + systable_endscan_ordered(sd); CatalogCloseIndexes(indstate); diff --git a/src/backend/utils/cache/ts_cache.c b/src/backend/utils/cache/ts_cache.c index 08ae22528a4..81ff577125e 100644 --- a/src/backend/utils/cache/ts_cache.c +++ b/src/backend/utils/cache/ts_cache.c @@ -20,7 +20,7 @@ * Copyright (c) 2006-2008, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/ts_cache.c,v 1.6 2008/03/26 21:10:39 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/ts_cache.c,v 1.7 2008/04/12 23:14:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -419,7 +419,7 @@ lookup_ts_config_cache(Oid cfgId) Relation maprel; Relation mapidx; ScanKeyData mapskey; - IndexScanDesc mapscan; + SysScanDesc mapscan; HeapTuple maptup; ListDictionary maplists[MAXTOKENTYPE + 1]; Oid mapdicts[MAXDICTSPERTT]; @@ -488,9 +488,10 @@ lookup_ts_config_cache(Oid cfgId) maprel = heap_open(TSConfigMapRelationId, AccessShareLock); mapidx = index_open(TSConfigMapIndexId, AccessShareLock); - mapscan = index_beginscan(maprel, mapidx, SnapshotNow, 1, &mapskey); + mapscan = systable_beginscan_ordered(maprel, mapidx, + SnapshotNow, 1, &mapskey); - while ((maptup = index_getnext(mapscan, ForwardScanDirection)) != NULL) + while ((maptup = systable_getnext_ordered(mapscan, ForwardScanDirection)) != NULL) { Form_pg_ts_config_map cfgmap = (Form_pg_ts_config_map) GETSTRUCT(maptup); int toktype = cfgmap->maptokentype; @@ -524,7 +525,7 @@ lookup_ts_config_cache(Oid cfgId) } } - index_endscan(mapscan); + systable_endscan_ordered(mapscan); index_close(mapidx, AccessShareLock); heap_close(maprel, AccessShareLock); diff --git a/src/include/access/genam.h b/src/include/access/genam.h index 57785913394..51ce6057665 100644 --- a/src/include/access/genam.h +++ b/src/include/access/genam.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.70 2008/04/10 22:25:25 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.71 2008/04/12 23:14:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -108,8 +108,6 @@ extern void index_endscan(IndexScanDesc scan); extern void index_markpos(IndexScanDesc scan); extern void index_restrpos(IndexScanDesc scan); extern HeapTuple index_getnext(IndexScanDesc scan, ScanDirection direction); -extern bool index_getnext_indexitem(IndexScanDesc scan, - ScanDirection direction); extern int64 index_getbitmap(IndexScanDesc scan, TIDBitmap *bitmap); extern IndexBulkDeleteResult *index_bulk_delete(IndexVacuumInfo *info, @@ -140,5 +138,12 @@ extern SysScanDesc systable_beginscan(Relation heapRelation, int nkeys, ScanKey key); extern HeapTuple systable_getnext(SysScanDesc sysscan); extern void systable_endscan(SysScanDesc sysscan); +extern SysScanDesc systable_beginscan_ordered(Relation heapRelation, + Relation indexRelation, + Snapshot snapshot, + int nkeys, ScanKey key); +extern HeapTuple systable_getnext_ordered(SysScanDesc sysscan, + ScanDirection direction); +extern void systable_endscan_ordered(SysScanDesc sysscan); #endif /* GENAM_H */ diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h index 677fd04e2c2..637b363f528 100644 --- a/src/include/access/relscan.h +++ b/src/include/access/relscan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.62 2008/04/10 22:25:25 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.63 2008/04/12 23:14:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -76,14 +76,12 @@ typedef struct IndexScanDescData /* index access method's private state */ void *opaque; /* access-method-specific info */ - /* - * xs_ctup/xs_cbuf are valid after a successful index_getnext. After - * index_getnext_indexitem, xs_ctup.t_self contains the heap tuple TID - * from the index entry, but its other fields are not valid. - */ + /* xs_ctup/xs_cbuf are valid after a successful index_getnext */ HeapTupleData xs_ctup; /* current heap tuple, if any */ Buffer xs_cbuf; /* current heap buffer in scan, if any */ /* NB: if xs_cbuf is not InvalidBuffer, we hold a pin on that buffer */ + + /* state data for traversing HOT chains in index_getnext */ TransactionId xs_prev_xmax; /* previous HOT chain member's XMAX, if any */ OffsetNumber xs_next_hot; /* next member of HOT chain, if any */ bool xs_hot_dead; /* T if all members of HOT chain are dead */ diff --git a/src/include/catalog/catalog.h b/src/include/catalog/catalog.h index 8ab902563e9..753926f14ea 100644 --- a/src/include/catalog/catalog.h +++ b/src/include/catalog/catalog.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catalog.h,v 1.38 2008/01/01 19:45:56 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catalog.h,v 1.39 2008/04/12 23:14:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,7 +34,8 @@ extern bool IsReservedName(const char *name); extern bool IsSharedRelation(Oid relationId); extern Oid GetNewOid(Relation relation); -extern Oid GetNewOidWithIndex(Relation relation, Relation indexrel); +extern Oid GetNewOidWithIndex(Relation relation, Oid indexId, + AttrNumber oidcolumn); extern Oid GetNewRelFileNode(Oid reltablespace, bool relisshared, Relation pg_class);