From baf0e7b28111337c6b9f138ddea7c2ef137fd930 Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Mon, 4 May 2026 14:29:35 -0700
Subject: [PATCH v4 3/3] Update Hash Aggregation to use memory pools.

This reverts commit 50a38f65177ea7858bc97f71ba0757ba04c1c167, which is
no longer needed.
---
 src/backend/executor/execUtils.c | 69 +++++++-------------------------
 src/backend/executor/nodeAgg.c   | 37 +++++------------
 src/include/executor/executor.h  |  1 -
 3 files changed, 24 insertions(+), 83 deletions(-)

diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 1eb6b9f1f40..4b8d1c900b3 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -234,13 +234,21 @@ FreeExecutorState(EState *estate)
 	MemoryContextDelete(estate->es_query_cxt);
 }
 
-/*
- * Internal implementation for CreateExprContext() and CreateWorkExprContext()
- * that allows control over the AllocSet parameters.
+/* ----------------
+ *		CreateExprContext
+ *
+ *		Create a context for expression evaluation within an EState.
+ *
+ * An executor run may require multiple ExprContexts (we usually make one
+ * for each Plan node, and a separate one for per-output-tuple processing
+ * such as constraint checking).  Each ExprContext has its own "per-tuple"
+ * memory context.
+ *
+ * Note we make no assumption about the caller's memory context.
+ * ----------------
  */
-static ExprContext *
-CreateExprContextInternal(EState *estate, Size minContextSize,
-						  Size initBlockSize, Size maxBlockSize)
+ExprContext *
+CreateExprContext(EState *estate)
 {
 	ExprContext *econtext;
 	MemoryContext oldcontext;
@@ -263,9 +271,7 @@ CreateExprContextInternal(EState *estate, Size minContextSize,
 	econtext->ecxt_per_tuple_memory =
 		AllocSetContextCreate(estate->es_query_cxt,
 							  "ExprContext",
-							  minContextSize,
-							  initBlockSize,
-							  maxBlockSize);
+							  ALLOCSET_DEFAULT_SIZES);
 
 	econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
 	econtext->ecxt_param_list_info = estate->es_param_list_info;
@@ -295,51 +301,6 @@ CreateExprContextInternal(EState *estate, Size minContextSize,
 	return econtext;
 }
 
-/* ----------------
- *		CreateExprContext
- *
- *		Create a context for expression evaluation within an EState.
- *
- * An executor run may require multiple ExprContexts (we usually make one
- * for each Plan node, and a separate one for per-output-tuple processing
- * such as constraint checking).  Each ExprContext has its own "per-tuple"
- * memory context.
- *
- * Note we make no assumption about the caller's memory context.
- * ----------------
- */
-ExprContext *
-CreateExprContext(EState *estate)
-{
-	return CreateExprContextInternal(estate, ALLOCSET_DEFAULT_SIZES);
-}
-
-
-/* ----------------
- *		CreateWorkExprContext
- *
- * Like CreateExprContext, but specifies the AllocSet sizes to be reasonable
- * in proportion to work_mem. If the maximum block allocation size is too
- * large, it's easy to skip right past work_mem with a single allocation.
- * ----------------
- */
-ExprContext *
-CreateWorkExprContext(EState *estate)
-{
-	Size		maxBlockSize;
-
-	maxBlockSize = pg_prevpower2_size_t(work_mem * (Size) 1024 / 16);
-
-	/* But no bigger than ALLOCSET_DEFAULT_MAXSIZE */
-	maxBlockSize = Min(maxBlockSize, ALLOCSET_DEFAULT_MAXSIZE);
-
-	/* and no smaller than ALLOCSET_DEFAULT_INITSIZE */
-	maxBlockSize = Max(maxBlockSize, ALLOCSET_DEFAULT_INITSIZE);
-
-	return CreateExprContextInternal(estate, ALLOCSET_DEFAULT_MINSIZE,
-									 ALLOCSET_DEFAULT_INITSIZE, maxBlockSize);
-}
-
 /* ----------------
  *		CreateStandaloneExprContext
  *
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 925caadd2ce..01334d6012e 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1866,12 +1866,9 @@ static void
 hash_agg_check_limits(AggState *aggstate)
 {
 	uint64		ngroups = aggstate->hash_ngroups_current;
-	Size		meta_mem = MemoryContextMemAllocated(aggstate->hash_metacxt,
-													 true);
-	Size		entry_mem = MemoryContextMemAllocated(aggstate->hash_tuplescxt,
-													  true);
-	Size		tval_mem = MemoryContextMemAllocated(aggstate->hashcontext->ecxt_per_tuple_memory,
-													 true);
+	Size		meta_mem = MemoryContextGetPool(aggstate->hash_metacxt)->allocated;
+	Size		entry_mem = MemoryContextGetPool(aggstate->hash_tuplescxt)->allocated;
+	Size		tval_mem = MemoryContextGetPool(aggstate->hashcontext->ecxt_per_tuple_memory)->allocated;
 	Size		total_mem = meta_mem + entry_mem + tval_mem;
 	bool		do_spill = false;
 
@@ -1998,13 +1995,13 @@ hash_agg_update_metrics(AggState *aggstate, bool from_tape, int npartitions)
 static void
 hash_create_memory(AggState *aggstate)
 {
-	Size		maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE;
-
 	/*
 	 * The hashcontext's per-tuple memory will be used for byref transition
 	 * values and returned by AggCheckCallContext().
 	 */
-	aggstate->hashcontext = CreateWorkExprContext(aggstate->ss.ps.state);
+	aggstate->hashcontext = CreateExprContext(aggstate->ss.ps.state);
+	MemoryContextCreatePool(aggstate->hashcontext->ecxt_per_tuple_memory,
+							work_mem * (Size) 1024);
 
 	/*
 	 * The meta context will be used for the bucket array of
@@ -2017,6 +2014,7 @@ hash_create_memory(AggState *aggstate)
 	aggstate->hash_metacxt = AllocSetContextCreate(aggstate->ss.ps.state->es_query_cxt,
 												   "HashAgg meta context",
 												   ALLOCSET_DEFAULT_SIZES);
+	MemoryContextCreatePool(aggstate->hash_metacxt, work_mem * (Size) 1024);
 
 	/*
 	 * The hash entries themselves, which include the grouping key
@@ -2025,29 +2023,12 @@ hash_create_memory(AggState *aggstate)
 	 * entire hash table is reset. The bump allocator is faster for
 	 * allocations and avoids wasting space on the chunk header or
 	 * power-of-two allocations.
-	 *
-	 * Like CreateWorkExprContext(), use smaller sizings for smaller work_mem,
-	 * to avoid large jumps in memory usage.
-	 */
-
-	/*
-	 * Like CreateWorkExprContext(), use smaller sizings for smaller work_mem,
-	 * to avoid large jumps in memory usage.
 	 */
-	maxBlockSize = pg_prevpower2_size_t(work_mem * (Size) 1024 / 16);
-
-	/* But no bigger than ALLOCSET_DEFAULT_MAXSIZE */
-	maxBlockSize = Min(maxBlockSize, ALLOCSET_DEFAULT_MAXSIZE);
-
-	/* and no smaller than ALLOCSET_DEFAULT_INITSIZE */
-	maxBlockSize = Max(maxBlockSize, ALLOCSET_DEFAULT_INITSIZE);
 
 	aggstate->hash_tuplescxt = BumpContextCreate(aggstate->ss.ps.state->es_query_cxt,
 												 "HashAgg hashed tuples",
-												 ALLOCSET_DEFAULT_MINSIZE,
-												 ALLOCSET_DEFAULT_INITSIZE,
-												 maxBlockSize);
-
+												 ALLOCSET_DEFAULT_SIZES);
+	MemoryContextCreatePool(aggstate->hash_tuplescxt, work_mem * (Size) 1024);
 }
 
 /*
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 33bbdbfeffb..1e72fbef6f9 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -653,7 +653,6 @@ extern void end_tup_output(TupOutputState *tstate);
 extern EState *CreateExecutorState(void);
 extern void FreeExecutorState(EState *estate);
 extern ExprContext *CreateExprContext(EState *estate);
-extern ExprContext *CreateWorkExprContext(EState *estate);
 extern ExprContext *CreateStandaloneExprContext(void);
 extern void FreeExprContext(ExprContext *econtext, bool isCommit);
 extern void ReScanExprContext(ExprContext *econtext);
-- 
2.43.0

