diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 68fd2a797e48db9c5a951d1e5c25613d388cc634..8201f8815aebea335d4df69351e5e40a6eac526b 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -922,10 +922,9 @@ get_pkey_attnames(Oid relid, int16 *numatts)
 	indexRelation = heap_openr(IndexRelationName, AccessShareLock);
 	ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid,
 						   F_OIDEQ, ObjectIdGetDatum(relid));
-	scan = heap_beginscan(indexRelation, false, SnapshotNow,
-						  1, &entry);
+	scan = heap_beginscan(indexRelation, SnapshotNow, 1, &entry);
 
-	while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
+	while ((indexTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_index	index = (Form_pg_index) GETSTRUCT(indexTuple);
 
diff --git a/contrib/dbsize/dbsize.c b/contrib/dbsize/dbsize.c
index d85822914dfda0f6743a339cc23e0d4b54612ec8..b072a86912f484d9602f2934fe72409d6200076c 100644
--- a/contrib/dbsize/dbsize.c
+++ b/contrib/dbsize/dbsize.c
@@ -59,8 +59,8 @@ database_size(PG_FUNCTION_ARGS)
 	relation = heap_openr(DatabaseRelationName, AccessShareLock);
 	ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
 						   F_NAMEEQ, NameGetDatum(dbname));
-	scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scanKey);
-	tuple = heap_getnext(scan, 0);
+	scan = heap_beginscan(relation, SnapshotNow, 1, &scanKey);
+	tuple = heap_getnext(scan, ForwardScanDirection);
 
 	if (!HeapTupleIsValid(tuple))
 		elog(ERROR, "database %s does not exist", NameStr(*dbname));
diff --git a/contrib/miscutil/misc_utils.c b/contrib/miscutil/misc_utils.c
index d3133929657b3c3290efacf18b5da7e1540337c0..26bbabe46f7037222d8adc55e86ce849f5c85024 100644
--- a/contrib/miscutil/misc_utils.c
+++ b/contrib/miscutil/misc_utils.c
@@ -93,12 +93,12 @@ active_listeners(text *relname)
 							   Anum_pg_listener_relname,
 							   F_NAMEEQ,
 							   PointerGetDatum(listen_name));
-		sRel = heap_beginscan(lRel, 0, SnapshotNow, 1, &key);
+		sRel = heap_beginscan(lRel, SnapshotNow, 1, &key);
 	}
 	else
-		sRel = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
+		sRel = heap_beginscan(lRel, SnapshotNow, 0, (ScanKey) NULL);
 
-	while (HeapTupleIsValid(lTuple = heap_getnext(sRel, 0)))
+	while ((lTuple = heap_getnext(sRel, ForwardScanDirection)) != NULL)
 	{
 		d = heap_getattr(lTuple, Anum_pg_listener_pid, tdesc, &isnull);
 		pid = DatumGetInt32(d);
@@ -111,14 +111,3 @@ active_listeners(text *relname)
 
 	return count;
 }
-
-
-/* end of file */
-
-/*
- * Local Variables:
- *	tab-width: 4
- *	c-indent-level: 4
- *	c-basic-offset: 4
- * End:
- */
diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c
index 39bd5d1f95e0b556159905e13688a1ea6ebb93b5..498f82095256043a352871bf6ebf6b3564c6588e 100644
--- a/contrib/pgstattuple/pgstattuple.c
+++ b/contrib/pgstattuple/pgstattuple.c
@@ -1,5 +1,5 @@
 /*
- * $Header: /cvsroot/pgsql/contrib/pgstattuple/pgstattuple.c,v 1.5 2002/03/30 01:02:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/contrib/pgstattuple/pgstattuple.c,v 1.6 2002/05/20 23:51:40 tgl Exp $
  *
  * Copyright (c) 2001  Tatsuo Ishii
  *
@@ -70,9 +70,9 @@ pgstattuple(PG_FUNCTION_ARGS)
 	rel = heap_openrv(relrv, AccessShareLock);
 
 	nblocks = RelationGetNumberOfBlocks(rel);
-	scan = heap_beginscan(rel, false, SnapshotAny, 0, NULL);
+	scan = heap_beginscan(rel, SnapshotAny, 0, NULL);
 
-	while ((tuple = heap_getnext(scan, 0)))
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		if (HeapTupleSatisfiesNow(tuple->t_data))
 		{
diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c
index ad6e7cc4e5b87ab8970ac4409b2c1c9b29034c1c..eab57302d2d729e98099b1431aa9acab2ed7f4bb 100644
--- a/src/backend/access/common/indextuple.c
+++ b/src/backend/access/common/indextuple.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.55 2001/10/25 05:49:20 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.56 2002/05/20 23:51:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -398,23 +398,6 @@ nocache_index_getattr(IndexTuple tup,
 	}
 }
 
-RetrieveIndexResult
-FormRetrieveIndexResult(ItemPointer indexItemPointer,
-						ItemPointer heapItemPointer)
-{
-	RetrieveIndexResult result;
-
-	Assert(ItemPointerIsValid(indexItemPointer));
-	Assert(ItemPointerIsValid(heapItemPointer));
-
-	result = (RetrieveIndexResult) palloc(sizeof *result);
-
-	result->index_iptr = *indexItemPointer;
-	result->heap_iptr = *heapItemPointer;
-
-	return result;
-}
-
 /*
  * Copies source into target.  If *target == NULL, we palloc space; otherwise
  * we assume we have space that is already palloc'ed.
@@ -423,12 +406,10 @@ void
 CopyIndexTuple(IndexTuple source, IndexTuple *target)
 {
 	Size		size;
-	IndexTuple	ret;
 
 	size = IndexTupleSize(source);
 	if (*target == NULL)
 		*target = (IndexTuple) palloc(size);
 
-	ret = *target;
-	memmove((char *) ret, (char *) source, size);
+	memmove((char *) *target, (char *) source, size);
 }
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 34013f468892b8117f03ea132eb87ae0182814fb..1da836a364842f7124b9352e5eb77821ede3d474 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.91 2002/03/06 06:09:15 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.92 2002/05/20 23:51:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1590,7 +1590,6 @@ gistbulkdelete(PG_FUNCTION_ARGS)
 	BlockNumber num_pages;
 	double		tuples_removed;
 	double		num_index_tuples;
-	RetrieveIndexResult res;
 	IndexScanDesc iscan;
 
 	tuples_removed = 0;
@@ -1607,23 +1606,20 @@ gistbulkdelete(PG_FUNCTION_ARGS)
 	 */
 
 	/* walk through the entire index */
-	iscan = index_beginscan(rel, false, 0, (ScanKey) NULL);
+	iscan = index_beginscan(NULL, rel, SnapshotAny, 0, (ScanKey) NULL);
 
-	while ((res = index_getnext(iscan, ForwardScanDirection))
-		   != (RetrieveIndexResult) NULL)
+	while (index_getnext_indexitem(iscan, ForwardScanDirection))
 	{
-		ItemPointer heapptr = &res->heap_iptr;
-
-		if (callback(heapptr, callback_state))
+		if (callback(&iscan->xs_ctup.t_self, callback_state))
 		{
-			ItemPointer indexptr = &res->index_iptr;
+			ItemPointerData indextup = iscan->currentItemData;
 			BlockNumber blkno;
 			OffsetNumber offnum;
 			Buffer		buf;
 			Page		page;
 
-			blkno = ItemPointerGetBlockNumber(indexptr);
-			offnum = ItemPointerGetOffsetNumber(indexptr);
+			blkno = ItemPointerGetBlockNumber(&indextup);
+			offnum = ItemPointerGetOffsetNumber(&indextup);
 
 			/* adjust any scans that will be affected by this deletion */
 			gistadjscans(rel, GISTOP_DEL, blkno, offnum);
@@ -1640,8 +1636,6 @@ gistbulkdelete(PG_FUNCTION_ARGS)
 		}
 		else
 			num_index_tuples += 1;
-
-		pfree(res);
 	}
 
 	index_endscan(iscan);
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index 826644288a27fef372750ca304ae5aa3fa8f74e0..96d2e5bc4e32518b3b70a27b014b2f28f7295b85 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/gist/gistget.c,v 1.32 2002/03/05 05:30:31 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/gist/gistget.c,v 1.33 2002/05/20 23:51:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,10 +20,9 @@
 
 static OffsetNumber gistfindnext(IndexScanDesc s, Page p, OffsetNumber n,
 			 ScanDirection dir);
-static RetrieveIndexResult gistscancache(IndexScanDesc s, ScanDirection dir);
-static RetrieveIndexResult gistfirst(IndexScanDesc s, ScanDirection dir);
-static RetrieveIndexResult gistnext(IndexScanDesc s, ScanDirection dir);
-static ItemPointer gistheapptr(Relation r, ItemPointer itemp);
+static bool gistscancache(IndexScanDesc s, ScanDirection dir);
+static bool gistfirst(IndexScanDesc s, ScanDirection dir);
+static bool gistnext(IndexScanDesc s, ScanDirection dir);
 static bool gistindex_keytest(IndexTuple tuple,
 				  int scanKeySize, ScanKey key, GISTSTATE *giststate,
 				  Relation r, Page p, OffsetNumber offset);
@@ -34,35 +33,34 @@ gistgettuple(PG_FUNCTION_ARGS)
 {
 	IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
 	ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1);
-	RetrieveIndexResult res;
+	bool res;
 
 	/* if we have it cached in the scan desc, just return the value */
-	if ((res = gistscancache(s, dir)) != (RetrieveIndexResult) NULL)
-		PG_RETURN_POINTER(res);
+	if (gistscancache(s, dir))
+		PG_RETURN_BOOL(true);
 
 	/* not cached, so we'll have to do some work */
 	if (ItemPointerIsValid(&(s->currentItemData)))
 		res = gistnext(s, dir);
 	else
 		res = gistfirst(s, dir);
-	PG_RETURN_POINTER(res);
+	PG_RETURN_BOOL(res);
 }
 
-static RetrieveIndexResult
+static bool
 gistfirst(IndexScanDesc s, ScanDirection dir)
 {
 	Buffer		b;
 	Page		p;
 	OffsetNumber n;
 	OffsetNumber maxoff;
-	RetrieveIndexResult res;
 	GISTPageOpaque po;
 	GISTScanOpaque so;
 	GISTSTACK  *stk;
 	BlockNumber blk;
 	IndexTuple	it;
 
-	b = ReadBuffer(s->relation, GISTP_ROOT);
+	b = ReadBuffer(s->indexRelation, GISTP_ROOT);
 	p = BufferGetPage(b);
 	po = (GISTPageOpaque) PageGetSpecialPointer(p);
 	so = (GISTScanOpaque) s->opaque;
@@ -77,13 +75,12 @@ gistfirst(IndexScanDesc s, ScanDirection dir)
 
 		while (n < FirstOffsetNumber || n > maxoff)
 		{
-
 			ReleaseBuffer(b);
 			if (so->s_stack == (GISTSTACK *) NULL)
-				return (RetrieveIndexResult) NULL;
+				return false;
 
 			stk = so->s_stack;
-			b = ReadBuffer(s->relation, stk->gs_blk);
+			b = ReadBuffer(s->indexRelation, stk->gs_blk);
 			p = BufferGetPage(b);
 			po = (GISTPageOpaque) PageGetSpecialPointer(p);
 			maxoff = PageGetMaxOffsetNumber(p);
@@ -103,10 +100,10 @@ gistfirst(IndexScanDesc s, ScanDirection dir)
 
 			it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
 
-			res = FormRetrieveIndexResult(&(s->currentItemData), &(it->t_tid));
+			s->xs_ctup.t_self = it->t_tid;
 
 			ReleaseBuffer(b);
-			return res;
+			return true;
 		}
 		else
 		{
@@ -120,21 +117,20 @@ gistfirst(IndexScanDesc s, ScanDirection dir)
 			blk = ItemPointerGetBlockNumber(&(it->t_tid));
 
 			ReleaseBuffer(b);
-			b = ReadBuffer(s->relation, blk);
+			b = ReadBuffer(s->indexRelation, blk);
 			p = BufferGetPage(b);
 			po = (GISTPageOpaque) PageGetSpecialPointer(p);
 		}
 	}
 }
 
-static RetrieveIndexResult
+static bool
 gistnext(IndexScanDesc s, ScanDirection dir)
 {
 	Buffer		b;
 	Page		p;
 	OffsetNumber n;
 	OffsetNumber maxoff;
-	RetrieveIndexResult res;
 	GISTPageOpaque po;
 	GISTScanOpaque so;
 	GISTSTACK  *stk;
@@ -149,7 +145,7 @@ gistnext(IndexScanDesc s, ScanDirection dir)
 	else
 		n = OffsetNumberPrev(n);
 
-	b = ReadBuffer(s->relation, blk);
+	b = ReadBuffer(s->indexRelation, blk);
 	p = BufferGetPage(b);
 	po = (GISTPageOpaque) PageGetSpecialPointer(p);
 	so = (GISTScanOpaque) s->opaque;
@@ -161,13 +157,12 @@ gistnext(IndexScanDesc s, ScanDirection dir)
 
 		while (n < FirstOffsetNumber || n > maxoff)
 		{
-
 			ReleaseBuffer(b);
 			if (so->s_stack == (GISTSTACK *) NULL)
-				return (RetrieveIndexResult) NULL;
+				return false;
 
 			stk = so->s_stack;
-			b = ReadBuffer(s->relation, stk->gs_blk);
+			b = ReadBuffer(s->indexRelation, stk->gs_blk);
 			p = BufferGetPage(b);
 			maxoff = PageGetMaxOffsetNumber(p);
 			po = (GISTPageOpaque) PageGetSpecialPointer(p);
@@ -187,10 +182,10 @@ gistnext(IndexScanDesc s, ScanDirection dir)
 
 			it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
 
-			res = FormRetrieveIndexResult(&(s->currentItemData), &(it->t_tid));
+			s->xs_ctup.t_self = it->t_tid;
 
 			ReleaseBuffer(b);
-			return res;
+			return true;
 		}
 		else
 		{
@@ -204,7 +199,7 @@ gistnext(IndexScanDesc s, ScanDirection dir)
 			blk = ItemPointerGetBlockNumber(&(it->t_tid));
 
 			ReleaseBuffer(b);
-			b = ReadBuffer(s->relation, blk);
+			b = ReadBuffer(s->indexRelation, blk);
 			p = BufferGetPage(b);
 			po = (GISTPageOpaque) PageGetSpecialPointer(p);
 
@@ -233,7 +228,6 @@ gistindex_keytest(IndexTuple tuple,
 
 	IncrIndexProcessed();
 
-
 	while (scanKeySize > 0)
 	{
 		datum = index_getattr(tuple,
@@ -314,7 +308,7 @@ gistfindnext(IndexScanDesc s, Page p, OffsetNumber n, ScanDirection dir)
 		it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
 		if (gistindex_keytest(it,
 							  s->numberOfKeys, s->keyData, giststate,
-							  s->relation, p, n))
+							  s->indexRelation, p, n))
 			break;
 
 		if (ScanDirectionIsBackward(dir))
@@ -326,57 +320,25 @@ gistfindnext(IndexScanDesc s, Page p, OffsetNumber n, ScanDirection dir)
 	return n;
 }
 
-static RetrieveIndexResult
+static bool
 gistscancache(IndexScanDesc s, ScanDirection dir)
-{
-	RetrieveIndexResult res;
-	ItemPointer ip;
-
-	if (!(ScanDirectionIsNoMovement(dir)
-		  && ItemPointerIsValid(&(s->currentItemData))))
-	{
-
-		return (RetrieveIndexResult) NULL;
-	}
-
-	ip = gistheapptr(s->relation, &(s->currentItemData));
-
-	if (ItemPointerIsValid(ip))
-		res = FormRetrieveIndexResult(&(s->currentItemData), ip);
-	else
-		res = (RetrieveIndexResult) NULL;
-
-	pfree(ip);
-
-	return res;
-}
-
-/*
- *	gistheapptr returns the item pointer to the tuple in the heap relation
- *	for which itemp is the index relation item pointer.
- */
-static ItemPointer
-gistheapptr(Relation r, ItemPointer itemp)
 {
 	Buffer		b;
 	Page		p;
-	IndexTuple	it;
-	ItemPointer ip;
 	OffsetNumber n;
+	IndexTuple	it;
 
-	ip = (ItemPointer) palloc(sizeof(ItemPointerData));
-	if (ItemPointerIsValid(itemp))
-	{
-		b = ReadBuffer(r, ItemPointerGetBlockNumber(itemp));
-		p = BufferGetPage(b);
-		n = ItemPointerGetOffsetNumber(itemp);
-		it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
-		memmove((char *) ip, (char *) &(it->t_tid),
-				sizeof(ItemPointerData));
-		ReleaseBuffer(b);
-	}
-	else
-		ItemPointerSetInvalid(ip);
+	if (!(ScanDirectionIsNoMovement(dir)
+		  && ItemPointerIsValid(&(s->currentItemData))))
+		return false;
 
-	return ip;
+	b = ReadBuffer(s->indexRelation,
+				   ItemPointerGetBlockNumber(&(s->currentItemData)));
+	p = BufferGetPage(b);
+	n = ItemPointerGetOffsetNumber(&(s->currentItemData));
+	it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
+	s->xs_ctup.t_self = it->t_tid;
+	ReleaseBuffer(b);
+
+	return true;
 }
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index 2d3a4f69419d9b30f63e6dc83cdaf360ab347b2e..67b10f7ddb06538ac0b3dcf694a58d23a7ec1ef4 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.41 2002/03/05 05:30:35 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.42 2002/05/20 23:51:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,12 +53,11 @@ Datum
 gistbeginscan(PG_FUNCTION_ARGS)
 {
 	Relation	r = (Relation) PG_GETARG_POINTER(0);
-	bool		fromEnd = PG_GETARG_BOOL(1);
-	uint16		nkeys = PG_GETARG_UINT16(2);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(3);
+	int			nkeys = PG_GETARG_INT32(1);
+	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
 	IndexScanDesc s;
 
-	s = RelationGetIndexScan(r, fromEnd, nkeys, key);
+	s = RelationGetIndexScan(r, nkeys, key);
 
 	gistregscan(s);
 
@@ -69,8 +68,7 @@ Datum
 gistrescan(PG_FUNCTION_ARGS)
 {
 	IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
-	bool		fromEnd = PG_GETARG_BOOL(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
+	ScanKey		key = (ScanKey) PG_GETARG_POINTER(1);
 	GISTScanOpaque p;
 	int			i;
 
@@ -80,18 +78,6 @@ gistrescan(PG_FUNCTION_ARGS)
 	ItemPointerSetInvalid(&s->currentItemData);
 	ItemPointerSetInvalid(&s->currentMarkData);
 
-	/*
-	 * Set flags.
-	 */
-	if (RelationGetNumberOfBlocks(s->relation) == 0)
-		s->flags = ScanUnmarked;
-	else if (fromEnd)
-		s->flags = ScanUnmarked | ScanUncheckedPrevious;
-	else
-		s->flags = ScanUnmarked | ScanUncheckedNext;
-
-	s->scanFromEnd = fromEnd;
-
 	if (s->numberOfKeys > 0)
 	{
 		memmove(s->keyData,
@@ -109,7 +95,8 @@ gistrescan(PG_FUNCTION_ARGS)
 		for (i = 0; i < s->numberOfKeys; i++)
 		{
 			s->keyData[i].sk_procedure
-				= RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno,
+				= RelationGetGISTStrategy(s->indexRelation,
+										  s->keyData[i].sk_attno,
 										  s->keyData[i].sk_procedure);
 			s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno - 1];
 		}
@@ -122,7 +109,7 @@ gistrescan(PG_FUNCTION_ARGS)
 		p->s_flags = 0x0;
 		s->opaque = p;
 		p->giststate = (GISTSTATE *) palloc(sizeof(GISTSTATE));
-		initGISTstate(p->giststate, s->relation);
+		initGISTstate(p->giststate, s->indexRelation);
 		if (s->numberOfKeys > 0)
 
 			/*
@@ -133,15 +120,10 @@ gistrescan(PG_FUNCTION_ARGS)
 			 */
 			for (i = 0; i < s->numberOfKeys; i++)
 			{
-
-				/*----------
-				 * s->keyData[i].sk_procedure =
-				 *		index_getprocid(s->relation, 1, GIST_CONSISTENT_PROC);
-				 *----------
-				 */
-				s->keyData[i].sk_procedure
-					= RelationGetGISTStrategy(s->relation, s->keyData[i].sk_attno,
-											  s->keyData[i].sk_procedure);
+				s->keyData[i].sk_procedure =
+					RelationGetGISTStrategy(s->indexRelation,
+											s->keyData[i].sk_attno,
+											s->keyData[i].sk_procedure);
 				s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno - 1];
 			}
 	}
@@ -309,7 +291,7 @@ gistadjscans(Relation rel, int op, BlockNumber blkno, OffsetNumber offnum)
 	relid = RelationGetRelid(rel);
 	for (l = GISTScans; l != (GISTScanList) NULL; l = l->gsl_next)
 	{
-		if (l->gsl_scan->relation->rd_id == relid)
+		if (l->gsl_scan->indexRelation->rd_id == relid)
 			gistadjone(l->gsl_scan, op, blkno, offnum);
 	}
 }
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index c0a22b62456fbfb7eeb6fb481ab8d5e7ff5824c6..6f06ffbfa039a94d06d31bfc7aee8e89421e60fe 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.56 2002/03/09 17:35:35 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.57 2002/05/20 23:51:41 tgl Exp $
  *
  * NOTES
  *	  This file contains only the public interface routines.
@@ -210,7 +210,7 @@ hashgettuple(PG_FUNCTION_ARGS)
 {
 	IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
 	ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1);
-	RetrieveIndexResult res;
+	bool res;
 
 	/*
 	 * If we've already initialized this scan, we can just advance it in
@@ -223,7 +223,7 @@ hashgettuple(PG_FUNCTION_ARGS)
 	else
 		res = _hash_first(scan, dir);
 
-	PG_RETURN_POINTER(res);
+	PG_RETURN_BOOL(res);
 }
 
 
@@ -234,17 +234,15 @@ Datum
 hashbeginscan(PG_FUNCTION_ARGS)
 {
 	Relation	rel = (Relation) PG_GETARG_POINTER(0);
-	bool		fromEnd = PG_GETARG_BOOL(1);
-	uint16		keysz = PG_GETARG_UINT16(2);
-	ScanKey		scankey = (ScanKey) PG_GETARG_POINTER(3);
+	int			keysz = PG_GETARG_INT32(1);
+	ScanKey		scankey = (ScanKey) PG_GETARG_POINTER(2);
 	IndexScanDesc scan;
 	HashScanOpaque so;
 
-	scan = RelationGetIndexScan(rel, fromEnd, keysz, scankey);
+	scan = RelationGetIndexScan(rel, keysz, scankey);
 	so = (HashScanOpaque) palloc(sizeof(HashScanOpaqueData));
 	so->hashso_curbuf = so->hashso_mrkbuf = InvalidBuffer;
 	scan->opaque = so;
-	scan->flags = 0x0;
 
 	/* register scan in case we change pages it's using */
 	_hash_regscan(scan);
@@ -259,11 +257,7 @@ Datum
 hashrescan(PG_FUNCTION_ARGS)
 {
 	IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
-
-#ifdef NOT_USED					/* XXX surely it's wrong to ignore this? */
-	bool		fromEnd = PG_GETARG_BOOL(1);
-#endif
-	ScanKey		scankey = (ScanKey) PG_GETARG_POINTER(2);
+	ScanKey		scankey = (ScanKey) PG_GETARG_POINTER(1);
 	ItemPointer iptr;
 	HashScanOpaque so;
 
@@ -272,13 +266,13 @@ hashrescan(PG_FUNCTION_ARGS)
 	/* we hold a read lock on the current page in the scan */
 	if (ItemPointerIsValid(iptr = &(scan->currentItemData)))
 	{
-		_hash_relbuf(scan->relation, so->hashso_curbuf, HASH_READ);
+		_hash_relbuf(scan->indexRelation, so->hashso_curbuf, HASH_READ);
 		so->hashso_curbuf = InvalidBuffer;
 		ItemPointerSetInvalid(iptr);
 	}
 	if (ItemPointerIsValid(iptr = &(scan->currentMarkData)))
 	{
-		_hash_relbuf(scan->relation, so->hashso_mrkbuf, HASH_READ);
+		_hash_relbuf(scan->indexRelation, so->hashso_mrkbuf, HASH_READ);
 		so->hashso_mrkbuf = InvalidBuffer;
 		ItemPointerSetInvalid(iptr);
 	}
@@ -309,7 +303,7 @@ hashendscan(PG_FUNCTION_ARGS)
 	/* release any locks we still hold */
 	if (ItemPointerIsValid(iptr = &(scan->currentItemData)))
 	{
-		_hash_relbuf(scan->relation, so->hashso_curbuf, HASH_READ);
+		_hash_relbuf(scan->indexRelation, so->hashso_curbuf, HASH_READ);
 		so->hashso_curbuf = InvalidBuffer;
 		ItemPointerSetInvalid(iptr);
 	}
@@ -317,7 +311,7 @@ hashendscan(PG_FUNCTION_ARGS)
 	if (ItemPointerIsValid(iptr = &(scan->currentMarkData)))
 	{
 		if (BufferIsValid(so->hashso_mrkbuf))
-			_hash_relbuf(scan->relation, so->hashso_mrkbuf, HASH_READ);
+			_hash_relbuf(scan->indexRelation, so->hashso_mrkbuf, HASH_READ);
 		so->hashso_mrkbuf = InvalidBuffer;
 		ItemPointerSetInvalid(iptr);
 	}
@@ -346,7 +340,7 @@ hashmarkpos(PG_FUNCTION_ARGS)
 	/* release lock on old marked data, if any */
 	if (ItemPointerIsValid(iptr = &(scan->currentMarkData)))
 	{
-		_hash_relbuf(scan->relation, so->hashso_mrkbuf, HASH_READ);
+		_hash_relbuf(scan->indexRelation, so->hashso_mrkbuf, HASH_READ);
 		so->hashso_mrkbuf = InvalidBuffer;
 		ItemPointerSetInvalid(iptr);
 	}
@@ -354,7 +348,7 @@ hashmarkpos(PG_FUNCTION_ARGS)
 	/* bump lock on currentItemData and copy to currentMarkData */
 	if (ItemPointerIsValid(&(scan->currentItemData)))
 	{
-		so->hashso_mrkbuf = _hash_getbuf(scan->relation,
+		so->hashso_mrkbuf = _hash_getbuf(scan->indexRelation,
 								 BufferGetBlockNumber(so->hashso_curbuf),
 										 HASH_READ);
 		scan->currentMarkData = scan->currentItemData;
@@ -378,7 +372,7 @@ hashrestrpos(PG_FUNCTION_ARGS)
 	/* release lock on current data, if any */
 	if (ItemPointerIsValid(iptr = &(scan->currentItemData)))
 	{
-		_hash_relbuf(scan->relation, so->hashso_curbuf, HASH_READ);
+		_hash_relbuf(scan->indexRelation, so->hashso_curbuf, HASH_READ);
 		so->hashso_curbuf = InvalidBuffer;
 		ItemPointerSetInvalid(iptr);
 	}
@@ -386,7 +380,7 @@ hashrestrpos(PG_FUNCTION_ARGS)
 	/* bump lock on currentMarkData and copy to currentItemData */
 	if (ItemPointerIsValid(&(scan->currentMarkData)))
 	{
-		so->hashso_curbuf = _hash_getbuf(scan->relation,
+		so->hashso_curbuf = _hash_getbuf(scan->indexRelation,
 								 BufferGetBlockNumber(so->hashso_mrkbuf),
 										 HASH_READ);
 
@@ -413,7 +407,6 @@ hashbulkdelete(PG_FUNCTION_ARGS)
 	BlockNumber num_pages;
 	double		tuples_removed;
 	double		num_index_tuples;
-	RetrieveIndexResult res;
 	IndexScanDesc iscan;
 
 	tuples_removed = 0;
@@ -424,30 +417,25 @@ hashbulkdelete(PG_FUNCTION_ARGS)
 	 */
 
 	/* walk through the entire index */
-	iscan = index_beginscan(rel, false, 0, (ScanKey) NULL);
+	iscan = index_beginscan(NULL, rel, SnapshotAny, 0, (ScanKey) NULL);
 
-	while ((res = index_getnext(iscan, ForwardScanDirection))
-		   != (RetrieveIndexResult) NULL)
+	while (index_getnext_indexitem(iscan, ForwardScanDirection))
 	{
-		ItemPointer heapptr = &res->heap_iptr;
-
-		if (callback(heapptr, callback_state))
+		if (callback(&iscan->xs_ctup.t_self, callback_state))
 		{
-			ItemPointer indexptr = &res->index_iptr;
+			ItemPointerData indextup = iscan->currentItemData;
 
 			/* adjust any active scans that will be affected by deletion */
 			/* (namely, my own scan) */
-			_hash_adjscans(rel, indexptr);
+			_hash_adjscans(rel, &indextup);
 
 			/* delete the data from the page */
-			_hash_pagedel(rel, indexptr);
+			_hash_pagedel(rel, &indextup);
 
 			tuples_removed += 1;
 		}
 		else
 			num_index_tuples += 1;
-
-		pfree(res);
 	}
 
 	index_endscan(iscan);
diff --git a/src/backend/access/hash/hashscan.c b/src/backend/access/hash/hashscan.c
index f4a91b5710fff91724032cd9b804664869914dd8..87dfcd60930acfcc3b2bcffab55b0466d5ab45e6 100644
--- a/src/backend/access/hash/hashscan.c
+++ b/src/backend/access/hash/hashscan.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/hash/hashscan.c,v 1.25 2001/07/15 22:48:15 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/hash/hashscan.c,v 1.26 2002/05/20 23:51:41 tgl Exp $
  *
  * NOTES
  *	  Because we can be doing an index scan on a relation while we
@@ -119,7 +119,7 @@ _hash_adjscans(Relation rel, ItemPointer tid)
 	relid = RelationGetRelid(rel);
 	for (l = HashScans; l != (HashScanList) NULL; l = l->hashsl_next)
 	{
-		if (relid == l->hashsl_scan->relation->rd_id)
+		if (relid == l->hashsl_scan->indexRelation->rd_id)
 			_hash_scandel(l->hashsl_scan, ItemPointerGetBlockNumber(tid),
 						  ItemPointerGetOffsetNumber(tid));
 	}
@@ -136,7 +136,7 @@ _hash_scandel(IndexScanDesc scan, BlockNumber blkno, OffsetNumber offno)
 	if (!_hash_scantouched(scan, blkno, offno))
 		return;
 
-	metabuf = _hash_getbuf(scan->relation, HASH_METAPAGE, HASH_READ);
+	metabuf = _hash_getbuf(scan->indexRelation, HASH_METAPAGE, HASH_READ);
 
 	so = (HashScanOpaque) scan->opaque;
 	buf = so->hashso_curbuf;
diff --git a/src/backend/access/hash/hashsearch.c b/src/backend/access/hash/hashsearch.c
index 6ea643dcaf5ad35a02e8f2ab0552af21b3f6560f..968efa363ac9e78119850ba23217478db8bc3f8a 100644
--- a/src/backend/access/hash/hashsearch.c
+++ b/src/backend/access/hash/hashsearch.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/hash/hashsearch.c,v 1.27 2001/10/25 05:49:21 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/hash/hashsearch.c,v 1.28 2002/05/20 23:51:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -59,7 +59,7 @@ _hash_search(Relation rel,
  *		exit, we have the page containing the next item locked but not
  *		pinned.
  */
-RetrieveIndexResult
+bool
 _hash_next(IndexScanDesc scan, ScanDirection dir)
 {
 	Relation	rel;
@@ -67,13 +67,12 @@ _hash_next(IndexScanDesc scan, ScanDirection dir)
 	Buffer		metabuf;
 	Page		page;
 	OffsetNumber offnum;
-	RetrieveIndexResult res;
 	ItemPointer current;
 	HashItem	hitem;
 	IndexTuple	itup;
 	HashScanOpaque so;
 
-	rel = scan->relation;
+	rel = scan->indexRelation;
 	so = (HashScanOpaque) scan->opaque;
 	current = &(scan->currentItemData);
 
@@ -101,7 +100,7 @@ _hash_next(IndexScanDesc scan, ScanDirection dir)
 	 * next tuple, we come back with a lock on that buffer.
 	 */
 	if (!_hash_step(scan, &buf, dir, metabuf))
-		return (RetrieveIndexResult) NULL;
+		return false;
 
 	/* if we're here, _hash_step found a valid tuple */
 	current = &(scan->currentItemData);
@@ -110,9 +109,9 @@ _hash_next(IndexScanDesc scan, ScanDirection dir)
 	_hash_checkpage(page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
 	hitem = (HashItem) PageGetItem(page, PageGetItemId(page, offnum));
 	itup = &hitem->hash_itup;
-	res = FormRetrieveIndexResult(current, &(itup->t_tid));
+	scan->xs_ctup.t_self = itup->t_tid;
 
-	return res;
+	return true;
 }
 
 static void
@@ -161,13 +160,13 @@ _hash_readprev(Relation rel,
 /*
  *	_hash_first() -- Find the first item in a scan.
  *
- *		Return the RetrieveIndexResult of the first item in the tree that
- *		satisfies the qualificatin associated with the scan descriptor. On
+ *		Find the first item in the tree that
+ *		satisfies the qualification associated with the scan descriptor. On
  *		exit, the page containing the current index tuple is read locked
  *		and pinned, and the scan's opaque data entry is updated to
  *		include the buffer.
  */
-RetrieveIndexResult
+bool
 _hash_first(IndexScanDesc scan, ScanDirection dir)
 {
 	Relation	rel;
@@ -180,10 +179,9 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
 	IndexTuple	itup;
 	ItemPointer current;
 	OffsetNumber offnum;
-	RetrieveIndexResult res;
 	HashScanOpaque so;
 
-	rel = scan->relation;
+	rel = scan->indexRelation;
 	so = (HashScanOpaque) scan->opaque;
 	current = &(scan->currentItemData);
 
@@ -230,7 +228,7 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
 			{
 				_hash_relbuf(rel, buf, HASH_READ);
 				_hash_relbuf(rel, metabuf, HASH_READ);
-				return (RetrieveIndexResult) NULL;
+				return false;
 			}
 		}
 	}
@@ -241,7 +239,7 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
 	}
 
 	if (!_hash_step(scan, &buf, dir, metabuf))
-		return (RetrieveIndexResult) NULL;
+		return false;
 
 	/* if we're here, _hash_step found a valid tuple */
 	current = &(scan->currentItemData);
@@ -250,9 +248,9 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
 	_hash_checkpage(page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
 	hitem = (HashItem) PageGetItem(page, PageGetItemId(page, offnum));
 	itup = &hitem->hash_itup;
-	res = FormRetrieveIndexResult(current, &(itup->t_tid));
+	scan->xs_ctup.t_self = itup->t_tid;
 
-	return res;
+	return true;
 }
 
 /*
@@ -285,7 +283,7 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir, Buffer metabuf)
 	HashItem	hitem;
 	IndexTuple	itup;
 
-	rel = scan->relation;
+	rel = scan->indexRelation;
 	current = &(scan->currentItemData);
 	so = (HashScanOpaque) scan->opaque;
 	allbuckets = (scan->numberOfKeys < 1);
diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c
index dd16d887fbff61bb12efceeb1749928baa55d795..06fef7777bcb7f0fe0a3e2fb36a524a227b55bb6 100644
--- a/src/backend/access/hash/hashutil.c
+++ b/src/backend/access/hash/hashutil.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/hash/hashutil.c,v 1.28 2002/03/06 20:49:43 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/hash/hashutil.c,v 1.29 2002/05/20 23:51:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -63,7 +63,7 @@ _hash_checkqual(IndexScanDesc scan, IndexTuple itup)
 {
 	if (scan->numberOfKeys > 0)
 		return (index_keytest(itup,
-							  RelationGetDescr(scan->relation),
+							  RelationGetDescr(scan->indexRelation),
 							  scan->numberOfKeys, scan->keyData));
 	else
 		return true;
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 88926adfe5e5583a713d562a50850371a4c86757..dac14ac33978305566b5e19f8f62f812699054ec 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.133 2002/05/01 01:23:37 inoue Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.134 2002/05/20 23:51:41 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -24,7 +24,7 @@
  *		heap_rescan		- restart a relation scan
  *		heap_endscan	- end relation scan
  *		heap_getnext	- retrieve next tuple in scan
- *		heap_fetch		- retrive tuple with tid
+ *		heap_fetch		- retrieve tuple with tid
  *		heap_insert		- insert tuple into a relation
  *		heap_delete		- delete a tuple from a relation
  *		heap_update		- replace a tuple in a relation with another tuple
@@ -70,11 +70,7 @@ static XLogRecPtr log_heap_update(Relation reln, Buffer oldbuf,
  * ----------------
  */
 static void
-initscan(HeapScanDesc scan,
-		 Relation relation,
-		 int atend,
-		 unsigned nkeys,
-		 ScanKey key)
+initscan(HeapScanDesc scan, ScanKey key)
 {
 	/*
 	 * Make sure we have up-to-date idea of number of blocks in relation.
@@ -82,7 +78,7 @@ initscan(HeapScanDesc scan,
 	 * added while the scan is in progress will be invisible to my
 	 * transaction anyway...
 	 */
-	relation->rd_nblocks = RelationGetNumberOfBlocks(relation);
+	scan->rs_rd->rd_nblocks = RelationGetNumberOfBlocks(scan->rs_rd);
 
 	scan->rs_ctup.t_datamcxt = NULL;
 	scan->rs_ctup.t_data = NULL;
@@ -95,7 +91,7 @@ initscan(HeapScanDesc scan,
 	 * copy the scan key, if appropriate
 	 */
 	if (key != NULL)
-		memmove(scan->rs_key, key, nkeys * sizeof(ScanKeyData));
+		memcpy(scan->rs_key, key, scan->rs_nkeys * sizeof(ScanKeyData));
 }
 
 /* ----------------
@@ -185,7 +181,7 @@ heapgettup(Relation relation,
 	/*
 	 * calculate next starting lineoff, given scan direction
 	 */
-	if (!dir)
+	if (dir == 0)
 	{
 		/*
 		 * ``no movement'' scan direction: refetch same tuple
@@ -216,8 +212,8 @@ heapgettup(Relation relation,
 		tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
 		tuple->t_len = ItemIdGetLength(lpp);
 		LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
-		return;
 
+		return;
 	}
 	else if (dir < 0)
 	{
@@ -255,7 +251,6 @@ heapgettup(Relation relation,
 				OffsetNumberPrev(ItemPointerGetOffsetNumber(tid));
 		}
 		/* page and lineoff now reference the physically previous tid */
-
 	}
 	else
 	{
@@ -287,7 +282,6 @@ heapgettup(Relation relation,
 		dp = (Page) BufferGetPage(*buffer);
 		lines = PageGetMaxOffsetNumber(dp);
 		/* page and lineoff now reference the physically next tid */
-
 	}
 
 	/* 'dir' is now non-zero */
@@ -675,11 +669,8 @@ heap_openr(const char *sysRelationName, LOCKMODE lockmode)
  * ----------------
  */
 HeapScanDesc
-heap_beginscan(Relation relation,
-			   int atend,
-			   Snapshot snapshot,
-			   unsigned nkeys,
-			   ScanKey key)
+heap_beginscan(Relation relation, Snapshot snapshot,
+			   int nkeys, ScanKey key)
 {
 	HeapScanDesc scan;
 
@@ -715,20 +706,20 @@ heap_beginscan(Relation relation,
 
 	scan->rs_rd = relation;
 	scan->rs_snapshot = snapshot;
-	scan->rs_nkeys = (short) nkeys;
-
-	pgstat_initstats(&scan->rs_pgstat_info, relation);
+	scan->rs_nkeys = nkeys;
 
 	/*
 	 * we do this here instead of in initscan() because heap_rescan also
 	 * calls initscan() and we don't want to allocate memory again
 	 */
-	if (nkeys)
+	if (nkeys > 0)
 		scan->rs_key = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);
 	else
 		scan->rs_key = NULL;
 
-	initscan(scan, relation, atend, nkeys, key);
+	pgstat_initstats(&scan->rs_pgstat_info, relation);
+
+	initscan(scan, key);
 
 	return scan;
 }
@@ -739,7 +730,6 @@ heap_beginscan(Relation relation,
  */
 void
 heap_rescan(HeapScanDesc scan,
-			bool scanFromEnd,
 			ScanKey key)
 {
 	/*
@@ -757,7 +747,7 @@ heap_rescan(HeapScanDesc scan,
 	/*
 	 * reinitialize scan descriptor
 	 */
-	initscan(scan, scan->rs_rd, scanFromEnd, scan->rs_nkeys, key);
+	initscan(scan, key);
 
 	pgstat_reset_heap_scan(&scan->rs_pgstat_info);
 }
@@ -808,14 +798,14 @@ heap_endscan(HeapScanDesc scan)
 
 #ifdef HEAPDEBUGALL
 #define HEAPDEBUG_1 \
-elog(LOG, "heap_getnext([%s,nkeys=%d],backw=%d) called", \
-	 RelationGetRelationName(scan->rs_rd), scan->rs_nkeys, backw)
+	elog(LOG, "heap_getnext([%s,nkeys=%d],dir=%d) called", \
+		 RelationGetRelationName(scan->rs_rd), scan->rs_nkeys, (int) direction)
 
 #define HEAPDEBUG_2 \
 	 elog(LOG, "heap_getnext returning EOS")
 
 #define HEAPDEBUG_3 \
-	 elog(LOG, "heap_getnext returning tuple");
+	 elog(LOG, "heap_getnext returning tuple")
 #else
 #define HEAPDEBUG_1
 #define HEAPDEBUG_2
@@ -824,7 +814,7 @@ elog(LOG, "heap_getnext([%s,nkeys=%d],backw=%d) called", \
 
 
 HeapTuple
-heap_getnext(HeapScanDesc scan, int backw)
+heap_getnext(HeapScanDesc scan, ScanDirection direction)
 {
 	/*
 	 * increment access statistics
@@ -842,43 +832,21 @@ heap_getnext(HeapScanDesc scan, int backw)
 
 	HEAPDEBUG_1;				/* heap_getnext( info ) */
 
-	if (backw)
-	{
-		/*
-		 * handle reverse scan
-		 */
-		heapgettup(scan->rs_rd,
-				   -1,
-				   &(scan->rs_ctup),
-				   &(scan->rs_cbuf),
-				   scan->rs_snapshot,
-				   scan->rs_nkeys,
-				   scan->rs_key);
-
-		if (scan->rs_ctup.t_data == NULL && !BufferIsValid(scan->rs_cbuf))
-		{
-			HEAPDEBUG_2;		/* heap_getnext returning EOS */
-			return NULL;
-		}
-	}
-	else
+	/*
+	 * Note: we depend here on the -1/0/1 encoding of ScanDirection.
+	 */
+	heapgettup(scan->rs_rd,
+			   (int) direction,
+			   &(scan->rs_ctup),
+			   &(scan->rs_cbuf),
+			   scan->rs_snapshot,
+			   scan->rs_nkeys,
+			   scan->rs_key);
+
+	if (scan->rs_ctup.t_data == NULL && !BufferIsValid(scan->rs_cbuf))
 	{
-		/*
-		 * handle forward scan
-		 */
-		heapgettup(scan->rs_rd,
-				   1,
-				   &(scan->rs_ctup),
-				   &(scan->rs_cbuf),
-				   scan->rs_snapshot,
-				   scan->rs_nkeys,
-				   scan->rs_key);
-
-		if (scan->rs_ctup.t_data == NULL && !BufferIsValid(scan->rs_cbuf))
-		{
-			HEAPDEBUG_2;		/* heap_getnext returning EOS */
-			return NULL;
-		}
+		HEAPDEBUG_2;			/* heap_getnext returning EOS */
+		return NULL;
 	}
 
 	pgstat_count_heap_scan(&scan->rs_pgstat_info);
@@ -897,16 +865,17 @@ heap_getnext(HeapScanDesc scan, int backw)
 }
 
 /* ----------------
- *		heap_fetch		- retrive tuple with tid
+ *		heap_fetch		- retrieve tuple with given tid
  *
- *		Currently ignores LP_IVALID during processing!
+ * On entry, tuple->t_self is the TID to fetch.
  *
- *		Because this is not part of a scan, there is no way to
- *		automatically lock/unlock the shared buffers.
- *		For this reason, we require that the user retrieve the buffer
- *		value, and they are required to BufferRelease() it when they
- *		are done.  If they want to make a copy of it before releasing it,
- *		they can call heap_copytyple().
+ * If successful (ie, tuple found and passes snapshot time qual),
+ * then the rest of *tuple is filled in, and *userbuf is set to the
+ * buffer holding the tuple.  A pin is obtained on the buffer; the
+ * caller must BufferRelease the buffer when done with the tuple.
+ *
+ * If not successful, tuple->t_data is set to NULL and *userbuf is set to
+ * InvalidBuffer.
  * ----------------
  */
 void
@@ -914,7 +883,7 @@ heap_fetch(Relation relation,
 		   Snapshot snapshot,
 		   HeapTuple tuple,
 		   Buffer *userbuf,
-		   IndexScanDesc iscan)
+		   PgStat_Info *pgstat_info)
 {
 	ItemId		lp;
 	Buffer		buffer;
@@ -936,8 +905,9 @@ heap_fetch(Relation relation,
 	buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
 
 	if (!BufferIsValid(buffer))
-		elog(ERROR, "heap_fetch: %s relation: ReadBuffer(%lx) failed",
-			 RelationGetRelationName(relation), (long) tid);
+		elog(ERROR, "heap_fetch: %s relation: ReadBuffer(%ld) failed",
+			 RelationGetRelationName(relation),
+			 (long) ItemPointerGetBlockNumber(tid));
 
 	LockBuffer(buffer, BUFFER_LOCK_SHARE);
 
@@ -990,8 +960,12 @@ heap_fetch(Relation relation,
 		 */
 		*userbuf = buffer;
 
-		if (iscan != NULL)
-			pgstat_count_heap_fetch(&iscan->xs_pgstat_info);
+		/*
+		 * Count the successful fetch in *pgstat_info if given,
+		 * otherwise in the relation's default statistics area.
+		 */
+		if (pgstat_info != NULL)
+			pgstat_count_heap_fetch(pgstat_info);
 		else
 			pgstat_count_heap_fetch(&relation->pgstat_info);
 	}
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 2a0b5c276295306348d013b62675ea669f1ea97f..18bc99982a5b0eb46000d2560796609ad2c4ad73 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.28 2002/03/05 05:33:06 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.29 2002/05/20 23:51:41 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -37,8 +37,6 @@
 #include "utils/pg_lzcompress.h"
 
 
-#ifdef TUPLE_TOASTER_ACTIVE
-
 #undef TOAST_DEBUG
 
 static void toast_delete(Relation rel, HeapTuple oldtup);
@@ -961,14 +959,12 @@ toast_save_datum(Relation rel, Datum value)
 static void
 toast_delete_datum(Relation rel, Datum value)
 {
-	register varattrib *attr = (varattrib *) value;
+	varattrib  *attr = (varattrib *) DatumGetPointer(value);
 	Relation	toastrel;
 	Relation	toastidx;
 	ScanKeyData toastkey;
 	IndexScanDesc toastscan;
-	HeapTupleData toasttup;
-	RetrieveIndexResult indexRes;
-	Buffer		buffer;
+	HeapTuple	toasttup;
 
 	if (!VARATT_IS_EXTERNAL(attr))
 		return;
@@ -993,22 +989,14 @@ toast_delete_datum(Relation rel, Datum value)
 	/*
 	 * Find the chunks by index
 	 */
-	toastscan = index_beginscan(toastidx, false, 1, &toastkey);
-	while ((indexRes = index_getnext(toastscan, ForwardScanDirection)) != NULL)
+	toastscan = index_beginscan(toastrel, toastidx, SnapshotToast,
+								1, &toastkey);
+	while ((toasttup = index_getnext(toastscan, ForwardScanDirection)) != NULL)
 	{
-		toasttup.t_self = indexRes->heap_iptr;
-		heap_fetch(toastrel, SnapshotToast, &toasttup, &buffer, toastscan);
-		pfree(indexRes);
-
-		if (!toasttup.t_data)
-			continue;
-
 		/*
 		 * Have a chunk, delete it
 		 */
-		simple_heap_delete(toastrel, &toasttup.t_self);
-
-		ReleaseBuffer(buffer);
+		simple_heap_delete(toastrel, &toasttup->t_self);
 	}
 
 	/*
@@ -1034,11 +1022,8 @@ toast_fetch_datum(varattrib *attr)
 	Relation	toastidx;
 	ScanKeyData toastkey;
 	IndexScanDesc toastscan;
-	HeapTupleData toasttup;
 	HeapTuple	ttup;
 	TupleDesc	toasttupDesc;
-	RetrieveIndexResult indexRes;
-	Buffer		buffer;
 	varattrib  *result;
 	int32		ressize;
 	int32		residx,
@@ -1082,17 +1067,10 @@ toast_fetch_datum(varattrib *attr)
 	 */
 	nextidx = 0;
 
-	toastscan = index_beginscan(toastidx, false, 1, &toastkey);
-	while ((indexRes = index_getnext(toastscan, ForwardScanDirection)) != NULL)
+	toastscan = index_beginscan(toastrel, toastidx, SnapshotToast,
+								1, &toastkey);
+	while ((ttup = index_getnext(toastscan, ForwardScanDirection)) != NULL)
 	{
-		toasttup.t_self = indexRes->heap_iptr;
-		heap_fetch(toastrel, SnapshotToast, &toasttup, &buffer, toastscan);
-		pfree(indexRes);
-
-		if (toasttup.t_data == NULL)
-			continue;
-		ttup = &toasttup;
-
 		/*
 		 * Have a chunk, extract the sequence number and the data
 		 */
@@ -1135,7 +1113,6 @@ toast_fetch_datum(varattrib *attr)
 			   VARATT_DATA(chunk),
 			   chunksize);
 
-		ReleaseBuffer(buffer);
 		nextidx++;
 	}
 
@@ -1170,16 +1147,12 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length)
 	Relation	toastrel;
 	Relation	toastidx;
 	ScanKeyData toastkey[3];
+	int			nscankeys;
 	IndexScanDesc toastscan;
-	HeapTupleData toasttup;
 	HeapTuple	ttup;
 	TupleDesc	toasttupDesc;
-	RetrieveIndexResult indexRes;
-	Buffer		buffer;
-
 	varattrib  *result;
 	int32		attrsize;
-	int32       nscankeys;
 	int32		residx;
 	int32       nextidx;
 	int		    numchunks;
@@ -1198,15 +1171,15 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length)
 	totalchunks = ((attrsize - 1) / TOAST_MAX_CHUNK_SIZE) + 1;
 
 	if (sliceoffset >= attrsize) 
-	  {
+	{
 	    sliceoffset = 0;
 	    length = 0;
-	  }
+	}
 
 	if (((sliceoffset + length) > attrsize) || length < 0)
-	  {
+	{
 	    length = attrsize - sliceoffset;
-	  }
+	}
 
 	result = (varattrib *) palloc(length + VARHDRSZ);
 	VARATT_SIZEP(result) = length + VARHDRSZ;
@@ -1274,17 +1247,10 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length)
 	 * The index is on (valueid, chunkidx) so they will come in order
 	 */
 	nextidx = startchunk;
-	toastscan = index_beginscan(toastidx, false, nscankeys, &toastkey[0]);
-	while ((indexRes = index_getnext(toastscan, ForwardScanDirection)) != NULL)
+	toastscan = index_beginscan(toastrel, toastidx, SnapshotToast,
+								nscankeys, toastkey);
+	while ((ttup = index_getnext(toastscan, ForwardScanDirection)) != NULL)
 	{
-		toasttup.t_self = indexRes->heap_iptr;
-		heap_fetch(toastrel, SnapshotToast, &toasttup, &buffer, toastscan);
-		pfree(indexRes);
-
-		if (toasttup.t_data == NULL)
-			continue;
-		ttup = &toasttup;
-
 		/*
 		 * Have a chunk, extract the sequence number and the data
 		 */
@@ -1329,7 +1295,6 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length)
 			   VARATT_DATA(chunk) + chcpystrt,
 			   (chcpyend - chcpystrt) + 1);
 		
-		ReleaseBuffer(buffer);
 		nextidx++;
 	}
 
@@ -1350,5 +1315,3 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length)
 
 	return result;
 }
-
-#endif   /* TUPLE_TOASTER_ACTIVE */
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index 2e70fb67cdef8ad160d11faf065d84a697738663..cc8c08c177c675bca2889c640685666cfee1b001 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -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);
 	}
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index ce2c8e62f45cd7b3134f299c5915decd515101f2..b616212bb505d7986fb66b13f6f42beed51486f3 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -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;
 
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 2cd9476c4e439f6ced085a6d0296afd44518ce38..206a1f17a3239b51a39e1e67015d613d8cb84149 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.88 2002/03/02 21:39:18 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.89 2002/05/20 23:51:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -296,7 +296,7 @@ btgettuple(PG_FUNCTION_ARGS)
 {
 	IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
 	ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1);
-	RetrieveIndexResult res;
+	bool res;
 
 	/*
 	 * If we've already initialized this scan, we can just advance it in
@@ -326,12 +326,12 @@ btgettuple(PG_FUNCTION_ARGS)
 	 */
 	if (res)
 	{
-		((BTScanOpaque) scan->opaque)->curHeapIptr = res->heap_iptr;
+		((BTScanOpaque) scan->opaque)->curHeapIptr = scan->xs_ctup.t_self;
 		LockBuffer(((BTScanOpaque) scan->opaque)->btso_curbuf,
 				   BUFFER_LOCK_UNLOCK);
 	}
 
-	PG_RETURN_POINTER(res);
+	PG_RETURN_BOOL(res);
 }
 
 /*
@@ -341,13 +341,12 @@ Datum
 btbeginscan(PG_FUNCTION_ARGS)
 {
 	Relation	rel = (Relation) PG_GETARG_POINTER(0);
-	bool		fromEnd = PG_GETARG_BOOL(1);
-	uint16		keysz = PG_GETARG_UINT16(2);
-	ScanKey		scankey = (ScanKey) PG_GETARG_POINTER(3);
+	int			keysz = PG_GETARG_INT32(1);
+	ScanKey		scankey = (ScanKey) PG_GETARG_POINTER(2);
 	IndexScanDesc scan;
 
 	/* get the scan */
-	scan = RelationGetIndexScan(rel, fromEnd, keysz, scankey);
+	scan = RelationGetIndexScan(rel, keysz, scankey);
 
 	PG_RETURN_POINTER(scan);
 }
@@ -359,11 +358,7 @@ Datum
 btrescan(PG_FUNCTION_ARGS)
 {
 	IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
-
-#ifdef NOT_USED					/* XXX surely it's wrong to ignore this? */
-	bool		fromEnd = PG_GETARG_BOOL(1);
-#endif
-	ScanKey		scankey = (ScanKey) PG_GETARG_POINTER(2);
+	ScanKey		scankey = (ScanKey) PG_GETARG_POINTER(1);
 	ItemPointer iptr;
 	BTScanOpaque so;
 
@@ -373,11 +368,13 @@ btrescan(PG_FUNCTION_ARGS)
 	{
 		so = (BTScanOpaque) palloc(sizeof(BTScanOpaqueData));
 		so->btso_curbuf = so->btso_mrkbuf = InvalidBuffer;
-		so->keyData = (ScanKey) NULL;
+		ItemPointerSetInvalid(&(so->curHeapIptr));
+		ItemPointerSetInvalid(&(so->mrkHeapIptr));
 		if (scan->numberOfKeys > 0)
 			so->keyData = (ScanKey) palloc(scan->numberOfKeys * sizeof(ScanKeyData));
+		else
+			so->keyData = (ScanKey) NULL;
 		scan->opaque = so;
-		scan->flags = 0x0;
 	}
 
 	/* we aren't holding any read locks, but gotta drop the pins */
@@ -385,6 +382,7 @@ btrescan(PG_FUNCTION_ARGS)
 	{
 		ReleaseBuffer(so->btso_curbuf);
 		so->btso_curbuf = InvalidBuffer;
+		ItemPointerSetInvalid(&(so->curHeapIptr));
 		ItemPointerSetInvalid(iptr);
 	}
 
@@ -392,6 +390,7 @@ btrescan(PG_FUNCTION_ARGS)
 	{
 		ReleaseBuffer(so->btso_mrkbuf);
 		so->btso_mrkbuf = InvalidBuffer;
+		ItemPointerSetInvalid(&(so->mrkHeapIptr));
 		ItemPointerSetInvalid(iptr);
 	}
 
@@ -491,7 +490,7 @@ btmarkpos(PG_FUNCTION_ARGS)
 	/* bump pin on current buffer for assignment to mark buffer */
 	if (ItemPointerIsValid(&(scan->currentItemData)))
 	{
-		so->btso_mrkbuf = ReadBuffer(scan->relation,
+		so->btso_mrkbuf = ReadBuffer(scan->indexRelation,
 								  BufferGetBlockNumber(so->btso_curbuf));
 		scan->currentMarkData = scan->currentItemData;
 		so->mrkHeapIptr = so->curHeapIptr;
@@ -523,7 +522,7 @@ btrestrpos(PG_FUNCTION_ARGS)
 	/* bump pin on marked buffer */
 	if (ItemPointerIsValid(&(scan->currentMarkData)))
 	{
-		so->btso_curbuf = ReadBuffer(scan->relation,
+		so->btso_curbuf = ReadBuffer(scan->indexRelation,
 								  BufferGetBlockNumber(so->btso_mrkbuf));
 		scan->currentItemData = scan->currentMarkData;
 		so->curHeapIptr = so->mrkHeapIptr;
@@ -549,7 +548,6 @@ btbulkdelete(PG_FUNCTION_ARGS)
 	BlockNumber num_pages;
 	double		tuples_removed;
 	double		num_index_tuples;
-	RetrieveIndexResult res;
 	IndexScanDesc scan;
 	BTScanOpaque so;
 	ItemPointer current;
@@ -569,19 +567,16 @@ btbulkdelete(PG_FUNCTION_ARGS)
 	 * doesn't care which kind of lock it's releasing).  This should
 	 * minimize the amount of work needed per page.
 	 */
-	scan = index_beginscan(rel, false, 0, (ScanKey) NULL);
+	scan = index_beginscan(NULL, rel, SnapshotAny, 0, (ScanKey) NULL);
 	so = (BTScanOpaque) scan->opaque;
 	current = &(scan->currentItemData);
 
 	/* Use _bt_first to get started, then _bt_step to remaining tuples */
-	res = _bt_first(scan, ForwardScanDirection);
-
-	if (res != NULL)
+	if (_bt_first(scan, ForwardScanDirection))
 	{
 		Buffer		buf;
 		BlockNumber lockedBlock = InvalidBlockNumber;
 
-		pfree(res);
 		/* we have the buffer pinned and locked */
 		buf = so->btso_curbuf;
 		Assert(BufferIsValid(buf));
@@ -683,7 +678,7 @@ btbulkdelete(PG_FUNCTION_ARGS)
 static void
 _bt_restscan(IndexScanDesc scan)
 {
-	Relation	rel = scan->relation;
+	Relation	rel = scan->indexRelation;
 	BTScanOpaque so = (BTScanOpaque) scan->opaque;
 	Buffer		buf = so->btso_curbuf;
 	Page		page;
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index c1a82f2b8560625175d21ecb2d232768b25db72e..2cfb8c8f00188219ff88508186ad33b366ec3cca 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.69 2001/10/25 05:49:21 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.70 2002/05/20 23:51:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,7 +19,7 @@
 #include "access/nbtree.h"
 
 
-static RetrieveIndexResult _bt_endpoint(IndexScanDesc scan, ScanDirection dir);
+static bool _bt_endpoint(IndexScanDesc scan, ScanDirection dir);
 
 
 /*
@@ -357,11 +357,11 @@ _bt_compare(Relation rel,
  *
  *		On entry, we have a valid currentItemData in the scan, and a
  *		read lock and pin count on the page that contains that item.
- *		We return the next item in the scan, or NULL if no more.
+ *		We return the next item in the scan, or false if no more.
  *		On successful exit, the page containing the new item is locked
- *		and pinned; on NULL exit, no lock or pin is held.
+ *		and pinned; on failure exit, no lock or pin is held.
  */
-RetrieveIndexResult
+bool
 _bt_next(IndexScanDesc scan, ScanDirection dir)
 {
 	Relation	rel;
@@ -374,7 +374,7 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
 	BTScanOpaque so;
 	bool		continuescan;
 
-	rel = scan->relation;
+	rel = scan->indexRelation;
 	so = (BTScanOpaque) scan->opaque;
 	current = &(scan->currentItemData);
 
@@ -386,7 +386,7 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
 	{
 		/* step one tuple in the appropriate direction */
 		if (!_bt_step(scan, &buf, dir))
-			return (RetrieveIndexResult) NULL;
+			return false;
 
 		/* current is the next candidate tuple to return */
 		offnum = ItemPointerGetOffsetNumber(current);
@@ -397,7 +397,8 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
 		if (_bt_checkkeys(scan, itup, dir, &continuescan))
 		{
 			/* tuple passes all scan key conditions, so return it */
-			return FormRetrieveIndexResult(current, &(itup->t_tid));
+			scan->xs_ctup.t_self = itup->t_tid;
+			return true;
 		}
 
 		/* This tuple doesn't pass, but there might be more that do */
@@ -408,20 +409,20 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
 	so->btso_curbuf = InvalidBuffer;
 	_bt_relbuf(rel, buf);
 
-	return (RetrieveIndexResult) NULL;
+	return false;
 }
 
 /*
  *	_bt_first() -- Find the first item in a scan.
  *
  *		We need to be clever about the type of scan, the operation it's
- *		performing, and the tree ordering.	We return the RetrieveIndexResult
- *		of the first item in the tree that satisfies the qualification
+ *		performing, and the tree ordering.	We find the
+ *		first item in the tree that satisfies the qualification
  *		associated with the scan descriptor.  On exit, the page containing
  *		the current index tuple is read locked and pinned, and the scan's
  *		opaque data entry is updated to include the buffer.
  */
-RetrieveIndexResult
+bool
 _bt_first(IndexScanDesc scan, ScanDirection dir)
 {
 	Relation	rel;
@@ -434,9 +435,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 	ItemPointer current;
 	BlockNumber blkno;
 	StrategyNumber strat;
-	RetrieveIndexResult res;
+	bool		res;
 	int32		result;
 	BTScanOpaque so;
+	bool		scanFromEnd;
 	bool		continuescan;
 	ScanKey		scankeys = NULL;
 	int			keysCount = 0;
@@ -445,7 +447,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 				j;
 	StrategyNumber strat_total;
 
-	rel = scan->relation;
+	rel = scan->indexRelation;
 	so = (BTScanOpaque) scan->opaque;
 
 	/*
@@ -459,12 +461,12 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 	 * be satisfied (eg, x == 1 AND x > 2).
 	 */
 	if (!so->qual_ok)
-		return (RetrieveIndexResult) NULL;
+		return false;
 
 	/*
 	 * Examine the scan keys to discover where we need to start the scan.
 	 */
-	scan->scanFromEnd = false;
+	scanFromEnd = false;
 	strat_total = BTEqualStrategyNumber;
 	if (so->numberOfKeys > 0)
 	{
@@ -511,13 +513,13 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 			}
 		}
 		if (keysCount == 0)
-			scan->scanFromEnd = true;
+			scanFromEnd = true;
 	}
 	else
-		scan->scanFromEnd = true;
+		scanFromEnd = true;
 
 	/* if we just need to walk down one edge of the tree, do that */
-	if (scan->scanFromEnd)
+	if (scanFromEnd)
 	{
 		if (nKeyIs)
 			pfree(nKeyIs);
@@ -544,7 +546,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 			pfree(nKeyIs);
 			pfree(scankeys);
 			elog(ERROR, "_bt_first: btree doesn't support is(not)null, yet");
-			return ((RetrieveIndexResult) NULL);
+			return false;
 		}
 		procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
 		ScanKeyEntryInitializeWithInfo(scankeys + i,
@@ -574,7 +576,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 		ItemPointerSetInvalid(current);
 		so->btso_curbuf = InvalidBuffer;
 		pfree(scankeys);
-		return (RetrieveIndexResult) NULL;
+		return false;
 	}
 
 	/* remember which buffer we have pinned */
@@ -598,7 +600,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 	 * the scan strategy to find the exact place to start the scan.
 	 *
 	 * Note: if _bt_step fails (meaning we fell off the end of the index in
-	 * one direction or the other), we either return NULL (no matches) or
+	 * one direction or the other), we either return false (no matches) or
 	 * call _bt_endpoint() to set up a scan starting at that index
 	 * endpoint, as appropriate for the desired scan type.
 	 *
@@ -615,7 +617,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 			if (!_bt_step(scan, &buf, BackwardScanDirection))
 			{
 				pfree(scankeys);
-				return (RetrieveIndexResult) NULL;
+				return false;
 			}
 			break;
 
@@ -649,7 +651,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 			if (!_bt_step(scan, &buf, BackwardScanDirection))
 			{
 				pfree(scankeys);
-				return (RetrieveIndexResult) NULL;
+				return false;
 			}
 			break;
 
@@ -664,7 +666,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 				if (!_bt_step(scan, &buf, ForwardScanDirection))
 				{
 					pfree(scankeys);
-					return (RetrieveIndexResult) NULL;
+					return false;
 				}
 				offnum = ItemPointerGetOffsetNumber(current);
 				page = BufferGetPage(buf);
@@ -706,7 +708,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 				if (!_bt_step(scan, &buf, ForwardScanDirection))
 				{
 					pfree(scankeys);
-					return (RetrieveIndexResult) NULL;
+					return false;
 				}
 			}
 			break;
@@ -722,7 +724,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 				if (!_bt_step(scan, &buf, ForwardScanDirection))
 				{
 					pfree(scankeys);
-					return (RetrieveIndexResult) NULL;
+					return false;
 				}
 				offnum = ItemPointerGetOffsetNumber(current);
 				page = BufferGetPage(buf);
@@ -733,7 +735,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 				if (!_bt_step(scan, &buf, ForwardScanDirection))
 				{
 					pfree(scankeys);
-					return (RetrieveIndexResult) NULL;
+					return false;
 				}
 				offnum = ItemPointerGetOffsetNumber(current);
 				page = BufferGetPage(buf);
@@ -752,7 +754,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 	if (_bt_checkkeys(scan, itup, dir, &continuescan))
 	{
 		/* yes, return it */
-		res = FormRetrieveIndexResult(current, &(itup->t_tid));
+		scan->xs_ctup.t_self = itup->t_tid;
+		res = true;
 	}
 	else if (continuescan)
 	{
@@ -766,7 +769,7 @@ nomatches:
 		ItemPointerSetInvalid(current);
 		so->btso_curbuf = InvalidBuffer;
 		_bt_relbuf(rel, buf);
-		res = (RetrieveIndexResult) NULL;
+		res = false;
 	}
 
 	pfree(scankeys);
@@ -788,7 +791,7 @@ nomatches:
 bool
 _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
 {
-	Relation	rel = scan->relation;
+	Relation	rel = scan->indexRelation;
 	ItemPointer current = &(scan->currentItemData);
 	BTScanOpaque so = (BTScanOpaque) scan->opaque;
 	Page		page;
@@ -902,7 +905,7 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
  * that the scan must start at the beginning or end of the index (for
  * a forward or backward scan respectively).
  */
-static RetrieveIndexResult
+static bool
 _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
 {
 	Relation	rel;
@@ -917,10 +920,10 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
 	BTItem		btitem;
 	IndexTuple	itup;
 	BTScanOpaque so;
-	RetrieveIndexResult res;
+	bool		res;
 	bool		continuescan;
 
-	rel = scan->relation;
+	rel = scan->indexRelation;
 	current = &(scan->currentItemData);
 	so = (BTScanOpaque) scan->opaque;
 
@@ -936,7 +939,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
 		/* empty index... */
 		ItemPointerSetInvalid(current);
 		so->btso_curbuf = InvalidBuffer;
-		return (RetrieveIndexResult) NULL;
+		return false;
 	}
 
 	blkno = BufferGetBlockNumber(buf);
@@ -1016,7 +1019,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
 	if (start > maxoff)
 	{
 		if (!_bt_step(scan, &buf, dir))
-			return (RetrieveIndexResult) NULL;
+			return false;
 		start = ItemPointerGetOffsetNumber(current);
 		page = BufferGetPage(buf);
 	}
@@ -1028,7 +1031,8 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
 	if (_bt_checkkeys(scan, itup, dir, &continuescan))
 	{
 		/* yes, return it */
-		res = FormRetrieveIndexResult(current, &(itup->t_tid));
+		scan->xs_ctup.t_self = itup->t_tid;
+		res = true;
 	}
 	else if (continuescan)
 	{
@@ -1041,7 +1045,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
 		ItemPointerSetInvalid(current);
 		so->btso_curbuf = InvalidBuffer;
 		_bt_relbuf(rel, buf);
-		res = (RetrieveIndexResult) NULL;
+		res = false;
 	}
 
 	return res;
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 55c4c323001a10616769eccb4f24bc3fdc7696d9..2f596eac1115be304a2ca16858d253be8461cf92 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.47 2001/10/25 05:49:21 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.48 2002/05/20 23:51:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -195,7 +195,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
 {
 	ScanKeyData xform[BTMaxStrategyNumber];
 	bool		init[BTMaxStrategyNumber];
-	uint16		numberOfKeys = so->numberOfKeys;
+	int			numberOfKeys = so->numberOfKeys;
 	ScanKey		key;
 	ScanKey		cur;
 	StrategyMap map;
@@ -203,7 +203,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
 	int			i,
 				j;
 	AttrNumber	attno;
-	uint16		new_numberOfKeys;
+	int			new_numberOfKeys;
 	bool		allEqualSoFar;
 
 	so->qual_ok = true;
@@ -439,10 +439,10 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
 			  ScanDirection dir, bool *continuescan)
 {
 	BTScanOpaque so = (BTScanOpaque) scan->opaque;
-	Size		keysz = so->numberOfKeys;
+	int			keysz = so->numberOfKeys;
+	int			keysok;
 	TupleDesc	tupdesc;
 	ScanKey		key;
-	Size		keysok;
 
 	*continuescan = true;
 
@@ -450,7 +450,7 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
 	if (keysz == 0)
 		return true;
 
-	tupdesc = RelationGetDescr(scan->relation);
+	tupdesc = RelationGetDescr(scan->indexRelation);
 	key = so->keyData;
 	keysok = 0;
 
diff --git a/src/backend/access/rtree/rtget.c b/src/backend/access/rtree/rtget.c
index c8fa6b18d684054e051cf86edd3a2da66d1db357..3185e72c23d1b40e092f1095e3dd4503494f7863 100644
--- a/src/backend/access/rtree/rtget.c
+++ b/src/backend/access/rtree/rtget.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtget.c,v 1.25 2001/03/22 03:59:16 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtget.c,v 1.26 2002/05/20 23:51:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,10 +21,9 @@
 
 static OffsetNumber findnext(IndexScanDesc s, Page p, OffsetNumber n,
 		 ScanDirection dir);
-static RetrieveIndexResult rtscancache(IndexScanDesc s, ScanDirection dir);
-static RetrieveIndexResult rtfirst(IndexScanDesc s, ScanDirection dir);
-static RetrieveIndexResult rtnext(IndexScanDesc s, ScanDirection dir);
-static ItemPointer rtheapptr(Relation r, ItemPointer itemp);
+static bool rtscancache(IndexScanDesc s, ScanDirection dir);
+static bool rtfirst(IndexScanDesc s, ScanDirection dir);
+static bool rtnext(IndexScanDesc s, ScanDirection dir);
 
 
 Datum
@@ -32,35 +31,34 @@ rtgettuple(PG_FUNCTION_ARGS)
 {
 	IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
 	ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1);
-	RetrieveIndexResult res;
+	bool res;
 
 	/* if we have it cached in the scan desc, just return the value */
-	if ((res = rtscancache(s, dir)) != (RetrieveIndexResult) NULL)
-		PG_RETURN_POINTER(res);
+	if (rtscancache(s, dir))
+		PG_RETURN_BOOL(true);
 
 	/* not cached, so we'll have to do some work */
 	if (ItemPointerIsValid(&(s->currentItemData)))
 		res = rtnext(s, dir);
 	else
 		res = rtfirst(s, dir);
-	PG_RETURN_POINTER(res);
+	PG_RETURN_BOOL(res);
 }
 
-static RetrieveIndexResult
+static bool
 rtfirst(IndexScanDesc s, ScanDirection dir)
 {
 	Buffer		b;
 	Page		p;
 	OffsetNumber n;
 	OffsetNumber maxoff;
-	RetrieveIndexResult res;
 	RTreePageOpaque po;
 	RTreeScanOpaque so;
 	RTSTACK    *stk;
 	BlockNumber blk;
 	IndexTuple	it;
 
-	b = ReadBuffer(s->relation, P_ROOT);
+	b = ReadBuffer(s->indexRelation, P_ROOT);
 	p = BufferGetPage(b);
 	po = (RTreePageOpaque) PageGetSpecialPointer(p);
 	so = (RTreeScanOpaque) s->opaque;
@@ -75,13 +73,12 @@ rtfirst(IndexScanDesc s, ScanDirection dir)
 
 		while (n < FirstOffsetNumber || n > maxoff)
 		{
-
 			ReleaseBuffer(b);
 			if (so->s_stack == (RTSTACK *) NULL)
-				return (RetrieveIndexResult) NULL;
+				return false;
 
 			stk = so->s_stack;
-			b = ReadBuffer(s->relation, stk->rts_blk);
+			b = ReadBuffer(s->indexRelation, stk->rts_blk);
 			p = BufferGetPage(b);
 			po = (RTreePageOpaque) PageGetSpecialPointer(p);
 			maxoff = PageGetMaxOffsetNumber(p);
@@ -101,10 +98,10 @@ rtfirst(IndexScanDesc s, ScanDirection dir)
 
 			it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
 
-			res = FormRetrieveIndexResult(&(s->currentItemData), &(it->t_tid));
+			s->xs_ctup.t_self = it->t_tid;
 
 			ReleaseBuffer(b);
-			return res;
+			return true;
 		}
 		else
 		{
@@ -118,21 +115,20 @@ rtfirst(IndexScanDesc s, ScanDirection dir)
 			blk = ItemPointerGetBlockNumber(&(it->t_tid));
 
 			ReleaseBuffer(b);
-			b = ReadBuffer(s->relation, blk);
+			b = ReadBuffer(s->indexRelation, blk);
 			p = BufferGetPage(b);
 			po = (RTreePageOpaque) PageGetSpecialPointer(p);
 		}
 	}
 }
 
-static RetrieveIndexResult
+static bool
 rtnext(IndexScanDesc s, ScanDirection dir)
 {
 	Buffer		b;
 	Page		p;
 	OffsetNumber n;
 	OffsetNumber maxoff;
-	RetrieveIndexResult res;
 	RTreePageOpaque po;
 	RTreeScanOpaque so;
 	RTSTACK    *stk;
@@ -147,7 +143,7 @@ rtnext(IndexScanDesc s, ScanDirection dir)
 	else
 		n = OffsetNumberPrev(n);
 
-	b = ReadBuffer(s->relation, blk);
+	b = ReadBuffer(s->indexRelation, blk);
 	p = BufferGetPage(b);
 	po = (RTreePageOpaque) PageGetSpecialPointer(p);
 	so = (RTreeScanOpaque) s->opaque;
@@ -159,13 +155,12 @@ rtnext(IndexScanDesc s, ScanDirection dir)
 
 		while (n < FirstOffsetNumber || n > maxoff)
 		{
-
 			ReleaseBuffer(b);
 			if (so->s_stack == (RTSTACK *) NULL)
-				return (RetrieveIndexResult) NULL;
+				return false;
 
 			stk = so->s_stack;
-			b = ReadBuffer(s->relation, stk->rts_blk);
+			b = ReadBuffer(s->indexRelation, stk->rts_blk);
 			p = BufferGetPage(b);
 			maxoff = PageGetMaxOffsetNumber(p);
 			po = (RTreePageOpaque) PageGetSpecialPointer(p);
@@ -185,10 +180,10 @@ rtnext(IndexScanDesc s, ScanDirection dir)
 
 			it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
 
-			res = FormRetrieveIndexResult(&(s->currentItemData), &(it->t_tid));
+			s->xs_ctup.t_self = it->t_tid;
 
 			ReleaseBuffer(b);
-			return res;
+			return true;
 		}
 		else
 		{
@@ -202,7 +197,7 @@ rtnext(IndexScanDesc s, ScanDirection dir)
 			blk = ItemPointerGetBlockNumber(&(it->t_tid));
 
 			ReleaseBuffer(b);
-			b = ReadBuffer(s->relation, blk);
+			b = ReadBuffer(s->indexRelation, blk);
 			p = BufferGetPage(b);
 			po = (RTreePageOpaque) PageGetSpecialPointer(p);
 
@@ -243,14 +238,14 @@ findnext(IndexScanDesc s, Page p, OffsetNumber n, ScanDirection dir)
 		if (po->flags & F_LEAF)
 		{
 			if (index_keytest(it,
-							  RelationGetDescr(s->relation),
+							  RelationGetDescr(s->indexRelation),
 							  s->numberOfKeys, s->keyData))
 				break;
 		}
 		else
 		{
 			if (index_keytest(it,
-							  RelationGetDescr(s->relation),
+							  RelationGetDescr(s->indexRelation),
 							  so->s_internalNKey, so->s_internalKey))
 				break;
 		}
@@ -264,57 +259,25 @@ findnext(IndexScanDesc s, Page p, OffsetNumber n, ScanDirection dir)
 	return n;
 }
 
-static RetrieveIndexResult
+static bool
 rtscancache(IndexScanDesc s, ScanDirection dir)
-{
-	RetrieveIndexResult res;
-	ItemPointer ip;
-
-	if (!(ScanDirectionIsNoMovement(dir)
-		  && ItemPointerIsValid(&(s->currentItemData))))
-	{
-
-		return (RetrieveIndexResult) NULL;
-	}
-
-	ip = rtheapptr(s->relation, &(s->currentItemData));
-
-	if (ItemPointerIsValid(ip))
-		res = FormRetrieveIndexResult(&(s->currentItemData), ip);
-	else
-		res = (RetrieveIndexResult) NULL;
-
-	pfree(ip);
-
-	return res;
-}
-
-/*
- *	rtheapptr returns the item pointer to the tuple in the heap relation
- *	for which itemp is the index relation item pointer.
- */
-static ItemPointer
-rtheapptr(Relation r, ItemPointer itemp)
 {
 	Buffer		b;
 	Page		p;
-	IndexTuple	it;
-	ItemPointer ip;
 	OffsetNumber n;
+	IndexTuple	it;
 
-	ip = (ItemPointer) palloc(sizeof(ItemPointerData));
-	if (ItemPointerIsValid(itemp))
-	{
-		b = ReadBuffer(r, ItemPointerGetBlockNumber(itemp));
-		p = BufferGetPage(b);
-		n = ItemPointerGetOffsetNumber(itemp);
-		it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
-		memmove((char *) ip, (char *) &(it->t_tid),
-				sizeof(ItemPointerData));
-		ReleaseBuffer(b);
-	}
-	else
-		ItemPointerSetInvalid(ip);
+	if (!(ScanDirectionIsNoMovement(dir)
+		  && ItemPointerIsValid(&(s->currentItemData))))
+		return false;
+
+	b = ReadBuffer(s->indexRelation,
+				   ItemPointerGetBlockNumber(&(s->currentItemData)));
+	p = BufferGetPage(b);
+	n = ItemPointerGetOffsetNumber(&(s->currentItemData));
+	it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
+	s->xs_ctup.t_self = it->t_tid;
+	ReleaseBuffer(b);
 
-	return ip;
+	return true;
 }
diff --git a/src/backend/access/rtree/rtree.c b/src/backend/access/rtree/rtree.c
index a0ab0b0c34ad2351eb92382c283d0979ee67ce3d..a72f7747600da4774e6760f2525b14e94c1ee1cc 100644
--- a/src/backend/access/rtree/rtree.c
+++ b/src/backend/access/rtree/rtree.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.70 2002/03/02 21:39:19 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.71 2002/05/20 23:51:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1189,7 +1189,6 @@ rtbulkdelete(PG_FUNCTION_ARGS)
 	BlockNumber num_pages;
 	double		tuples_removed;
 	double		num_index_tuples;
-	RetrieveIndexResult res;
 	IndexScanDesc iscan;
 
 	tuples_removed = 0;
@@ -1206,23 +1205,20 @@ rtbulkdelete(PG_FUNCTION_ARGS)
 	 */
 
 	/* walk through the entire index */
-	iscan = index_beginscan(rel, false, 0, (ScanKey) NULL);
+	iscan = index_beginscan(NULL, rel, SnapshotAny, 0, (ScanKey) NULL);
 
-	while ((res = index_getnext(iscan, ForwardScanDirection))
-		   != (RetrieveIndexResult) NULL)
+	while (index_getnext_indexitem(iscan, ForwardScanDirection))
 	{
-		ItemPointer heapptr = &res->heap_iptr;
-
-		if (callback(heapptr, callback_state))
+		if (callback(&iscan->xs_ctup.t_self, callback_state))
 		{
-			ItemPointer indexptr = &res->index_iptr;
+			ItemPointerData indextup = iscan->currentItemData;
 			BlockNumber blkno;
 			OffsetNumber offnum;
 			Buffer		buf;
 			Page		page;
 
-			blkno = ItemPointerGetBlockNumber(indexptr);
-			offnum = ItemPointerGetOffsetNumber(indexptr);
+			blkno = ItemPointerGetBlockNumber(&indextup);
+			offnum = ItemPointerGetOffsetNumber(&indextup);
 
 			/* adjust any scans that will be affected by this deletion */
 			/* (namely, my own scan) */
@@ -1240,8 +1236,6 @@ rtbulkdelete(PG_FUNCTION_ARGS)
 		}
 		else
 			num_index_tuples += 1;
-
-		pfree(res);
 	}
 
 	index_endscan(iscan);
diff --git a/src/backend/access/rtree/rtscan.c b/src/backend/access/rtree/rtscan.c
index 81e0aafd5f342e6e67e7cc6090d06523ca345e7b..12af667825c1f67e5c9f4085bbae88e0204a810e 100644
--- a/src/backend/access/rtree/rtscan.c
+++ b/src/backend/access/rtree/rtscan.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.40 2002/03/05 05:30:40 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.41 2002/05/20 23:51:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -54,12 +54,11 @@ Datum
 rtbeginscan(PG_FUNCTION_ARGS)
 {
 	Relation	r = (Relation) PG_GETARG_POINTER(0);
-	bool		fromEnd = PG_GETARG_BOOL(1);
-	uint16		nkeys = PG_GETARG_UINT16(2);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(3);
+	int			nkeys = PG_GETARG_INT32(1);
+	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
 	IndexScanDesc s;
 
-	s = RelationGetIndexScan(r, fromEnd, nkeys, key);
+	s = RelationGetIndexScan(r, nkeys, key);
 
 	rtregscan(s);
 
@@ -70,8 +69,7 @@ Datum
 rtrescan(PG_FUNCTION_ARGS)
 {
 	IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
-	bool		fromEnd = PG_GETARG_BOOL(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
+	ScanKey		key = (ScanKey) PG_GETARG_POINTER(1);
 	RTreeScanOpaque p;
 	RegProcedure internal_proc;
 	int			i;
@@ -82,18 +80,6 @@ rtrescan(PG_FUNCTION_ARGS)
 	ItemPointerSetInvalid(&s->currentItemData);
 	ItemPointerSetInvalid(&s->currentMarkData);
 
-	/*
-	 * Set flags.
-	 */
-	if (RelationGetNumberOfBlocks(s->relation) == 0)
-		s->flags = ScanUnmarked;
-	else if (fromEnd)
-		s->flags = ScanUnmarked | ScanUncheckedPrevious;
-	else
-		s->flags = ScanUnmarked | ScanUncheckedNext;
-
-	s->scanFromEnd = fromEnd;
-
 	if (s->numberOfKeys > 0)
 	{
 		memmove(s->keyData,
@@ -133,7 +119,7 @@ rtrescan(PG_FUNCTION_ARGS)
 			for (i = 0; i < s->numberOfKeys; i++)
 			{
 				p->s_internalKey[i].sk_argument = s->keyData[i].sk_argument;
-				internal_proc = RTMapOperator(s->relation,
+				internal_proc = RTMapOperator(s->indexRelation,
 											  s->keyData[i].sk_attno,
 											  s->keyData[i].sk_procedure);
 				ScanKeyEntryInitialize(&(p->s_internalKey[i]),
@@ -306,7 +292,7 @@ rtadjscans(Relation r, int op, BlockNumber blkno, OffsetNumber offnum)
 	relid = RelationGetRelid(r);
 	for (l = RTScans; l != (RTScanList) NULL; l = l->rtsl_next)
 	{
-		if (RelationGetRelid(l->rtsl_scan->relation) == relid)
+		if (RelationGetRelid(l->rtsl_scan->indexRelation) == relid)
 			rtadjone(l->rtsl_scan, op, blkno, offnum);
 	}
 }
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 1a13786a04d10776d53d087d969394171b54f34e..5f734ff544768de5f20329fddada3012fb0bbe68 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.129 2002/05/17 01:19:16 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.130 2002/05/20 23:51:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -482,18 +482,18 @@ boot_openrel(char *relname)
 	if (Typ == (struct typmap **) NULL)
 	{
 		rel = heap_openr(TypeRelationName, NoLock);
-		scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
+		scan = heap_beginscan(rel, SnapshotNow, 0, (ScanKey) NULL);
 		i = 0;
-		while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
+		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
 			++i;
 		heap_endscan(scan);
 		app = Typ = ALLOC(struct typmap *, i + 1);
 		while (i-- > 0)
 			*app++ = ALLOC(struct typmap, 1);
 		*app = (struct typmap *) NULL;
-		scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
+		scan = heap_beginscan(rel, SnapshotNow, 0, (ScanKey) NULL);
 		app = Typ;
-		while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
+		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
 		{
 			(*app)->am_oid = tup->t_data->t_oid;
 			memcpy((char *) &(*app)->am_typ,
@@ -858,18 +858,18 @@ gettype(char *type)
 		}
 		elog(DEBUG3, "external type: %s", type);
 		rel = heap_openr(TypeRelationName, NoLock);
-		scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
+		scan = heap_beginscan(rel, SnapshotNow, 0, (ScanKey) NULL);
 		i = 0;
-		while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
+		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
 			++i;
 		heap_endscan(scan);
 		app = Typ = ALLOC(struct typmap *, i + 1);
 		while (i-- > 0)
 			*app++ = ALLOC(struct typmap, 1);
 		*app = (struct typmap *) NULL;
-		scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
+		scan = heap_beginscan(rel, SnapshotNow, 0, (ScanKey) NULL);
 		app = Typ;
-		while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
+		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
 		{
 			(*app)->am_oid = tup->t_data->t_oid;
 			memmove((char *) &(*app++)->am_typ,
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 194292bb4220253ebd360afe65a99fd0844a232f..2d090616b11c63770fdcef39a708de036b484c4a 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.67 2002/04/27 03:45:00 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.68 2002/05/20 23:51:41 tgl Exp $
  *
  * NOTES
  *	  See acl.h.
@@ -295,8 +295,8 @@ ExecuteGrantStmt_Database(GrantStmt *stmt)
 		ScanKeyEntryInitialize(&entry[0], 0,
 							   Anum_pg_database_datname, F_NAMEEQ,
 							   CStringGetDatum(dbname));
-		scan = heap_beginscan(relation, 0, SnapshotNow, 1, entry);
-		tuple = heap_getnext(scan, 0);
+		scan = heap_beginscan(relation, SnapshotNow, 1, entry);
+		tuple = heap_getnext(scan, ForwardScanDirection);
 		if (!HeapTupleIsValid(tuple))
 			elog(ERROR, "database \"%s\" not found", dbname);
 		pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
@@ -1045,8 +1045,8 @@ pg_database_aclcheck(Oid db_oid, Oid userid, AclMode mode)
 	ScanKeyEntryInitialize(&entry[0], 0x0,
 						   ObjectIdAttributeNumber, F_OIDEQ,
 						   ObjectIdGetDatum(db_oid));
-	scan = heap_beginscan(pg_database, 0, SnapshotNow, 1, entry);
-	tuple = heap_getnext(scan, 0);
+	scan = heap_beginscan(pg_database, SnapshotNow, 1, entry);
+	tuple = heap_getnext(scan, ForwardScanDirection);
 	if (!HeapTupleIsValid(tuple))
 		elog(ERROR, "pg_database_aclcheck: database %u not found", db_oid);
 
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index df6c44f5bc5a735092520a8ef2c72c03667bcc48..176973363308ec194f1ad65ceae06610f4522d77 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.199 2002/05/12 23:43:02 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.200 2002/05/20 23:51:41 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -776,7 +776,6 @@ RelationRemoveInheritance(Relation relation)
 						   ObjectIdGetDatum(RelationGetRelid(relation)));
 
 	scan = heap_beginscan(catalogRelation,
-						  false,
 						  SnapshotNow,
 						  1,
 						  &entry);
@@ -784,8 +783,7 @@ RelationRemoveInheritance(Relation relation)
 	/*
 	 * if any subclasses exist, then we disallow the deletion.
 	 */
-	tuple = heap_getnext(scan, 0);
-	if (HeapTupleIsValid(tuple))
+	if ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Oid			subclass = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrelid;
 		char	   *subclassname;
@@ -808,12 +806,11 @@ RelationRemoveInheritance(Relation relation)
 	entry.sk_attno = Anum_pg_inherits_inhrelid;
 
 	scan = heap_beginscan(catalogRelation,
-						  false,
 						  SnapshotNow,
 						  1,
 						  &entry);
 
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		simple_heap_delete(catalogRelation, &tuple->t_self);
 		found = true;
@@ -1074,7 +1071,6 @@ DeleteTypeTuple(Relation rel)
 						   ObjectIdGetDatum(RelationGetRelid(rel)));
 
 	pg_type_scan = heap_beginscan(pg_type_desc,
-								  0,
 								  SnapshotNow,
 								  1,
 								  &key);
@@ -1083,7 +1079,7 @@ DeleteTypeTuple(Relation rel)
 	 * use heap_getnext() to fetch the pg_type tuple.  If this tuple is
 	 * not valid then something's wrong.
 	 */
-	tup = heap_getnext(pg_type_scan, 0);
+	tup = heap_getnext(pg_type_scan, ForwardScanDirection);
 
 	if (!HeapTupleIsValid(tup))
 	{
@@ -1109,7 +1105,6 @@ DeleteTypeTuple(Relation rel)
 						   ObjectIdGetDatum(typoid));
 
 	pg_attribute_scan = heap_beginscan(pg_attribute_desc,
-									   0,
 									   SnapshotNow,
 									   1,
 									   &attkey);
@@ -1118,7 +1113,7 @@ DeleteTypeTuple(Relation rel)
 	 * try and get a pg_attribute tuple.  if we succeed it means we can't
 	 * delete the relation because something depends on the schema.
 	 */
-	atttup = heap_getnext(pg_attribute_scan, 0);
+	atttup = heap_getnext(pg_attribute_scan, ForwardScanDirection);
 
 	if (HeapTupleIsValid(atttup))
 	{
@@ -1833,9 +1828,9 @@ RemoveAttrDefaults(Relation rel)
 						   F_OIDEQ,
 						   ObjectIdGetDatum(RelationGetRelid(rel)));
 
-	adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
+	adscan = heap_beginscan(adrel, SnapshotNow, 1, &key);
 
-	while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
+	while ((tup = heap_getnext(adscan, ForwardScanDirection)) != NULL)
 		simple_heap_delete(adrel, &tup->t_self);
 
 	heap_endscan(adscan);
@@ -1856,9 +1851,9 @@ RemoveRelChecks(Relation rel)
 						   F_OIDEQ,
 						   ObjectIdGetDatum(RelationGetRelid(rel)));
 
-	rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
+	rcscan = heap_beginscan(rcrel, SnapshotNow, 1, &key);
 
-	while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
+	while ((tup = heap_getnext(rcscan, ForwardScanDirection)) != NULL)
 		simple_heap_delete(rcrel, &tup->t_self);
 
 	heap_endscan(rcscan);
@@ -1946,14 +1941,14 @@ RemoveCheckConstraint(Relation rel, const char *constrName, bool inh)
 						   PointerGetDatum(constrName));
 
 	/* Begin scanning the heap */
-	rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 2, key);
+	rcscan = heap_beginscan(rcrel, SnapshotNow, 2, key);
 
 	/*
 	 * Scan over the result set, removing any matching entries.  Note that
 	 * this has the side-effect of removing ALL CHECK constraints that
 	 * share the specified constraint name.
 	 */
-	while (HeapTupleIsValid(rctup = heap_getnext(rcscan, 0)))
+	while ((rctup = heap_getnext(rcscan, ForwardScanDirection)) != NULL)
 	{
 		simple_heap_delete(rcrel, &rctup->t_self);
 		++rel_deleted;
@@ -2008,9 +2003,9 @@ RemoveStatistics(Relation rel)
 	ScanKeyEntryInitialize(&key, 0x0, Anum_pg_statistic_starelid,
 						   F_OIDEQ,
 						   ObjectIdGetDatum(RelationGetRelid(rel)));
-	scan = heap_beginscan(pgstatistic, false, SnapshotNow, 1, &key);
+	scan = heap_beginscan(pgstatistic, SnapshotNow, 1, &key);
 
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 		simple_heap_delete(pgstatistic, &tuple->t_self);
 
 	heap_endscan(scan);
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index cc17b7192374de66531ce95dfd0b492d8dac9864..84cc2fe9b1d8d2c9bb9b18e2df2d4d2da4a2cc5b 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.177 2002/04/27 21:24:34 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.178 2002/05/20 23:51:41 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1067,10 +1067,9 @@ IndexesAreActive(Oid relid, bool confirmCommitted)
 	indexRelation = heap_openr(IndexRelationName, AccessShareLock);
 	ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid,
 						   F_OIDEQ, ObjectIdGetDatum(relid));
-	scan = heap_beginscan(indexRelation, false, SnapshotNow,
-						  1, &entry);
-	if (!heap_getnext(scan, 0))
-		isactive = true;
+	scan = heap_beginscan(indexRelation, SnapshotNow, 1, &entry);
+	if (heap_getnext(scan, ForwardScanDirection) == NULL)
+		isactive = true;		/* no indexes, so report "active" */
 	heap_endscan(scan);
 	heap_close(indexRelation, AccessShareLock);
 	return isactive;
@@ -1121,8 +1120,8 @@ setRelhasindex(Oid relid, bool hasindex, bool isprimary, Oid reltoastidxid)
 							   F_OIDEQ,
 							   ObjectIdGetDatum(relid));
 
-		pg_class_scan = heap_beginscan(pg_class, 0, SnapshotNow, 1, key);
-		tuple = heap_getnext(pg_class_scan, 0);
+		pg_class_scan = heap_beginscan(pg_class, SnapshotNow, 1, key);
+		tuple = heap_getnext(pg_class_scan, ForwardScanDirection);
 	}
 
 	if (!HeapTupleIsValid(tuple))
@@ -1341,8 +1340,8 @@ UpdateStats(Oid relid, double reltuples)
 							   F_OIDEQ,
 							   ObjectIdGetDatum(relid));
 
-		pg_class_scan = heap_beginscan(pg_class, 0, SnapshotNow, 1, key);
-		tuple = heap_getnext(pg_class_scan, 0);
+		pg_class_scan = heap_beginscan(pg_class, SnapshotNow, 1, key);
+		tuple = heap_getnext(pg_class_scan, ForwardScanDirection);
 	}
 
 	if (!HeapTupleIsValid(tuple))
@@ -1563,7 +1562,6 @@ IndexBuildHeapScan(Relation heapRelation,
 	}
 
 	scan = heap_beginscan(heapRelation, /* relation */
-						  0,	/* start at end */
 						  snapshot,		/* seeself */
 						  0,	/* number of keys */
 						  (ScanKey) NULL);		/* scan key */
@@ -1573,7 +1571,7 @@ IndexBuildHeapScan(Relation heapRelation,
 	/*
 	 * Scan all tuples in the base relation.
 	 */
-	while (HeapTupleIsValid(heapTuple = heap_getnext(scan, 0)))
+	while ((heapTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		bool		tupleIsAlive;
 
@@ -1967,10 +1965,9 @@ reindex_relation(Oid relid, bool force)
 	indexRelation = heap_openr(IndexRelationName, AccessShareLock);
 	ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid,
 						   F_OIDEQ, ObjectIdGetDatum(relid));
-	scan = heap_beginscan(indexRelation, false, SnapshotNow,
-						  1, &entry);
+	scan = heap_beginscan(indexRelation, SnapshotNow, 1, &entry);
 	reindexed = false;
-	while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
+	while ((indexTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple);
 
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 56f2d14527dda0a922598b8e72445621225f0dcb..3f217a5b5b7176f9211fa79bf2c2af6d929fa898 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.21 2002/05/17 20:53:33 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.22 2002/05/20 23:51:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1588,9 +1588,9 @@ FindTempRelations(Oid tempNamespaceId)
 						   ObjectIdGetDatum(tempNamespaceId));
 
 	pgclass = heap_openr(RelationRelationName, AccessShareLock);
-	scan = heap_beginscan(pgclass, false, SnapshotNow, 1, &key);
+	scan = heap_beginscan(pgclass, SnapshotNow, 1, &key);
 
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		switch (((Form_pg_class) GETSTRUCT(tuple))->relkind)
 		{
@@ -1627,9 +1627,9 @@ FindDeletionConstraints(List *relOids)
 	 * Scan pg_inherits to find parents and children that are in the list.
 	 */
 	inheritsrel = heap_openr(InheritsRelationName, AccessShareLock);
-	scan = heap_beginscan(inheritsrel, 0, SnapshotNow, 0, NULL);
+	scan = heap_beginscan(inheritsrel, SnapshotNow, 0, NULL);
 
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Oid		inhrelid = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrelid;
 		Oid		inhparent = ((Form_pg_inherits) GETSTRUCT(tuple))->inhparent;
diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c
index 819099329ced41ab90f722b69b30b53c17872434..d4b5e6bfeb3c34f9f822b3f2adca6cd540bf858a 100644
--- a/src/backend/catalog/pg_largeobject.c
+++ b/src/backend/catalog/pg_largeobject.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.10 2001/08/10 20:52:24 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.11 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -88,9 +88,7 @@ LargeObjectDrop(Oid loid)
 	Relation	pg_lo_idx;
 	ScanKeyData skey[1];
 	IndexScanDesc sd;
-	RetrieveIndexResult indexRes;
-	HeapTupleData tuple;
-	Buffer		buffer;
+	HeapTuple	tuple;
 
 	ScanKeyEntryInitialize(&skey[0],
 						   (bits16) 0x0,
@@ -101,22 +99,12 @@ LargeObjectDrop(Oid loid)
 	pg_largeobject = heap_openr(LargeObjectRelationName, RowShareLock);
 	pg_lo_idx = index_openr(LargeObjectLOidPNIndex);
 
-	sd = index_beginscan(pg_lo_idx, false, 1, skey);
+	sd = index_beginscan(pg_largeobject, pg_lo_idx, SnapshotNow, 1, skey);
 
-	tuple.t_datamcxt = CurrentMemoryContext;
-	tuple.t_data = NULL;
-
-	while ((indexRes = index_getnext(sd, ForwardScanDirection)))
+	while ((tuple = index_getnext(sd, ForwardScanDirection)) != NULL)
 	{
-		tuple.t_self = indexRes->heap_iptr;
-		heap_fetch(pg_largeobject, SnapshotNow, &tuple, &buffer, sd);
-		pfree(indexRes);
-		if (tuple.t_data != NULL)
-		{
-			simple_heap_delete(pg_largeobject, &tuple.t_self);
-			ReleaseBuffer(buffer);
-			found = true;
-		}
+		simple_heap_delete(pg_largeobject, &tuple->t_self);
+		found = true;
 	}
 
 	index_endscan(sd);
@@ -136,9 +124,7 @@ LargeObjectExists(Oid loid)
 	Relation	pg_lo_idx;
 	ScanKeyData skey[1];
 	IndexScanDesc sd;
-	RetrieveIndexResult indexRes;
-	HeapTupleData tuple;
-	Buffer		buffer;
+	HeapTuple	tuple;
 
 	/*
 	 * See if we can find any tuples belonging to the specified LO
@@ -152,23 +138,10 @@ LargeObjectExists(Oid loid)
 	pg_largeobject = heap_openr(LargeObjectRelationName, RowShareLock);
 	pg_lo_idx = index_openr(LargeObjectLOidPNIndex);
 
-	sd = index_beginscan(pg_lo_idx, false, 1, skey);
-
-	tuple.t_datamcxt = CurrentMemoryContext;
-	tuple.t_data = NULL;
+	sd = index_beginscan(pg_largeobject, pg_lo_idx, SnapshotNow, 1, skey);
 
-	while ((indexRes = index_getnext(sd, ForwardScanDirection)))
-	{
-		tuple.t_self = indexRes->heap_iptr;
-		heap_fetch(pg_largeobject, SnapshotNow, &tuple, &buffer, sd);
-		pfree(indexRes);
-		if (tuple.t_data != NULL)
-		{
-			retval = true;
-			ReleaseBuffer(buffer);
-			break;
-		}
-	}
+	if ((tuple = index_getnext(sd, ForwardScanDirection)) != NULL)
+		retval = true;
 
 	index_endscan(sd);
 
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index f4c8e6919e146c8365ced3fe7e5237b5bb596fb0..c015043843843bef5a0655d4fcbc629f315a12a0 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.32 2002/04/16 23:08:10 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.33 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -524,8 +524,8 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
 	/*
 	 * Do a simple linear scan until we reach the target number of rows.
 	 */
-	scan = heap_beginscan(onerel, false, SnapshotNow, 0, NULL);
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	scan = heap_beginscan(onerel, SnapshotNow, 0, NULL);
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		rows[numrows++] = heap_copytuple(tuple);
 		if (numrows >= targrows)
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 8193174aec946576d9595b627dd0a933c6f8eb61..271be1511955c3c6b493f4aed381203a7fc1a2ee 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.84 2002/05/05 00:03:28 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.85 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -204,8 +204,8 @@ Async_Listen(char *relname, int pid)
 	lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
 
 	/* Detect whether we are already listening on this relname */
-	scan = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	scan = heap_beginscan(lRel, SnapshotNow, 0, (ScanKey) NULL);
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_listener listener = (Form_pg_listener) GETSTRUCT(tuple);
 
@@ -305,8 +305,8 @@ Async_Unlisten(char *relname, int pid)
 
 	lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
 
-	scan = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	scan = heap_beginscan(lRel, SnapshotNow, 0, (ScanKey) NULL);
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_listener listener = (Form_pg_listener) GETSTRUCT(tuple);
 
@@ -369,9 +369,9 @@ Async_UnlistenAll(void)
 						   Anum_pg_listener_pid,
 						   F_INT4EQ,
 						   Int32GetDatum(MyProcPid));
-	scan = heap_beginscan(lRel, 0, SnapshotNow, 1, key);
+	scan = heap_beginscan(lRel, SnapshotNow, 1, key);
 
-	while (HeapTupleIsValid(lTuple = heap_getnext(scan, 0)))
+	while ((lTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 		simple_heap_delete(lRel, &lTuple->t_self);
 
 	heap_endscan(scan);
@@ -472,9 +472,9 @@ AtCommit_Notify(void)
 
 	lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
 	tdesc = RelationGetDescr(lRel);
-	scan = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
+	scan = heap_beginscan(lRel, SnapshotNow, 0, (ScanKey) NULL);
 
-	while (HeapTupleIsValid(lTuple = heap_getnext(scan, 0)))
+	while ((lTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_listener listener = (Form_pg_listener) GETSTRUCT(lTuple);
 		char	   *relname = NameStr(listener->relname);
@@ -773,7 +773,7 @@ ProcessIncomingNotify(void)
 						   Anum_pg_listener_pid,
 						   F_INT4EQ,
 						   Int32GetDatum(MyProcPid));
-	scan = heap_beginscan(lRel, 0, SnapshotNow, 1, key);
+	scan = heap_beginscan(lRel, SnapshotNow, 1, key);
 
 	/* Prepare data for rewriting 0 into notification field */
 	nulls[0] = nulls[1] = nulls[2] = ' ';
@@ -782,7 +782,7 @@ ProcessIncomingNotify(void)
 	value[0] = value[1] = value[2] = (Datum) 0;
 	value[Anum_pg_listener_notify - 1] = Int32GetDatum(0);
 
-	while (HeapTupleIsValid(lTuple = heap_getnext(scan, 0)))
+	while ((lTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_listener listener = (Form_pg_listener) GETSTRUCT(lTuple);
 		char	   *relname = NameStr(listener->relname);
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 01a45b0625b25d7ebaf36f11d2cb05c588da78ed..a6215cb23f4140bad06238cd4bc28520db985c93 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.79 2002/04/27 21:24:34 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.80 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -217,7 +217,7 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
 				LocalOldHeap,
 				LocalOldIndex;
 	IndexScanDesc ScanDesc;
-	RetrieveIndexResult ScanResult;
+	HeapTuple	LocalHeapTuple;
 
 	/*
 	 * Open the relations I need. Scan through the OldHeap on the OldIndex
@@ -227,36 +227,24 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
 	LocalOldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
 	LocalOldIndex = index_open(OIDOldIndex);
 
-	ScanDesc = index_beginscan(LocalOldIndex, false, 0, (ScanKey) NULL);
+	ScanDesc = index_beginscan(LocalOldHeap, LocalOldIndex,
+							   SnapshotNow, 0, (ScanKey) NULL);
 
-	while ((ScanResult = index_getnext(ScanDesc, ForwardScanDirection)) != NULL)
+	while ((LocalHeapTuple = index_getnext(ScanDesc, ForwardScanDirection)) != NULL)
 	{
-		HeapTupleData LocalHeapTuple;
-		Buffer		LocalBuffer;
+		/*
+		 * We must copy the tuple because heap_insert() will overwrite
+		 * the commit-status fields of the tuple it's handed, and the
+		 * retrieved tuple will actually be in a disk buffer!  Thus,
+		 * the source relation would get trashed, which is bad news if
+		 * we abort later on.  (This was a bug in releases thru 7.0)
+		 */
+		HeapTuple	copiedTuple = heap_copytuple(LocalHeapTuple);
+
+		heap_insert(LocalNewHeap, copiedTuple);
+		heap_freetuple(copiedTuple);
 
 		CHECK_FOR_INTERRUPTS();
-
-		LocalHeapTuple.t_self = ScanResult->heap_iptr;
-		LocalHeapTuple.t_datamcxt = NULL;
-		LocalHeapTuple.t_data = NULL;
-		heap_fetch(LocalOldHeap, SnapshotNow, &LocalHeapTuple, &LocalBuffer,
-				   ScanDesc);
-		if (LocalHeapTuple.t_data != NULL)
-		{
-			/*
-			 * We must copy the tuple because heap_insert() will overwrite
-			 * the commit-status fields of the tuple it's handed, and the
-			 * retrieved tuple will actually be in a disk buffer!  Thus,
-			 * the source relation would get trashed, which is bad news if
-			 * we abort later on.  (This was a bug in releases thru 7.0)
-			 */
-			HeapTuple	copiedTuple = heap_copytuple(&LocalHeapTuple);
-
-			ReleaseBuffer(LocalBuffer);
-			heap_insert(LocalNewHeap, copiedTuple);
-			heap_freetuple(copiedTuple);
-		}
-		pfree(ScanResult);
 	}
 
 	index_endscan(ScanDesc);
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 1c12061ba553d297a2707391bc896da84f438294..9d48e33b2c0c0fd92f7dcb0e97a2c56f8d3f06d6 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -7,7 +7,7 @@
  * Copyright (c) 1999-2001, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.46 2002/05/13 17:45:30 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.47 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -122,12 +122,9 @@ void
 CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
 {
 	Relation	description;
-	Relation	descriptionindex;
 	ScanKeyData skey[3];
-	IndexScanDesc sd;
-	RetrieveIndexResult indexRes;
-	HeapTupleData oldtuple;
-	Buffer		buffer;
+	SysScanDesc sd;
+	HeapTuple	oldtuple;
 	HeapTuple	newtuple = NULL;
 	Datum		values[Natts_pg_description];
 	char		nulls[Natts_pg_description];
@@ -153,11 +150,6 @@ CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
 		values[i++] = DirectFunctionCall1(textin, CStringGetDatum(comment));
 	}
 
-	/* Open pg_description and its index */
-
-	description = heap_openr(DescriptionRelationName, RowExclusiveLock);
-	descriptionindex = index_openr(DescriptionObjIndex);
-
 	/* Use the index to search for a matching old tuple */
 
 	ScanKeyEntryInitialize(&skey[0],
@@ -178,40 +170,32 @@ CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
 						   (RegProcedure) F_INT4EQ,
 						   Int32GetDatum(subid));
 
-	sd = index_beginscan(descriptionindex, false, 3, skey);
+	description = heap_openr(DescriptionRelationName, RowExclusiveLock);
 
-	oldtuple.t_datamcxt = CurrentMemoryContext;
-	oldtuple.t_data = NULL;
+	sd = systable_beginscan(description, DescriptionObjIndex, true,
+							SnapshotNow, 3, skey);
 
-	while ((indexRes = index_getnext(sd, ForwardScanDirection)))
+	while ((oldtuple = systable_getnext(sd)) != NULL)
 	{
-		oldtuple.t_self = indexRes->heap_iptr;
-		heap_fetch(description, SnapshotNow, &oldtuple, &buffer, sd);
-		pfree(indexRes);
-
-		if (oldtuple.t_data == NULL)
-			continue;			/* time qual failed */
-
 		/* Found the old tuple, so delete or update it */
 
 		if (comment == NULL)
-			simple_heap_delete(description, &oldtuple.t_self);
+			simple_heap_delete(description, &oldtuple->t_self);
 		else
 		{
-			newtuple = heap_modifytuple(&oldtuple, description, values,
+			newtuple = heap_modifytuple(oldtuple, description, values,
 										nulls, replaces);
-			simple_heap_update(description, &oldtuple.t_self, newtuple);
+			simple_heap_update(description, &oldtuple->t_self, newtuple);
 		}
 
-		ReleaseBuffer(buffer);
 		break;					/* Assume there can be only one match */
 	}
 
-	index_endscan(sd);
+	systable_endscan(sd);
 
 	/* If we didn't find an old tuple, insert a new one */
 
-	if (oldtuple.t_data == NULL && comment != NULL)
+	if (newtuple == NULL && comment != NULL)
 	{
 		newtuple = heap_formtuple(RelationGetDescr(description),
 								  values, nulls);
@@ -237,7 +221,6 @@ CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
 
 	/* Done */
 
-	index_close(descriptionindex);
 	heap_close(description, NoLock);
 }
 
@@ -252,17 +235,9 @@ void
 DeleteComments(Oid oid, Oid classoid)
 {
 	Relation	description;
-	Relation	descriptionindex;
 	ScanKeyData skey[2];
-	IndexScanDesc sd;
-	RetrieveIndexResult indexRes;
-	HeapTupleData oldtuple;
-	Buffer		buffer;
-
-	/* Open pg_description and its index */
-
-	description = heap_openr(DescriptionRelationName, RowExclusiveLock);
-	descriptionindex = index_openr(DescriptionObjIndex);
+	SysScanDesc	sd;
+	HeapTuple	oldtuple;
 
 	/* Use the index to search for all matching old tuples */
 
@@ -278,26 +253,19 @@ DeleteComments(Oid oid, Oid classoid)
 						   (RegProcedure) F_OIDEQ,
 						   ObjectIdGetDatum(classoid));
 
-	sd = index_beginscan(descriptionindex, false, 2, skey);
-
-	while ((indexRes = index_getnext(sd, ForwardScanDirection)))
-	{
-		oldtuple.t_self = indexRes->heap_iptr;
-		heap_fetch(description, SnapshotNow, &oldtuple, &buffer, sd);
-		pfree(indexRes);
-
-		if (oldtuple.t_data == NULL)
-			continue;			/* time qual failed */
+	description = heap_openr(DescriptionRelationName, RowExclusiveLock);
 
-		simple_heap_delete(description, &oldtuple.t_self);
+	sd = systable_beginscan(description, DescriptionObjIndex, true,
+							SnapshotNow, 2, skey);
 
-		ReleaseBuffer(buffer);
+	while ((oldtuple = systable_getnext(sd)) != NULL)
+	{
+		simple_heap_delete(description, &oldtuple->t_self);
 	}
 
 	/* Done */
 
-	index_endscan(sd);
-	index_close(descriptionindex);
+	systable_endscan(sd);
 	heap_close(description, NoLock);
 }
 
@@ -449,8 +417,8 @@ CommentDatabase(List *qualname, char *comment)
 	pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
 	ScanKeyEntryInitialize(&entry, 0, Anum_pg_database_datname,
 						   F_NAMEEQ, CStringGetDatum(database));
-	scan = heap_beginscan(pg_database, 0, SnapshotNow, 1, &entry);
-	dbtuple = heap_getnext(scan, 0);
+	scan = heap_beginscan(pg_database, SnapshotNow, 1, &entry);
+	dbtuple = heap_getnext(scan, ForwardScanDirection);
 
 	/* Validate database exists, and fetch the db oid */
 
@@ -566,10 +534,10 @@ CommentRule(List *qualname, char *comment)
 							   PointerGetDatum(rulename));
 
 		RewriteRelation = heap_openr(RewriteRelationName, AccessShareLock);
-		scanDesc = heap_beginscan(RewriteRelation,
-								  0, SnapshotNow, 1, &scanKeyData);
+		scanDesc = heap_beginscan(RewriteRelation, SnapshotNow,
+								  1, &scanKeyData);
 
-		tuple = heap_getnext(scanDesc, 0);
+		tuple = heap_getnext(scanDesc, ForwardScanDirection);
 		if (HeapTupleIsValid(tuple))
 		{
 			reloid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
@@ -581,7 +549,8 @@ CommentRule(List *qualname, char *comment)
 			reloid = ruleoid = 0; /* keep compiler quiet */
 		}
 
-		if (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0)))
+		if (HeapTupleIsValid(tuple = heap_getnext(scanDesc,
+												  ForwardScanDirection)))
 			elog(ERROR, "There are multiple rules \"%s\""
 				 "\n\tPlease specify a relation name as well as a rule name",
 				 rulename);
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 1ab3ae14fcf4d4ad3f24600f99a93ac79d205385..1f9aef8fc0dc7e739a8b2325922d3807bb35d305 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.153 2002/04/27 03:45:00 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.154 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -494,9 +494,9 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp,
 		CopySendData(&tmp, sizeof(int32), fp);
 	}
 
-	scandesc = heap_beginscan(rel, 0, QuerySnapshot, 0, NULL);
+	scandesc = heap_beginscan(rel, QuerySnapshot, 0, NULL);
 
-	while (HeapTupleIsValid(tuple = heap_getnext(scandesc, 0)))
+	while ((tuple = heap_getnext(scandesc, ForwardScanDirection)) != NULL)
 	{
 		bool		need_delim = false;
 
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index bb53ad8b3bbdccfd4c6c74a665c87e9bc37091db..d4bc274ba29575615b933ac94069e2700438f92c 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.89 2002/05/17 01:19:17 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.90 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -387,9 +387,9 @@ dropdb(const char *dbname)
 	ScanKeyEntryInitialize(&key, 0, ObjectIdAttributeNumber,
 						   F_OIDEQ, ObjectIdGetDatum(db_id));
 
-	pgdbscan = heap_beginscan(pgdbrel, 0, SnapshotNow, 1, &key);
+	pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key);
 
-	tup = heap_getnext(pgdbscan, 0);
+	tup = heap_getnext(pgdbscan, ForwardScanDirection);
 	if (!HeapTupleIsValid(tup))
 	{
 		/*
@@ -463,8 +463,8 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
 	rel = heap_openr(DatabaseRelationName, RowExclusiveLock);
 	ScanKeyEntryInitialize(&scankey, 0, Anum_pg_database_datname,
 						   F_NAMEEQ, NameGetDatum(stmt->dbname));
-	scan = heap_beginscan(rel, 0, SnapshotNow, 1, &scankey);
-	tuple = heap_getnext(scan, 0);
+	scan = heap_beginscan(rel, SnapshotNow, 1, &scankey);
+	tuple = heap_getnext(scan, ForwardScanDirection);
 	if (!HeapTupleIsValid(tuple))
 		elog(ERROR, "database \"%s\" does not exist", stmt->dbname);
 
@@ -535,9 +535,9 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
 	ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
 						   F_NAMEEQ, NameGetDatum(name));
 
-	scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scanKey);
+	scan = heap_beginscan(relation, SnapshotNow, 1, &scanKey);
 
-	tuple = heap_getnext(scan, 0);
+	tuple = heap_getnext(scan, ForwardScanDirection);
 
 	gottuple = HeapTupleIsValid(tuple);
 	if (gottuple)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index e2ae7f06314dd0509b6916af22cdc99fa464b697..ba270838b6dbe25a32b725d79dc3242c7bbe7ba0 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.73 2002/05/12 20:10:02 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.74 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -736,9 +736,9 @@ ReindexDatabase(const char *dbname, bool force, bool all)
 	 * Scan pg_class to build a list of the relations we need to reindex.
 	 */
 	relationRelation = heap_openr(RelationRelationName, AccessShareLock);
-	scan = heap_beginscan(relationRelation, false, SnapshotNow, 0, NULL);
+	scan = heap_beginscan(relationRelation, SnapshotNow, 0, NULL);
 	relcnt = relalc = 0;
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		if (!all)
 		{
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 864ad65eab0684114baa46cd251f6f479c9f2b82..f2bbdb01075d4085beb9be9bd21fbeda23d21945 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.14 2002/05/17 22:35:12 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.15 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1314,32 +1314,38 @@ update_ri_trigger_args(Oid relid,
 					   bool update_relname)
 {
 	Relation	tgrel;
-	Relation	irel;
 	ScanKeyData skey[1];
-	IndexScanDesc idxtgscan;
-	RetrieveIndexResult idxres;
+	SysScanDesc	trigscan;
+	HeapTuple	tuple;
 	Datum		values[Natts_pg_trigger];
 	char		nulls[Natts_pg_trigger];
 	char		replaces[Natts_pg_trigger];
 
 	tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
 	if (fk_scan)
-		irel = index_openr(TriggerConstrRelidIndex);
+	{
+		ScanKeyEntryInitialize(&skey[0], 0x0,
+							   Anum_pg_trigger_tgconstrrelid,
+							   F_OIDEQ,
+							   ObjectIdGetDatum(relid));
+		trigscan = systable_beginscan(tgrel, TriggerConstrRelidIndex,
+									  true, SnapshotNow,
+									  1, skey);
+	}
 	else
-		irel = index_openr(TriggerRelidNameIndex);
-
-	ScanKeyEntryInitialize(&skey[0], 0x0,
-						   1,	/* column 1 of index in either case */
-						   F_OIDEQ,
-						   ObjectIdGetDatum(relid));
-	idxtgscan = index_beginscan(irel, false, 1, skey);
+	{
+		ScanKeyEntryInitialize(&skey[0], 0x0,
+							   Anum_pg_trigger_tgrelid,
+							   F_OIDEQ,
+							   ObjectIdGetDatum(relid));
+		trigscan = systable_beginscan(tgrel, TriggerRelidNameIndex,
+									  true, SnapshotNow,
+									  1, skey);
+	}
 
-	while ((idxres = index_getnext(idxtgscan, ForwardScanDirection)) != NULL)
+	while ((tuple = systable_getnext(trigscan)) != NULL)
 	{
-		HeapTupleData tupledata;
-		Buffer		buffer;
-		HeapTuple	tuple;
-		Form_pg_trigger pg_trigger;
+		Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
 		bytea	   *val;
 		bytea	   *newtgargs;
 		bool		isnull;
@@ -1352,18 +1358,10 @@ update_ri_trigger_args(Oid relid,
 		const char *arga[RI_MAX_ARGUMENTS];
 		const char *argp;
 
-		tupledata.t_self = idxres->heap_iptr;
-		heap_fetch(tgrel, SnapshotNow, &tupledata, &buffer, idxtgscan);
-		pfree(idxres);
-		if (!tupledata.t_data)
-			continue;
-		tuple = &tupledata;
-		pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
 		tg_type = ri_trigger_type(pg_trigger->tgfoid);
 		if (tg_type == RI_TRIGGER_NONE)
 		{
 			/* Not an RI trigger, forget it */
-			ReleaseBuffer(buffer);
 			continue;
 		}
 
@@ -1381,7 +1379,6 @@ update_ri_trigger_args(Oid relid,
 			tgnargs > RI_MAX_ARGUMENTS)
 		{
 			/* This probably shouldn't happen, but ignore busted triggers */
-			ReleaseBuffer(buffer);
 			continue;
 		}
 		argp = (const char *) VARDATA(val);
@@ -1429,7 +1426,6 @@ update_ri_trigger_args(Oid relid,
 		if (!changed)
 		{
 			/* Don't need to update this tuple */
-			ReleaseBuffer(buffer);
 			continue;
 		}
 
@@ -1462,11 +1458,6 @@ update_ri_trigger_args(Oid relid,
 
 		tuple = heap_modifytuple(tuple, tgrel, values, nulls, replaces);
 
-		/*
-		 * Now we can release hold on original tuple.
-		 */
-		ReleaseBuffer(buffer);
-
 		/*
 		 * Update pg_trigger and its indexes
 		 */
@@ -1485,8 +1476,7 @@ update_ri_trigger_args(Oid relid,
 		heap_freetuple(tuple);
 	}
 
-	index_endscan(idxtgscan);
-	index_close(irel);
+	systable_endscan(trigscan);
 
 	heap_close(tgrel, RowExclusiveLock);
 
@@ -1979,9 +1969,9 @@ AlterTableAlterColumnSetNotNull(Oid myrelid,
 	 */
 	tupdesc = RelationGetDescr(rel);
 
-	scan = heap_beginscan(rel, false, SnapshotNow, 0, NULL);
+	scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
 
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Datum 		d;
 		bool		isnull;
@@ -2177,9 +2167,9 @@ drop_default(Oid relid, int16 attnum)
 						   Anum_pg_attrdef_adnum, F_INT2EQ,
 						   Int16GetDatum(attnum));
 
-	scan = heap_beginscan(attrdef_rel, false, SnapshotNow, 2, scankeys);
+	scan = heap_beginscan(attrdef_rel, SnapshotNow, 2, scankeys);
 
-	if (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	if ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 		simple_heap_delete(attrdef_rel, &tuple->t_self);
 
 	heap_endscan(scan);
@@ -2501,9 +2491,9 @@ AlterTableAddConstraint(Oid myrelid,
 								 * Scan through the rows now, checking the
 								 * expression at each row.
 								 */
-								scan = heap_beginscan(rel, false, SnapshotNow, 0, NULL);
+								scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
 
-								while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+								while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 								{
 									ExecStoreTuple(tuple, slot, InvalidBuffer, false);
 									if (!ExecQual(qual, econtext, true))
@@ -2621,9 +2611,9 @@ AlterTableAddConstraint(Oid myrelid,
 					}
 					trig.tgnargs = count - 1;
 
-					scan = heap_beginscan(rel, false, SnapshotNow, 0, NULL);
+					scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
 
-					while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+					while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 					{
 						/* Make a call to the check function */
 
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 5398d718b63b3ad2ca076395c3eb1859a1f2793b..c7c3da9dd42ef4f79802485f805ae483b19842ef 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.101 2002/05/17 01:19:17 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.102 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -140,8 +140,8 @@ write_group_file(Relation urel, Relation grel)
 		elog(ERROR, "write_group_file: unable to write %s: %m", tempname);
 
 	/* read table */
-	scan = heap_beginscan(grel, false, SnapshotSelf, 0, NULL);
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	scan = heap_beginscan(grel, SnapshotSelf, 0, NULL);
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Datum		datum, grolist_datum;
 		bool		isnull;
@@ -284,8 +284,8 @@ write_user_file(Relation urel)
 		elog(ERROR, "write_password_file: unable to write %s: %m", tempname);
 
 	/* read table */
-	scan = heap_beginscan(urel, false, SnapshotSelf, 0, NULL);
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	scan = heap_beginscan(urel, SnapshotSelf, 0, NULL);
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Datum		datum;
 		bool		isnull;
@@ -517,10 +517,10 @@ CreateUser(CreateUserStmt *stmt)
 	pg_shadow_rel = heap_openr(ShadowRelationName, ExclusiveLock);
 	pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
 
-	scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, NULL);
+	scan = heap_beginscan(pg_shadow_rel, SnapshotNow, 0, NULL);
 	max_id = 99;				/* start auto-assigned ids at 100 */
 	while (!user_exists && !sysid_exists &&
-		   HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+		   (tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_shadow shadow_form = (Form_pg_shadow) GETSTRUCT(tuple);
 		int32		this_sysid;
@@ -977,9 +977,9 @@ DropUser(DropUserStmt *stmt)
 							   Anum_pg_database_datdba, F_INT4EQ,
 							   Int32GetDatum(usesysid));
 
-		scan = heap_beginscan(pg_rel, false, SnapshotNow, 1, &scankey);
+		scan = heap_beginscan(pg_rel, SnapshotNow, 1, &scankey);
 
-		if (HeapTupleIsValid(tmp_tuple = heap_getnext(scan, 0)))
+		if ((tmp_tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 		{
 			char	   *dbname;
 
@@ -1012,8 +1012,8 @@ DropUser(DropUserStmt *stmt)
 		 */
 		pg_rel = heap_openr(GroupRelationName, ExclusiveLock);
 		pg_dsc = RelationGetDescr(pg_rel);
-		scan = heap_beginscan(pg_rel, false, SnapshotNow, 0, NULL);
-		while (HeapTupleIsValid(tmp_tuple = heap_getnext(scan, 0)))
+		scan = heap_beginscan(pg_rel, SnapshotNow, 0, NULL);
+		while ((tmp_tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 		{
 			AlterGroupStmt ags;
 
@@ -1148,10 +1148,10 @@ CreateGroup(CreateGroupStmt *stmt)
 	pg_group_rel = heap_openr(GroupRelationName, ExclusiveLock);
 	pg_group_dsc = RelationGetDescr(pg_group_rel);
 
-	scan = heap_beginscan(pg_group_rel, false, SnapshotNow, 0, NULL);
+	scan = heap_beginscan(pg_group_rel, SnapshotNow, 0, NULL);
 	max_id = 99;				/* start auto-assigned ids at 100 */
 	while (!group_exists && !sysid_exists &&
-		   HeapTupleIsValid(tuple = heap_getnext(scan, false)))
+		   (tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_group group_form = (Form_pg_group) GETSTRUCT(tuple);
 		int32		this_sysid;
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index eaee990c69d85631059f9e27344dbe14c459a0bc..4889e30040682fe654940fe984aed0a80442279f 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.224 2002/04/15 23:39:42 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.225 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -350,9 +350,9 @@ getrels(const RangeVar *vacrel, const char *stmttype)
 
 		pgclass = heap_openr(RelationRelationName, AccessShareLock);
 
-		scan = heap_beginscan(pgclass, false, SnapshotNow, 1, &key);
+		scan = heap_beginscan(pgclass, SnapshotNow, 1, &key);
 
-		while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+		while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 		{
 			/* Make a relation list entry for this guy */
 			oldcontext = MemoryContextSwitchTo(vac_context);
@@ -521,9 +521,9 @@ vac_update_dbstats(Oid dbid,
 						   ObjectIdAttributeNumber, F_OIDEQ,
 						   ObjectIdGetDatum(dbid));
 
-	scan = heap_beginscan(relation, 0, SnapshotNow, 1, entry);
+	scan = heap_beginscan(relation, SnapshotNow, 1, entry);
 
-	tuple = heap_getnext(scan, 0);
+	tuple = heap_getnext(scan, ForwardScanDirection);
 
 	if (!HeapTupleIsValid(tuple))
 		elog(ERROR, "database %u does not exist", dbid);
@@ -573,9 +573,9 @@ vac_truncate_clog(TransactionId vacuumXID, TransactionId frozenXID)
 
 	relation = heap_openr(DatabaseRelationName, AccessShareLock);
 
-	scan = heap_beginscan(relation, 0, SnapshotNow, 0, NULL);
+	scan = heap_beginscan(relation, SnapshotNow, 0, NULL);
 
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_database dbform = (Form_pg_database) GETSTRUCT(tuple);
 
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 3ab73f62f9a9746d77e6eb0d4eea8dda256f3643..f258ba9ba83731367b6f994f38c1f26b385e2af5 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.67 2002/02/19 20:11:13 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.68 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -72,14 +72,10 @@ IndexNext(IndexScan *node)
 	IndexScanState *indexstate;
 	ExprContext *econtext;
 	ScanDirection direction;
-	Snapshot	snapshot;
 	IndexScanDescPtr scanDescs;
 	IndexScanDesc scandesc;
-	Relation	heapRelation;
-	RetrieveIndexResult result;
 	HeapTuple	tuple;
 	TupleTableSlot *slot;
-	Buffer		buffer = InvalidBuffer;
 	int			numIndices;
 	bool		bBackward;
 	int			indexNumber;
@@ -96,11 +92,9 @@ IndexNext(IndexScan *node)
 		else if (ScanDirectionIsBackward(direction))
 			direction = ForwardScanDirection;
 	}
-	snapshot = estate->es_snapshot;
 	scanstate = node->scan.scanstate;
 	indexstate = node->indxstate;
 	scanDescs = indexstate->iss_ScanDescs;
-	heapRelation = scanstate->css_currentRelation;
 	numIndices = indexstate->iss_NumIndices;
 	econtext = scanstate->cstate.cs_ExprContext;
 	slot = scanstate->css_ScanTupleSlot;
@@ -142,8 +136,6 @@ IndexNext(IndexScan *node)
 		return slot;
 	}
 
-	tuple = &(indexstate->iss_htup);
-
 	/*
 	 * ok, now that we have what we need, fetch an index tuple. if
 	 * scanning this index succeeded then return the appropriate heap
@@ -170,48 +162,37 @@ IndexNext(IndexScan *node)
 	while (indexNumber < numIndices)
 	{
 		scandesc = scanDescs[indexstate->iss_IndexPtr];
-		while ((result = index_getnext(scandesc, direction)) != NULL)
+		while ((tuple = index_getnext(scandesc, direction)) != NULL)
 		{
-			tuple->t_self = result->heap_iptr;
-			heap_fetch(heapRelation, snapshot, tuple, &buffer, scandesc);
-			pfree(result);
+			/*
+			 * store the scanned tuple in the scan tuple slot of the
+			 * scan state.  Note: we pass 'false' because tuples
+			 * returned by amgetnext are pointers onto disk pages and
+			 * must not be pfree()'d.
+			 */
+			ExecStoreTuple(tuple,	/* tuple to store */
+						   slot,	/* slot to store in */
+						   scandesc->xs_cbuf, /* buffer containing tuple */
+						   false);	/* don't pfree */
 
-			if (tuple->t_data != NULL)
+			/*
+			 * We must check to see if the current tuple was already
+			 * matched by an earlier index, so we don't double-report
+			 * it. We do this by passing the tuple through ExecQual
+			 * and checking for failure with all previous
+			 * qualifications.
+			 */
+			if (indexstate->iss_IndexPtr > 0)
 			{
 				bool		prev_matches = false;
 				int			prev_index;
 				List	   *qual;
 
-				/*
-				 * store the scanned tuple in the scan tuple slot of the
-				 * scan state.	Eventually we will only do this and not
-				 * return a tuple.	Note: we pass 'false' because tuples
-				 * returned by amgetnext are pointers onto disk pages and
-				 * must not be pfree()'d.
-				 */
-				ExecStoreTuple(tuple,	/* tuple to store */
-							   slot,	/* slot to store in */
-							   buffer,	/* buffer associated with tuple  */
-							   false);	/* don't pfree */
-
-				/*
-				 * At this point we have an extra pin on the buffer,
-				 * because ExecStoreTuple incremented the pin count. Drop
-				 * our local pin.
-				 */
-				ReleaseBuffer(buffer);
-
-				/*
-				 * We must check to see if the current tuple was already
-				 * matched by an earlier index, so we don't double-report
-				 * it. We do this by passing the tuple through ExecQual
-				 * and checking for failure with all previous
-				 * qualifications.
-				 */
 				econtext->ecxt_scantuple = slot;
 				ResetExprContext(econtext);
 				qual = node->indxqualorig;
-				for (prev_index = 0; prev_index < indexstate->iss_IndexPtr;
+				for (prev_index = 0;
+					 prev_index < indexstate->iss_IndexPtr;
 					 prev_index++)
 				{
 					if (ExecQual((List *) lfirst(qual), econtext, false))
@@ -221,12 +202,17 @@ IndexNext(IndexScan *node)
 					}
 					qual = lnext(qual);
 				}
-				if (!prev_matches)
-					return slot;	/* OK to return tuple */
-				/* Duplicate tuple, so drop it and loop back for another */
-				ExecClearTuple(slot);
+				if (prev_matches)
+				{
+					/* Duplicate, so drop it and loop back for another */
+					ExecClearTuple(slot);
+					continue;
+				}
 			}
+
+			return slot;		/* OK to return tuple */
 		}
+
 		if (indexNumber < numIndices)
 		{
 			indexNumber++;
@@ -300,7 +286,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
 	EState	   *estate;
 	IndexScanState *indexstate;
 	ExprContext *econtext;
-	ScanDirection direction;
 	int			numIndices;
 	IndexScanDescPtr scanDescs;
 	ScanKey    *scanKeys;
@@ -313,7 +298,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
 	indexstate = node->indxstate;
 	econtext = indexstate->iss_RuntimeContext;	/* context for runtime
 												 * keys */
-	direction = estate->es_direction;
 	numIndices = indexstate->iss_NumIndices;
 	scanDescs = indexstate->iss_ScanDescs;
 	scanKeys = indexstate->iss_ScanKeys;
@@ -431,7 +415,7 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
 		IndexScanDesc scan = scanDescs[i];
 		ScanKey		skey = scanKeys[i];
 
-		index_rescan(scan, direction, skey);
+		index_rescan(scan, skey);
 	}
 }
 
@@ -622,16 +606,14 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
 	int			indexPtr;
 	ScanKey    *scanKeys;
 	int		   *numScanKeys;
-	RelationPtr relationDescs;
+	RelationPtr indexDescs;
 	IndexScanDescPtr scanDescs;
 	int		  **runtimeKeyInfo;
 	bool		have_runtime_keys;
-	List	   *rangeTable;
 	RangeTblEntry *rtentry;
 	Index		relid;
 	Oid			reloid;
 	Relation	currentRelation;
-	ScanDirection direction;
 
 	/*
 	 * assign execution state to node
@@ -701,7 +683,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
 	 */
 	numScanKeys = (int *) palloc(numIndices * sizeof(int));
 	scanKeys = (ScanKey *) palloc(numIndices * sizeof(ScanKey));
-	relationDescs = (RelationPtr) palloc(numIndices * sizeof(Relation));
+	indexDescs = (RelationPtr) palloc(numIndices * sizeof(Relation));
 	scanDescs = (IndexScanDescPtr) palloc(numIndices * sizeof(IndexScanDesc));
 
 	/*
@@ -1010,18 +992,11 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
 		pfree(runtimeKeyInfo);
 	}
 
-	/*
-	 * get the range table and direction information from the execution
-	 * state (these are needed to open the relations).
-	 */
-	rangeTable = estate->es_range_table;
-	direction = estate->es_direction;
-
 	/*
 	 * open the base relation and acquire AccessShareLock on it.
 	 */
 	relid = node->scan.scanrelid;
-	rtentry = rt_fetch(relid, rangeTable);
+	rtentry = rt_fetch(relid, estate->es_range_table);
 	reloid = rtentry->relid;
 
 	currentRelation = heap_open(reloid, AccessShareLock);
@@ -1049,24 +1024,16 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
 	{
 		Oid			indexOid = (Oid) lfirsti(listscan);
 
-		if (indexOid != 0)
-		{
-			relationDescs[i] = index_open(indexOid);
-
-			/*
-			 * Note: index_beginscan()'s second arg is a boolean indicating
-			 * that the scan should be done in reverse.  That is, if you pass
-			 * it true, then the scan is backward.
-			 */
-			scanDescs[i] = index_beginscan(relationDescs[i],
-										   false, /* see above comment */
-										   numScanKeys[i],
-										   scanKeys[i]);
-		}
+		indexDescs[i] = index_open(indexOid);
+		scanDescs[i] = index_beginscan(currentRelation,
+									   indexDescs[i],
+									   estate->es_snapshot,
+									   numScanKeys[i],
+									   scanKeys[i]);
 		listscan = lnext(listscan);
 	}
 
-	indexstate->iss_RelationDescs = relationDescs;
+	indexstate->iss_RelationDescs = indexDescs;
 	indexstate->iss_ScanDescs = scanDescs;
 
 	/*
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 957a1bb2b722813b2f888cc0969616ed7a4b7d46..2ad3193debc25a1d71535a6b30963d6345eec638 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.34 2002/02/19 20:11:14 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.35 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -93,7 +93,7 @@ SeqNext(SeqScan *node)
 	/*
 	 * get the next tuple from the access methods
 	 */
-	tuple = heap_getnext(scandesc, ScanDirectionIsBackward(direction));
+	tuple = heap_getnext(scandesc, direction);
 
 	/*
 	 * save the tuple and the buffer returned to us by the access methods
@@ -148,7 +148,6 @@ InitScanRelation(SeqScan *node, EState *estate,
 	List	   *rangeTable;
 	RangeTblEntry *rtentry;
 	Oid			reloid;
-	ScanDirection direction;
 	Relation	currentRelation;
 	HeapScanDesc currentScanDesc;
 
@@ -162,12 +161,10 @@ InitScanRelation(SeqScan *node, EState *estate,
 	rangeTable = estate->es_range_table;
 	rtentry = rt_fetch(relid, rangeTable);
 	reloid = rtentry->relid;
-	direction = estate->es_direction;
 
 	currentRelation = heap_open(reloid, AccessShareLock);
 
 	currentScanDesc = heap_beginscan(currentRelation,
-									 ScanDirectionIsBackward(direction),
 									 estate->es_snapshot,
 									 0,
 									 NULL);
@@ -316,7 +313,6 @@ ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent)
 	CommonScanState *scanstate;
 	EState	   *estate;
 	HeapScanDesc scan;
-	ScanDirection direction;
 
 	scanstate = node->scanstate;
 	estate = node->plan.state;
@@ -330,10 +326,8 @@ ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent)
 	}
 
 	scan = scanstate->css_currentScanDesc;
-	direction = estate->es_direction;
 
 	heap_rescan(scan,			/* scan desc */
-				ScanDirectionIsBackward(direction), /* backward flag */
 				NULL);			/* new scan keys */
 }
 
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 6ec1d5af8fa66ab9777c501a1e211bb8f28fc631..f02195a4f702fa9583e6cbe1534570e50636a41e 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.117 2002/05/12 23:43:02 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.118 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1233,9 +1233,9 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
 						   ObjectIdGetDatum(pred_op));
 
 	relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
-	scan = heap_beginscan(relation, false, SnapshotNow, 1, entry);
+	scan = heap_beginscan(relation, SnapshotNow, 1, entry);
 
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		aform = (Form_pg_amop) GETSTRUCT(tuple);
 		if (opclass_is_btree(aform->amopclaid))
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 6ae9e1b7e903023d2c459dc8b552d25e28a2ec72..fbe36292a43a41af3a97891dc58dd14be9baf57f 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.71 2002/04/12 20:38:26 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.72 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -290,8 +290,8 @@ find_inheritance_children(Oid inhparent)
 						   (RegProcedure) F_OIDEQ,
 						   ObjectIdGetDatum(inhparent));
 	relation = heap_openr(InheritsRelationName, AccessShareLock);
-	scan = heap_beginscan(relation, 0, SnapshotNow, 1, key);
-	while (HeapTupleIsValid(inheritsTuple = heap_getnext(scan, 0)))
+	scan = heap_beginscan(relation, SnapshotNow, 1, key);
+	while ((inheritsTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		inhrelid = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhrelid;
 		list = lappendi(list, inhrelid);
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index ec54bae387bcfa5d8a6b36a32ee4a8c2da22e450..832195a21569119558598084d20a27ebc098b131 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.130 2002/05/17 22:35:13 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.131 2002/05/20 23:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -959,9 +959,9 @@ find_inheritors(Oid relid, Oid **supervec)
 							   F_OIDEQ,
 							   ObjectIdGetDatum(relid));
 
-		inhscan = heap_beginscan(inhrel, 0, SnapshotNow, 1, &skey);
+		inhscan = heap_beginscan(inhrel, SnapshotNow, 1, &skey);
 
-		while (HeapTupleIsValid(inhtup = heap_getnext(inhscan, 0)))
+		while ((inhtup = heap_getnext(inhscan, ForwardScanDirection)) != NULL)
 		{
 			Form_pg_inherits inh = (Form_pg_inherits) GETSTRUCT(inhtup);
 
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 15fbc31e6010e81e0caf04d797bb33395b51088f..b578305b4c5d04084bc70461ba84341704221821 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -16,7 +16,7 @@
  *
  *	Copyright (c) 2001, PostgreSQL Global Development Group
  *
- *	$Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.20 2002/05/05 00:03:28 tgl Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.21 2002/05/20 23:51:43 tgl Exp $
  * ----------
  */
 #include "postgres.h"
@@ -619,8 +619,8 @@ pgstat_vacuum_tabstat(void)
 	dbidlist = (Oid *) palloc(sizeof(Oid) * dbidalloc);
 
 	dbrel = heap_openr(DatabaseRelationName, AccessShareLock);
-	dbscan = heap_beginscan(dbrel, 0, SnapshotNow, 0, NULL);
-	while (HeapTupleIsValid(dbtup = heap_getnext(dbscan, FALSE)))
+	dbscan = heap_beginscan(dbrel, SnapshotNow, 0, NULL);
+	while ((dbtup = heap_getnext(dbscan, ForwardScanDirection)) != NULL)
 	{
 		if (dbidused >= dbidalloc)
 		{
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index f35540128cfa627e1df7f9d3a25055b24a474d0d..4b1799ff2e953161563cc3769e729ab04dd7ebfa 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.70 2002/05/12 20:10:04 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.71 2002/05/20 23:51:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -292,18 +292,11 @@ DefineQueryRewrite(RuleStmt *stmt)
 		if (event_relation->rd_rel->relkind != RELKIND_VIEW)
 		{
 			HeapScanDesc scanDesc;
-			HeapTuple	tuple;
 
-			scanDesc = heap_beginscan(event_relation, 0, SnapshotNow, 0, NULL);
-			tuple = heap_getnext(scanDesc, 0);
-			if (HeapTupleIsValid(tuple))
+			scanDesc = heap_beginscan(event_relation, SnapshotNow, 0, NULL);
+			if (heap_getnext(scanDesc, ForwardScanDirection) != NULL)
 				elog(ERROR, "Relation \"%s\" is not empty. Cannot convert it to view",
 					 event_obj->relname);
-
-			/*
-			 * don't need heap_freetuple because we never got a valid
-			 * tuple
-			 */
 			heap_endscan(scanDesc);
 
 			RelisBecomingView = true;
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index c3efe502708ffd25171e71ef195cad52b38c7158..a470a870df725500eb7b6b43d1bd7e0dc1525de2 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.90 2001/10/25 05:49:42 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.91 2002/05/20 23:51:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -198,12 +198,7 @@ inv_getsize(LargeObjectDesc *obj_desc)
 	uint32		lastbyte = 0;
 	ScanKeyData skey[1];
 	IndexScanDesc sd;
-	RetrieveIndexResult indexRes;
-	HeapTupleData tuple;
-	Buffer		buffer;
-	Form_pg_largeobject data;
-	bytea	   *datafield;
-	bool		pfreeit;
+	HeapTuple	tuple;
 
 	Assert(PointerIsValid(obj_desc));
 
@@ -213,10 +208,8 @@ inv_getsize(LargeObjectDesc *obj_desc)
 						   (RegProcedure) F_OIDEQ,
 						   ObjectIdGetDatum(obj_desc->id));
 
-	sd = index_beginscan(obj_desc->index_r, true, 1, skey);
-
-	tuple.t_datamcxt = CurrentMemoryContext;
-	tuple.t_data = NULL;
+	sd = index_beginscan(obj_desc->heap_r, obj_desc->index_r,
+						 SnapshotNow, 1, skey);
 
 	/*
 	 * Because the pg_largeobject index is on both loid and pageno, but we
@@ -224,15 +217,14 @@ 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 ((indexRes = index_getnext(sd, BackwardScanDirection)))
+	while ((tuple = index_getnext(sd, BackwardScanDirection)) != NULL)
 	{
-		tuple.t_self = indexRes->heap_iptr;
-		heap_fetch(obj_desc->heap_r, SnapshotNow, &tuple, &buffer, sd);
-		pfree(indexRes);
-		if (tuple.t_data == NULL)
-			continue;
+		Form_pg_largeobject data;
+		bytea	   *datafield;
+		bool		pfreeit;
+
 		found = true;
-		data = (Form_pg_largeobject) GETSTRUCT(&tuple);
+		data = (Form_pg_largeobject) GETSTRUCT(tuple);
 		datafield = &(data->data);
 		pfreeit = false;
 		if (VARATT_IS_EXTENDED(datafield))
@@ -244,7 +236,6 @@ inv_getsize(LargeObjectDesc *obj_desc)
 		lastbyte = data->pageno * LOBLKSIZE + getbytealen(datafield);
 		if (pfreeit)
 			pfree(datafield);
-		ReleaseBuffer(buffer);
 		break;
 	}
 
@@ -306,12 +297,7 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 	uint32		pageoff;
 	ScanKeyData skey[2];
 	IndexScanDesc sd;
-	RetrieveIndexResult indexRes;
-	HeapTupleData tuple;
-	Buffer		buffer;
-	Form_pg_largeobject data;
-	bytea	   *datafield;
-	bool		pfreeit;
+	HeapTuple	tuple;
 
 	Assert(PointerIsValid(obj_desc));
 	Assert(buf != NULL);
@@ -331,21 +317,16 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 						   (RegProcedure) F_INT4GE,
 						   Int32GetDatum(pageno));
 
-	sd = index_beginscan(obj_desc->index_r, false, 2, skey);
-
-	tuple.t_datamcxt = CurrentMemoryContext;
-	tuple.t_data = NULL;
+	sd = index_beginscan(obj_desc->heap_r, obj_desc->index_r,
+						 SnapshotNow, 2, skey);
 
-	while ((indexRes = index_getnext(sd, ForwardScanDirection)))
+	while ((tuple = index_getnext(sd, ForwardScanDirection)) != NULL)
 	{
-		tuple.t_self = indexRes->heap_iptr;
-		heap_fetch(obj_desc->heap_r, SnapshotNow, &tuple, &buffer, sd);
-		pfree(indexRes);
+		Form_pg_largeobject data;
+		bytea	   *datafield;
+		bool		pfreeit;
 
-		if (tuple.t_data == NULL)
-			continue;
-
-		data = (Form_pg_largeobject) GETSTRUCT(&tuple);
+		data = (Form_pg_largeobject) GETSTRUCT(tuple);
 
 		/*
 		 * We assume the indexscan will deliver pages in order.  However,
@@ -389,7 +370,6 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 				pfree(datafield);
 		}
 
-		ReleaseBuffer(buffer);
 		if (nread >= nbytes)
 			break;
 	}
@@ -409,9 +389,7 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 	int32		pageno = (int32) (obj_desc->offset / LOBLKSIZE);
 	ScanKeyData skey[2];
 	IndexScanDesc sd;
-	RetrieveIndexResult indexRes;
-	HeapTupleData oldtuple;
-	Buffer		buffer;
+	HeapTuple	oldtuple;
 	Form_pg_largeobject olddata;
 	bool		neednextpage;
 	bytea	   *datafield;
@@ -453,12 +431,11 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 						   (RegProcedure) F_INT4GE,
 						   Int32GetDatum(pageno));
 
-	sd = index_beginscan(obj_desc->index_r, false, 2, skey);
+	sd = index_beginscan(obj_desc->heap_r, obj_desc->index_r,
+						 SnapshotNow, 2, skey);
 
-	oldtuple.t_datamcxt = CurrentMemoryContext;
-	oldtuple.t_data = NULL;
+	oldtuple = NULL;
 	olddata = NULL;
-	buffer = InvalidBuffer;
 	neednextpage = true;
 
 	while (nwritten < nbytes)
@@ -470,17 +447,10 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 		 */
 		if (neednextpage)
 		{
-			while ((indexRes = index_getnext(sd, ForwardScanDirection)))
+			if ((oldtuple = index_getnext(sd, ForwardScanDirection)) != NULL)
 			{
-				oldtuple.t_self = indexRes->heap_iptr;
-				heap_fetch(obj_desc->heap_r, SnapshotNow, &oldtuple, &buffer, sd);
-				pfree(indexRes);
-				if (oldtuple.t_data != NULL)
-				{
-					olddata = (Form_pg_largeobject) GETSTRUCT(&oldtuple);
-					Assert(olddata->pageno >= pageno);
-					break;
-				}
+				olddata = (Form_pg_largeobject) GETSTRUCT(oldtuple);
+				Assert(olddata->pageno >= pageno);
 			}
 			neednextpage = false;
 		}
@@ -538,7 +508,7 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 			memset(replace, ' ', sizeof(replace));
 			values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);
 			replace[Anum_pg_largeobject_data - 1] = 'r';
-			newtup = heap_modifytuple(&oldtuple, obj_desc->heap_r,
+			newtup = heap_modifytuple(oldtuple, obj_desc->heap_r,
 									  values, nulls, replace);
 			simple_heap_update(obj_desc->heap_r, &newtup->t_self, newtup);
 			if (write_indices)
@@ -549,9 +519,7 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 			/*
 			 * We're done with this old page.
 			 */
-			ReleaseBuffer(buffer);
-			oldtuple.t_datamcxt = CurrentMemoryContext;
-			oldtuple.t_data = NULL;
+			oldtuple = NULL;
 			olddata = NULL;
 			neednextpage = true;
 		}
@@ -596,9 +564,6 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 		pageno++;
 	}
 
-	if (olddata != NULL)
-		ReleaseBuffer(buffer);
-
 	index_endscan(sd);
 
 	if (write_indices)
diff --git a/src/backend/utils/adt/not_in.c b/src/backend/utils/adt/not_in.c
index 970b1fc9c29c95ba4bf266d4880dd5a4345bfb98..96a6457faded81362965b996ec1be3c3ef199f6a 100644
--- a/src/backend/utils/adt/not_in.c
+++ b/src/backend/utils/adt/not_in.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.28 2002/03/30 01:02:41 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.29 2002/05/20 23:51:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -75,13 +75,13 @@ int4notin(PG_FUNCTION_ARGS)
 		elog(ERROR, "int4notin: unknown attribute %s for relation %s",
 			 attribute, RelationGetRelationName(relation_to_scan));
 
-	scan_descriptor = heap_beginscan(relation_to_scan, false, SnapshotNow,
+	scan_descriptor = heap_beginscan(relation_to_scan, SnapshotNow,
 									 0, (ScanKey) NULL);
 
 	retval = true;
 
 	/* do a scan of the relation, and do the check */
-	while (HeapTupleIsValid(current_tuple = heap_getnext(scan_descriptor, 0)))
+	while ((current_tuple = heap_getnext(scan_descriptor, ForwardScanDirection)) != NULL)
 	{
 		value = heap_getattr(current_tuple,
 							 (AttrNumber) attrid,
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 817c87c80a0aca256e829a5baf7565e6a5ac9cc4..5c0fd2d3ea7ad97008c5fbfe6e25d3cf7aa5291a 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.105 2002/05/17 01:19:18 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.106 2002/05/20 23:51:43 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -95,9 +95,9 @@ ReverifyMyDatabase(const char *name)
 	ScanKeyEntryInitialize(&key, 0, Anum_pg_database_datname,
 						   F_NAMEEQ, NameGetDatum(name));
 
-	pgdbscan = heap_beginscan(pgdbrel, 0, SnapshotNow, 1, &key);
+	pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key);
 
-	tup = heap_getnext(pgdbscan, 0);
+	tup = heap_getnext(pgdbscan, ForwardScanDirection);
 	if (!HeapTupleIsValid(tup) ||
 		tup->t_data->t_oid != MyDatabaseId)
 	{
@@ -456,8 +456,8 @@ ThereIsAtLeastOneUser(void)
 	pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
 	pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
 
-	scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, 0);
-	result = HeapTupleIsValid(heap_getnext(scan, 0));
+	scan = heap_beginscan(pg_shadow_rel, SnapshotNow, 0, NULL);
+	result = (heap_getnext(scan, ForwardScanDirection) != NULL);
 
 	heap_endscan(scan);
 	heap_close(pg_shadow_rel, AccessExclusiveLock);
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
index 4a3f3de1c540fe197362cb154ef678de6691c6a1..5848b444199aa63c6f20e03cd9201172a74f8fd7 100644
--- a/src/backend/utils/misc/superuser.c
+++ b/src/backend/utils/misc/superuser.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.21 2002/04/11 05:32:03 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.22 2002/05/20 23:51:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -80,8 +80,8 @@ is_dbadmin(Oid dbid)
 	ScanKeyEntryInitialize(&entry[0], 0x0,
 						   ObjectIdAttributeNumber, F_OIDEQ,
 						   ObjectIdGetDatum(dbid));
-	scan = heap_beginscan(pg_database, 0, SnapshotNow, 1, entry);
-	dbtuple = heap_getnext(scan, 0);
+	scan = heap_beginscan(pg_database, SnapshotNow, 1, entry);
+	dbtuple = heap_getnext(scan, ForwardScanDirection);
 	if (!HeapTupleIsValid(dbtuple))
 		elog(ERROR, "database %u does not exist", dbid);
 	dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index ad169856a172773ead7f9e3fc50c2db2ec277bad..b4b86b95b87a85b0d4545351c7bf2785a6c58e99 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -78,7 +78,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.22 2002/01/06 00:37:44 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.23 2002/05/20 23:51:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2076,9 +2076,9 @@ SelectSortFunction(Oid sortOperator,
 						   ObjectIdGetDatum(sortOperator));
 
 	relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
-	scan = heap_beginscan(relation, false, SnapshotNow, 1, skey);
+	scan = heap_beginscan(relation, SnapshotNow, 1, skey);
 
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
 
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
index fe0ab0fba15bf5d6c2a29686256c00130e6730c8..610afa11f01f7ae1d8a4e88f883716d2dc3e6e90 100644
--- a/src/include/access/genam.h
+++ b/src/include/access/genam.h
@@ -1,13 +1,13 @@
 /*-------------------------------------------------------------------------
  *
  * genam.h
- *	  POSTGRES general access method definitions.
+ *	  POSTGRES generalized index access method definitions.
  *
  *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: genam.h,v 1.33 2002/03/26 19:16:17 tgl Exp $
+ * $Id: genam.h,v 1.34 2002/05/20 23:51:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,12 +36,9 @@ typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, void *state);
 typedef struct SysScanDescData
 {
 	Relation	heap_rel;		/* catalog being scanned */
-	Snapshot	snapshot;		/* time qual (normally SnapshotNow) */
 	Relation	irel;			/* NULL if doing heap scan */
 	HeapScanDesc scan;			/* only valid in heap-scan case */
 	IndexScanDesc iscan;		/* only valid in index-scan case */
-	HeapTupleData tuple;		/* workspace for indexscan */
-	Buffer		buffer;			/* working state for indexscan */
 } SysScanDescData;
 
 typedef SysScanDescData *SysScanDesc;
@@ -54,22 +51,27 @@ extern Relation index_open(Oid relationId);
 extern Relation index_openrv(const RangeVar *relation);
 extern Relation index_openr(const char *sysRelationName);
 extern void index_close(Relation relation);
-extern InsertIndexResult index_insert(Relation relation,
-			 Datum *datum, char *nulls,
+extern InsertIndexResult index_insert(Relation indexRelation,
+			 Datum *datums, char *nulls,
 			 ItemPointer heap_t_ctid,
-			 Relation heapRel);
-extern IndexScanDesc index_beginscan(Relation relation, bool scanFromEnd,
-				uint16 numberOfKeys, ScanKey key);
-extern void index_rescan(IndexScanDesc scan, bool scanFromEnd, ScanKey key);
+			 Relation heapRelation);
+
+extern IndexScanDesc index_beginscan(Relation heapRelation,
+									 Relation indexRelation,
+									 Snapshot snapshot,
+									 int nkeys, ScanKey key);
+extern void index_rescan(IndexScanDesc scan, ScanKey key);
 extern void index_endscan(IndexScanDesc scan);
 extern void index_markpos(IndexScanDesc scan);
 extern void index_restrpos(IndexScanDesc scan);
-extern RetrieveIndexResult index_getnext(IndexScanDesc scan,
-			  ScanDirection direction);
-extern IndexBulkDeleteResult *index_bulk_delete(Relation relation,
+extern HeapTuple index_getnext(IndexScanDesc scan, ScanDirection direction);
+extern bool index_getnext_indexitem(IndexScanDesc scan,
+									ScanDirection direction);
+
+extern IndexBulkDeleteResult *index_bulk_delete(Relation indexRelation,
 				  IndexBulkDeleteCallback callback,
 				  void *callback_state);
-extern RegProcedure index_cost_estimator(Relation relation);
+extern RegProcedure index_cost_estimator(Relation indexRelation);
 extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum,
 				uint16 procnum);
 extern struct FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
@@ -78,18 +80,18 @@ extern struct FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
 /*
  * index access method support routines (in genam.c)
  */
-extern IndexScanDesc RelationGetIndexScan(Relation relation, bool scanFromEnd,
-					 uint16 numberOfKeys, ScanKey key);
+extern IndexScanDesc RelationGetIndexScan(Relation indexRelation,
+										  int nkeys, ScanKey key);
 extern void IndexScanEnd(IndexScanDesc scan);
 
 /*
  * heap-or-index access to system catalogs (in genam.c)
  */
-extern SysScanDesc systable_beginscan(Relation rel,
+extern SysScanDesc systable_beginscan(Relation heapRelation,
 									  const char *indexRelname,
 									  bool indexOK,
 									  Snapshot snapshot,
-									  unsigned nkeys, ScanKey key);
+									  int nkeys, ScanKey key);
 extern HeapTuple systable_getnext(SysScanDesc sysscan);
 extern void systable_endscan(SysScanDesc sysscan);
 
diff --git a/src/include/access/hash.h b/src/include/access/hash.h
index c809a139a40ac30dd84b08a40a292f3896de329d..d1e45fdde81d929e886cef9f4b08bea65e953d69 100644
--- a/src/include/access/hash.h
+++ b/src/include/access/hash.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: hash.h,v 1.45 2002/03/09 17:35:37 tgl Exp $
+ * $Id: hash.h,v 1.46 2002/05/20 23:51:43 tgl Exp $
  *
  * NOTES
  *		modeled after Margo Seltzer's hash implementation for unix.
@@ -306,8 +306,8 @@ extern void AtEOXact_hash(void);
 /* hashsearch.c */
 extern void _hash_search(Relation rel, int keysz, ScanKey scankey,
 			 Buffer *bufP, HashMetaPage metap);
-extern RetrieveIndexResult _hash_next(IndexScanDesc scan, ScanDirection dir);
-extern RetrieveIndexResult _hash_first(IndexScanDesc scan, ScanDirection dir);
+extern bool _hash_next(IndexScanDesc scan, ScanDirection dir);
+extern bool _hash_first(IndexScanDesc scan, ScanDirection dir);
 extern bool _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir,
 		   Buffer metabuf);
 
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index c0909584f99826e0521b5d3d82a70f92fd81010b..b8f2394fc54ca58215ea45440930c649e7905957 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: heapam.h,v 1.73 2002/03/26 19:16:17 tgl Exp $
+ * $Id: heapam.h,v 1.74 2002/05/20 23:51:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #include "access/htup.h"
 #include "access/relscan.h"
+#include "access/sdir.h"
 #include "access/tupmacs.h"
 #include "access/xlogutils.h"
 #include "nodes/primnodes.h"
@@ -145,12 +146,16 @@ extern Relation heap_openr(const char *sysRelationName, LOCKMODE lockmode);
 
 #define heap_close(r,l)  relation_close(r,l)
 
-extern HeapScanDesc heap_beginscan(Relation relation, int atend,
-			   Snapshot snapshot, unsigned nkeys, ScanKey key);
-extern void heap_rescan(HeapScanDesc scan, bool scanFromEnd, ScanKey key);
+extern HeapScanDesc heap_beginscan(Relation relation, Snapshot snapshot,
+								   int nkeys, ScanKey key);
+extern void heap_rescan(HeapScanDesc scan, ScanKey key);
 extern void heap_endscan(HeapScanDesc scan);
-extern HeapTuple heap_getnext(HeapScanDesc scandesc, int backw);
-extern void heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tup, Buffer *userbuf, IndexScanDesc iscan);
+extern HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction);
+
+extern void heap_fetch(Relation relation, Snapshot snapshot,
+					   HeapTuple tuple, Buffer *userbuf,
+					   PgStat_Info *pgstat_info);
+
 extern ItemPointer heap_get_latest_tid(Relation relation, Snapshot snapshot, ItemPointer tid);
 extern void setLastTid(const ItemPointer tid);
 extern Oid	heap_insert(Relation relation, HeapTuple tup);
diff --git a/src/include/access/itup.h b/src/include/access/itup.h
index 81c7a61cd2bab88d7387eceaf87f9cba0aa923bb..42745f8ed9551156c8fa1f219d3c5d46c1c60c71 100644
--- a/src/include/access/itup.h
+++ b/src/include/access/itup.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: itup.h,v 1.33 2001/11/05 17:46:31 momjian Exp $
+ * $Id: itup.h,v 1.34 2002/05/20 23:51:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -54,15 +54,6 @@ typedef struct InsertIndexResultData
 typedef InsertIndexResultData *InsertIndexResult;
 
 
-typedef struct RetrieveIndexResultData
-{
-	ItemPointerData index_iptr;
-	ItemPointerData heap_iptr;
-} RetrieveIndexResultData;
-
-typedef RetrieveIndexResultData *RetrieveIndexResult;
-
-
 /* ----------------
  *		externs
  * ----------------
@@ -147,8 +138,6 @@ extern IndexTuple index_formtuple(TupleDesc tupleDescriptor,
 				Datum *value, char *null);
 extern Datum nocache_index_getattr(IndexTuple tup, int attnum,
 					  TupleDesc tupleDesc, bool *isnull);
-extern RetrieveIndexResult FormRetrieveIndexResult(ItemPointer indexItemPointer,
-						ItemPointer heapItemPointer);
 extern void CopyIndexTuple(IndexTuple source, IndexTuple *target);
 
 #endif   /* ITUP_H */
diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h
index 40ff15e2df0c6f85b38b1dba19f179d6a0417590..c29defba8f737f6879b7d6a309195ef0730a6dc9 100644
--- a/src/include/access/nbtree.h
+++ b/src/include/access/nbtree.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nbtree.h,v 1.59 2001/11/05 17:46:31 momjian Exp $
+ * $Id: nbtree.h,v 1.60 2002/05/20 23:51:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -100,8 +100,8 @@ typedef struct BTScanOpaqueData
 	ItemPointerData mrkHeapIptr;
 	/* these fields are set by _bt_orderkeys(), which see for more info: */
 	bool		qual_ok;		/* false if qual can never be satisfied */
-	uint16		numberOfKeys;	/* number of scan keys */
-	uint16		numberOfRequiredKeys;	/* number of keys that must be
+	int			numberOfKeys;	/* number of scan keys */
+	int			numberOfRequiredKeys;	/* number of keys that must be
 										 * matched to continue the scan */
 	ScanKey		keyData;		/* array of scan keys */
 } BTScanOpaqueData;
@@ -366,8 +366,8 @@ extern OffsetNumber _bt_binsrch(Relation rel, Buffer buf, int keysz,
 			ScanKey scankey);
 extern int32 _bt_compare(Relation rel, int keysz, ScanKey scankey,
 			Page page, OffsetNumber offnum);
-extern RetrieveIndexResult _bt_next(IndexScanDesc scan, ScanDirection dir);
-extern RetrieveIndexResult _bt_first(IndexScanDesc scan, ScanDirection dir);
+extern bool _bt_next(IndexScanDesc scan, ScanDirection dir);
+extern bool _bt_first(IndexScanDesc scan, ScanDirection dir);
 extern bool _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir);
 
 /*
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 65ac7721660c5a38170d2d9812bb7a3803080ce7..87e3b523696d604454d02e8d4f310c79d5526d18 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -1,13 +1,13 @@
 /*-------------------------------------------------------------------------
  *
  * relscan.h
- *	  POSTGRES internal relation scan descriptor definitions.
+ *	  POSTGRES relation scan descriptor definitions.
  *
  *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: relscan.h,v 1.25 2001/11/05 17:46:31 momjian Exp $
+ * $Id: relscan.h,v 1.26 2002/05/20 23:51:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,42 +19,54 @@
 
 typedef struct HeapScanDescData
 {
-	Relation	rs_rd;			/* pointer to relation descriptor */
+	/* scan parameters */
+	Relation	rs_rd;			/* heap relation descriptor */
+	Snapshot	rs_snapshot;	/* snapshot to see */
+	int			rs_nkeys;		/* number of scan keys */
+	ScanKey		rs_key;			/* array of scan key descriptors */
+
+	/* scan current state */
 	HeapTupleData rs_ctup;		/* current tuple in scan, if any */
 	Buffer		rs_cbuf;		/* current buffer in scan, if any */
 	/* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
-	ItemPointerData rs_mctid;	/* marked tid, if any */
-	Snapshot	rs_snapshot;	/* snapshot to see */
-	uint16		rs_nkeys;		/* number of scan keys to select tuples */
-	ScanKey		rs_key;			/* key descriptors */
+	ItemPointerData rs_mctid;	/* marked scan position, if any */
 
 	PgStat_Info rs_pgstat_info; /* statistics collector hook */
 } HeapScanDescData;
 
 typedef HeapScanDescData *HeapScanDesc;
 
+
 typedef struct IndexScanDescData
 {
-	Relation	relation;		/* relation descriptor */
+	/* scan parameters */
+	Relation	heapRelation;	/* heap relation descriptor, or NULL */
+	Relation	indexRelation;	/* index relation descriptor */
+	Snapshot	xs_snapshot;	/* snapshot to see */
+	int			numberOfKeys;	/* number of scan keys */
+	ScanKey		keyData;		/* array of scan key descriptors */
+
+	/* scan current state */
 	void	   *opaque;			/* access-method-specific info */
 	ItemPointerData currentItemData;	/* current index pointer */
-	ItemPointerData currentMarkData;	/* marked current pointer */
-	uint8		flags;			/* scan position flags */
-	bool		scanFromEnd;	/* restart scan at end? */
-	uint16		numberOfKeys;	/* number of scan keys to select tuples */
-	ScanKey		keyData;		/* key descriptors */
-	FmgrInfo	fn_getnext;		/* cached lookup info for am's getnext fn */
+	ItemPointerData currentMarkData;	/* marked position, if any */
+	/*
+	 * 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.
+	 */
+	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 */
+
+	FmgrInfo	fn_getnext;		/* cached lookup info for AM's getnext fn */
 
 	PgStat_Info xs_pgstat_info; /* statistics collector hook */
 } IndexScanDescData;
 
 typedef IndexScanDescData *IndexScanDesc;
 
-/* IndexScanDesc flag bits (none of these are actually used currently) */
-#define ScanUnmarked			0x01
-#define ScanUncheckedPrevious	0x02
-#define ScanUncheckedNext		0x04
-
 
 /* ----------------
  *		IndexScanDescPtr is used in the executor where we have to
diff --git a/src/include/access/rtree.h b/src/include/access/rtree.h
index d271f83b4592b17420e0b92210938094f020fac4..f67014defc4bbdfb82da20c4c949b799062627d9 100644
--- a/src/include/access/rtree.h
+++ b/src/include/access/rtree.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rtree.h,v 1.27 2001/11/05 17:46:31 momjian Exp $
+ * $Id: rtree.h,v 1.28 2002/05/20 23:51:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -71,7 +71,7 @@ typedef struct RTreeScanOpaqueData
 	struct RTSTACK *s_stack;
 	struct RTSTACK *s_markstk;
 	uint16		s_flags;
-	uint16		s_internalNKey;
+	int			s_internalNKey;
 	ScanKey		s_internalKey;
 } RTreeScanOpaqueData;
 
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index d13acc85fc67dedc7e4e54d8fc1a81af0efcaf29..c7f829c3153687f457ad6b3ab32372ba71d9d5e8 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.237 2002/05/18 13:48:00 petere Exp $
+ * $Id: pg_proc.h,v 1.238 2002/05/20 23:51:43 tgl Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -681,7 +681,7 @@ DATA(insert OID = 322 (  rtgettuple		   PGNSP PGUID 12 f f f t f v 2 23 "0 0" 10
 DESCR("r-tree(internal)");
 DATA(insert OID = 323 (  rtbuild		   PGNSP PGUID 12 f f f t f v 3 23 "0 0 0" 100 0 0 100	rtbuild - _null_ ));
 DESCR("r-tree(internal)");
-DATA(insert OID = 324 (  rtbeginscan	   PGNSP PGUID 12 f f f t f v 4 23 "0 0 0 0" 100 0 0 100  rtbeginscan - _null_ ));
+DATA(insert OID = 324 (  rtbeginscan	   PGNSP PGUID 12 f f f t f v 3 23 "0 0 0" 100 0 0 100  rtbeginscan - _null_ ));
 DESCR("r-tree(internal)");
 DATA(insert OID = 325 (  rtendscan		   PGNSP PGUID 12 f f f t f v 1 23 "0" 100 0 0 100	rtendscan - _null_ ));
 DESCR("r-tree(internal)");
@@ -689,7 +689,7 @@ DATA(insert OID = 326 (  rtmarkpos		   PGNSP PGUID 12 f f f t f v 1 23 "0" 100 0
 DESCR("r-tree(internal)");
 DATA(insert OID = 327 (  rtrestrpos		   PGNSP PGUID 12 f f f t f v 1 23 "0" 100 0 0 100	rtrestrpos - _null_ ));
 DESCR("r-tree(internal)");
-DATA(insert OID = 328 (  rtrescan		   PGNSP PGUID 12 f f f t f v 3 23 "0 0 0" 100 0 0 100	rtrescan - _null_ ));
+DATA(insert OID = 328 (  rtrescan		   PGNSP PGUID 12 f f f t f v 2 23 "0 0" 100 0 0 100	rtrescan - _null_ ));
 DESCR("r-tree(internal)");
 DATA(insert OID = 321 (  rtbulkdelete	   PGNSP PGUID 12 f f f t f v 3 23 "0 0 0" 100 0 0 100	rtbulkdelete - _null_ ));
 DESCR("r-tree(internal)");
@@ -700,9 +700,9 @@ DATA(insert OID = 330 (  btgettuple		   PGNSP PGUID 12 f f f t f v 2 23 "0 0" 10
 DESCR("btree(internal)");
 DATA(insert OID = 331 (  btinsert		   PGNSP PGUID 12 f f f t f v 5 23 "0 0 0 0 0" 100 0 0 100	btinsert - _null_ ));
 DESCR("btree(internal)");
-DATA(insert OID = 333 (  btbeginscan	   PGNSP PGUID 12 f f f t f v 4 23 "0 0 0 0" 100 0 0 100  btbeginscan - _null_ ));
+DATA(insert OID = 333 (  btbeginscan	   PGNSP PGUID 12 f f f t f v 3 23 "0 0 0" 100 0 0 100  btbeginscan - _null_ ));
 DESCR("btree(internal)");
-DATA(insert OID = 334 (  btrescan		   PGNSP PGUID 12 f f f t f v 3 23 "0 0 0" 100 0 0 100	btrescan - _null_ ));
+DATA(insert OID = 334 (  btrescan		   PGNSP PGUID 12 f f f t f v 2 23 "0 0" 100 0 0 100	btrescan - _null_ ));
 DESCR("btree(internal)");
 DATA(insert OID = 335 (  btendscan		   PGNSP PGUID 12 f f f t f v 1 23 "0" 100 0 0 100	btendscan - _null_ ));
 DESCR("btree(internal)");
@@ -803,9 +803,9 @@ DATA(insert OID = 440 (  hashgettuple	   PGNSP PGUID 12 f f f t f v 2 23 "0 0" 1
 DESCR("hash(internal)");
 DATA(insert OID = 441 (  hashinsert		   PGNSP PGUID 12 f f f t f v 5 23 "0 0 0 0 0" 100 0 0 100	hashinsert - _null_ ));
 DESCR("hash(internal)");
-DATA(insert OID = 443 (  hashbeginscan	   PGNSP PGUID 12 f f f t f v 4 23 "0 0 0 0" 100 0 0 100  hashbeginscan - _null_ ));
+DATA(insert OID = 443 (  hashbeginscan	   PGNSP PGUID 12 f f f t f v 3 23 "0 0 0" 100 0 0 100  hashbeginscan - _null_ ));
 DESCR("hash(internal)");
-DATA(insert OID = 444 (  hashrescan		   PGNSP PGUID 12 f f f t f v 3 23 "0 0 0" 100 0 0 100	hashrescan - _null_ ));
+DATA(insert OID = 444 (  hashrescan		   PGNSP PGUID 12 f f f t f v 2 23 "0 0" 100 0 0 100	hashrescan - _null_ ));
 DESCR("hash(internal)");
 DATA(insert OID = 445 (  hashendscan	   PGNSP PGUID 12 f f f t f v 1 23 "0" 100 0 0 100	hashendscan - _null_ ));
 DESCR("hash(internal)");
@@ -1033,9 +1033,9 @@ DATA(insert OID = 774 (  gistgettuple	   PGNSP PGUID 12 f f f t f v 2 23 "0 0" 1
 DESCR("gist(internal)");
 DATA(insert OID = 775 (  gistinsert		   PGNSP PGUID 12 f f f t f v 5 23 "0 0 0 0 0" 100 0 0 100	gistinsert - _null_ ));
 DESCR("gist(internal)");
-DATA(insert OID = 777 (  gistbeginscan	   PGNSP PGUID 12 f f f t f v 4 23 "0 0 0 0" 100 0 0 100  gistbeginscan - _null_ ));
+DATA(insert OID = 777 (  gistbeginscan	   PGNSP PGUID 12 f f f t f v 3 23 "0 0 0" 100 0 0 100  gistbeginscan - _null_ ));
 DESCR("gist(internal)");
-DATA(insert OID = 778 (  gistrescan		   PGNSP PGUID 12 f f f t f v 3 23 "0 0 0" 100 0 0 100	gistrescan - _null_ ));
+DATA(insert OID = 778 (  gistrescan		   PGNSP PGUID 12 f f f t f v 2 23 "0 0" 100 0 0 100	gistrescan - _null_ ));
 DESCR("gist(internal)");
 DATA(insert OID = 779 (  gistendscan	   PGNSP PGUID 12 f f f t f v 1 23 "0" 100 0 0 100	gistendscan - _null_ ));
 DESCR("gist(internal)");
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 66f93df451da719cc8e88175df7b8b94ada02239..99fb0d33270e0d3be2e44de05a53814e71e17268 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: execnodes.h,v 1.68 2002/05/12 20:10:04 tgl Exp $
+ * $Id: execnodes.h,v 1.69 2002/05/20 23:51:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -463,7 +463,6 @@ typedef struct IndexScanState
 	bool		iss_RuntimeKeysReady;
 	RelationPtr iss_RelationDescs;
 	IndexScanDescPtr iss_ScanDescs;
-	HeapTupleData iss_htup;
 } IndexScanState;
 
 /* ----------------