From: Teodor Sigaev <teodor@sigaev.ru>
Date: Wed, 22 Oct 2008 12:54:25 +0000 (+0000)
Subject: Fix GiST's killing tuple: GISTScanOpaque->curpos wasn't
X-Git-Tag: REL8_3_5~14
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=666aad267b6a5abdf808524f563189cef0d9e90e;p=postgresql

Fix GiST's killing tuple: GISTScanOpaque->curpos wasn't
correctly set. As result, killtuple() marks as dead
wrong tuple on page. Bug was introduced by me while fixing
possible duplicates during GiST index scan.
---

diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index 20bc99482d..775240a0fd 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.69.2.2 2008/10/17 17:02:42 teodor Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.69.2.3 2008/10/22 12:54:25 teodor Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -49,7 +49,7 @@ killtuple(Relation r, GISTScanOpaque so, ItemPointer iptr)
 
 		for (offset = FirstOffsetNumber; offset <= maxoff; offset = OffsetNumberNext(offset))
 		{
-				IndexTuple	ituple = (IndexTuple) PageGetItem(p, PageGetItemId(p, offset));
+			IndexTuple	ituple = (IndexTuple) PageGetItem(p, PageGetItemId(p, offset));
 
 			if (ItemPointerEquals(&(ituple->t_tid), iptr))
 			{
@@ -157,7 +157,11 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids,
 	{
 		while( ntids < maxtids && so->curPageData < so->nPageData )
 		{
-			tids[ ntids ] = scan->xs_ctup.t_self = so->pageData[ so->curPageData ];
+			tids[ ntids ] = scan->xs_ctup.t_self = so->pageData[ so->curPageData ].heapPtr;
+			ItemPointerSet(&(so->curpos),
+							   BufferGetBlockNumber(so->curbuf), 
+							   so->pageData[ so->curPageData ].pageOffset);
+
 				
 			so->curPageData ++;
 			ntids++;
@@ -251,8 +255,13 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids,
 			{
 				while( ntids < maxtids && so->curPageData < so->nPageData )
 				{
-					tids[ ntids ] = scan->xs_ctup.t_self = so->pageData[ so->curPageData ];
+					tids[ ntids ] = scan->xs_ctup.t_self = 
+						so->pageData[ so->curPageData ].heapPtr;
 				
+					ItemPointerSet(&(so->curpos),
+								   BufferGetBlockNumber(so->curbuf), 
+								   so->pageData[ so->curPageData ].pageOffset);
+
 					so->curPageData ++;
 					ntids++;
 				}
@@ -297,13 +306,11 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids,
 				 * we can efficiently resume the index scan later.
 				 */
 
-				ItemPointerSet(&(so->curpos),
-							   BufferGetBlockNumber(so->curbuf), n);
-
 				if (!(ignore_killed_tuples && ItemIdIsDead(PageGetItemId(p, n))))
 				{
 					it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
-					so->pageData[ so->nPageData ] = it->t_tid;
+					so->pageData[ so->nPageData ].heapPtr = it->t_tid;
+					so->pageData[ so->nPageData ].pageOffset = n;
 					so->nPageData ++;
 				}
 			}
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index 31fb549e53..05e47b9dc3 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.68.2.2 2008/10/17 17:02:42 teodor Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.68.2.3 2008/10/22 12:54:25 teodor Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -163,7 +163,7 @@ gistmarkpos(PG_FUNCTION_ARGS)
 	so->markNPageData = so->nPageData;
 	so->markCurPageData = so->curPageData;
 	if ( so->markNPageData > 0 )
-		memcpy( so->markPageData, so->pageData, sizeof(ItemPointerData) * so->markNPageData );		
+		memcpy( so->markPageData, so->pageData, sizeof(MatchedItemPtr) * so->markNPageData );		
 
 	PG_RETURN_VOID();
 }
@@ -217,7 +217,7 @@ gistrestrpos(PG_FUNCTION_ARGS)
 	so->nPageData = so->markNPageData;
 	so->curPageData = so->markNPageData;
 	if ( so->markNPageData > 0 )
-		memcpy( so->pageData, so->markPageData, sizeof(ItemPointerData) * so->markNPageData );		
+		memcpy( so->pageData, so->markPageData, sizeof(MatchedItemPtr) * so->markNPageData );		
 
 	PG_RETURN_VOID();
 }
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index 1f4ceab37e..b231492d7a 100644
--- a/src/include/access/gist_private.h
+++ b/src/include/access/gist_private.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.28.2.2 2008/10/17 17:02:42 teodor Exp $
+ * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.28.2.3 2008/10/22 12:54:25 teodor Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -60,6 +60,12 @@ typedef struct GISTSTATE
 	TupleDesc	tupdesc;
 } GISTSTATE;
 
+typedef struct MatchedItemPtr 
+{
+	ItemPointerData		heapPtr;
+	OffsetNumber		pageOffset; /* offset in index page */
+} MatchedItemPtr;
+
 /*
  *	When we're doing a scan, we need to keep track of the parent stack
  *	for the marked and current items.
@@ -77,10 +83,10 @@ typedef struct GISTScanOpaqueData
 	Buffer		markbuf;
 	ItemPointerData markpos;
 
-	ItemPointerData	pageData[BLCKSZ/sizeof(IndexTupleData)];
+	MatchedItemPtr	pageData[BLCKSZ/sizeof(IndexTupleData)];
 	OffsetNumber	nPageData;
 	OffsetNumber	curPageData;
-	ItemPointerData	markPageData[BLCKSZ/sizeof(IndexTupleData)];
+	MatchedItemPtr	markPageData[BLCKSZ/sizeof(IndexTupleData)];
 	OffsetNumber	markNPageData;
 	OffsetNumber	markCurPageData;
 } GISTScanOpaqueData;