Fix GiST's killing tuple: GISTScanOpaque->curpos wasn't
authorTeodor Sigaev <[email protected]>
Wed, 22 Oct 2008 12:54:25 +0000 (12:54 +0000)
committerTeodor Sigaev <[email protected]>
Wed, 22 Oct 2008 12:54:25 +0000 (12:54 +0000)
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.

src/backend/access/gist/gistget.c
src/backend/access/gist/gistscan.c
src/include/access/gist_private.h

index 20bc99482dd838896073379f75cc5e8090c912a2..775240a0fdf26319f32f343a0506c145d791a677 100644 (file)
@@ -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 ++;
                }
            }
index 31fb549e53fc34c423a68f5d4b0085a7c387544b..05e47b9dc3aaaa781c8eb641d232cb41d28467aa 100644 (file)
@@ -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();
 }
index 1f4ceab37e950dc6fe40a42976799c92fb20b6cd..b231492d7a9bff5b8b630182e291b2fcc316a78f 100644 (file)
@@ -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;