]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix amcheck child check pg_upgrade bug.
authorPeter Geoghegan <pg@bowt.ie>
Wed, 16 Sep 2020 17:42:28 +0000 (10:42 -0700)
committerPeter Geoghegan <pg@bowt.ie>
Wed, 16 Sep 2020 17:42:28 +0000 (10:42 -0700)
Commit d114cc53 overlooked the fact that pg_upgrade'd B-Tree indexes
have leaf page high keys whose offset numbers do not match the one from
the copy of the tuple one level up (the copy stored with a downlink for
leaf page's right sibling page).  This led to false positive reports of
corruption from bt_index_parent_check() when it was called to verify a
pg_upgrade'd index.

To fix, skip comparing the offset number on pg_upgrade'd B-Tree indexes.

Author: Anastasia Lubennikova <a.lubennikova@postgrespro.ru>
Author: Peter Geoghegan <pg@bowt.ie>
Reported-By: Andrew Bille <andrewbille@gmail.com>
Diagnosed-By: Anastasia Lubennikova <a.lubennikova@postgrespro.ru>
Bug: #16619
Discussion: https://postgr.es/m/16619-aaba10f83fdc1c3c@postgresql.org
Backpatch: 13-, where child check was enhanced.

contrib/amcheck/verify_nbtree.c

index 060600a556a20b190e2031e9d66d69f78b80a7f7..be833d258e5a68d231e550922cbcdf4da41e44d4 100644 (file)
@@ -1624,14 +1624,36 @@ bt_right_page_check_scankey(BtreeCheckState *state)
  * this function is capable to compare pivot keys on different levels.
  */
 static bool
-bt_pivot_tuple_identical(IndexTuple itup1, IndexTuple itup2)
+bt_pivot_tuple_identical(bool heapkeyspace, IndexTuple itup1, IndexTuple itup2)
 {
        if (IndexTupleSize(itup1) != IndexTupleSize(itup2))
                return false;
 
-       if (memcmp(&itup1->t_tid.ip_posid, &itup2->t_tid.ip_posid,
-                          IndexTupleSize(itup1) - offsetof(ItemPointerData, ip_posid)) != 0)
-               return false;
+       if (heapkeyspace)
+       {
+               /*
+                * Offset number will contain important information in heapkeyspace
+                * indexes: the number of attributes left in the pivot tuple following
+                * suffix truncation.  Don't skip over it (compare it too).
+                */
+               if (memcmp(&itup1->t_tid.ip_posid, &itup2->t_tid.ip_posid,
+                                  IndexTupleSize(itup1) -
+                                  offsetof(ItemPointerData, ip_posid)) != 0)
+                       return false;
+       }
+       else
+       {
+               /*
+                * Cannot rely on offset number field having consistent value across
+                * levels on pg_upgrade'd !heapkeyspace indexes.  Compare contents of
+                * tuple starting from just after item pointer (i.e. after block
+                * number and offset number).
+                */
+               if (memcmp(&itup1->t_info, &itup2->t_info,
+                                  IndexTupleSize(itup1) -
+                                  offsetof(IndexTupleData, t_info)) != 0)
+                       return false;
+       }
 
        return true;
 }
@@ -1785,7 +1807,7 @@ bt_child_highkey_check(BtreeCheckState *state,
                rightsplit = P_INCOMPLETE_SPLIT(opaque);
 
                /*
-                * If we visit page with high key, check that it is be equal to the
+                * If we visit page with high key, check that it is equal to the
                 * target key next to corresponding downlink.
                 */
                if (!rightsplit && !P_RIGHTMOST(opaque))
@@ -1879,7 +1901,7 @@ bt_child_highkey_check(BtreeCheckState *state,
                                itup = state->lowkey;
                        }
 
-                       if (!bt_pivot_tuple_identical(highkey, itup))
+                       if (!bt_pivot_tuple_identical(state->heapkeyspace, highkey, itup))
                        {
                                ereport(ERROR,
                                                (errcode(ERRCODE_INDEX_CORRUPTED),