0001-Don-t-form-heap-tuple-in-ExecComputeStoredGenerated.patch

text/plain

Filename: 0001-Don-t-form-heap-tuple-in-ExecComputeStoredGenerated.patch
Type: text/plain
Part: 0
Message: Re: Why does ExecComputeStoredGenerated() form a heap tuple

Patch

Format: format-patch
Series: patch 0001
Subject: Don't form heap tuple in ExecComputeStoredGenerated
File+
src/backend/executor/nodeModifyTable.c 12 15
From d87b94d555c1d863a65e738a6953a1c87b0af2b2 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Tue, 23 Apr 2019 10:18:39 +0200
Subject: [PATCH] Don't form heap tuple in ExecComputeStoredGenerated

---
 src/backend/executor/nodeModifyTable.c | 27 ++++++++++++--------------
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 444c0c0574..216c3baa64 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -53,6 +53,7 @@
 #include "storage/bufmgr.h"
 #include "storage/lmgr.h"
 #include "utils/builtins.h"
+#include "utils/datum.h"
 #include "utils/memutils.h"
 #include "utils/rel.h"
 
@@ -254,9 +255,6 @@ ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot)
 	MemoryContext oldContext;
 	Datum	   *values;
 	bool	   *nulls;
-	bool	   *replaces;
-	HeapTuple	oldtuple, newtuple;
-	bool		should_free;
 
 	Assert(tupdesc->constr && tupdesc->constr->has_generated_stored);
 
@@ -294,7 +292,10 @@ ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot)
 
 	values = palloc(sizeof(*values) * natts);
 	nulls = palloc(sizeof(*nulls) * natts);
-	replaces = palloc0(sizeof(*replaces) * natts);
+
+	slot_getallattrs(slot);
+	memcpy(values, slot->tts_values, sizeof(*values) * natts);
+	memcpy(nulls, slot->tts_isnull, sizeof(*nulls) * natts);
 
 	for (int i = 0; i < natts; i++)
 	{
@@ -311,20 +312,16 @@ ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot)
 
 			values[i] = val;
 			nulls[i] = isnull;
-			replaces[i] = true;
 		}
+		else
+			values[i] = datumCopy(values[i], TupleDescAttr(tupdesc, i)->attbyval, TupleDescAttr(tupdesc, i)->attlen);
 	}
 
-	oldtuple = ExecFetchSlotHeapTuple(slot, true, &should_free);
-	newtuple = heap_modify_tuple(oldtuple, tupdesc, values, nulls, replaces);
-	/*
-	 * The tuple will be freed by way of the memory context - the slot might
-	 * only be cleared after the context is reset, and we'd thus potentially
-	 * double free.
-	 */
-	ExecForceStoreHeapTuple(newtuple, slot, false);
-	if (should_free)
-		heap_freetuple(oldtuple);
+	ExecClearTuple(slot);
+	memcpy(slot->tts_values, values, sizeof(*values) * natts);
+	memcpy(slot->tts_isnull, nulls, sizeof(*nulls) * natts);
+	ExecStoreVirtualTuple(slot);
+	ExecMaterializeSlot(slot);
 
 	MemoryContextSwitchTo(oldContext);
 }
-- 
2.21.0