From 880a70639504cabf00d7d60d665f4025df3d64ef Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 25 Sep 2024 18:39:47 -0400
Subject: [PATCH 2/2] Move BitmapHeapScan-specific members into suffix

Make a new scan descriptor, BitmapHeapScanDesc, which inherits from
HeapScanDescData but has a few extra members that are specific to
BitmapHeapScans. These were in the generic HeapScanDescData but they
don't need to be. This saves space and sets the precedent that future
scan type-specific members shouldn't be put in the generic
HeapScanDescData.
---
 src/backend/access/heap/heapam.c         | 35 ++++++++++++++++--------
 src/backend/access/heap/heapam_handler.c | 12 ++++----
 src/include/access/heapam.h              | 19 ++++++++-----
 3 files changed, 42 insertions(+), 24 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index f167107257..61cb3350bd 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1036,7 +1036,15 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	/*
 	 * allocate and initialize scan descriptor
 	 */
-	scan = (HeapScanDesc) palloc(sizeof(HeapScanDescData));
+	if (flags & SO_TYPE_BITMAPSCAN)
+	{
+		BitmapHeapScanDesc *bscan = palloc(sizeof(BitmapHeapScanDesc));
+		bscan->rs_vmbuffer = InvalidBuffer;
+		bscan->rs_empty_tuples_pending = 0;
+		scan = &bscan->heap;
+	}
+	else
+		scan = palloc(sizeof(HeapScanDescData));
 
 	scan->rs_base.rs_rd = relation;
 	scan->rs_base.rs_snapshot = snapshot;
@@ -1044,8 +1052,6 @@ heap_beginscan(Relation relation, Snapshot snapshot,
 	scan->rs_base.rs_flags = flags;
 	scan->rs_base.rs_parallel = parallel_scan;
 	scan->rs_strategy = NULL;	/* set in initscan */
-	scan->rs_vmbuffer = InvalidBuffer;
-	scan->rs_empty_tuples_pending = 0;
 
 	/*
 	 * Disable page-at-a-time mode if it's not a MVCC-safe snapshot.
@@ -1161,18 +1167,20 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-	{
-		ReleaseBuffer(scan->rs_vmbuffer);
-		scan->rs_vmbuffer = InvalidBuffer;
-	}
-
 	/*
 	 * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
 	 * to avoid incorrectly emitting NULL-filled tuples from a previous scan
 	 * on rescan.
 	 */
-	scan->rs_empty_tuples_pending = 0;
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		((BitmapHeapScanDesc *) scan)->rs_empty_tuples_pending = 0;
+		if (BufferIsValid(((BitmapHeapScanDesc *) scan)->rs_vmbuffer))
+		{
+			ReleaseBuffer(((BitmapHeapScanDesc *) scan)->rs_vmbuffer);
+			((BitmapHeapScanDesc *) scan)->rs_vmbuffer = InvalidBuffer;
+		}
+	}
 
 	/*
 	 * The read stream is reset on rescan. This must be done before
@@ -1201,8 +1209,11 @@ heap_endscan(TableScanDesc sscan)
 	if (BufferIsValid(scan->rs_cbuf))
 		ReleaseBuffer(scan->rs_cbuf);
 
-	if (BufferIsValid(scan->rs_vmbuffer))
-		ReleaseBuffer(scan->rs_vmbuffer);
+	if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN)
+	{
+		if (BufferIsValid(((BitmapHeapScanDesc *) scan)->rs_vmbuffer))
+			ReleaseBuffer(((BitmapHeapScanDesc *) scan)->rs_vmbuffer);
+	}
 
 	/*
 	 * Must free the read stream before freeing the BufferAccessStrategy.
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 1c6da286d4..6fa1fec8f3 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2119,6 +2119,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 							  TBMIterateResult *tbmres)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) hscan;
 	BlockNumber block = tbmres->blockno;
 	Buffer		buffer;
 	Snapshot	snapshot;
@@ -2134,13 +2135,13 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
 	 */
 	if (!(scan->rs_flags & SO_NEED_TUPLES) &&
 		!tbmres->recheck &&
-		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer))
+		VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
 	{
 		/* can't be lossy in the skip_fetch case */
 		Assert(tbmres->ntuples >= 0);
-		Assert(hscan->rs_empty_tuples_pending >= 0);
+		Assert(bscan->rs_empty_tuples_pending >= 0);
 
-		hscan->rs_empty_tuples_pending += tbmres->ntuples;
+		((BitmapHeapScanDesc *) hscan)->rs_empty_tuples_pending += tbmres->ntuples;
 
 		return true;
 	}
@@ -2253,17 +2254,18 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan,
 							  TupleTableSlot *slot)
 {
 	HeapScanDesc hscan = (HeapScanDesc) scan;
+	BitmapHeapScanDesc *bscan = (BitmapHeapScanDesc *) hscan;
 	OffsetNumber targoffset;
 	Page		page;
 	ItemId		lp;
 
-	if (hscan->rs_empty_tuples_pending > 0)
+	if (bscan->rs_empty_tuples_pending > 0)
 	{
 		/*
 		 * If we don't have to fetch the tuple, just return nulls.
 		 */
 		ExecStoreAllNullTuple(slot);
-		hscan->rs_empty_tuples_pending--;
+		bscan->rs_empty_tuples_pending--;
 		return true;
 	}
 
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index b92eb506ec..752bf40c5e 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -92,6 +92,17 @@ typedef struct HeapScanDescData
 	 */
 	ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
 
+
+	/* these fields only used in page-at-a-time mode and for bitmap scans */
+	int			rs_cindex;		/* current tuple's index in vistuples */
+	int			rs_ntuples;		/* number of visible tuples on page */
+	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
+}			HeapScanDescData;
+typedef struct HeapScanDescData *HeapScanDesc;
+
+typedef struct BitmapHeapScanDesc {
+	HeapScanDescData heap;
+
 	/*
 	 * These fields are only used for bitmap scans for the "skip fetch"
 	 * optimization. Bitmap scans needing no fields from the heap may skip
@@ -101,13 +112,7 @@ typedef struct HeapScanDescData
 	 */
 	Buffer		rs_vmbuffer;
 	int			rs_empty_tuples_pending;
-
-	/* these fields only used in page-at-a-time mode and for bitmap scans */
-	int			rs_cindex;		/* current tuple's index in vistuples */
-	int			rs_ntuples;		/* number of visible tuples on page */
-	OffsetNumber rs_vistuples[MaxHeapTuplesPerPage];	/* their offsets */
-}			HeapScanDescData;
-typedef struct HeapScanDescData *HeapScanDesc;
+} BitmapHeapScanDesc;
 
 /*
  * Descriptor for fetches from heap via an index.
-- 
2.45.2

