From 8229afde1dfc3d4ddcb2252a227ee6166d1c99a9 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 22 Nov 2021 09:52:45 -0800
Subject: [PATCH v3 3/3] Verify redirect items are still correct after
 heap_page_prune().

---
 src/backend/access/heap/pruneheap.c | 39 +++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c
index d304fd3dcdb..b65c87bb5d7 100644
--- a/src/backend/access/heap/pruneheap.c
+++ b/src/backend/access/heap/pruneheap.c
@@ -76,6 +76,7 @@ static void heap_prune_record_redirect(PruneState *prstate,
 static void heap_prune_record_dead(PruneState *prstate, OffsetNumber offnum);
 static void heap_prune_record_unused(PruneState *prstate, OffsetNumber offnum);
 
+static void page_verify_redirects(Page page);
 
 /*
  * Optionally prune and repair fragmentation in the specified page.
@@ -885,6 +886,40 @@ heap_prune_record_unused(PruneState *prstate, OffsetNumber offnum)
 }
 
 
+static void
+page_verify_redirects(Page page)
+{
+#ifdef USE_ASSERT_CHECKING
+	OffsetNumber offnum,
+		maxoff;
+
+	maxoff = PageGetMaxOffsetNumber(page);
+	for (offnum = FirstOffsetNumber;
+		 offnum <= maxoff;
+		 offnum = OffsetNumberNext(offnum))
+	{
+		ItemId		itemid;
+		OffsetNumber targoff;
+		ItemId		targitem;
+		HeapTupleHeader htup;
+
+		itemid = PageGetItemId(page, offnum);
+		if (!ItemIdIsRedirected(itemid))
+			continue;
+
+		targoff = ItemIdGetRedirect(itemid);
+		targitem = PageGetItemId(page, targoff);
+
+		Assert(ItemIdIsUsed(targitem));
+		Assert(ItemIdIsNormal(targitem));
+		Assert(ItemIdHasStorage(targitem));
+		htup = (HeapTupleHeader) PageGetItem(page, targitem);
+		Assert(HeapTupleHeaderIsHeapOnly(htup));
+	}
+#endif
+}
+
+
 /*
  * Perform the actual page changes needed by heap_page_prune.
  * It is expected that the caller has a super-exclusive lock on the
@@ -1010,11 +1045,15 @@ heap_page_prune_execute(Buffer buffer,
 		ItemIdSetUnused(lp);
 	}
 
+	page_verify_redirects(page);
+
 	/*
 	 * Finally, repair any fragmentation, and update the page's hint bit about
 	 * whether it has free pointers.
 	 */
 	PageRepairFragmentation(page);
+
+	page_verify_redirects(page);
 }
 
 
-- 
2.34.0

