From ae8419d0a166372789cd94acc0b9c8a8d9c864cf Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas 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