From 35efdfae7cf4112561f3db24d6804f2124817b59 Mon Sep 17 00:00:00 2001 From: Rui Zhao Date: Wed, 21 Oct 2026 23:15:15 +0800 Subject: [PATCH 2/2] Fix two detoasted-value cleanup loops The scan-and-sort path starts at the first bitmap member but then walks backward, freeing only the first detoasted attribute. Walk forward to free the remaining attributes too. When toast_tuple_init() cannot fetch an external value, its cleanup loop stops before attribute zero. Include that attribute so a value fetched from the first column is freed when a later column is missing. --- src/backend/access/heap/heapam_handler.c | 2 +- src/backend/access/table/toast_helper.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 30b070e903b..d641f70fa46 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -956,7 +956,7 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap, cleanup_and_next: for (int i = bms_next_member(detoasted, -1); i >= 0; - i = bms_prev_member(detoasted, i)) + i = bms_next_member(detoasted, i)) { pfree(DatumGetPointer(values[i])); } diff --git a/src/backend/access/table/toast_helper.c b/src/backend/access/table/toast_helper.c index a8e58d8573c..aa87452d35d 100644 --- a/src/backend/access/table/toast_helper.c +++ b/src/backend/access/table/toast_helper.c @@ -194,7 +194,7 @@ toast_tuple_init(ToastTupleContext *ttc, uint32 flags) return true; broken_toast_missing_ok: - for (; i > 0; i--) + for (; i >= 0; i--) { if (ttc->ttc_attr[i].tai_colflags & TOASTCOL_NEEDS_FREE) { -- 2.43.7