Fix scan adjustment.

This commit is contained in:
Vadim B. Mikheev 1998-07-30 05:05:05 +00:00
parent 957ff1a0b5
commit f73fc6eb29
3 changed files with 148 additions and 12 deletions

View 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;
}
}
}
}

View 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 <postgres.h>
#include <storage/bufpage.h>
#include <storage/bufmgr.h>
#include <access/nbtree.h>
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;
}
}
}

View 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;