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);