summaryrefslogtreecommitdiff
path: root/src/backend/access/nbtree/nbtree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/nbtree/nbtree.c')
-rw-r--r--src/backend/access/nbtree/nbtree.c105
1 files changed, 103 insertions, 2 deletions
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index c4ea6aa612..c30d7d56ac 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -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;
+ }
+ }
+ }
+}