diff options
Diffstat (limited to 'src/backend/access/nbtree/nbtree.c')
| -rw-r--r-- | src/backend/access/nbtree/nbtree.c | 105 |
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; + } + } + } +} |
