From 3aa4cb9ea6e2e84d1f075f0fdd6d0db8765feb9b Mon Sep 17 00:00:00 2001
From: xiaoyu liu <xliu19163@gmail.com>
Date: Mon, 7 Sep 2026 16:49:19 +0800
Subject: [PATCH] tableam: Assume successful scans return nonempty slots

Record the one-way scan_getnextslot contract with pg_assume so the compiler can remove a redundant slot emptiness check from executor scan paths.
---
 src/include/access/tableam.h | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index ff03a2b816f..b4cac9b177c 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -378,7 +378,8 @@ typedef struct TableAmRoutine
 								bool allow_sync, bool allow_pagemode);
 
 	/*
-	 * Return next tuple from `scan`, store in slot.
+	 * Return true if the next tuple from `scan` was stored in slot. A
+	 * successful call must leave slot non-empty.
 	 */
 	bool		(*scan_getnextslot) (TableScanDesc scan,
 									 ScanDirection direction,
@@ -1095,13 +1096,18 @@ table_rescan_set_params(TableScanDesc scan, ScanKeyData *key,
 static inline bool
 table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
 {
+	bool		found;
+
 	slot->tts_tableOid = RelationGetRelid(sscan->rs_rd);
 
 	/* We don't expect actual scans using NoMovementScanDirection */
 	Assert(direction == ForwardScanDirection ||
 		   direction == BackwardScanDirection);
 
-	return sscan->rs_rd->rd_tableam->scan_getnextslot(sscan, direction, slot);
+	found = sscan->rs_rd->rd_tableam->scan_getnextslot(sscan, direction, slot);
+	pg_assume(!found || !TupIsNull(slot));
+
+	return found;
 }
 
 /* ----------------------------------------------------------------------------
-- 
2.44.0

