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 */
416426int
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