*
*
* 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.
bool FastBuild = true; /* use sort/build instead of insertion
* build */
+static void _bt_restscan(IndexScanDesc scan);
+
/*
* btbuild() -- build a new btree index.
*
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);
}
*/
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);
}
BufferGetBlockNumber(so->btso_curbuf),
BT_READ);
scan->currentMarkData = scan->currentItemData;
+ so->mrkHeapIptr = so->curHeapIptr;
}
}
BT_READ);
scan->currentItemData = scan->currentMarkData;
+ so->curHeapIptr = so->mrkHeapIptr;
}
}
/* 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;
+ }
+ }
+ }
+}
*
*
* 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
#include <postgres.h>
#include <storage/bufpage.h>
+#include <storage/bufmgr.h>
#include <access/nbtree.h>
typedef struct BTScanListData
{
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;
/* 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);
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;
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;
+ }
}
}
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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;