From f73fc6eb2908104e4ca0a28106806364cc085c98 Mon Sep 17 00:00:00 2001 From: "Vadim B. Mikheev" Date: Thu, 30 Jul 1998 05:05:05 +0000 Subject: [PATCH] Fix scan adjustment. --- src/backend/access/nbtree/nbtree.c | 105 +++++++++++++++++++++++++++++++++++- src/backend/access/nbtree/nbtscan.c | 29 +++++++++- src/include/access/nbtree.h | 26 +++++---- 3 files changed, 148 insertions(+), 12 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; + } + } + } +} diff --git a/src/backend/access/nbtree/nbtscan.c b/src/backend/access/nbtree/nbtscan.c index 8fc6e736c6..7aa9d2ac57 100644 --- a/src/backend/access/nbtree/nbtscan.c +++ b/src/backend/access/nbtree/nbtscan.c @@ -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; + } } } diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index c701200556..5e3d03af3b 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -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; -- 2.11.0