Fix longstanding error in _bt_search(): should moveright at top of loop not
authorTom Lane <[email protected]>
Tue, 29 Jul 2003 22:18:53 +0000 (22:18 +0000)
committerTom Lane <[email protected]>
Tue, 29 Jul 2003 22:18:53 +0000 (22:18 +0000)
bottom.  Otherwise we fail to moveright when the root page was split while
we were "in flight" to it.  This is not a significant problem when the root
is above the leaf level, but if the root was also a leaf (ie, a single-page
index just got split) we may return the wrong leaf page to the caller,
resulting in failure to find a key that is in fact present.  Bug has existed
at least since 7.1, probably forever.

src/backend/access/nbtree/nbtsearch.c

index c1a82f2b8560625175d21ecb2d232768b25db72e..433d881dc3e384817355252fdc7509257542bec8 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.69 2001/10/25 05:49:21 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.69.2.1 2003/07/29 22:18:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -61,6 +61,13 @@ _bt_search(Relation rel, int keysz, ScanKey scankey,
                BlockNumber par_blkno;
                BTStack         new_stack;
 
+               /*
+                * Race -- the page we just grabbed may have split since we read
+                * its pointer in the parent (or metapage).  If it has, we may need
+                * to move right to its new sibling.  Do that.
+                */
+               *bufP = _bt_moveright(rel, *bufP, keysz, scankey, BT_READ);
+
                /* if this is a leaf page, we're done */
                page = BufferGetPage(*bufP);
                opaque = (BTPageOpaque) PageGetSpecialPointer(page);
@@ -97,13 +104,6 @@ _bt_search(Relation rel, int keysz, ScanKey scankey,
                _bt_relbuf(rel, *bufP);
                *bufP = _bt_getbuf(rel, blkno, BT_READ);
 
-               /*
-                * Race -- the page we just grabbed may have split since we read
-                * its pointer in the parent.  If it has, we may need to move
-                * right to its new sibling.  Do that.
-                */
-               *bufP = _bt_moveright(rel, *bufP, keysz, scankey, BT_READ);
-
                /* okay, all set to move down a level */
                stack_in = new_stack;
        }
@@ -590,8 +590,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
        /*
         * At this point we are positioned at the first item >= scan key, or
         * possibly at the end of a page on which all the existing items are
-        * greater than the scan key and we know that everything on later
-        * pages is less than or equal to scan key.
+        * less than the scan key and we know that everything on later
+        * pages is greater than or equal to scan key.
         *
         * We could step forward in the latter case, but that'd be a waste of
         * time if we want to scan backwards.  So, it's now time to examine