From b94fed5ea689c680329a6b436e5e16171e0a5c7b Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Mon, 2 Mar 2026 04:19:54 +1300
Subject: [PATCH v2 14/19] Use stack buffer in logical replication.

Mechanical changes to temporary datum and null arrays.
---
 src/backend/replication/logical/reorderbuffer.c | 16 +++++++++-------
 src/backend/replication/logical/worker.c        | 10 ++++++++--
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 4c230bcc8e4..5f0888fc159 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -113,6 +113,7 @@
 #include "utils/memutils.h"
 #include "utils/rel.h"
 #include "utils/relfilenumbermap.h"
+#include "utils/stack_buffer.h"
 #include "utils/wait_event.h"
 
 /*
@@ -5092,6 +5093,8 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
 	HeapTuple	newtup;
 	Size		old_size;
 
+	DECLARE_STACK_BUFFER();
+
 	/* no toast tuples changed */
 	if (txn->toast_hash == NULL)
 		return;
@@ -5122,10 +5125,9 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
 
 	toast_desc = RelationGetDescr(toast_rel);
 
-	/* should we allocate from stack instead? */
-	attrs = palloc0_array(Datum, desc->natts);
-	isnull = palloc0_array(bool, desc->natts);
-	free = palloc0_array(bool, desc->natts);
+	attrs = stack_buffer_alloc0_array(Datum, desc->natts);
+	isnull = stack_buffer_alloc0_array(bool, desc->natts);
+	free = stack_buffer_alloc0_array(bool, desc->natts);
 
 	newtup = change->data.tp.newtuple;
 
@@ -5247,9 +5249,9 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
 		if (free[natt])
 			pfree(DatumGetPointer(attrs[natt]));
 	}
-	pfree(attrs);
-	pfree(free);
-	pfree(isnull);
+	stack_buffer_free(attrs);
+	stack_buffer_free(free);
+	stack_buffer_free(isnull);
 
 	MemoryContextSwitchTo(oldcontext);
 
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 033858752d9..54828cb7e0e 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -294,6 +294,7 @@
 #include "utils/rel.h"
 #include "utils/rls.h"
 #include "utils/snapmgr.h"
+#include "utils/stack_buffer.h"
 #include "utils/syscache.h"
 #include "utils/usercontext.h"
 #include "utils/wait_event.h"
@@ -972,14 +973,16 @@ slot_fill_defaults(LogicalRepRelMapEntry *rel, EState *estate,
 	ExprState **defexprs;
 	ExprContext *econtext;
 
+	DECLARE_STACK_BUFFER();
+
 	econtext = GetPerTupleExprContext(estate);
 
 	/* We got all the data via replication, no need to evaluate anything. */
 	if (num_phys_attrs == rel->remoterel.natts)
 		return;
 
-	defmap = palloc_array(int, num_phys_attrs);
-	defexprs = palloc_array(ExprState *, num_phys_attrs);
+	defmap = stack_buffer_alloc_array(int, num_phys_attrs);
+	defexprs = stack_buffer_alloc_array(ExprState *, num_phys_attrs);
 
 	Assert(rel->attrmap->maplen == num_phys_attrs);
 	for (attnum = 0; attnum < num_phys_attrs; attnum++)
@@ -1010,6 +1013,9 @@ slot_fill_defaults(LogicalRepRelMapEntry *rel, EState *estate,
 	for (i = 0; i < num_defaults; i++)
 		slot->tts_values[defmap[i]] =
 			ExecEvalExpr(defexprs[i], econtext, &slot->tts_isnull[defmap[i]]);
+
+	stack_buffer_free(defmap);
+	stack_buffer_free(defexprs);
 }
 
 /*
-- 
2.53.0

