Fix GiST's killing tuple: GISTScanOpaque->curpos wasn't
authorTeodor Sigaev <teodor@sigaev.ru>
Wed, 22 Oct 2008 12:53:56 +0000 (12:53 +0000)
committerTeodor Sigaev <teodor@sigaev.ru>
Wed, 22 Oct 2008 12:53:56 +0000 (12:53 +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/include/access/gist_private.h

index 50d5fc21a47acdf97c0087f888aa2a2bb7b85222..c7d14ecf2327e1ae957e720861b9c0d804e7c621 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.78 2008/10/20 16:35:14 teodor Exp $
+ *   $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.79 2008/10/22 12:53:56 teodor Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -51,7 +51,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))
            {
@@ -139,24 +139,28 @@ gistnext(IndexScanDesc scan, TIDBitmap *tbm)
    if ( so->qual_ok == false )
        return 0;
 
-   if (ItemPointerIsValid(&so->curpos) == false)
+   if ( so->curbuf == InvalidBuffer ) 
    {
-       /* Being asked to fetch the first entry, so start at the root */
-       Assert(so->curbuf == InvalidBuffer);
-       Assert(so->stack == NULL);
+       if (ItemPointerIsValid(&so->curpos) == false)
+       {
+           /* Being asked to fetch the first entry, so start at the root */
+           Assert(so->curbuf == InvalidBuffer);
+           Assert(so->stack == NULL);
 
-       so->curbuf = ReadBuffer(scan->indexRelation, GIST_ROOT_BLKNO);
+           so->curbuf = ReadBuffer(scan->indexRelation, GIST_ROOT_BLKNO);
 
-       stk = so->stack = (GISTSearchStack *) palloc0(sizeof(GISTSearchStack));
+           stk = so->stack = (GISTSearchStack *) palloc0(sizeof(GISTSearchStack));
 
-       stk->next = NULL;
-       stk->block = GIST_ROOT_BLKNO;
+           stk->next = NULL;
+           stk->block = GIST_ROOT_BLKNO;
 
-       pgstat_count_index_scan(scan->indexRelation);
-   }
-   else if (so->curbuf == InvalidBuffer)
-   {
-       return 0;
+           pgstat_count_index_scan(scan->indexRelation);
+       } 
+       else
+       {
+           /* scan is finished */
+           return 0;
+       }
    }
 
    /*
@@ -171,8 +175,13 @@ gistnext(IndexScanDesc scan, TIDBitmap *tbm)
 
        if ( so->curPageData < so->nPageData )
        {
-           scan->xs_ctup.t_self = so->pageData[ so->curPageData ].iptr;
+           scan->xs_ctup.t_self = so->pageData[ so->curPageData ].heapPtr;
            scan->xs_recheck = so->pageData[ so->curPageData ].recheck;
+
+           ItemPointerSet(&so->curpos,
+                           BufferGetBlockNumber(so->curbuf),
+                           so->pageData[ so->curPageData ].pageOffset);
+
            so->curPageData ++;
 
            return 1;
@@ -307,8 +316,6 @@ gistnext(IndexScanDesc scan, TIDBitmap *tbm)
                 * return success. Note that we keep "curbuf" pinned so that
                 * we can efficiently resume the index scan later.
                 */
-               ItemPointerSet(&(so->curpos),
-                              BufferGetBlockNumber(so->curbuf), n);
 
                if (!(scan->ignore_killed_tuples &&
                      ItemIdIsDead(PageGetItemId(p, n))))
@@ -319,7 +326,8 @@ gistnext(IndexScanDesc scan, TIDBitmap *tbm)
                        tbm_add_tuples(tbm, &it->t_tid, 1, scan->xs_recheck);
                    else 
                    {
-                       so->pageData[ so->nPageData ].iptr = it->t_tid;
+                       so->pageData[ so->nPageData ].heapPtr = it->t_tid;
+                       so->pageData[ so->nPageData ].pageOffset = n;
                        so->pageData[ so->nPageData ].recheck = scan->xs_recheck;
                        so->nPageData ++;
                    }
index 2d942e54b4930f5190fdda6450ed4a336369eee7..42f9bc76365f7912a6f34ae90e22f27e46755b47 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.34 2008/10/20 13:39:44 teodor Exp $
+ * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.35 2008/10/22 12:53:56 teodor Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -60,7 +60,8 @@ typedef struct GISTSTATE
 
 typedef struct ItemResult
 {
-   ItemPointerData     iptr;
+   ItemPointerData     heapPtr;
+   OffsetNumber        pageOffset; /* offset in index page */
    bool                recheck;
 } ItemResult;