Fix missing rows in query
authorTeodor Sigaev <[email protected]>
Tue, 30 Aug 2005 07:57:48 +0000 (07:57 +0000)
committerTeodor Sigaev <[email protected]>
Tue, 30 Aug 2005 07:57:48 +0000 (07:57 +0000)
update a=.. where a... with GiST index on column 'a'

src/backend/access/gist/gist.c
src/backend/access/gist/gistget.c
src/backend/access/gist/gistscan.c

index c752f93760557ce7b764ed7a44a1b2c30e683957..7a81c6dfa7b0b899fdb2c7fc8524e1f139fadf91 100644 (file)
@@ -503,7 +503,7 @@ gistlayerinsert(Relation r, BlockNumber blkno,
                 * changed beginning from 'child' offset
                 */
                if (ret & SPLITED)
-                       gistadjscans(r, GISTOP_SPLIT, blkno, child);
+                       gistadjscans(r, GISTOP_SPLIT, nblkno, FirstOffsetNumber);
        }
 
        ret = INSERTED;
@@ -1420,6 +1420,9 @@ gistnewroot(Relation r, IndexTuple *itup, int len)
        Page            p;
 
        b = ReadBuffer(r, GISTP_ROOT);
+
+       gistadjscans(r, GISTOP_SPLIT, GISTP_ROOT, FirstOffsetNumber);
+
        GISTInitBuffer(b, 0);
        p = BufferGetPage(b);
 
index 6e1e2955ba2023a2058e3cca9839621428445f2b..ad24d436e2efd7f1bf2ec929036a4e74b2f1c8ef 100644 (file)
@@ -167,10 +167,18 @@ gistnext(IndexScanDesc s, ScanDirection dir)
                        maxoff = PageGetMaxOffsetNumber(p);
                        po = (GISTPageOpaque) PageGetSpecialPointer(p);
 
-                       if (ScanDirectionIsBackward(dir))
-                               n = OffsetNumberPrev(stk->gs_child);
-                       else
-                               n = OffsetNumberNext(stk->gs_child);
+                       if ( stk->gs_child == InvalidOffsetNumber ) { 
+                               /* rescan page */
+                               if (ScanDirectionIsBackward(dir))
+                                       n = PageGetMaxOffsetNumber(p);
+                               else
+                                       n = FirstOffsetNumber;
+                       } else {
+                               if (ScanDirectionIsBackward(dir))
+                                       n = OffsetNumberPrev(stk->gs_child);
+                               else
+                                       n = OffsetNumberNext(stk->gs_child);
+                       }
                        so->s_stack = stk->gs_parent;
                        pfree(stk);
 
index 125ecf816f3352ccb6a726978810cad2f9fb4969..a27a79b62fc54fe732bc959c92764688cd063566 100644 (file)
@@ -25,7 +25,7 @@ static void gistregscan(IndexScanDesc s);
 static void gistdropscan(IndexScanDesc s);
 static void gistadjone(IndexScanDesc s, int op, BlockNumber blkno,
                   OffsetNumber offnum);
-static void adjuststack(GISTSTACK *stk, BlockNumber blkno);
+static void adjuststack(GISTSTACK *stk, int op,BlockNumber blkno, OffsetNumber offnum);
 static void adjustiptr(IndexScanDesc s, ItemPointer iptr,
                   int op, BlockNumber blkno, OffsetNumber offnum);
 
@@ -325,11 +325,8 @@ gistadjone(IndexScanDesc s,
 
        so = (GISTScanOpaque) s->opaque;
 
-       if (op == GISTOP_SPLIT)
-       {
-               adjuststack(so->s_stack, blkno);
-               adjuststack(so->s_markstk, blkno);
-       }
+       adjuststack(so->s_stack, op, blkno, offnum);
+       adjuststack(so->s_markstk, op, blkno, offnum);
 }
 
 /*
@@ -411,14 +408,31 @@ adjustiptr(IndexScanDesc s,
  *             access method update code for heaps; if we've modified the tuple we
  *             are looking at already in this transaction, we ignore the update
  *             request.
+ *             If index tuple on our parent stack has been deleted, we need 
+ *             to make step back to avoid miss.
  */
 static void
-adjuststack(GISTSTACK *stk, BlockNumber blkno)
+adjuststack(GISTSTACK *stk, int op, BlockNumber blkno, OffsetNumber offnum)
 {
        while (stk != NULL)
        {
-               if (stk->gs_blk == blkno)
-                       stk->gs_child = FirstOffsetNumber;
+               if (stk->gs_blk == blkno) {
+                       switch (op) {
+                               case GISTOP_DEL:
+                                       if ( stk->gs_child >= offnum ) {
+                                               if ( stk->gs_child > FirstOffsetNumber )
+                                                       stk->gs_child = OffsetNumberPrev( stk->gs_child );
+                                               else
+                                                       stk->gs_child = InvalidOffsetNumber;
+                                       }
+                                       break;
+                               case GISTOP_SPLIT:
+                                       stk->gs_child = InvalidOffsetNumber;
+                                       break;
+                               default:
+                                       elog(ERROR, "Bad operation in GiST scan adjust: %d", op);
+                       }
+               }
 
                stk = stk->gs_parent;
        }