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