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
441453opaque = (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 */
457471if (!P_RIGHTMOST (opaque )) {
458472elog (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,
469489return (0 );
470490}
471491return (1 );
492+ #endif
472493 }
473494
474495btitem = (BTItem )PageGetItem (page ,PageGetItemId (page ,offnum ));
@@ -601,6 +622,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
601622Page page ;
602623BTStack stack ;
603624OffsetNumber offnum ,maxoff ;
625+ bool offGmax = false;
604626BTItem btitem ;
605627IndexTuple itup ;
606628ItemPointer current ;
@@ -665,7 +687,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
665687maxoff = PageGetMaxOffsetNumber (page );
666688
667689if (offnum > maxoff )
690+ {
668691offnum = maxoff ;
692+ offGmax = true;
693+ }
669694
670695blkno = BufferGetBlockNumber (buf );
671696ItemPointerSet (current ,blkno ,offnum );
@@ -736,10 +761,21 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
736761if (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+ }
739774break ;
740775
741776case BTGreaterStrategyNumber :
742- if (result >=0 ) {
777+ /* offGmax helps as above */
778+ if (result >=0 || offGmax ) {
743779do {
744780if (!_bt_twostep (scan ,& buf ,ForwardScanDirection ))
745781break ;
@@ -1084,32 +1120,77 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
10841120maxoff = PageGetMaxOffsetNumber (page );
10851121
10861122if (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 );
10921125start = 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
10941134if (PageIsEmpty (page )|| start > maxoff ) {
10951135ItemPointerSet (current ,blkno ,maxoff );
10961136if (!_bt_step (scan ,& buf ,BackwardScanDirection ))
10971137return ((RetrieveIndexResult )NULL );
10981138
10991139start = ItemPointerGetOffsetNumber (current );
11001140page = 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 {
11021161ItemPointerSet (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
11051170if (PageIsEmpty (page )) {
11061171ItemPointerSet (current ,blkno ,FirstOffsetNumber );
11071172if (!_bt_step (scan ,& buf ,ForwardScanDirection ))
11081173return ((RetrieveIndexResult )NULL );
11091174
11101175start = ItemPointerGetOffsetNumber (current );
11111176page = 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 {
11131194start = PageGetMaxOffsetNumber (page );
11141195ItemPointerSet (current ,blkno ,start );
11151196}