From 727295ae6dd2a120d8cefd802a555a3e1a8d4e34 Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Mon, 17 Aug 2026 17:31:07 -0400 Subject: [PATCH] GiST: Deprecate F_TUPLES_DELETED opaque area flag. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This flag hasn't been useful since the removal of old-style VACUUM FULL, so remove it now (this includes removing vestigial code that unnecessarily set the flag). Also add test coverage of gistprunepage(). Had that test case been available before now, the issue fixed by this commit would have been detected by wal_consistency_checking buildfarm animals. Author: Peter Geoghegan Reviewed-by: Michael Paquiër Discussion: https://postgr.es/m/CAH2-WznbTsQCrjmd=eSawfPqcxCjSFUkk6Qzd3z+gpNte5i03Q@mail.gmail.com Backpatch-through: 14 --- src/backend/access/gist/gistvacuum.c | 1 - src/backend/access/gist/gistxlog.c | 3 --- src/include/access/gist.h | 8 ++------ src/test/regress/expected/gist.out | 26 ++++++++++++++++++++++++++ src/test/regress/sql/gist.sql | 21 +++++++++++++++++++++ 5 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c index 24fb94f473e..2a2b4593e2b 100644 --- a/src/backend/access/gist/gistvacuum.c +++ b/src/backend/access/gist/gistvacuum.c @@ -364,7 +364,6 @@ restart: MarkBufferDirty(buffer); PageIndexMultiDelete(page, todelete, ntodelete); - GistMarkTuplesDeleted(page); if (RelationNeedsWAL(rel)) { diff --git a/src/backend/access/gist/gistxlog.c b/src/backend/access/gist/gistxlog.c index 451e8d8d98e..a564230bad3 100644 --- a/src/backend/access/gist/gistxlog.c +++ b/src/backend/access/gist/gistxlog.c @@ -115,8 +115,6 @@ gistRedoPageUpdateRecord(XLogReaderState *record) data += sizeof(OffsetNumber) * xldata->ntodelete; PageIndexMultiDelete(page, todelete, xldata->ntodelete); - if (GistPageIsLeaf(page)) - GistMarkTuplesDeleted(page); } /* Add new tuples if any */ @@ -206,7 +204,6 @@ gistRedoDeleteRecord(XLogReaderState *record) PageIndexMultiDelete(page, toDelete, xldata->ntodelete); GistClearPageHasGarbage(page); - GistMarkTuplesDeleted(page); PageSetLSN(page, lsn); MarkBufferDirty(buffer); diff --git a/src/include/access/gist.h b/src/include/access/gist.h index c6dcd6a90dd..04f4f080a84 100644 --- a/src/include/access/gist.h +++ b/src/include/access/gist.h @@ -45,8 +45,8 @@ */ #define F_LEAF (1 << 0) /* leaf page */ #define F_DELETED (1 << 1) /* the page has been deleted */ -#define F_TUPLES_DELETED (1 << 2) /* some tuples on the page were - * deleted */ +#define F_TUPLES_DELETED (1 << 2) /* old-style VACUUM FULL flag + * (deprecated) */ #define F_FOLLOW_RIGHT (1 << 3) /* page to the right has no downlink */ #define F_HAS_GARBAGE (1 << 4) /* some tuples on the page are dead, * but not deleted yet */ @@ -171,10 +171,6 @@ typedef struct GISTENTRY #define GistPageIsDeleted(page) ( GistPageGetOpaque(page)->flags & F_DELETED) -#define GistTuplesDeleted(page) ( GistPageGetOpaque(page)->flags & F_TUPLES_DELETED) -#define GistMarkTuplesDeleted(page) ( GistPageGetOpaque(page)->flags |= F_TUPLES_DELETED) -#define GistClearTuplesDeleted(page) ( GistPageGetOpaque(page)->flags &= ~F_TUPLES_DELETED) - #define GistPageHasGarbage(page) ( GistPageGetOpaque(page)->flags & F_HAS_GARBAGE) #define GistMarkPageHasGarbage(page) ( GistPageGetOpaque(page)->flags |= F_HAS_GARBAGE) #define GistClearPageHasGarbage(page) ( GistPageGetOpaque(page)->flags &= ~F_HAS_GARBAGE) diff --git a/src/test/regress/expected/gist.out b/src/test/regress/expected/gist.out index ae5b522b3c6..ac79f94aa80 100644 --- a/src/test/regress/expected/gist.out +++ b/src/test/regress/expected/gist.out @@ -423,6 +423,32 @@ select lower(r) = repeat('7', 200)::numeric as lower_ok, (1 row) drop table gist_ios_tupdesc; +-- test deletion of LP_DEAD-marked index tuples +create table gist_prune_tbl (k int, p point); +create index gist_prune_tbl_p_index on gist_prune_tbl using gist (p); +begin; +insert into gist_prune_tbl select i, point(1, i) from generate_series(1, 600) i; +rollback; +set enable_bitmapscan = off; +set enable_indexonlyscan = off; +set enable_seqscan = off; +select count(*) from gist_prune_tbl where p <@ box(point(0,0), point(2,1000)); + count +------- + 0 +(1 row) + +insert into gist_prune_tbl select i, point(1, i) from generate_series(1, 600) i; +select count(*) from gist_prune_tbl where p <@ box(point(0,0), point(2,1000)); + count +------- + 600 +(1 row) + +reset enable_bitmapscan; +reset enable_indexonlyscan; +reset enable_seqscan; +drop table gist_prune_tbl; -- Force an index build using buffering. create index gist_tbl_box_index_forcing_buffering on gist_tbl using gist (p) with (buffering=on, fillfactor=50); diff --git a/src/test/regress/sql/gist.sql b/src/test/regress/sql/gist.sql index 1ebb1d9ee43..57dcc082450 100644 --- a/src/test/regress/sql/gist.sql +++ b/src/test/regress/sql/gist.sql @@ -198,6 +198,27 @@ select lower(r) = repeat('7', 200)::numeric as lower_ok, drop table gist_ios_tupdesc; +-- test deletion of LP_DEAD-marked index tuples +create table gist_prune_tbl (k int, p point); +create index gist_prune_tbl_p_index on gist_prune_tbl using gist (p); + +begin; +insert into gist_prune_tbl select i, point(1, i) from generate_series(1, 600) i; +rollback; + +set enable_bitmapscan = off; +set enable_indexonlyscan = off; +set enable_seqscan = off; + +select count(*) from gist_prune_tbl where p <@ box(point(0,0), point(2,1000)); +insert into gist_prune_tbl select i, point(1, i) from generate_series(1, 600) i; +select count(*) from gist_prune_tbl where p <@ box(point(0,0), point(2,1000)); + +reset enable_bitmapscan; +reset enable_indexonlyscan; +reset enable_seqscan; +drop table gist_prune_tbl; + -- Force an index build using buffering. create index gist_tbl_box_index_forcing_buffering on gist_tbl using gist (p) with (buffering=on, fillfactor=50);