summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorAlexander Korotkov2024-05-22 23:13:43 +0000
committerAlexander Korotkov2024-05-22 23:13:43 +0000
commit97e5b0026fc276ab1bcde58ae98ae1fcd9c3acc3 (patch)
tree1c2ec4796a1db2290af5f5029e9c4531df08b2d3 /contrib
parent0b5c161248110b164a3333006004c78f9529a109 (diff)
amcheck: Report an error when the next page to a leaf is not a leaf
This is a very unlikely condition during checking a B-tree unique constraint, meaning that the index structure is violated badly, and we shouldn't continue checking to avoid endless loops, etc. So it's worth immediately throwing an error. Reported-by: Peter Geoghegan Discussion: https://postgr.es/m/CAH2-Wzk%2B2116uOXdOViA27SHcr31WKPgmjsxXLBs_aTxAeThzg%40mail.gmail.com Author: Pavel Borisov
Diffstat (limited to 'contrib')
-rw-r--r--contrib/amcheck/verify_nbtree.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c
index 5354b393b11..4347f9594c9 100644
--- a/contrib/amcheck/verify_nbtree.c
+++ b/contrib/amcheck/verify_nbtree.c
@@ -1831,7 +1831,6 @@ bt_target_page_check(BtreeCheckState *state)
if (offset == max)
{
BTScanInsert rightkey;
- BlockNumber rightblock_number;
/* first offset on a right index page (log only) */
OffsetNumber rightfirstoffset = InvalidOffsetNumber;
@@ -1876,10 +1875,11 @@ bt_target_page_check(BtreeCheckState *state)
* If index has unique constraint make sure that no more than one
* found equal items is visible.
*/
- rightblock_number = topaque->btpo_next;
if (state->checkunique && state->indexinfo->ii_Unique &&
- rightkey && P_ISLEAF(topaque) && rightblock_number != P_NONE)
+ rightkey && P_ISLEAF(topaque) && !P_RIGHTMOST(topaque))
{
+ BlockNumber rightblock_number = topaque->btpo_next;
+
elog(DEBUG2, "check cross page unique condition");
/*
@@ -1899,9 +1899,19 @@ bt_target_page_check(BtreeCheckState *state)
rightblock_number);
topaque = BTPageGetOpaque(rightpage);
- if (P_IGNORE(topaque) || !P_ISLEAF(topaque))
- break;
-
+ if (P_IGNORE(topaque))
+ {
+ if (unlikely(!P_ISLEAF(topaque)))
+ ereport(ERROR,
+ (errcode(ERRCODE_INDEX_CORRUPTED),
+ errmsg("right block of leaf block is non-leaf for index \"%s\"",
+ RelationGetRelationName(state->rel)),
+ errdetail_internal("Block=%u page lsn=%X/%X.",
+ state->targetblock,
+ LSN_FORMAT_ARGS(state->targetlsn))));
+ else
+ break;
+ }
itemid = PageGetItemIdCareful(state, rightblock_number,
rightpage,
rightfirstoffset);