Fix scan adjustment.
authorVadim B. Mikheev
Thu, 30 Jul 1998 05:05:05 +0000 (05:05 +0000)
committerVadim B. Mikheev
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 c4ea6aa61275d82579e7facb9b06fb5aa559bcea..c30d7d56acaaeeb5bdec771fb3056763f5a48557 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 8fc6e736c69df3151db0e497b6ad4cc2d0f31b83..7aa9d2ac5716da481ae5eba41062021e5b8e45ed 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 
 
 #include 
+#include 
 #include 
 
 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 c70120055632c14356eb41742f1f3f71527629b3..5e3d03af3b888619fda923e417052ad9cbae7db8 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;