From 2b7334d4877ba445003f96b0bb7eed4e7078a39b Mon Sep 17 00:00:00 2001
From: Neil Conway <neilc@samurai.com>
Date: Sat, 20 Jan 2007 18:43:35 +0000
Subject: [PATCH] Refactor the index AM API slightly: move currentItemData and
 currentMarkData from IndexScanDesc to the opaque structs for the AMs that
 need this information (currently gist and hash).

Patch from Heikki Linnakangas, fixes by Neil Conway.
---
 src/backend/access/gist/gistget.c    | 17 ++++++-----
 src/backend/access/gist/gistscan.c   | 18 ++++++------
 src/backend/access/hash/hash.c       | 44 ++++++++++++++--------------
 src/backend/access/hash/hashsearch.c | 12 ++++----
 src/backend/access/index/genam.c     |  5 +---
 src/include/access/gist_private.h    |  4 ++-
 src/include/access/hash.h            |  6 +++-
 src/include/access/nbtree.h          |  5 +---
 src/include/access/relscan.h         |  5 +---
 9 files changed, 57 insertions(+), 59 deletions(-)

diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index f36653babdf..f1d2c777c2f 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
- *	  $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.63 2007/01/05 22:19:22 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.64 2007/01/20 18:43:35 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -106,8 +106,8 @@ gistgettuple(PG_FUNCTION_ARGS)
 	 * If we have produced an index tuple in the past and the executor has
 	 * informed us we need to mark it as "killed", do so now.
 	 */
-	if (scan->kill_prior_tuple && ItemPointerIsValid(&(scan->currentItemData)))
-		killtuple(scan->indexRelation, so, &(scan->currentItemData));
+	if (scan->kill_prior_tuple && ItemPointerIsValid(&(so->curpos)))
+		killtuple(scan->indexRelation, so, &(so->curpos));
 
 	/*
 	 * Get the next tuple that matches the search key. If asked to skip killed
@@ -138,7 +138,8 @@ gistgetmulti(PG_FUNCTION_ARGS)
  * tuples. Returns true iff a matching tuple was found.
  */
 static int
-gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, bool ignore_killed_tuples)
+gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids,
+		 int maxtids, bool ignore_killed_tuples)
 {
 	Page		p;
 	OffsetNumber n;
@@ -151,7 +152,7 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
 
 	so = (GISTScanOpaque) scan->opaque;
 
-	if (ItemPointerIsValid(&scan->currentItemData) == false)
+	if (ItemPointerIsValid(&so->curpos) == false)
 	{
 		/* Being asked to fetch the first entry, so start at the root */
 		Assert(so->curbuf == InvalidBuffer);
@@ -226,7 +227,7 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
 		}
 
 		if (!GistPageIsLeaf(p) || resetoffset ||
-			!ItemPointerIsValid(&scan->currentItemData))
+			!ItemPointerIsValid(&so->curpos))
 		{
 			if (ScanDirectionIsBackward(dir))
 				n = PageGetMaxOffsetNumber(p);
@@ -235,7 +236,7 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
 		}
 		else
 		{
-			n = ItemPointerGetOffsetNumber(&(scan->currentItemData));
+			n = ItemPointerGetOffsetNumber(&(so->curpos));
 
 			if (ScanDirectionIsBackward(dir))
 				n = OffsetNumberPrev(n);
@@ -285,7 +286,7 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
 				 * we can efficiently resume the index scan later.
 				 */
 
-				ItemPointerSet(&(scan->currentItemData),
+				ItemPointerSet(&(so->curpos),
 							   BufferGetBlockNumber(so->curbuf), n);
 
 				if (!(ignore_killed_tuples && ItemIdDeleted(PageGetItemId(p, n))))
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index 08ca73357c0..a275bb257ce 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
- *	  $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.66 2007/01/05 22:19:22 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.67 2007/01/20 18:43:35 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,12 +42,6 @@ gistrescan(PG_FUNCTION_ARGS)
 	GISTScanOpaque so;
 	int			i;
 
-	/*
-	 * Clear all the pointers.
-	 */
-	ItemPointerSetInvalid(&scan->currentItemData);
-	ItemPointerSetInvalid(&scan->currentMarkData);
-
 	so = (GISTScanOpaque) scan->opaque;
 	if (so != NULL)
 	{
@@ -82,6 +76,12 @@ gistrescan(PG_FUNCTION_ARGS)
 		scan->opaque = so;
 	}
 
+	/*
+	 * Clear all the pointers.
+	 */
+	ItemPointerSetInvalid(&so->curpos);
+	ItemPointerSetInvalid(&so->markpos);
+
 	/* Update scan key, if a new one is given */
 	if (key && scan->numberOfKeys > 0)
 	{
@@ -111,8 +111,8 @@ gistmarkpos(PG_FUNCTION_ARGS)
 			   *n,
 			   *tmp;
 
-	scan->currentMarkData = scan->currentItemData;
 	so = (GISTScanOpaque) scan->opaque;
+	so->markpos = so->curpos;
 	if (so->flags & GS_CURBEFORE)
 		so->flags |= GS_MRKBEFORE;
 	else
@@ -160,8 +160,8 @@ gistrestrpos(PG_FUNCTION_ARGS)
 			   *n,
 			   *tmp;
 
-	scan->currentItemData = scan->currentMarkData;
 	so = (GISTScanOpaque) scan->opaque;
+	so->curpos = so->markpos;
 	if (so->flags & GS_MRKBEFORE)
 		so->flags |= GS_CURBEFORE;
 	else
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index aa64c1d88bd..6a5eb37592d 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.92 2007/01/05 22:19:22 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.93 2007/01/20 18:43:35 neilc Exp $
  *
  * NOTES
  *	  This file contains only the public interface routines.
@@ -185,7 +185,7 @@ hashgettuple(PG_FUNCTION_ARGS)
 	 * appropriate direction.  If we haven't done so yet, we call a routine to
 	 * get the first item in the scan.
 	 */
-	if (ItemPointerIsValid(&(scan->currentItemData)))
+	if (ItemPointerIsValid(&(so->hashso_curpos)))
 	{
 		/*
 		 * Check to see if we should kill the previously-fetched tuple.
@@ -195,7 +195,7 @@ hashgettuple(PG_FUNCTION_ARGS)
 			/*
 			 * Yes, so mark it by setting the LP_DELETE bit in the item flags.
 			 */
-			offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData));
+			offnum = ItemPointerGetOffsetNumber(&(so->hashso_curpos));
 			page = BufferGetPage(so->hashso_curbuf);
 			PageGetItemId(page, offnum)->lp_flags |= LP_DELETE;
 
@@ -222,7 +222,7 @@ hashgettuple(PG_FUNCTION_ARGS)
 	{
 		while (res)
 		{
-			offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData));
+			offnum = ItemPointerGetOffsetNumber(&(so->hashso_curpos));
 			page = BufferGetPage(so->hashso_curbuf);
 			if (!ItemIdDeleted(PageGetItemId(page, offnum)))
 				break;
@@ -269,7 +269,7 @@ hashgetmulti(PG_FUNCTION_ARGS)
 		/*
 		 * Start scan, or advance to next tuple.
 		 */
-		if (ItemPointerIsValid(&(scan->currentItemData)))
+		if (ItemPointerIsValid(&(so->hashso_curpos)))
 			res = _hash_next(scan, ForwardScanDirection);
 		else
 			res = _hash_first(scan, ForwardScanDirection);
@@ -284,7 +284,7 @@ hashgetmulti(PG_FUNCTION_ARGS)
 				Page		page;
 				OffsetNumber offnum;
 
-				offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData));
+				offnum = ItemPointerGetOffsetNumber(&(so->hashso_curpos));
 				page = BufferGetPage(so->hashso_curbuf);
 				if (!ItemIdDeleted(PageGetItemId(page, offnum)))
 					break;
@@ -325,6 +325,10 @@ hashbeginscan(PG_FUNCTION_ARGS)
 	so->hashso_bucket_valid = false;
 	so->hashso_bucket_blkno = 0;
 	so->hashso_curbuf = so->hashso_mrkbuf = InvalidBuffer;
+	/* set positions invalid (this will cause _hash_first call) */
+	ItemPointerSetInvalid(&(so->hashso_curpos));
+	ItemPointerSetInvalid(&(so->hashso_mrkpos));
+
 	scan->opaque = so;
 
 	/* register scan in case we change pages it's using */
@@ -360,11 +364,11 @@ hashrescan(PG_FUNCTION_ARGS)
 		if (so->hashso_bucket_blkno)
 			_hash_droplock(rel, so->hashso_bucket_blkno, HASH_SHARE);
 		so->hashso_bucket_blkno = 0;
-	}
 
-	/* set positions invalid (this will cause _hash_first call) */
-	ItemPointerSetInvalid(&(scan->currentItemData));
-	ItemPointerSetInvalid(&(scan->currentMarkData));
+		/* set positions invalid (this will cause _hash_first call) */
+		ItemPointerSetInvalid(&(so->hashso_curpos));
+		ItemPointerSetInvalid(&(so->hashso_mrkpos));
+	}
 
 	/* Update scan key, if a new one is given */
 	if (scankey && scan->numberOfKeys > 0)
@@ -406,10 +410,6 @@ hashendscan(PG_FUNCTION_ARGS)
 		_hash_droplock(rel, so->hashso_bucket_blkno, HASH_SHARE);
 	so->hashso_bucket_blkno = 0;
 
-	/* be tidy */
-	ItemPointerSetInvalid(&(scan->currentItemData));
-	ItemPointerSetInvalid(&(scan->currentMarkData));
-
 	pfree(so);
 	scan->opaque = NULL;
 
@@ -430,14 +430,14 @@ hashmarkpos(PG_FUNCTION_ARGS)
 	if (BufferIsValid(so->hashso_mrkbuf))
 		_hash_dropbuf(rel, so->hashso_mrkbuf);
 	so->hashso_mrkbuf = InvalidBuffer;
-	ItemPointerSetInvalid(&(scan->currentMarkData));
+	ItemPointerSetInvalid(&(so->hashso_mrkpos));
 
-	/* bump pin count on currentItemData and copy to currentMarkData */
-	if (ItemPointerIsValid(&(scan->currentItemData)))
+	/* bump pin count on current buffer and copy to marked buffer */
+	if (ItemPointerIsValid(&(so->hashso_curpos)))
 	{
 		IncrBufferRefCount(so->hashso_curbuf);
 		so->hashso_mrkbuf = so->hashso_curbuf;
-		scan->currentMarkData = scan->currentItemData;
+		so->hashso_mrkpos = so->hashso_curpos;
 	}
 
 	PG_RETURN_VOID();
@@ -457,14 +457,14 @@ hashrestrpos(PG_FUNCTION_ARGS)
 	if (BufferIsValid(so->hashso_curbuf))
 		_hash_dropbuf(rel, so->hashso_curbuf);
 	so->hashso_curbuf = InvalidBuffer;
-	ItemPointerSetInvalid(&(scan->currentItemData));
+	ItemPointerSetInvalid(&(so->hashso_curpos));
 
-	/* bump pin count on currentMarkData and copy to currentItemData */
-	if (ItemPointerIsValid(&(scan->currentMarkData)))
+	/* bump pin count on marked buffer and copy to current buffer */
+	if (ItemPointerIsValid(&(so->hashso_mrkpos)))
 	{
 		IncrBufferRefCount(so->hashso_mrkbuf);
 		so->hashso_curbuf = so->hashso_mrkbuf;
-		scan->currentItemData = scan->currentMarkData;
+		so->hashso_curpos = so->hashso_mrkpos;
 	}
 
 	PG_RETURN_VOID();
diff --git a/src/backend/access/hash/hashsearch.c b/src/backend/access/hash/hashsearch.c
index 29b2ea545ab..5582c036417 100644
--- a/src/backend/access/hash/hashsearch.c
+++ b/src/backend/access/hash/hashsearch.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.46 2007/01/05 22:19:22 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.47 2007/01/20 18:43:35 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,7 +21,7 @@
 /*
  *	_hash_next() -- Get the next item in a scan.
  *
- *		On entry, we have a valid currentItemData in the scan, and a
+ *		On entry, we have a valid hashso_curpos in the scan, and a
  *		pin and read lock on the page that contains that item.
  *		We find the next item in the scan, if any.
  *		On success exit, we have the page containing the next item
@@ -49,7 +49,7 @@ _hash_next(IndexScanDesc scan, ScanDirection dir)
 		return false;
 
 	/* if we're here, _hash_step found a valid tuple */
-	current = &(scan->currentItemData);
+	current = &(so->hashso_curpos);
 	offnum = ItemPointerGetOffsetNumber(current);
 	_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
 	page = BufferGetPage(buf);
@@ -129,7 +129,7 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
 
 	pgstat_count_index_scan(&scan->xs_pgstat_info);
 
-	current = &(scan->currentItemData);
+	current = &(so->hashso_curpos);
 	ItemPointerSetInvalid(current);
 
 	/*
@@ -224,7 +224,7 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
  *	_hash_step() -- step to the next valid item in a scan in the bucket.
  *
  *		If no valid record exists in the requested direction, return
- *		false.	Else, return true and set the CurrentItemData for the
+ *		false.	Else, return true and set the hashso_curpos for the
  *		scan to the right thing.
  *
  *		'bufP' points to the current buffer, which is pinned and read-locked.
@@ -245,7 +245,7 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
 	BlockNumber blkno;
 	IndexTuple	itup;
 
-	current = &(scan->currentItemData);
+	current = &(so->hashso_curpos);
 
 	buf = *bufP;
 	_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index d0db99af75d..49ffff6e51d 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.60 2007/01/05 22:19:22 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.61 2007/01/20 18:43:35 neilc Exp $
  *
  * NOTES
  *	  many of the old access method routines have been turned into
@@ -92,9 +92,6 @@ RelationGetIndexScan(Relation indexRelation,
 
 	scan->opaque = NULL;
 
-	ItemPointerSetInvalid(&scan->currentItemData);
-	ItemPointerSetInvalid(&scan->currentMarkData);
-
 	ItemPointerSetInvalid(&scan->xs_ctup.t_self);
 	scan->xs_ctup.t_data = NULL;
 	scan->xs_cbuf = InvalidBuffer;
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index 25d2c213c00..6cb2e5294e5 100644
--- a/src/include/access/gist_private.h
+++ b/src/include/access/gist_private.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.25 2007/01/05 22:19:51 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.26 2007/01/20 18:43:35 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -72,7 +72,9 @@ typedef struct GISTScanOpaqueData
 	GISTSTATE  *giststate;
 	MemoryContext tempCxt;
 	Buffer		curbuf;
+	ItemPointerData curpos;
 	Buffer		markbuf;
+	ItemPointerData markpos;
 } GISTScanOpaqueData;
 
 typedef GISTScanOpaqueData *GISTScanOpaque;
diff --git a/src/include/access/hash.h b/src/include/access/hash.h
index 0a88b9203f6..40c86b74552 100644
--- a/src/include/access/hash.h
+++ b/src/include/access/hash.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.74 2007/01/05 22:19:51 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.75 2007/01/20 18:43:35 neilc Exp $
  *
  * NOTES
  *		modeled after Margo Seltzer's hash implementation for unix.
@@ -97,6 +97,10 @@ typedef struct HashScanOpaqueData
 	 */
 	Buffer		hashso_curbuf;
 	Buffer		hashso_mrkbuf;
+
+	/* Current and marked position of the scan */
+	ItemPointerData hashso_curpos;
+	ItemPointerData hashso_mrkpos;
 } HashScanOpaqueData;
 
 typedef HashScanOpaqueData *HashScanOpaque;
diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h
index 435826cf457..574aec496f8 100644
--- a/src/include/access/nbtree.h
+++ b/src/include/access/nbtree.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.108 2007/01/09 02:14:15 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.109 2007/01/20 18:43:35 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -390,9 +390,6 @@ typedef BTStackData *BTStack;
  * items were killed, we re-lock the page to mark them killed, then unlock.
  * Finally we drop the pin and step to the next page in the appropriate
  * direction.
- *
- * NOTE: in this implementation, btree does not use or set the
- * currentItemData and currentMarkData fields of IndexScanDesc at all.
  */
 
 typedef struct BTScanPosItem	/* what we remember about each match */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index bd1a9a4c3f8..77bca6be482 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.51 2007/01/05 22:19:51 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.52 2007/01/20 18:43:35 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -69,9 +69,6 @@ typedef struct IndexScanDescData
 
 	/* index access method's private state */
 	void	   *opaque;			/* access-method-specific info */
-	/* these fields are used by some but not all AMs: */
-	ItemPointerData currentItemData;	/* current index pointer */
-	ItemPointerData currentMarkData;	/* marked position, if any */
 
 	/*
 	 * xs_ctup/xs_cbuf are valid after a successful index_getnext. After
-- 
GitLab