From c6d89d6bdcda3bd53beb120be77f24838e4b5b3d Mon Sep 17 00:00:00 2001
From: reshke <reshke@double.cloud>
Date: Thu, 15 Jan 2026 06:34:42 +0000
Subject: [PATCH v2] Fix gistkillitems for GiST ROOT page.

GiST index killitems feature misbehaves for single-page
(ROOT-only) GiST index. This is caused by GiST scan
"current block" variable not beign initialized for
very first-to-scan page (which is ROOT page).
Fix this by moving variable initialization in
read pgae utility function. Also adjust test output
that used to test exactly this bug (starting 377b7ab).

Discussion: https://postgr.es/m/CALdSSPgZWX_D8%2BFx4YQqRN5eW5iSx_rJdqQhCfdWTvqKXVfJ4w%40mail.gmail.com
Discussion: https://postgr.es/m/lxzj26ga6ippdeunz6kuncectr5gfuugmm2ry22qu6hcx6oid6@lzx3sjsqhmt6
---
 src/backend/access/gist/gistget.c              | 6 +++---
 src/test/modules/index/expected/killtuples.out | 2 +-
 src/test/modules/index/specs/killtuples.spec   | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index 11b214eb99b..7dc34680e2d 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -407,6 +407,9 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem,
 	 */
 	so->curPageLSN = BufferGetLSNAtomic(buffer);
 
+	/* save current item BlockNumber for gistkillitems() call */
+	so->curBlkno = pageItem->blkno;
+
 	/*
 	 * check all tuples on page
 	 */
@@ -722,9 +725,6 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir)
 
 				CHECK_FOR_INTERRUPTS();
 
-				/* save current item BlockNumber for next gistkillitems() call */
-				so->curBlkno = item->blkno;
-
 				/*
 				 * While scanning a leaf page, ItemPointers of matching heap
 				 * tuples are stored in so->pageData.  If there are any on
diff --git a/src/test/modules/index/expected/killtuples.out b/src/test/modules/index/expected/killtuples.out
index be7ddd756ef..f504eca76df 100644
--- a/src/test/modules/index/expected/killtuples.out
+++ b/src/test/modules/index/expected/killtuples.out
@@ -223,7 +223,7 @@ step flush: SELECT FROM pg_stat_force_next_flush();
 step result: SELECT heap_blks_read + heap_blks_hit - counter.heap_accesses AS new_heap_accesses FROM counter, pg_statio_all_tables WHERE relname = 'kill_prior_tuple';
 new_heap_accesses
 -----------------
-                1
+                0
 (1 row)
 
 step drop_table: DROP TABLE IF EXISTS kill_prior_tuple;
diff --git a/src/test/modules/index/specs/killtuples.spec b/src/test/modules/index/specs/killtuples.spec
index 77fe8c689a7..7f912a40f1f 100644
--- a/src/test/modules/index/specs/killtuples.spec
+++ b/src/test/modules/index/specs/killtuples.spec
@@ -94,7 +94,7 @@ permutation
   measure access flush result
   drop_table drop_ext_btree_gist
 
-# Test gist, but with fewer rows - shows that killitems doesn't work anymore!
+# Test gist, but with fewer rows - that killitems used to be buggy.
 permutation
   create_table fill_10 create_ext_btree_gist create_gist flush
   disable_seq disable_bitmap
-- 
2.43.0

