Fix longstanding error in _bt_search(): should moveright at top of loop not
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 29 Jul 2003 22:18:53 +0000 (22:18 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
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