OSDN Git Service

Fix scan adjustment.
authorVadim B. Mikheev <vadim4o@yahoo.com>
Thu, 30 Jul 1998 05:05:05 +0000 (05:05 +0000)
committerVadim B. Mikheev <vadim4o@yahoo.com>
Thu, 30 Jul 1998 05:05:05 +0000 (05:05 +0000)
src/backend/access/nbtree/nbtree.c
src/backend/access/nbtree/nbtscan.c
src/include/access/nbtree.h

index c4ea6aa..c30d7d5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.27 1998/07/27 19:37:40 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.28 1998/07/30 05:04:49 vadim Exp $
  *
  * NOTES
  *       This file contains only the public interface routines.
@@ -44,6 +44,8 @@ bool          BuildingBtree = false;          /* see comment in btbuild() */
 bool           FastBuild = true;       /* use sort/build instead of insertion
                                                                 * build */
 
+static void    _bt_restscan(IndexScanDesc scan);
+
 /*
  *     btbuild() -- build a new btree index.
  *
@@ -374,8 +376,10 @@ btinsert(Relation rel, Datum *datum, char *nulls, ItemPointer ht_ctid, Relation
        pfree(btitem);
        pfree(itup);
 
+#if 0
        /* adjust any active scans that will be affected by this insertion */
        _bt_adjscans(rel, &(res->pointerData), BT_INSERT);
+#endif
 
        return (res);
 }
@@ -395,10 +399,28 @@ btgettuple(IndexScanDesc scan, ScanDirection dir)
         */
 
        if (ItemPointerIsValid(&(scan->currentItemData)))
+       {
+               /*
+                * Now we don't adjust scans on insertion (comments in
+                * nbtscan.c:_bt_scandel()) and I hope that we will unlock
+                * current index page before leaving index in LLL: this
+                * means that current index tuple could be moved right
+                * before we get here and we have to restore our scan
+                * position. We save heap TID pointed by current index
+                * tuple and use it. This will work untill we start
+                * to re-use (move heap tuples) without vacuum...
+                *              - vadim 07/29/98
+                */
+               _bt_restscan(scan);
                res = _bt_next(scan, dir);
+       }
        else
                res = _bt_first(scan, dir);
-
+       
+       /* Save heap TID to use it in _bt_restscan */
+       if (res)
+               ((BTScanOpaque)scan->opaque)->curHeapIptr = res->heap_iptr;
+       
        return ((char *) res);
 }
 
@@ -555,6 +577,7 @@ btmarkpos(IndexScanDesc scan)
                                                                   BufferGetBlockNumber(so->btso_curbuf),
                                                                         BT_READ);
                scan->currentMarkData = scan->currentItemData;
+               so->mrkHeapIptr = so->curHeapIptr;
        }
 }
 
@@ -585,6 +608,7 @@ btrestrpos(IndexScanDesc scan)
                                                                         BT_READ);
 
                scan->currentItemData = scan->currentMarkData;
+               so->curHeapIptr = so->mrkHeapIptr;
        }
 }
 
@@ -598,3 +622,80 @@ btdelete(Relation rel, ItemPointer tid)
        /* delete the data from the page */
        _bt_pagedel(rel, tid);
 }
+
+/*
+ * Reasons are in btgettuple... We have to find index item that
+ * points to heap tuple returned by previous call to btgettuple().
+ */
+static void
+_bt_restscan(IndexScanDesc scan)
+{
+       Relation                rel = scan->relation;
+       BTScanOpaque    so = (BTScanOpaque) scan->opaque;
+       Buffer                  buf = so->btso_curbuf;
+       Page                    page = BufferGetPage(buf);
+       ItemPointer             current = &(scan->currentItemData);
+       OffsetNumber    offnum = ItemPointerGetOffsetNumber(current),
+                                       maxoff = PageGetMaxOffsetNumber(page);
+       BTPageOpaque    opaque = (BTPageOpaque) PageGetSpecialPointer(page);
+       ItemPointerData target = so->curHeapIptr;
+       BTItem                  item;
+       BlockNumber             blkno;
+
+       if (maxoff >= offnum)
+       {
+               /* 
+                * if the item is where we left it or has just moved right 
+                * on this page, we're done 
+                */
+               for ( ;
+                        offnum <= maxoff;
+                        offnum = OffsetNumberNext(offnum))
+               {
+                       item = (BTItem) PageGetItem(page, PageGetItemId(page, offnum));
+                       if (item->bti_itup.t_tid.ip_blkid.bi_hi == \
+                                       target.ip_blkid.bi_hi && \
+                               item->bti_itup.t_tid.ip_blkid.bi_lo == \
+                                       target.ip_blkid.bi_lo && \
+                               item->bti_itup.t_tid.ip_posid == target.ip_posid)
+                       {
+                               current->ip_posid = offnum;
+                               return;
+                       }
+               }
+       }
+
+       /* 
+        * By here, the item we're looking for moved right at least one page 
+        */
+       for (;;)
+       {
+               if (P_RIGHTMOST(opaque))
+                       elog(FATAL, "_bt_restscan: my bits moved right off the end of the world!");
+
+               blkno = opaque->btpo_next;
+               _bt_relbuf(rel, buf, BT_READ);
+               buf = _bt_getbuf(rel, blkno, BT_READ);
+               page = BufferGetPage(buf);
+               maxoff = PageGetMaxOffsetNumber(page);
+               opaque = (BTPageOpaque) PageGetSpecialPointer(page);
+
+               /* see if it's on this page */
+               for (offnum = P_RIGHTMOST(opaque) ? P_HIKEY : P_FIRSTKEY ;
+                        offnum <= maxoff;
+                        offnum = OffsetNumberNext(offnum))
+               {
+                       item = (BTItem) PageGetItem(page, PageGetItemId(page, offnum));
+                       if (item->bti_itup.t_tid.ip_blkid.bi_hi == \
+                                       target.ip_blkid.bi_hi && \
+                               item->bti_itup.t_tid.ip_blkid.bi_lo == \
+                                       target.ip_blkid.bi_lo && \
+                               item->bti_itup.t_tid.ip_posid == target.ip_posid)
+                       {
+                               ItemPointerSet(current, blkno, offnum);
+                               so->btso_curbuf = buf;
+                               return;
+                       }
+               }
+       }
+}
index 8fc6e73..7aa9d2a 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/Attic/nbtscan.c,v 1.14 1998/06/15 19:27:57 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/Attic/nbtscan.c,v 1.15 1998/07/30 05:04:50 vadim Exp $
  *
  *
  * NOTES
@@ -30,6 +30,7 @@
 #include <postgres.h>
 
 #include <storage/bufpage.h>
+#include <storage/bufmgr.h>
 #include <access/nbtree.h>
 
 typedef struct BTScanListData
@@ -145,9 +146,16 @@ _bt_scandel(IndexScanDesc scan, int op, BlockNumber blkno, OffsetNumber offno)
        {
                switch (op)
                {
+/*
+ * Problems occure when current scan page is splitted!
+ * We saw "Non-functional updates" (ie index tuples were read twice)
+ * and partial updates ("good" tuples were not read at all) - due to
+ * losing scan position here. Look @ nbtree.c:btgettuple()
+ * what we do now...           - vadim 07/29/98
                        case BT_INSERT:
                                _bt_step(scan, &buf, ForwardScanDirection);
                                break;
+ */
                        case BT_DELETE:
                                _bt_step(scan, &buf, BackwardScanDirection);
                                break;
@@ -156,6 +164,14 @@ _bt_scandel(IndexScanDesc scan, int op, BlockNumber blkno, OffsetNumber offno)
                                /* NOTREACHED */
                }
                so->btso_curbuf = buf;
+               if (ItemPointerIsValid(current))
+               {
+                       Page    page = BufferGetPage(buf);
+                       BTItem  btitem = (BTItem) PageGetItem(page, 
+                                       PageGetItemId(page, ItemPointerGetOffsetNumber(current)));
+                       
+                       so->curHeapIptr = btitem->bti_itup.t_tid;
+               }
        }
 
        current = &(scan->currentMarkData);
@@ -173,9 +189,12 @@ _bt_scandel(IndexScanDesc scan, int op, BlockNumber blkno, OffsetNumber offno)
                buf = so->btso_curbuf;
                switch (op)
                {
+/*
+ * ...comments are above...
                        case BT_INSERT:
                                _bt_step(scan, &buf, ForwardScanDirection);
                                break;
+ */
                        case BT_DELETE:
                                _bt_step(scan, &buf, BackwardScanDirection);
                                break;
@@ -188,6 +207,14 @@ _bt_scandel(IndexScanDesc scan, int op, BlockNumber blkno, OffsetNumber offno)
                tmp = *current;
                *current = scan->currentItemData;
                scan->currentItemData = tmp;
+               if (ItemPointerIsValid(current))
+               {
+                       Page    page = BufferGetPage(buf);
+                       BTItem  btitem = (BTItem) PageGetItem(page, 
+                                       PageGetItemId(page, ItemPointerGetOffsetNumber(current)));
+                       
+                       so->mrkHeapIptr = btitem->bti_itup.t_tid;
+               }
        }
 }
 
index c701200..5e3d03a 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nbtree.h,v 1.20 1998/02/26 04:40:22 momjian Exp $
+ * $Id: nbtree.h,v 1.21 1998/07/30 05:05:05 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -62,18 +62,26 @@ typedef BTPageOpaqueData *BTPageOpaque;
  *     semop() calls, which are expensive.
  *
  *     And it's used to remember actual scankey info (we need in it
- *     if some scankeys evaled at runtime.
+ *     if some scankeys evaled at runtime).
+ *
+ *     curHeapIptr & mrkHeapIptr are heap iptr-s from current/marked
+ *     index tuples: we don't adjust scans on insertions (and, if LLL
+ *     is ON, don't hold locks on index pages between passes) - we
+ *     use these pointers to restore index scan positions...
+ *             - vadim 07/29/98
  */
 
 typedef struct BTScanOpaqueData
 {
-       Buffer          btso_curbuf;
-       Buffer          btso_mrkbuf;
-       uint16          qual_ok;                /* 0 for quals like key == 1 && key > 2 */
-       uint16          numberOfKeys;   /* number of keys */
-       uint16          numberOfFirstKeys;              /* number of keys for 1st
-                                                                                * attribute */
-       ScanKey         keyData;                /* key descriptor */
+       Buffer                  btso_curbuf;
+       Buffer                  btso_mrkbuf;
+       ItemPointerData curHeapIptr;
+       ItemPointerData mrkHeapIptr;
+       uint16                  qual_ok;                /* 0 for quals like key == 1 && key > 2 */
+       uint16                  numberOfKeys;   /* number of keys */
+       uint16                  numberOfFirstKeys;              /* number of keys for 1st
+                                                                                        * attribute */
+       ScanKey                 keyData;                /* key descriptor */
 } BTScanOpaqueData;
 
 typedef BTScanOpaqueData *BTScanOpaque;