Fix GiST's killing tuple: GISTScanOpaque->curpos wasn't
authorTeodor Sigaev <teodor@sigaev.ru>
Wed, 22 Oct 2008 12:56:25 +0000 (12:56 +0000)
committerTeodor Sigaev <teodor@sigaev.ru>
Wed, 22 Oct 2008 12:56:25 +0000 (12:56 +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 447a8d9a148a8da2420c6bec89975f9ef7d11fa8..b1e9270be26457a8b7b0cff3b2374c4265dc546c 100644 (file)
@@ -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 7fb6554edcf3a296fc855039a90d3ec1a2e9b722..2b73e83632451d7dccf21b6c471d44a9149ac7cc 100644 (file)
@@ -60,7 +60,8 @@ typedef struct GISTSTATE
 
 typedef struct ItemResult
 {
-       ItemPointerData         iptr;
+       ItemPointerData         heapPtr;
+       OffsetNumber            pageOffset; /* offset in index page */
        bool                            recheck;
 } ItemResult;