mirror of
https://github.com/postgres/postgres.git
synced 2025-06-02 00:01:40 -04:00
1. BTREE_VERSION_1: using bti_itup->t_tid as unique identifier for a given
index tuple (logical position within A LEVEL). bti_oid & bti_dummy taken off from BTItemData. 2. Fix for multi-column indices (nbtsearch.c): _bt_binsrch() - for searches on internal pages having keysize < number of attrs we point at the last item < the scankey, not at the first item = the scankey; _bt_moveright() - if keysize < number of attrs we compare scankey with _last_ item on current page to decide should we move right or not.
This commit is contained in:
parent
afd9295786
commit
329fb11262
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.11 1997/03/24 08:48:09 vadim Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.12 1997/04/16 01:48:11 vadim Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -33,7 +33,7 @@ static OffsetNumber _bt_findsplitloc(Relation rel, Page page, OffsetNumber start
|
|||||||
static void _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf);
|
static void _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf);
|
||||||
static OffsetNumber _bt_pgaddtup(Relation rel, Buffer buf, int keysz, ScanKey itup_scankey, Size itemsize, BTItem btitem, BTItem afteritem);
|
static OffsetNumber _bt_pgaddtup(Relation rel, Buffer buf, int keysz, ScanKey itup_scankey, Size itemsize, BTItem btitem, BTItem afteritem);
|
||||||
static bool _bt_goesonpg(Relation rel, Buffer buf, Size keysz, ScanKey scankey, BTItem afteritem);
|
static bool _bt_goesonpg(Relation rel, Buffer buf, Size keysz, ScanKey scankey, BTItem afteritem);
|
||||||
static void _bt_updateitem(Relation rel, Size keysz, Buffer buf, Oid bti_oid, BTItem newItem);
|
static void _bt_updateitem(Relation rel, Size keysz, Buffer buf, BTItem oldItem, BTItem newItem);
|
||||||
static bool _bt_isequal (TupleDesc itupdesc, Page page, OffsetNumber offnum, int keysz, ScanKey scankey);
|
static bool _bt_isequal (TupleDesc itupdesc, Page page, OffsetNumber offnum, int keysz, ScanKey scankey);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -357,7 +357,7 @@ _bt_insertonpg(Relation rel,
|
|||||||
DOUBLEALIGN (IndexTupleDSize (stack->bts_btitem->bti_itup)) )
|
DOUBLEALIGN (IndexTupleDSize (stack->bts_btitem->bti_itup)) )
|
||||||
{
|
{
|
||||||
_bt_updateitem(rel, keysz, pbuf,
|
_bt_updateitem(rel, keysz, pbuf,
|
||||||
stack->bts_btitem->bti_oid, lowLeftItem);
|
stack->bts_btitem, lowLeftItem);
|
||||||
_bt_relbuf(rel, buf, BT_WRITE);
|
_bt_relbuf(rel, buf, BT_WRITE);
|
||||||
_bt_relbuf(rel, rbuf, BT_WRITE);
|
_bt_relbuf(rel, rbuf, BT_WRITE);
|
||||||
}
|
}
|
||||||
@ -644,23 +644,14 @@ _bt_findsplitloc(Relation rel,
|
|||||||
OffsetNumber saferight;
|
OffsetNumber saferight;
|
||||||
ItemId nxtitemid, safeitemid;
|
ItemId nxtitemid, safeitemid;
|
||||||
BTItem safeitem, nxtitem;
|
BTItem safeitem, nxtitem;
|
||||||
IndexTuple safetup, nxttup;
|
|
||||||
Size nbytes;
|
Size nbytes;
|
||||||
TupleDesc itupdesc;
|
|
||||||
int natts;
|
int natts;
|
||||||
int attno;
|
|
||||||
Datum attsafe;
|
|
||||||
Datum attnext;
|
|
||||||
bool null;
|
|
||||||
|
|
||||||
itupdesc = RelationGetTupleDescriptor(rel);
|
|
||||||
natts = rel->rd_rel->relnatts;
|
natts = rel->rd_rel->relnatts;
|
||||||
|
|
||||||
saferight = start;
|
saferight = start;
|
||||||
safeitemid = PageGetItemId(page, saferight);
|
safeitemid = PageGetItemId(page, saferight);
|
||||||
nbytes = ItemIdGetLength(safeitemid) + sizeof(ItemIdData);
|
nbytes = ItemIdGetLength(safeitemid) + sizeof(ItemIdData);
|
||||||
safeitem = (BTItem) PageGetItem(page, safeitemid);
|
safeitem = (BTItem) PageGetItem(page, safeitemid);
|
||||||
safetup = &(safeitem->bti_itup);
|
|
||||||
|
|
||||||
i = OffsetNumberNext(start);
|
i = OffsetNumberNext(start);
|
||||||
|
|
||||||
@ -670,26 +661,17 @@ _bt_findsplitloc(Relation rel,
|
|||||||
nxtitemid = PageGetItemId(page, i);
|
nxtitemid = PageGetItemId(page, i);
|
||||||
nbytes += (ItemIdGetLength(nxtitemid) + sizeof(ItemIdData));
|
nbytes += (ItemIdGetLength(nxtitemid) + sizeof(ItemIdData));
|
||||||
nxtitem = (BTItem) PageGetItem(page, nxtitemid);
|
nxtitem = (BTItem) PageGetItem(page, nxtitemid);
|
||||||
nxttup = &(nxtitem->bti_itup);
|
|
||||||
|
|
||||||
/* test against last known safe item */
|
|
||||||
for (attno = 1; attno <= natts; attno++) {
|
|
||||||
attsafe = index_getattr(safetup, attno, itupdesc, &null);
|
|
||||||
attnext = index_getattr(nxttup, attno, itupdesc, &null);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the tuple we're looking at isn't equal to the last safe one
|
* Test against last known safe item:
|
||||||
* we saw, then it's our new safe tuple.
|
* if the tuple we're looking at isn't equal to the last safe
|
||||||
|
* one we saw, then it's our new safe tuple.
|
||||||
*/
|
*/
|
||||||
|
if ( !_bt_itemcmp (rel, natts,
|
||||||
if (!_bt_invokestrat(rel, attno, BTEqualStrategyNumber,
|
safeitem, nxtitem, BTEqualStrategyNumber) )
|
||||||
attsafe, attnext)) {
|
{
|
||||||
safetup = nxttup;
|
safeitem = nxtitem;
|
||||||
saferight = i;
|
saferight = i;
|
||||||
|
|
||||||
/* break is for the attno for loop */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
i = OffsetNumberNext(i);
|
i = OffsetNumberNext(i);
|
||||||
}
|
}
|
||||||
@ -793,7 +775,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
|
|||||||
_bt_wrtbuf(rel, rootbuf);
|
_bt_wrtbuf(rel, rootbuf);
|
||||||
|
|
||||||
/* update metadata page with new root block number */
|
/* update metadata page with new root block number */
|
||||||
_bt_metaproot(rel, rootbknum);
|
_bt_metaproot(rel, rootbknum, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -820,7 +802,6 @@ _bt_pgaddtup(Relation rel,
|
|||||||
Page page;
|
Page page;
|
||||||
BTPageOpaque opaque;
|
BTPageOpaque opaque;
|
||||||
BTItem chkitem;
|
BTItem chkitem;
|
||||||
Oid afteroid;
|
|
||||||
|
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||||
@ -829,14 +810,13 @@ _bt_pgaddtup(Relation rel,
|
|||||||
if (afteritem == (BTItem) NULL) {
|
if (afteritem == (BTItem) NULL) {
|
||||||
itup_off = _bt_binsrch(rel, buf, keysz, itup_scankey, BT_INSERTION);
|
itup_off = _bt_binsrch(rel, buf, keysz, itup_scankey, BT_INSERTION);
|
||||||
} else {
|
} else {
|
||||||
afteroid = afteritem->bti_oid;
|
|
||||||
itup_off = first;
|
itup_off = first;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
chkitem =
|
chkitem =
|
||||||
(BTItem) PageGetItem(page, PageGetItemId(page, itup_off));
|
(BTItem) PageGetItem(page, PageGetItemId(page, itup_off));
|
||||||
itup_off = OffsetNumberNext(itup_off);
|
itup_off = OffsetNumberNext(itup_off);
|
||||||
} while (chkitem->bti_oid != afteroid);
|
} while ( ! BTItemSame (chkitem, afteritem) );
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) PageAddItem(page, (Item) btitem, itemsize, itup_off, LP_USED);
|
(void) PageAddItem(page, (Item) btitem, itemsize, itup_off, LP_USED);
|
||||||
@ -870,7 +850,6 @@ _bt_goesonpg(Relation rel,
|
|||||||
BTPageOpaque opaque;
|
BTPageOpaque opaque;
|
||||||
BTItem chkitem;
|
BTItem chkitem;
|
||||||
OffsetNumber offnum, maxoff;
|
OffsetNumber offnum, maxoff;
|
||||||
Oid afteroid;
|
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
@ -908,7 +887,6 @@ _bt_goesonpg(Relation rel,
|
|||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
/* damn, have to work for it. i hate that. */
|
/* damn, have to work for it. i hate that. */
|
||||||
afteroid = afteritem->bti_oid;
|
|
||||||
maxoff = PageGetMaxOffsetNumber(page);
|
maxoff = PageGetMaxOffsetNumber(page);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -924,7 +902,8 @@ _bt_goesonpg(Relation rel,
|
|||||||
offnum <= maxoff;
|
offnum <= maxoff;
|
||||||
offnum = OffsetNumberNext(offnum)) {
|
offnum = OffsetNumberNext(offnum)) {
|
||||||
chkitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum));
|
chkitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum));
|
||||||
if (chkitem->bti_oid == afteroid) {
|
|
||||||
|
if ( BTItemSame (chkitem, afteritem) ) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1029,7 +1008,7 @@ static void
|
|||||||
_bt_updateitem(Relation rel,
|
_bt_updateitem(Relation rel,
|
||||||
Size keysz,
|
Size keysz,
|
||||||
Buffer buf,
|
Buffer buf,
|
||||||
Oid bti_oid,
|
BTItem oldItem,
|
||||||
BTItem newItem)
|
BTItem newItem)
|
||||||
{
|
{
|
||||||
Page page;
|
Page page;
|
||||||
@ -1050,10 +1029,10 @@ _bt_updateitem(Relation rel,
|
|||||||
do {
|
do {
|
||||||
item = (BTItem) PageGetItem(page, PageGetItemId(page, i));
|
item = (BTItem) PageGetItem(page, PageGetItemId(page, i));
|
||||||
i = OffsetNumberNext(i);
|
i = OffsetNumberNext(i);
|
||||||
} while (i <= maxoff && item->bti_oid != bti_oid);
|
} while (i <= maxoff && ! BTItemSame (item, oldItem));
|
||||||
|
|
||||||
/* this should never happen (in theory) */
|
/* this should never happen (in theory) */
|
||||||
if (item->bti_oid != bti_oid) {
|
if ( ! BTItemSame (item, oldItem) ) {
|
||||||
elog(FATAL, "_bt_getstackbuf was lying!!");
|
elog(FATAL, "_bt_getstackbuf was lying!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.6 1996/11/05 10:35:30 scrappy Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.7 1997/04/16 01:48:15 vadim Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Postgres btree pages look like ordinary relation pages. The opaque
|
* Postgres btree pages look like ordinary relation pages. The opaque
|
||||||
@ -38,12 +38,20 @@
|
|||||||
|
|
||||||
#define BTREE_METAPAGE 0
|
#define BTREE_METAPAGE 0
|
||||||
#define BTREE_MAGIC 0x053162
|
#define BTREE_MAGIC 0x053162
|
||||||
|
|
||||||
|
#ifdef BTREE_VERSION_1
|
||||||
|
#define BTREE_VERSION 1
|
||||||
|
#else
|
||||||
#define BTREE_VERSION 0
|
#define BTREE_VERSION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct BTMetaPageData {
|
typedef struct BTMetaPageData {
|
||||||
uint32 btm_magic;
|
uint32 btm_magic;
|
||||||
uint32 btm_version;
|
uint32 btm_version;
|
||||||
BlockNumber btm_root;
|
BlockNumber btm_root;
|
||||||
|
#ifdef BTREE_VERSION_1
|
||||||
|
int32 btm_level;
|
||||||
|
#endif
|
||||||
} BTMetaPageData;
|
} BTMetaPageData;
|
||||||
|
|
||||||
#define BTPageGetMeta(p) \
|
#define BTPageGetMeta(p) \
|
||||||
@ -95,6 +103,9 @@ _bt_metapinit(Relation rel)
|
|||||||
metad.btm_magic = BTREE_MAGIC;
|
metad.btm_magic = BTREE_MAGIC;
|
||||||
metad.btm_version = BTREE_VERSION;
|
metad.btm_version = BTREE_VERSION;
|
||||||
metad.btm_root = P_NONE;
|
metad.btm_root = P_NONE;
|
||||||
|
#ifdef BTREE_VERSION_1
|
||||||
|
metad.btm_level = 0;
|
||||||
|
#endif
|
||||||
memmove((char *) BTPageGetMeta(pg), (char *) &metad, sizeof(metad));
|
memmove((char *) BTPageGetMeta(pg), (char *) &metad, sizeof(metad));
|
||||||
|
|
||||||
op = (BTPageOpaque) PageGetSpecialPointer(pg);
|
op = (BTPageOpaque) PageGetSpecialPointer(pg);
|
||||||
@ -180,6 +191,17 @@ _bt_getroot(Relation rel, int access)
|
|||||||
Assert(metaopaque->btpo_flags & BTP_META);
|
Assert(metaopaque->btpo_flags & BTP_META);
|
||||||
metad = BTPageGetMeta(metapg);
|
metad = BTPageGetMeta(metapg);
|
||||||
|
|
||||||
|
if (metad->btm_magic != BTREE_MAGIC) {
|
||||||
|
elog(WARN, "Index %s is not a btree",
|
||||||
|
RelationGetRelationName(rel));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metad->btm_version != BTREE_VERSION) {
|
||||||
|
elog(WARN, "Version mismatch on %s: version %d file, version %d code",
|
||||||
|
RelationGetRelationName(rel),
|
||||||
|
metad->btm_version, BTREE_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
/* if no root page initialized yet, do it */
|
/* if no root page initialized yet, do it */
|
||||||
if (metad->btm_root == P_NONE) {
|
if (metad->btm_root == P_NONE) {
|
||||||
|
|
||||||
@ -209,6 +231,9 @@ _bt_getroot(Relation rel, int access)
|
|||||||
rootblkno = BufferGetBlockNumber(rootbuf);
|
rootblkno = BufferGetBlockNumber(rootbuf);
|
||||||
rootpg = BufferGetPage(rootbuf);
|
rootpg = BufferGetPage(rootbuf);
|
||||||
metad->btm_root = rootblkno;
|
metad->btm_root = rootblkno;
|
||||||
|
#ifdef BTREE_VERSION_1
|
||||||
|
metad->btm_level = 1;
|
||||||
|
#endif
|
||||||
_bt_pageinit(rootpg, BufferGetPageSize(rootbuf));
|
_bt_pageinit(rootpg, BufferGetPageSize(rootbuf));
|
||||||
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpg);
|
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpg);
|
||||||
rootopaque->btpo_flags |= (BTP_LEAF | BTP_ROOT);
|
rootopaque->btpo_flags |= (BTP_LEAF | BTP_ROOT);
|
||||||
@ -387,7 +412,7 @@ _bt_pageinit(Page page, Size size)
|
|||||||
* a reference to or lock on the metapage.
|
* a reference to or lock on the metapage.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
_bt_metaproot(Relation rel, BlockNumber rootbknum)
|
_bt_metaproot(Relation rel, BlockNumber rootbknum, int level)
|
||||||
{
|
{
|
||||||
Buffer metabuf;
|
Buffer metabuf;
|
||||||
Page metap;
|
Page metap;
|
||||||
@ -400,6 +425,12 @@ _bt_metaproot(Relation rel, BlockNumber rootbknum)
|
|||||||
Assert(metaopaque->btpo_flags & BTP_META);
|
Assert(metaopaque->btpo_flags & BTP_META);
|
||||||
metad = BTPageGetMeta(metap);
|
metad = BTPageGetMeta(metap);
|
||||||
metad->btm_root = rootbknum;
|
metad->btm_root = rootbknum;
|
||||||
|
#ifdef BTREE_VERSION_1
|
||||||
|
if ( level == 0 ) /* called from _do_insert */
|
||||||
|
metad->btm_level += 1;
|
||||||
|
else
|
||||||
|
metad->btm_level = level; /* called from btsort */
|
||||||
|
#endif
|
||||||
_bt_wrtbuf(rel, metabuf);
|
_bt_wrtbuf(rel, metabuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +465,7 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
|
|||||||
item = (BTItem) PageGetItem(page, itemid);
|
item = (BTItem) PageGetItem(page, itemid);
|
||||||
|
|
||||||
/* if the item is where we left it, we're done */
|
/* if the item is where we left it, we're done */
|
||||||
if (item->bti_oid == stack->bts_btitem->bti_oid)
|
if ( BTItemSame (item, stack->bts_btitem) )
|
||||||
return (buf);
|
return (buf);
|
||||||
|
|
||||||
/* if the item has just moved right on this page, we're done */
|
/* if the item has just moved right on this page, we're done */
|
||||||
@ -445,7 +476,7 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
|
|||||||
item = (BTItem) PageGetItem(page, itemid);
|
item = (BTItem) PageGetItem(page, itemid);
|
||||||
|
|
||||||
/* if the item is where we left it, we're done */
|
/* if the item is where we left it, we're done */
|
||||||
if (item->bti_oid == stack->bts_btitem->bti_oid)
|
if ( BTItemSame (item, stack->bts_btitem) )
|
||||||
return (buf);
|
return (buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -471,7 +502,7 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
|
|||||||
offnum = OffsetNumberNext(offnum)) {
|
offnum = OffsetNumberNext(offnum)) {
|
||||||
itemid = PageGetItemId(page, offnum);
|
itemid = PageGetItemId(page, offnum);
|
||||||
item = (BTItem) PageGetItem(page, itemid);
|
item = (BTItem) PageGetItem(page, itemid);
|
||||||
if (item->bti_oid == stack->bts_btitem->bti_oid)
|
if ( BTItemSame (item, stack->bts_btitem) )
|
||||||
return (buf);
|
return (buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.16 1997/03/24 08:48:12 vadim Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.17 1997/04/16 01:48:17 vadim Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -160,6 +160,7 @@ _bt_moveright(Relation rel,
|
|||||||
ItemId hikey;
|
ItemId hikey;
|
||||||
ItemId itemid;
|
ItemId itemid;
|
||||||
BlockNumber rblkno;
|
BlockNumber rblkno;
|
||||||
|
int natts = rel->rd_rel->relnatts;
|
||||||
|
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||||
@ -178,22 +179,43 @@ _bt_moveright(Relation rel,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (_bt_skeycmp(rel, keysz, scankey, page, hikey,
|
if (_bt_skeycmp(rel, keysz, scankey, page, hikey,
|
||||||
BTGreaterEqualStrategyNumber)) {
|
BTGreaterEqualStrategyNumber))
|
||||||
|
{
|
||||||
/* move right as long as we need to */
|
/* move right as long as we need to */
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
|
OffsetNumber offmax;
|
||||||
/*
|
/*
|
||||||
* If this page consists of all duplicate keys (hikey and first
|
* If this page consists of all duplicate keys (hikey and first
|
||||||
* key on the page have the same value), then we don't need to
|
* key on the page have the same value), then we don't need to
|
||||||
* step right.
|
* step right.
|
||||||
|
*
|
||||||
|
* NOTE for multi-column indices: we may do scan using
|
||||||
|
* keys not for all attrs. But we handle duplicates
|
||||||
|
* using all attrs in _bt_insert/_bt_spool code.
|
||||||
|
* And so we've to compare scankey with _last_ item
|
||||||
|
* on this page to do not lose "good" tuples if number
|
||||||
|
* of attrs > keysize. Example: (2,0) - last items on
|
||||||
|
* this page, (2,1) - first item on next page (hikey),
|
||||||
|
* our scankey is x = 2. Scankey >= (2,1) because of
|
||||||
|
* we compare first attrs only, but we shouldn't to move
|
||||||
|
* right of here. - vadim 04/15/97
|
||||||
*/
|
*/
|
||||||
if (PageGetMaxOffsetNumber(page) > P_HIKEY) {
|
if ( (offmax = PageGetMaxOffsetNumber(page)) > P_HIKEY)
|
||||||
|
{
|
||||||
itemid = PageGetItemId(page, P_FIRSTKEY);
|
itemid = PageGetItemId(page, P_FIRSTKEY);
|
||||||
if (_bt_skeycmp(rel, keysz, scankey, page, itemid,
|
if (_bt_skeycmp(rel, keysz, scankey, page, itemid,
|
||||||
BTEqualStrategyNumber)) {
|
BTEqualStrategyNumber)) {
|
||||||
/* break is for the "move right" while loop */
|
/* break is for the "move right" while loop */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if ( natts > keysz )
|
||||||
|
{
|
||||||
|
itemid = PageGetItemId(page, offmax);
|
||||||
|
if (_bt_skeycmp(rel, keysz, scankey, page, itemid,
|
||||||
|
BTLessEqualStrategyNumber))
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* step right one page */
|
/* step right one page */
|
||||||
@ -346,6 +368,7 @@ _bt_binsrch(Relation rel,
|
|||||||
Page page;
|
Page page;
|
||||||
BTPageOpaque opaque;
|
BTPageOpaque opaque;
|
||||||
OffsetNumber low, mid, high;
|
OffsetNumber low, mid, high;
|
||||||
|
int natts = rel->rd_rel->relnatts;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
@ -379,7 +402,26 @@ _bt_binsrch(Relation rel,
|
|||||||
else if (result < 0)
|
else if (result < 0)
|
||||||
high = mid - 1;
|
high = mid - 1;
|
||||||
else
|
else
|
||||||
return (_bt_firsteq(rel, itupdesc, page, keysz, scankey, mid));
|
{
|
||||||
|
mid = _bt_firsteq(rel, itupdesc, page, keysz, scankey, mid);
|
||||||
|
/*
|
||||||
|
* NOTE for multi-column indices: we may do scan using
|
||||||
|
* keys not for all attrs. But we handle duplicates using
|
||||||
|
* all attrs in _bt_insert/_bt_spool code. And so while
|
||||||
|
* searching on internal pages having number of attrs > keysize
|
||||||
|
* we want to point at the last item < the scankey, not at the
|
||||||
|
* first item = the scankey (!!!), and let _bt_moveright
|
||||||
|
* decide later whether to move right or not (see comments and
|
||||||
|
* example there). Note also that INSERTions are not affected
|
||||||
|
* by this code (natts == keysz). - vadim 04/15/97
|
||||||
|
*/
|
||||||
|
if ( natts == keysz || opaque->btpo_flags & BTP_LEAF )
|
||||||
|
return (mid);
|
||||||
|
low = P_RIGHTMOST(opaque) ? P_HIKEY : P_FIRSTKEY;
|
||||||
|
if ( mid == low )
|
||||||
|
return (mid);
|
||||||
|
return (OffsetNumberPrev(mid));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -389,35 +431,45 @@ _bt_binsrch(Relation rel,
|
|||||||
* For non-insertion searches on internal pages, we want to point at
|
* For non-insertion searches on internal pages, we want to point at
|
||||||
* the last key <, or first key =, the scankey on the page. This
|
* the last key <, or first key =, the scankey on the page. This
|
||||||
* guarantees that we'll descend the tree correctly.
|
* guarantees that we'll descend the tree correctly.
|
||||||
|
* (NOTE comments above for multi-column indices).
|
||||||
*
|
*
|
||||||
* For all other cases, we want to point at the first key >=
|
* For all other cases, we want to point at the first key >=
|
||||||
* the scankey on the page. This guarantees that scans and
|
* the scankey on the page. This guarantees that scans and
|
||||||
* insertions will happen correctly.
|
* insertions will happen correctly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
if (!(opaque->btpo_flags & BTP_LEAF) && srchtype == BT_DESCENT)
|
||||||
if (!(opaque->btpo_flags & BTP_LEAF) && srchtype == BT_DESCENT) {
|
{ /*
|
||||||
|
|
||||||
/*
|
|
||||||
* We want the last key <, or first key ==, the scan key.
|
* We want the last key <, or first key ==, the scan key.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
result = _bt_compare(rel, itupdesc, page, keysz, scankey, high);
|
result = _bt_compare(rel, itupdesc, page, keysz, scankey, high);
|
||||||
|
|
||||||
if (result == 0) {
|
if (result == 0)
|
||||||
return (_bt_firsteq(rel, itupdesc, page, keysz, scankey, high));
|
{
|
||||||
} else if (result > 0) {
|
mid = _bt_firsteq(rel, itupdesc, page, keysz, scankey, high);
|
||||||
|
/*
|
||||||
|
* If natts > keysz we want last item < the scan key.
|
||||||
|
* See comments above for multi-column indices.
|
||||||
|
*/
|
||||||
|
if ( natts == keysz )
|
||||||
|
return (mid);
|
||||||
|
low = P_RIGHTMOST(opaque) ? P_HIKEY : P_FIRSTKEY;
|
||||||
|
if ( mid == low )
|
||||||
|
return (mid);
|
||||||
|
return (OffsetNumberPrev(mid));
|
||||||
|
}
|
||||||
|
else if (result > 0)
|
||||||
return (high);
|
return (high);
|
||||||
} else {
|
else
|
||||||
return (low);
|
return (low);
|
||||||
}
|
}
|
||||||
} else {
|
else /* we want the first key >= the scan key */
|
||||||
|
{
|
||||||
/* we want the first key >= the scan key */
|
|
||||||
result = _bt_compare(rel, itupdesc, page, keysz, scankey, low);
|
result = _bt_compare(rel, itupdesc, page, keysz, scankey, low);
|
||||||
if (result <= 0) {
|
if (result <= 0)
|
||||||
return (low);
|
return (low);
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
if (low == high)
|
if (low == high)
|
||||||
return (OffsetNumberNext(low));
|
return (OffsetNumberNext(low));
|
||||||
|
|
||||||
@ -1107,7 +1159,7 @@ _bt_twostep(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
|
|||||||
while (offnum <= maxoff) {
|
while (offnum <= maxoff) {
|
||||||
itemid = PageGetItemId(page, offnum);
|
itemid = PageGetItemId(page, offnum);
|
||||||
btitem = (BTItem) PageGetItem(page, itemid);
|
btitem = (BTItem) PageGetItem(page, itemid);
|
||||||
if (btitem->bti_oid == svitem->bti_oid) {
|
if ( BTItemSame (btitem, svitem) ) {
|
||||||
pfree(svitem);
|
pfree(svitem);
|
||||||
ItemPointerSet(current, blkno, offnum);
|
ItemPointerSet(current, blkno, offnum);
|
||||||
return (false);
|
return (false);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Id: nbtsort.c,v 1.13 1997/03/24 08:48:15 vadim Exp $
|
* $Id: nbtsort.c,v 1.14 1997/04/16 01:48:27 vadim Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
*
|
*
|
||||||
@ -1021,9 +1021,13 @@ _bt_buildadd(Relation index, void *pstate, BTItem bti, int flags)
|
|||||||
}
|
}
|
||||||
#endif /* FASTBUILD_DEBUG && FASTBUILD_MERGE */
|
#endif /* FASTBUILD_DEBUG && FASTBUILD_MERGE */
|
||||||
#endif
|
#endif
|
||||||
if (last_bti == (BTItem) NULL) {
|
if (last_bti == (BTItem) NULL)
|
||||||
|
{
|
||||||
first_off = P_FIRSTKEY;
|
first_off = P_FIRSTKEY;
|
||||||
} else if (!_bt_itemcmp(index, _bt_nattr, bti, last_bti, BTEqualStrategyNumber)) {
|
}
|
||||||
|
else if ( !_bt_itemcmp(index, _bt_nattr,
|
||||||
|
bti, last_bti, BTEqualStrategyNumber) )
|
||||||
|
{
|
||||||
first_off = off;
|
first_off = off;
|
||||||
}
|
}
|
||||||
last_off = off;
|
last_off = off;
|
||||||
@ -1061,7 +1065,7 @@ _bt_uppershutdown(Relation index, BTPageState *state)
|
|||||||
if (s->btps_doupper) {
|
if (s->btps_doupper) {
|
||||||
if (s->btps_next == (BTPageState *) NULL) {
|
if (s->btps_next == (BTPageState *) NULL) {
|
||||||
opaque->btpo_flags |= BTP_ROOT;
|
opaque->btpo_flags |= BTP_ROOT;
|
||||||
_bt_metaproot(index, blkno);
|
_bt_metaproot(index, blkno, s->btps_level + 1);
|
||||||
} else {
|
} else {
|
||||||
bti = _bt_minitem(s->btps_page, blkno, 0);
|
bti = _bt_minitem(s->btps_page, blkno, 0);
|
||||||
(void) _bt_buildadd(index, s->btps_next, bti, 0);
|
(void) _bt_buildadd(index, s->btps_next, bti, 0);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.9 1997/03/24 08:48:16 vadim Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.10 1997/04/16 01:48:29 vadim Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -297,7 +297,9 @@ _bt_formitem(IndexTuple itup)
|
|||||||
btitem = (BTItem) palloc(nbytes_btitem);
|
btitem = (BTItem) palloc(nbytes_btitem);
|
||||||
memmove((char *) &(btitem->bti_itup), (char *) itup, tuplen);
|
memmove((char *) &(btitem->bti_itup), (char *) itup, tuplen);
|
||||||
|
|
||||||
|
#ifndef BTREE_VERSION_1
|
||||||
btitem->bti_oid = newoid();
|
btitem->bti_oid = newoid();
|
||||||
|
#endif
|
||||||
return (btitem);
|
return (btitem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user