From 377172183a63e133d62996768e0f927d54aa7adf Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Sat, 6 Jan 2024 13:14:47 -0500
Subject: [PATCH v3 01/17] lazy_scan_prune tests tuple vis with GlobalVisTest

One requirement for eventually combining the prune and freeze records,
is that we must check during pruning if live tuples on the page are
visible to everyone and thus, whether or not the page is all visible. We
only consider opportunistically freezing tuples if the whole page is all
visible and could be set all frozen.

During pruning (in heap_page_prune()), we do not have access to
VacuumCutoffs -- as on access pruning also calls heap_page_prune(). We
do, however, have access to a GlobalVisState. This can be used to
determine whether or not the tuple is visible to everyone. It also has
the potential of being more up-to-date than VacuumCutoffs->OldestXmin.

This commit simply modifies lazy_scan_prune() to use GlobalVisState
instead of OldestXmin. Future commits will move the
all_visible/all_frozen calculation into heap_page_prune().
---
 src/backend/access/heap/vacuumlazy.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 18004907750..fe31c0125d6 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -1373,6 +1373,20 @@ lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno,
 	return false;
 }
 
+/*
+ * Wrap GlobalVisTestIsRemovableXid() to handle FrozenTransactionIds when we
+ * are examining tuple xmins to determine if the page is all-visible during
+ * pruning. Old tuples may have FrozenTransactionId xmins.
+ */
+static inline bool
+prune_freeze_xmin_is_removable(GlobalVisState *visstate, TransactionId xmin)
+{
+	if (xmin == FrozenTransactionId)
+		return true;
+
+	return GlobalVisTestIsRemovableXid(visstate, xmin);
+}
+
 /*
  *	lazy_scan_prune() -- lazy_scan_heap() pruning and freezing.
  *
@@ -1582,8 +1596,7 @@ lazy_scan_prune(LVRelState *vacrel,
 					 * that everyone sees it as committed?
 					 */
 					xmin = HeapTupleHeaderGetXmin(htup);
-					if (!TransactionIdPrecedes(xmin,
-											   vacrel->cutoffs.OldestXmin))
+					if (!prune_freeze_xmin_is_removable(vacrel->vistest, xmin))
 					{
 						all_visible = false;
 						break;
-- 
2.40.1

