v37-0004-Fix-for-gin_index_check.patch
application/octet-stream
Filename: v37-0004-Fix-for-gin_index_check.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v37-0004
Subject: Fix for gin_index_check.
| File | + | − |
|---|---|---|
| contrib/amcheck/verify_gin.c | 35 | 21 |
From 0e86a027ab785cb134d8cb5b8eee200b7c046569 Mon Sep 17 00:00:00 2001
From: reshke kirill <reshke@double.cloud>
Date: Mon, 16 Dec 2024 10:49:43 +0000
Subject: [PATCH v37 4/7] Fix for gin_index_check.
Never explicitly check high key on rightmost page is entry tree.
Its value is not stored explicitly and is equal to infitity.
Also never compare gin entries for different attnums.
---
contrib/amcheck/verify_gin.c | 56 ++++++++++++++++++++++--------------
1 file changed, 35 insertions(+), 21 deletions(-)
diff --git a/contrib/amcheck/verify_gin.c b/contrib/amcheck/verify_gin.c
index 2dc5fbba619..ae3d24a8b86 100644
--- a/contrib/amcheck/verify_gin.c
+++ b/contrib/amcheck/verify_gin.c
@@ -163,6 +163,7 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
Page page;
OffsetNumber i,
maxoff;
+ BlockNumber rightlink;
CHECK_FOR_INTERRUPTS();
@@ -170,6 +171,7 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
RBM_NORMAL, strategy);
LockBuffer(buffer, GIN_SHARE);
page = (Page) BufferGetPage(buffer);
+
Assert(GinPageIsData(page));
/* Check that the tree has the same height in all branches */
@@ -182,7 +184,7 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
ItemPointerSetMin(&minItem);
- elog(DEBUG1, "page blk: %u, type leaf", stack->blkno);
+ elog(DEBUG2, "page blk: %u, type leaf", stack->blkno);
if (leafdepth == -1)
leafdepth = stack->depth;
@@ -234,8 +236,8 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
* Check that tuples in each page are properly ordered and
* consistent with parent high key
*/
- Assert(GinPageIsData(page));
maxoff = GinPageGetOpaque(page)->maxoff;
+ rightlink = GinPageGetOpaque(page)->rightlink;
elog(DEBUG1, "page blk: %u, type data, maxoff %d", stack->blkno, maxoff);
@@ -273,7 +275,12 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
*/
bound = *GinDataPageGetRightBound(page);
- if (stack->parentblk != InvalidBlockNumber &&
+ /*
+ * Gin page right bound has sane value if only not a highkey on
+ * rightmost page on level.
+ */
+ if (ItemPointerIsValid(&stack->parentkey) &&
+ rightlink != InvalidBlockNumber &&
!ItemPointerEquals(&stack->parentkey, &bound))
ereport(ERROR,
(errcode(ERRCODE_INDEX_CORRUPTED),
@@ -287,11 +294,12 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{
+ GinPostingTreeScanItem *ptr;
PostingItem *posting_item = GinDataPageGetPostingItem(page, i);
/* ItemPointerGetOffsetNumber expects a valid pointer */
if (!(i == maxoff &&
- GinPageGetOpaque(page)->rightlink == InvalidBlockNumber))
+ rightlink == InvalidBlockNumber))
elog(DEBUG3, "key (%u, %u) -> %u",
ItemPointerGetBlockNumber(&posting_item->key),
ItemPointerGetOffsetNumber(&posting_item->key),
@@ -300,8 +308,7 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
elog(DEBUG3, "key (%u, %u) -> %u",
0, 0, BlockIdGetBlockNumber(&posting_item->child_blkno));
- if (i == maxoff &&
- GinPageGetOpaque(page)->rightlink == InvalidBlockNumber)
+ if (i == maxoff && rightlink == InvalidBlockNumber)
{
/*
* The rightmost item in the tree level has (0, 0) as the
@@ -340,19 +347,23 @@ gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting
RelationGetRelationName(rel),
stack->blkno, i)));
- /* If this is an internal page, recurse into the child */
- if (!GinPageIsLeaf(page))
- {
- GinPostingTreeScanItem *ptr;
+ /* This is an internal page, recurse into the child */
+ ptr = (GinPostingTreeScanItem *) palloc(sizeof(GinPostingTreeScanItem));
+ ptr->depth = stack->depth + 1;
- ptr = (GinPostingTreeScanItem *) palloc(sizeof(GinPostingTreeScanItem));
- ptr->depth = stack->depth + 1;
+ /*
+ * Set rightmost parent key to invalid iterm pointer. Its
+ * value is 'Infinity' and not explicitly stored.
+ */
+ if (rightlink == InvalidBlockNumber)
+ ItemPointerSetInvalid(&ptr->parentkey);
+ else
ptr->parentkey = posting_item->key;
- ptr->parentblk = stack->blkno;
- ptr->blkno = BlockIdGetBlockNumber(&posting_item->child_blkno);
- ptr->next = stack->next;
- stack->next = ptr;
- }
+
+ ptr->parentblk = stack->blkno;
+ ptr->blkno = BlockIdGetBlockNumber(&posting_item->child_blkno);
+ ptr->next = stack->next;
+ stack->next = ptr;
}
}
LockBuffer(buffer, GIN_UNLOCK);
@@ -411,7 +422,8 @@ gin_check_parent_keys_consistency(Relation rel,
Buffer buffer;
Page page;
OffsetNumber i,
- maxoff;
+ maxoff,
+ prev_attnum;
XLogRecPtr lsn;
IndexTuple prev_tuple;
BlockNumber rightlink;
@@ -488,6 +500,7 @@ gin_check_parent_keys_consistency(Relation rel,
* with parent high key
*/
prev_tuple = NULL;
+ prev_attnum = InvalidAttrNumber;
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{
ItemId iid = PageGetItemIdCareful(rel, stack->blkno, page, i);
@@ -511,7 +524,7 @@ gin_check_parent_keys_consistency(Relation rel,
* for high key on rightmost page, as this key is not really
* stored explicitly.
*/
- if (i != FirstOffsetNumber && stack->blkno != GIN_ROOT_BLKNO &&
+ if (i != FirstOffsetNumber && attnum == prev_attnum && stack->blkno != GIN_ROOT_BLKNO &&
!(i == maxoff && rightlink == InvalidBlockNumber))
{
prev_key = gintuple_get_key(&state, prev_tuple, &prev_key_category);
@@ -520,8 +533,8 @@ gin_check_parent_keys_consistency(Relation rel,
current_key_category) >= 0)
ereport(ERROR,
(errcode(ERRCODE_INDEX_CORRUPTED),
- errmsg("index \"%s\" has wrong tuple order on entry tree page, block %u, offset %u",
- RelationGetRelationName(rel), stack->blkno, i)));
+ errmsg("index \"%s\" has wrong tuple order on entry tree page, block %u, offset %u, rightlink %u",
+ RelationGetRelationName(rel), stack->blkno, i, rightlink)));
}
/*
@@ -620,6 +633,7 @@ gin_check_parent_keys_consistency(Relation rel,
}
prev_tuple = CopyIndexTuple(idxtuple);
+ prev_attnum = attnum;
}
LockBuffer(buffer, GIN_UNLOCK);
--
2.43.0