From 39433853ddfb67fdd3ccc2e2b083c6ea329e0f96 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Mon, 1 Dec 2025 23:18:26 +0200
Subject: [PATCH v1 2/4] Fix amcheck's handling of incomplete root splits in
 B-tree

Discussion: https://www.postgresql.org/message-id/abd65090-5336-42cc-b768-2bdd66738404@iki.fi
---
 contrib/amcheck/verify_nbtree.c                            | 2 +-
 .../modules/nbtree/expected/nbtree_incomplete_splits.out   | 7 +++++++
 src/test/modules/nbtree/sql/nbtree_incomplete_splits.sql   | 7 +++++++
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c
index 0949c88983a..f26c20b59aa 100644
--- a/contrib/amcheck/verify_nbtree.c
+++ b/contrib/amcheck/verify_nbtree.c
@@ -721,7 +721,7 @@ bt_check_level_from_leftmost(BtreeCheckState *state, BtreeLevel level)
 							 errmsg("block %u is not leftmost in index \"%s\"",
 									current, RelationGetRelationName(state->rel))));
 
-				if (level.istruerootlevel && !P_ISROOT(opaque))
+				if (level.istruerootlevel && (!P_ISROOT(opaque) && !P_INCOMPLETE_SPLIT(opaque)))
 					ereport(ERROR,
 							(errcode(ERRCODE_INDEX_CORRUPTED),
 							 errmsg("block %u is not true root in index \"%s\"",
diff --git a/src/test/modules/nbtree/expected/nbtree_incomplete_splits.out b/src/test/modules/nbtree/expected/nbtree_incomplete_splits.out
index 88e87e875c8..161eb3cbfa8 100644
--- a/src/test/modules/nbtree/expected/nbtree_incomplete_splits.out
+++ b/src/test/modules/nbtree/expected/nbtree_incomplete_splits.out
@@ -14,6 +14,7 @@
 -- splits in "incomplete" state
 set client_min_messages TO 'warning';
 create extension if not exists injection_points;
+create extension if not exists amcheck;
 reset client_min_messages;
 -- Make all injection points local to this process, for concurrency.
 SELECT injection_points_set_local();
@@ -87,6 +88,12 @@ begin
   if c <> 200 then
     raise 'unexpected count % ', c;
   end if;
+
+  -- Also check the index with amcheck. Both to test that the index is
+  -- valid, but also to test that amcheck doesn't wrongly complain
+  -- about incomplete splits.
+  perform bt_index_parent_check('nbtree_incomplete_splits_i_idx'::regclass, true, true);
+
   return true;
 end;
 $$;
diff --git a/src/test/modules/nbtree/sql/nbtree_incomplete_splits.sql b/src/test/modules/nbtree/sql/nbtree_incomplete_splits.sql
index 0609ed7464e..f6b22786d37 100644
--- a/src/test/modules/nbtree/sql/nbtree_incomplete_splits.sql
+++ b/src/test/modules/nbtree/sql/nbtree_incomplete_splits.sql
@@ -15,6 +15,7 @@
 -- splits in "incomplete" state
 set client_min_messages TO 'warning';
 create extension if not exists injection_points;
+create extension if not exists amcheck;
 reset client_min_messages;
 
 -- Make all injection points local to this process, for concurrency.
@@ -86,6 +87,12 @@ begin
   if c <> 200 then
     raise 'unexpected count % ', c;
   end if;
+
+  -- Also check the index with amcheck. Both to test that the index is
+  -- valid, but also to test that amcheck doesn't wrongly complain
+  -- about incomplete splits.
+  perform bt_index_parent_check('nbtree_incomplete_splits_i_idx'::regclass, true, true);
+
   return true;
 end;
 $$;
-- 
2.47.3

