Skip to content

Commit c3e10a4

Browse files
committed
1. _bt_compare fixed to work properly with new code in _bt_insertonpg
(old _bt_compare always returned >= 0 while comparing with P_HIKEY on root page - it breaks root page when _bt_insertonpg tries insert new minimal key into root page). 2. Fixed bug concerns "empty" pages: non-rightmost pages with only P_HIKEY present on it. Such pages appear after vacuum.
1 parent 64397b7 commit c3e10a4

File tree

1 file changed

+91
-10
lines changed

1 file changed

+91
-10
lines changed

src/backend/access/nbtree/nbtsearch.c

Lines changed: 91 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.10 1996/11/21 06:10:55 vadim Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.11 1996/12/06 09:41:45 vadim Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -409,9 +409,19 @@ _bt_firsteq(Relation rel,
409409
* 0 if scankey == tuple at offnum;
410410
* +1 if scankey > tuple at offnum.
411411
*
412+
* -- Old comments:
412413
* In order to avoid having to propagate changes up the tree any time
413414
* a new minimal key is inserted, the leftmost entry on the leftmost
414415
* page is less than all possible keys, by definition.
416+
*
417+
* -- New ones:
418+
* New insertion code (fix against updating _in_place_ if new minimal
419+
* key has bigger size than old one) may delete P_HIKEY entry on the
420+
* root page in order to insert new minimal key - and so this definition
421+
* does not work properly in this case and breaks key' order on root
422+
* page. BTW, this propagation occures only while page' splitting,
423+
* but not "any time a new min key is inserted" (see _bt_insertonpg).
424+
* - vadim 12/05/96
415425
*/
416426
int
417427
_bt_compare(Relation rel,
@@ -436,6 +446,8 @@ _bt_compare(Relation rel,
436446
* If this is a leftmost internal page, and if our comparison is
437447
* with the first key on the page, then the item at that position is
438448
* by definition less than the scan key.
449+
*
450+
* - see new comments above...
439451
*/
440452

441453
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
@@ -453,12 +465,20 @@ _bt_compare(Relation rel,
453465
* well as the rightmost page. but that implies that this
454466
* code path only applies to the root -- which seems
455467
* unlikely..
468+
*
469+
* - see new comments above...
456470
*/
457471
if (! P_RIGHTMOST(opaque)) {
458472
elog(WARN, "_bt_compare: invalid comparison to high key");
459473
}
460474

475+
#ifdef 0
461476
/*
477+
* We just have to belive that right answer will not
478+
* break anything. I've checked code and all seems to be ok.
479+
* See new comments above...
480+
*
481+
* -- Old comments
462482
* If the item on the page is equal to the scankey, that's
463483
* okay to admit. We just can't claim that the first key on
464484
* the page is greater than anything.
@@ -469,6 +489,7 @@ _bt_compare(Relation rel,
469489
return (0);
470490
}
471491
return (1);
492+
#endif
472493
}
473494

474495
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum));
@@ -601,6 +622,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
601622
Page page;
602623
BTStack stack;
603624
OffsetNumber offnum, maxoff;
625+
bool offGmax = false;
604626
BTItem btitem;
605627
IndexTuple itup;
606628
ItemPointer current;
@@ -665,7 +687,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
665687
maxoff = PageGetMaxOffsetNumber(page);
666688

667689
if (offnum > maxoff)
690+
{
668691
offnum = maxoff;
692+
offGmax = true;
693+
}
669694

670695
blkno = BufferGetBlockNumber(buf);
671696
ItemPointerSet(current, blkno, offnum);
@@ -736,10 +761,21 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
736761
if (result > 0)
737762
(void) _bt_twostep(scan, &buf, ForwardScanDirection);
738763
}
764+
else if ( offGmax && result > 0 )
765+
{ /*
766+
* Just remember: _bt_binsrch() returns the OffsetNumber of
767+
* the first matching key on the page, or the OffsetNumber at
768+
* which the matching key WOULD APPEAR IF IT WERE on this page.
769+
* No key on this page, but offnum from _bt_binsrch() greater
770+
* maxoff - have to move right. - vadim 12/06/96
771+
*/
772+
(void) _bt_twostep(scan, &buf, ForwardScanDirection);
773+
}
739774
break;
740775

741776
case BTGreaterStrategyNumber:
742-
if (result >= 0) {
777+
/* offGmax helps as above */
778+
if (result >= 0 || offGmax) {
743779
do {
744780
if (!_bt_twostep(scan, &buf, ForwardScanDirection))
745781
break;
@@ -1084,32 +1120,77 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
10841120
maxoff = PageGetMaxOffsetNumber(page);
10851121

10861122
if (ScanDirectionIsForward(dir)) {
1087-
if (PageIsEmpty(page)) {
1088-
maxoff = FirstOffsetNumber;
1089-
} else {
1090-
maxoff = PageGetMaxOffsetNumber(page);
1091-
}
1123+
if ( !P_LEFTMOST(opaque) ) /* non-leftmost page ? */
1124+
elog (WARN, "_bt_endpoint: leftmost page (%u) has not leftmost flag", blkno);
10921125
start = P_RIGHTMOST(opaque) ? P_HIKEY : P_FIRSTKEY;
1093-
1126+
/*
1127+
* I don't understand this stuff! It doesn't work for non-rightmost
1128+
* pages with only one element (P_HIKEY) which we have after
1129+
* deletion itups by vacuum (it's case of start > maxoff).
1130+
* Scanning in BackwardScanDirection is not understandable at all.
1131+
* Well - new stuff. - vadim 12/06/96
1132+
*/
1133+
#ifdef 0
10941134
if (PageIsEmpty(page) || start > maxoff) {
10951135
ItemPointerSet(current, blkno, maxoff);
10961136
if (!_bt_step(scan, &buf, BackwardScanDirection))
10971137
return ((RetrieveIndexResult) NULL);
10981138

10991139
start = ItemPointerGetOffsetNumber(current);
11001140
page = BufferGetPage(buf);
1101-
} else {
1141+
}
1142+
#endif
1143+
if ( PageIsEmpty (page) )
1144+
{
1145+
if ( start != P_HIKEY ) /* non-rightmost page */
1146+
elog (WARN, "_bt_endpoint: non-rightmost page (%u) is empty", blkno);
1147+
/* It's left- & right- most page - root page, - and it's empty... */
1148+
return ((RetrieveIndexResult) NULL);
1149+
}
1150+
if ( start > maxoff ) /* start == 2 && maxoff == 1 */
1151+
{
1152+
ItemPointerSet(current, blkno, maxoff);
1153+
if (!_bt_step(scan, &buf, ForwardScanDirection))
1154+
return ((RetrieveIndexResult) NULL);
1155+
1156+
start = ItemPointerGetOffsetNumber(current);
1157+
page = BufferGetPage(buf);
1158+
}
1159+
/* new stuff ends here */
1160+
else {
11021161
ItemPointerSet(current, blkno, start);
11031162
}
11041163
} else if (ScanDirectionIsBackward(dir)) {
1164+
/*
1165+
* I don't understand this stuff too! If RIGHT-most leaf page is
1166+
* empty why do scanning in ForwardScanDirection ???
1167+
* Well - new stuff. - vadim 12/06/96
1168+
*/
1169+
#ifdef 0
11051170
if (PageIsEmpty(page)) {
11061171
ItemPointerSet(current, blkno, FirstOffsetNumber);
11071172
if (!_bt_step(scan, &buf, ForwardScanDirection))
11081173
return ((RetrieveIndexResult) NULL);
11091174

11101175
start = ItemPointerGetOffsetNumber(current);
11111176
page = BufferGetPage(buf);
1112-
} else {
1177+
}
1178+
#endif
1179+
if (PageIsEmpty(page))
1180+
{
1181+
/* If it's leftmost page too - it's empty root page... */
1182+
if ( P_LEFTMOST(opaque) )
1183+
return ((RetrieveIndexResult) NULL);
1184+
/* Go back ! */
1185+
ItemPointerSet(current, blkno, FirstOffsetNumber);
1186+
if (!_bt_step(scan, &buf, BackwardScanDirection))
1187+
return ((RetrieveIndexResult) NULL);
1188+
1189+
start = ItemPointerGetOffsetNumber(current);
1190+
page = BufferGetPage(buf);
1191+
}
1192+
/* new stuff ends here */
1193+
else {
11131194
start = PageGetMaxOffsetNumber(page);
11141195
ItemPointerSet(current, blkno, start);
11151196
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy