Hello,I think that pgstattuple should use PageGetExactFreeSpace() instead of PageGetHeapFreeSpace() or PageGetFreeSpace(). The latter two compute the free space minus the space of a line pointer. They are used like this in the rest of the code (heapam.c):
pagefree = PageGetHeapFreeSpace(page); if (newtupsize > pagefree) { we need a another page for the tuple } ... so it makes sense to take the line pointer into account in this context. But it in the pgstattuple context, I think we want the exact free space. I have attached a patch. Best regards, Frédéric
From 350abec004fe472922800135d5d94ca3d8212da4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Yhuel?= <frederic.yh...@dalibo.com> Date: Wed, 21 Aug 2024 15:05:11 +0200 Subject: [PATCH] pgstattuple: use PageGetExactFreeSpace() instead of PageGetHeapFreeSpace() and PageGetFreeSpace() We want the exact free space, we don't care if there's enough room for another line pointer. --- contrib/pgstattuple/pgstatapprox.c | 2 +- contrib/pgstattuple/pgstatindex.c | 2 +- contrib/pgstattuple/pgstattuple.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contrib/pgstattuple/pgstatapprox.c b/contrib/pgstattuple/pgstatapprox.c index c84c642355..a27dea621e 100644 --- a/contrib/pgstattuple/pgstatapprox.c +++ b/contrib/pgstattuple/pgstatapprox.c @@ -111,7 +111,7 @@ statapprox_heap(Relation rel, output_type *stat) * treat them as being free space for our purposes. */ if (!PageIsNew(page)) - stat->free_space += PageGetHeapFreeSpace(page); + stat->free_space += PageGetExactFreeSpace(page); else stat->free_space += BLCKSZ - SizeOfPageHeaderData; diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c index 5c06ba6db4..1b6b768cf8 100644 --- a/contrib/pgstattuple/pgstatindex.c +++ b/contrib/pgstattuple/pgstatindex.c @@ -311,7 +311,7 @@ pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo) max_avail = BLCKSZ - (BLCKSZ - ((PageHeader) page)->pd_special + SizeOfPageHeaderData); indexStat.max_avail += max_avail; - indexStat.free_space += PageGetFreeSpace(page); + indexStat.free_space += PageGetExactFreeSpace(page); indexStat.leaf_pages++; diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c index 3bd8b96197..7e2a7262a3 100644 --- a/contrib/pgstattuple/pgstattuple.c +++ b/contrib/pgstattuple/pgstattuple.c @@ -372,7 +372,7 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo) buffer = ReadBufferExtended(rel, MAIN_FORKNUM, block, RBM_NORMAL, hscan->rs_strategy); LockBuffer(buffer, BUFFER_LOCK_SHARE); - stat.free_space += PageGetHeapFreeSpace((Page) BufferGetPage(buffer)); + stat.free_space += PageGetExactFreeSpace((Page) BufferGetPage(buffer)); UnlockReleaseBuffer(buffer); block++; } @@ -385,7 +385,7 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo) buffer = ReadBufferExtended(rel, MAIN_FORKNUM, block, RBM_NORMAL, hscan->rs_strategy); LockBuffer(buffer, BUFFER_LOCK_SHARE); - stat.free_space += PageGetHeapFreeSpace((Page) BufferGetPage(buffer)); + stat.free_space += PageGetExactFreeSpace((Page) BufferGetPage(buffer)); UnlockReleaseBuffer(buffer); block++; } @@ -565,7 +565,7 @@ pgstat_index_page(pgstattuple_type *stat, Page page, { OffsetNumber i; - stat->free_space += PageGetFreeSpace(page); + stat->free_space += PageGetExactFreeSpace(page); for (i = minoff; i <= maxoff; i = OffsetNumberNext(i)) { -- 2.39.2