From 7d535ebe5bf95ca88891c0288fa1c6575498185e Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 1 Nov 2009 22:30:54 +0000
Subject: [PATCH] Dept of second thoughts: after studying index_getnext() a bit
 more I realize that it can scribble on scan->xs_ctup.t_self while following
 HOT chains, so we can't rely on that to stay valid between hashgettuple()
 calls. Introduce a private variable in HashScanOpaque, instead.

---
 src/backend/access/hash/hash.c       | 11 ++++++++---
 src/backend/access/hash/hashsearch.c |  6 +++---
 src/include/access/hash.h            |  7 +++++--
 3 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 25e601518a0..999d0cfc318 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.114 2009/11/01 21:25:25 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.115 2009/11/01 22:30:54 tgl Exp $
  *
  * NOTES
  *	  This file contains only the public interface routines.
@@ -251,7 +251,7 @@ hashgettuple(PG_FUNCTION_ARGS)
 			IndexTuple	itup;
 
 			itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
-			if (ItemPointerEquals(&scan->xs_ctup.t_self, &itup->t_tid))
+			if (ItemPointerEquals(&(so->hashso_heappos), &(itup->t_tid)))
 				break;
 		}
 		if (offnum > maxoffnum)
@@ -304,6 +304,9 @@ hashgettuple(PG_FUNCTION_ARGS)
 	if (BufferIsValid(so->hashso_curbuf))
 		_hash_chgbufaccess(rel, so->hashso_curbuf, HASH_READ, HASH_NOLOCK);
 
+	/* Return current heap TID on success */
+	scan->xs_ctup.t_self = so->hashso_heappos;
+
 	PG_RETURN_BOOL(res);
 }
 
@@ -345,7 +348,7 @@ hashgetbitmap(PG_FUNCTION_ARGS)
 		if (add_tuple)
 		{
 			/* Note we mark the tuple ID as requiring recheck */
-			tbm_add_tuples(tbm, &scan->xs_ctup.t_self, 1, true);
+			tbm_add_tuples(tbm, &(so->hashso_heappos), 1, true);
 			ntids++;
 		}
 
@@ -375,6 +378,7 @@ hashbeginscan(PG_FUNCTION_ARGS)
 	so->hashso_curbuf = InvalidBuffer;
 	/* set position invalid (this will cause _hash_first call) */
 	ItemPointerSetInvalid(&(so->hashso_curpos));
+	ItemPointerSetInvalid(&(so->hashso_heappos));
 
 	scan->opaque = so;
 
@@ -410,6 +414,7 @@ hashrescan(PG_FUNCTION_ARGS)
 
 		/* set position invalid (this will cause _hash_first call) */
 		ItemPointerSetInvalid(&(so->hashso_curpos));
+		ItemPointerSetInvalid(&(so->hashso_heappos));
 	}
 
 	/* Update scan key, if a new one is given */
diff --git a/src/backend/access/hash/hashsearch.c b/src/backend/access/hash/hashsearch.c
index fec2f5d78a1..eadd45750a7 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.57 2009/06/11 14:48:53 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.58 2009/11/01 22:30:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,7 +58,7 @@ _hash_next(IndexScanDesc scan, ScanDirection dir)
 	_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
 	page = BufferGetPage(buf);
 	itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
-	scan->xs_ctup.t_self = itup->t_tid;
+	so->hashso_heappos = itup->t_tid;
 
 	return true;
 }
@@ -242,7 +242,7 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
 	_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
 	page = BufferGetPage(buf);
 	itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
-	scan->xs_ctup.t_self = itup->t_tid;
+	so->hashso_heappos = itup->t_tid;
 
 	return true;
 }
diff --git a/src/include/access/hash.h b/src/include/access/hash.h
index 100ccb9e6db..ce5417044a2 100644
--- a/src/include/access/hash.h
+++ b/src/include/access/hash.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.94 2009/11/01 21:25:25 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.95 2009/11/01 22:30:54 tgl Exp $
  *
  * NOTES
  *		modeled after Margo Seltzer's hash implementation for unix.
@@ -99,8 +99,11 @@ typedef struct HashScanOpaqueData
 	 */
 	Buffer		hashso_curbuf;
 
-	/* Current position of the scan */
+	/* Current position of the scan, as an index TID */
 	ItemPointerData hashso_curpos;
+
+	/* Current position of the scan, as a heap TID */
+	ItemPointerData hashso_heappos;
 } HashScanOpaqueData;
 
 typedef HashScanOpaqueData *HashScanOpaque;
-- 
GitLab