From ae8419d0a166372789cd94acc0b9c8a8d9c864cf Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Wed, 8 Jul 2026 12:36:48 +0300
Subject: [PATCH v3 2/2] Smuggle the 'missing_ok' arg in a global var, for
 backpatching

---
 src/backend/access/heap/heaptoast.c | 21 ++++++++++++++++---
 src/backend/access/table/tableam.c  |  4 ++++
 src/include/access/heaptoast.h      | 15 +++++++++++---
 src/include/access/tableam.h        | 31 ++++++++++++++++++++---------
 4 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/src/backend/access/heap/heaptoast.c b/src/backend/access/heap/heaptoast.c
index 38896a0c749..7ab54225059 100644
--- a/src/backend/access/heap/heaptoast.c
+++ b/src/backend/access/heap/heaptoast.c
@@ -613,6 +613,21 @@ toast_build_flattened_tuple(TupleDesc tupleDesc,
 	return new_tuple;
 }
 
+/*
+ * Adapter for the old API in backbranches, where the 'missing_ok' flag is
+ * passed in a global variable.
+ */
+void
+heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize,
+						   int32 sliceoffset, int32 slicelength,
+						   varlena *result)
+{
+	fetch_toast_slice_was_missing =
+		heap_fetch_toast_slice_ext(toastrel, valueid, attrsize,
+								   sliceoffset, slicelength,
+								   result, fetch_toast_slice_missing_ok);
+}
+
 /*
  * Fetch a TOAST slice from a heap table.
  *
@@ -627,9 +642,9 @@ toast_build_flattened_tuple(TupleDesc tupleDesc,
  * Returns true on success, false if missing_ok and chunks are missing.
  */
 bool
-heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize,
-					   int32 sliceoffset, int32 slicelength,
-					   varlena *result, bool missing_ok)
+heap_fetch_toast_slice_ext(Relation toastrel, Oid valueid, int32 attrsize,
+						   int32 sliceoffset, int32 slicelength,
+						   varlena *result, bool missing_ok)
 {
 	Relation   *toastidxs;
 	ScanKeyData toastkey[3];
diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index 68ff0966f1c..f3164c3d627 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -49,6 +49,10 @@
 char	   *default_table_access_method = DEFAULT_TABLE_ACCESS_METHOD;
 bool		synchronize_seqscans = true;
 
+/* hack to pass extra argument and return value to/from relation_fetch_toast_slice */
+bool fetch_toast_slice_missing_ok = false;
+bool fetch_toast_slice_was_missing = false;
+
 
 /* ----------------------------------------------------------------------------
  * Slot functions.
diff --git a/src/include/access/heaptoast.h b/src/include/access/heaptoast.h
index 1be85db6ddd..4c763447d2b 100644
--- a/src/include/access/heaptoast.h
+++ b/src/include/access/heaptoast.h
@@ -148,9 +148,18 @@ extern HeapTuple toast_build_flattened_tuple(TupleDesc tupleDesc,
  *	instead of raising an error.  Returns true on success.
  * ----------
  */
-extern bool heap_fetch_toast_slice(Relation toastrel, Oid valueid,
+extern bool heap_fetch_toast_slice_ext(Relation toastrel, Oid valueid,
+									   int32 attrsize, int32 sliceoffset,
+									   int32 slicelength, varlena *result,
+									   bool missing_ok);
+
+/*
+ * Legacy API used in the tableam. Instead of a 'missing_ok' arg, looks
+ * at the 'fetch_toast_slice_missing_ok' variable, and returns the return
+ * value 'fetch_toast_slice_was_missing'.
+ */
+extern void heap_fetch_toast_slice(Relation toastrel, Oid valueid,
 								   int32 attrsize, int32 sliceoffset,
-								   int32 slicelength, varlena *result,
-								   bool missing_ok);
+								   int32 slicelength, varlena *result);
 
 #endif							/* HEAPTOAST_H */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index a90b15dd82b..979b3f63fb2 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -307,6 +307,9 @@ typedef void (*IndexBuildCallback) (Relation index,
 									bool tupleIsAlive,
 									void *state);
 
+extern bool fetch_toast_slice_missing_ok;
+extern bool fetch_toast_slice_was_missing;
+
 /*
  * API struct for a table AM.  Note this must be allocated in a
  * server-lifetime manner, typically as a static const struct, which then gets
@@ -783,15 +786,15 @@ typedef struct TableAmRoutine
 	 * table implemented by this AM.  See table_relation_fetch_toast_slice()
 	 * for more details.
 	 *
-	 * If missing_ok is true, returns false when chunks are missing instead of
-	 * raising an error.  Returns true on success.
+	 * If the 'fetch_toast_slice_missing_ok' global variable is true and some
+	 * chunks are missing, the callback should set the
+	 * 'fetch_toast_slice_was_missing' flag instead of raising an error
 	 */
-	bool		(*relation_fetch_toast_slice) (Relation toastrel, Oid valueid,
+	void		(*relation_fetch_toast_slice) (Relation toastrel, Oid valueid,
 											   int32 attrsize,
 											   int32 sliceoffset,
 											   int32 slicelength,
-											   varlena *result,
-											   bool missing_ok);
+											   varlena *result);
 
 
 	/* ------------------------------------------------------------------------
@@ -1995,10 +1998,20 @@ table_relation_fetch_toast_slice(Relation toastrel, Oid valueid,
 								 int32 slicelength, varlena *result,
 								 bool missing_ok)
 {
-	return toastrel->rd_tableam->relation_fetch_toast_slice(toastrel, valueid,
-															attrsize,
-															sliceoffset, slicelength,
-															result, missing_ok);
+	fetch_toast_slice_missing_ok = missing_ok;
+	fetch_toast_slice_was_missing = false;
+	toastrel->rd_tableam->relation_fetch_toast_slice(toastrel, valueid,
+													 attrsize,
+													 sliceoffset, slicelength,
+													 result);
+	if (missing_ok)
+	{
+		/* reset the flag just in case there are other direct callers */
+		fetch_toast_slice_missing_ok = false;
+		return fetch_toast_slice_was_missing;
+	}
+	else
+		return true;
 }
 
 
-- 
2.47.3

