diff options
author | Peter Geoghegan <pg@bowt.ie> | 2020-09-16 10:42:30 -0700 |
---|---|---|
committer | Peter Geoghegan <pg@bowt.ie> | 2020-09-16 10:42:30 -0700 |
commit | aac80bfcddf7df3fbd1eb73e8a386115d922c714 (patch) | |
tree | ac0b52df9a0d93d6f9920b3bf5f5d4e9eb9ecb5c | |
parent | e5fac1cb1941e4adbcb88206f914e2035e5cccf2 (diff) | |
download | postgresql-aac80bfcddf7df3fbd1eb73e8a386115d922c714.tar.gz postgresql-aac80bfcddf7df3fbd1eb73e8a386115d922c714.zip |
Fix amcheck child check pg_upgrade bug.
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.
-rw-r--r-- | contrib/amcheck/verify_nbtree.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c index 5f3de3c0b7f..6d86e3ccdac 100644 --- a/contrib/amcheck/verify_nbtree.c +++ b/contrib/amcheck/verify_nbtree.c @@ -1752,14 +1752,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; } @@ -1913,7 +1935,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)) @@ -2007,7 +2029,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), |