v1-0001-segfault-after-trigger.patch

text/plain

Filename: v1-0001-segfault-after-trigger.patch
Type: text/plain
Part: 0
Message: [BUG] segfault during delete

Patch

Format: unified
Series: patch v1-0001
File+
src/backend/commands/trigger.c 6 0
src/backend/executor/execTuples.c 44 0
src/include/executor/tuptable.h 2 0
 src/backend/commands/trigger.c    |  6 ++++++
 src/backend/executor/execTuples.c | 44 +++++++++++++++++++++++++++++++++++++++
 src/include/executor/tuptable.h   |  2 ++
 3 files changed, 52 insertions(+)
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 8908847c6c..a6c464b120 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -5475,8 +5475,11 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
 			if (map != NULL)
 			{
 				TupleTableSlot *storeslot;
+				MemoryContext oldcontext;
+				oldcontext = MemoryContextSwitchTo(TopTransactionContext);
 
 				storeslot = transition_capture->tcs_private->storeslot;
+
 				if (!storeslot)
 				{
 					storeslot = ExecAllocTableSlot(&estate->es_tupleTable,
@@ -5484,7 +5487,10 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
 												   &TTSOpsVirtual);
 					transition_capture->tcs_private->storeslot = storeslot;
 				}
+				else
+					InitTupleTableSlot(&estate->es_tupleTable, map->outdesc, &TTSOpsVirtual, storeslot);
 
+				MemoryContextSwitchTo(oldcontext);
 				execute_attr_map_slot(map->attrMap, oldslot, storeslot);
 				tuplestore_puttupleslot(old_tuplestore, storeslot);
 			}
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 73c35df9c9..5f31287529 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -1131,6 +1131,50 @@ MakeTupleTableSlot(TupleDesc tupleDesc,
 	return slot;
 }
 
+/* --------------------------------
+ *		InitTupleTableSlot
+ *
+ *		Basic routine to make an empty TupleTableSlot for an existing slot of given
+ *		TupleTableSlotType. If tupleDesc is specified the slot's descriptor is
+ *		fixed for its lifetime, gaining some efficiency. If that's
+ *		undesirable, pass NULL.
+ * --------------------------------
+ */
+void
+InitTupleTableSlot(List** tupleTable, TupleDesc tupleDesc,
+				   const TupleTableSlotOps *tts_ops, TupleTableSlot *slot)
+{
+	Size		basesz;
+
+	basesz = tts_ops->base_slot_size;
+
+	/* const for optimization purposes, OK to modify at allocation time */
+	*((const TupleTableSlotOps **) &slot->tts_ops) = tts_ops;
+	slot->type = T_TupleTableSlot;
+	slot->tts_flags |= TTS_FLAG_EMPTY;
+	if (tupleDesc != NULL)
+		slot->tts_flags |= TTS_FLAG_FIXED;
+	slot->tts_tupleDescriptor = tupleDesc;
+	slot->tts_mcxt = CurrentMemoryContext;
+	slot->tts_nvalid = 0;
+
+	if (tupleDesc != NULL)
+	{
+		slot->tts_values = (Datum *)
+			(((char *) slot)
+			 + MAXALIGN(basesz));
+		slot->tts_isnull = (bool *)
+			(((char *) slot)
+			 + MAXALIGN(basesz)
+			 + MAXALIGN(tupleDesc->natts * sizeof(Datum)));
+	}
+
+	/*
+	 * And allow slot type specific initialization.
+	 */
+	slot->tts_ops->init(slot);
+}
+
 /* --------------------------------
  *		ExecAllocTableSlot
  *
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index 679e57fbdd..6c82883877 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -295,6 +295,8 @@ typedef struct MinimalTupleTableSlot
 /* in executor/execTuples.c */
 extern TupleTableSlot *MakeTupleTableSlot(TupleDesc tupleDesc,
 										  const TupleTableSlotOps *tts_ops);
+extern void InitTupleTableSlot(List **tupleTable, TupleDesc tupleDesc,
+										  const TupleTableSlotOps *tts_ops, TupleTableSlot *slot);
 extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable, TupleDesc desc,
 										  const TupleTableSlotOps *tts_ops);
 extern void ExecResetTupleTable(List *tupleTable, bool shouldFree);