From d05492e9078f00f1b4585312108f9f2fe0b48976 Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Tue, 4 Mar 2025 12:46:48 -0800
Subject: [PATCH v8 6/7] Use ExecCopySlotMinimalTupleExtra() to avoid a memcpy.

Previously, ExecFetchSlotMinimalTuple() could cause an unnecessary
copy for hash-based set operations.

Use the new API ExecCopySlotMinimalTupleExtra() to perform the copy
while also allocating the extra space needed for the 'additional'
data.

Discussion: https://postgr.es/m/AApHDvpN4v3t_sdz4dvrv1Fx_ZPw=twSnxuTEytRYP7LFz5K9A@mail.gmail.com
Reviewed-by: David Rowley <dgrowleyml@gmail.com>
---
 src/backend/executor/execGrouping.c | 21 +++++----------------
 1 file changed, 5 insertions(+), 16 deletions(-)

diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index 5c06cc6da40..255bd795361 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -481,21 +481,13 @@ LookupTupleHashEntry_internal(TupleHashTable hashtable, TupleTableSlot *slot,
 		else
 		{
 			/* created new entry */
-			bool		shouldFree;
-			char	   *mem;
-			MinimalTuple mtup;
-
 			*isnew = true;
 
-			MemoryContextSwitchTo(hashtable->tempcxt);
-
-			/* ignore shouldFree, because we're in the temp context anyway */
-			mtup = ExecFetchSlotMinimalTuple(slot, &shouldFree);
+			MemoryContextSwitchTo(hashtable->tablecxt);
 
 			/*
-			 * Allocate enough memory in the tablecxt for the additionalsize
-			 * followed by the tuple. Clear the additional data, and copy the
-			 * tuple.
+			 * Copy the first tuple into the table context, and request
+			 * additionalsize extra bytes before the allocation.
 			 *
 			 * The caller can get a pointer to the additional data with
 			 * TupleHashEntryGetAdditional(), and store arbitrary data there.
@@ -503,11 +495,8 @@ LookupTupleHashEntry_internal(TupleHashTable hashtable, TupleTableSlot *slot,
 			 * allocation avoids the need to store an extra pointer in
 			 * TupleHashEntryData or allocate an additional chunk.
 			 */
-			mem = MemoryContextAlloc(hashtable->tablecxt,
-									 mtup->t_len + hashtable->additionalsize);
-			memset(mem, 0, hashtable->additionalsize);
-			entry->firstTuple = (MinimalTuple) (mem + hashtable->additionalsize);
-			memcpy(entry->firstTuple, mtup, mtup->t_len);
+			entry->firstTuple = ExecCopySlotMinimalTupleExtra(slot,
+															  hashtable->additionalsize);
 		}
 	}
 	else
-- 
2.34.1

