From ba3d5cc709e9b1f0adef6616f77baba04a63f471 Mon Sep 17 00:00:00 2001
From: reshke kirill <reshke@double.cloud>
Date: Mon, 16 Dec 2024 10:49:43 +0000
Subject: [PATCH v35] 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.
---
 contrib/amcheck/verify_gin.c | 43 ++++++++++++++++++++++--------------
 1 file changed, 27 insertions(+), 16 deletions(-)

diff --git a/contrib/amcheck/verify_gin.c b/contrib/amcheck/verify_gin.c
index 2dc5fbba619..74783af54d4 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 */
@@ -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);
-- 
2.34.1

