From 940dad96d9810692e660b0f289af7c7ed2bf2022 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@vondra.me>
Date: Wed, 18 Mar 2026 16:30:28 +0100
Subject: [PATCH v3 5/6] get rid of TableScanStats[Data]

finish replacing it with IOStats
---
 src/backend/commands/explain.c            |  4 +--
 src/backend/executor/nodeBitmapHeapscan.c |  2 +-
 src/backend/executor/nodeSeqscan.c        |  2 +-
 src/include/access/relscan.h              | 41 -----------------------
 src/include/executor/instrument_node.h    | 13 +++++++
 5 files changed, 17 insertions(+), 45 deletions(-)

diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 25af6550098..1b0feeadd9e 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4093,7 +4093,7 @@ show_scan_io_usage(ScanState *planstate, ExplainState *es)
 					for (int i = 0; i < sinstrument->num_workers; ++i)
 					{
 						SeqScanInstrumentation *winstrument = &sinstrument->sinstrument[i];
-						ACCUMULATE_TABLE_STATS(&stats, &winstrument->io);
+						ACCUMULATE_IO_STATS(&stats, &winstrument->io);
 					}
 				}
 
@@ -4110,7 +4110,7 @@ show_scan_io_usage(ScanState *planstate, ExplainState *es)
 					for (int i = 0; i < sinstrument->num_workers; ++i)
 					{
 						BitmapHeapScanInstrumentation *winstrument = &sinstrument->sinstrument[i];
-						ACCUMULATE_TABLE_STATS(&stats, &winstrument->io);
+						ACCUMULATE_IO_STATS(&stats, &winstrument->io);
 					}
 				}
 
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 55b1e294d6c..b785cb7a237 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -330,7 +330,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 		si->lossy_pages += node->stats.lossy_pages;
 
 		/* collect prefetch info for this process from the read_stream */
-		ACCUMULATE_TABLE_STATS(&node->ss.ss_currentScanDesc->rs_iostats, &si->io);
+		ACCUMULATE_IO_STATS(&si->io, &node->ss.ss_currentScanDesc->rs_iostats);
 	}
 
 	/*
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 28e33aa391d..2ecc0e3054d 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -316,7 +316,7 @@ ExecEndSeqScan(SeqScanState *node)
 		 */
 
 		/* collect prefetch info for this process from the read_stream */
-		ACCUMULATE_TABLE_STATS(&node->ss.ss_currentScanDesc->rs_iostats, &si->io);
+		ACCUMULATE_IO_STATS(&si->io, &node->ss.ss_currentScanDesc->rs_iostats);
 	}
 
 	/*
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index e41f0f8ee13..32ef27c546f 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -120,47 +120,6 @@ typedef struct ParallelBlockTableScanWorkerData
 } ParallelBlockTableScanWorkerData;
 typedef struct ParallelBlockTableScanWorkerData *ParallelBlockTableScanWorker;
 
-/*
- * Generic prefetch stats for table scans.
- */
-typedef struct TableScanStatsData
-{
-	/* number of buffers returned to consumer (for averaging distance) */
-	uint64		prefetch_count;
-
-	/* sum of pinned_buffers sampled at each buffer return */
-	uint64		distance_sum;
-
-	/* maximum actual pinned_buffers observed during the scan */
-	int16		distance_max;
-
-	/* maximum possible look-ahead distance (max_pinned_buffers) */
-	int16		distance_capacity;
-
-	/* number of stalled reads (waiting for I/O) */
-	uint64		stall_count;
-
-	/* I/O stats */
-	uint64		io_count;		/* number of I/Os */
-	uint64		io_nblocks;		/* sum of blocks for all I/Os */
-	uint64		io_in_progress;	/* sum of in-progress I/Os */
-} TableScanStatsData;
-typedef struct TableScanStatsData *TableScanStats;
-
-#define ACCUMULATE_TABLE_STATS(dst, src) \
-	do { \
-		(dst)->prefetch_count += (src)->prefetch_count; \
-		(dst)->distance_sum += (src)->distance_sum; \
-		if ((src)->distance_max > (dst)->distance_max) \
-			(dst)->distance_max = (src)->distance_max; \
-		if ((src)->distance_capacity > (dst)->distance_capacity) \
-			(dst)->distance_capacity = (src)->distance_capacity; \
-		(dst)->stall_count += (src)->stall_count; \
-		(dst)->io_count += (src)->io_count; \
-		(dst)->io_nblocks += (src)->io_nblocks; \
-		(dst)->io_in_progress += (src)->io_in_progress; \
-	} while (0)
-
 /*
  * Base class for fetches from a table via an index. This is the base-class
  * for such scans, which needs to be embedded in the respective struct for
diff --git a/src/include/executor/instrument_node.h b/src/include/executor/instrument_node.h
index cda00ad40e9..ce643ef0635 100644
--- a/src/include/executor/instrument_node.h
+++ b/src/include/executor/instrument_node.h
@@ -67,6 +67,19 @@ typedef struct IOStats
 	uint64		io_in_progress;	/* sum of in-progress I/Os */
 } IOStats;
 
+#define ACCUMULATE_IO_STATS(dst, src) \
+	do { \
+		(dst)->prefetch_count += (src)->prefetch_count; \
+		(dst)->distance_sum += (src)->distance_sum; \
+		if ((src)->distance_max > (dst)->distance_max) \
+			(dst)->distance_max = (src)->distance_max; \
+		if ((src)->distance_capacity > (dst)->distance_capacity) \
+			(dst)->distance_capacity = (src)->distance_capacity; \
+		(dst)->stall_count += (src)->stall_count; \
+		(dst)->io_count += (src)->io_count; \
+		(dst)->io_nblocks += (src)->io_nblocks; \
+		(dst)->io_in_progress += (src)->io_in_progress; \
+	} while (0)
 
 /* ---------------------
  *	Instrumentation information for sequential scans
-- 
2.53.0

