Create new routines systable_beginscan_ordered, systable_getnext_ordered,
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 12 Apr 2008 23:14:21 +0000 (23:14 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 12 Apr 2008 23:14:21 +0000 (23:14 +0000)
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
src/backend/access/index/genam.c
src/backend/access/index/indexam.c
src/backend/catalog/catalog.c
src/backend/storage/large_object/inv_api.c
src/backend/utils/cache/ts_cache.c
src/include/access/genam.h
src/include/access/relscan.h
src/include/catalog/catalog.h

index 20f047989ca335fb57e90bbb9e8ae68ba1dc1584..6400b002312db692c557507c13ae65b129de3b1f 100644 (file)
@@ -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);
 
index 3cccd1e783b91f6b63c98bd47a922bca78aaf2fb..d0cc53e4cbee6e7cbd9587d79d27d6a67acd0853 100644 (file)
@@ -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);
+}
index 754f8eaabbb46928820f3a1f3f82c91be89d0a6a..13c4f63465ece4bbe9a0b6900d10a1985f2a7eca 100644 (file)
@@ -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
  *
index 32a1a8b2a93bcc4b0e2ca1ba3ebf474d29890f50..cd0d9e232cd53561eb45ba9aaabae50f04f26cfb 100644 (file)
@@ -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;
index 51946a33e1244cd3b260dea09a581d2c03707b53..20d2138bd98d9e84340f1ff111c15b7a29246ea8 100644 (file)
@@ -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);
 
index b18c19db1168456dc8f214f95e049d58a604cb0b..47925a1308076abab22b395eba60b2029aaa4bb2 100644 (file)
@@ -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);
 
index bbf4ab5809446a4cff8cbd82bb918b3dcb9872e3..b07993bfe899868ef35bf3c71c7c03ba4fff4e24 100644 (file)
@@ -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 */
index b516adf21f031c3f426cd80628a6d7148ea10904..f4a05af1d087b9441fe8c5debcbd8879fedffde6 100644 (file)
@@ -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 */
index 58c6601af6e482c60114bcfc9f03b902aca32305..1510ccc00f6731906b3952590f809dae26c6fe08 100644 (file)
@@ -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);