Commit ff11e7f4 authored by Andres Freund's avatar Andres Freund

Use slots in trigger infrastructure, except for the actual invocation.

In preparation for abstracting table storage, convert trigger.c to
track tuples in slots. Which also happens to make code calling
triggers simpler.

As the calling interface for triggers themselves is not changed in
this patch, HeapTuples still are extracted from the slot at that
time. But that's handled solely inside trigger.c, not visible to
callers. It's quite likely that we'll want to revise the external
trigger interface, but that's a separate large project.

As part of this work the slots used for old/new/return tuples are
moved from EState into ResultRelInfo, as different updated tables
might need different slots. The slots are now also now created
on-demand, which is good both from an efficiency POV, but also makes
the modifying code simpler.

Author: Andres Freund, Amit Khandekar and Ashutosh Bapat
Discussion: https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de
parent b8d71745
...@@ -3507,8 +3507,13 @@ store_returning_result(PgFdwModifyState *fmstate, ...@@ -3507,8 +3507,13 @@ store_returning_result(PgFdwModifyState *fmstate,
fmstate->retrieved_attrs, fmstate->retrieved_attrs,
NULL, NULL,
fmstate->temp_cxt); fmstate->temp_cxt);
/* tuple will be deleted when it is cleared from the slot */ /*
ExecStoreHeapTuple(newtup, slot, true); * The returning slot will not necessarily be suitable to store
* heaptuples directly, so allow for conversion.
*/
ExecForceStoreHeapTuple(newtup, slot);
ExecMaterializeSlot(slot);
pfree(newtup);
} }
PG_CATCH(); PG_CATCH();
{ {
...@@ -3886,6 +3891,7 @@ apply_returning_filter(PgFdwDirectModifyState *dmstate, ...@@ -3886,6 +3891,7 @@ apply_returning_filter(PgFdwDirectModifyState *dmstate,
TupleTableSlot *slot, TupleTableSlot *slot,
EState *estate) EState *estate)
{ {
ResultRelInfo *relInfo = estate->es_result_relation_info;
TupleDesc resultTupType = RelationGetDescr(dmstate->resultRel); TupleDesc resultTupType = RelationGetDescr(dmstate->resultRel);
TupleTableSlot *resultSlot; TupleTableSlot *resultSlot;
Datum *values; Datum *values;
...@@ -3895,11 +3901,9 @@ apply_returning_filter(PgFdwDirectModifyState *dmstate, ...@@ -3895,11 +3901,9 @@ apply_returning_filter(PgFdwDirectModifyState *dmstate,
int i; int i;
/* /*
* Use the trigger tuple slot as a place to store the result tuple. * Use the return tuple slot as a place to store the result tuple.
*/ */
resultSlot = estate->es_trig_tuple_slot; resultSlot = ExecGetReturningSlot(estate, relInfo);
if (resultSlot->tts_tupleDescriptor != resultTupType)
ExecSetSlotDescriptor(resultSlot, resultTupType);
/* /*
* Extract all the values of the scan tuple. * Extract all the values of the scan tuple.
......
...@@ -2519,9 +2519,6 @@ CopyFrom(CopyState cstate) ...@@ -2519,9 +2519,6 @@ CopyFrom(CopyState cstate)
/* Set up a tuple slot too */ /* Set up a tuple slot too */
myslot = ExecInitExtraTupleSlot(estate, tupDesc, myslot = ExecInitExtraTupleSlot(estate, tupDesc,
&TTSOpsHeapTuple); &TTSOpsHeapTuple);
/* Triggers might need a slot as well */
estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL,
&TTSOpsHeapTuple);
/* /*
* Set up a ModifyTableState so we can let FDW(s) init themselves for * Set up a ModifyTableState so we can let FDW(s) init themselves for
...@@ -2870,7 +2867,7 @@ CopyFrom(CopyState cstate) ...@@ -2870,7 +2867,7 @@ CopyFrom(CopyState cstate)
* Otherwise, just remember the original unconverted * Otherwise, just remember the original unconverted
* tuple, to avoid a needless round trip conversion. * tuple, to avoid a needless round trip conversion.
*/ */
cstate->transition_capture->tcs_original_insert_tuple = tuple; cstate->transition_capture->tcs_original_insert_tuple = myslot;
cstate->transition_capture->tcs_map = NULL; cstate->transition_capture->tcs_map = NULL;
} }
} }
...@@ -2907,12 +2904,8 @@ CopyFrom(CopyState cstate) ...@@ -2907,12 +2904,8 @@ CopyFrom(CopyState cstate)
/* BEFORE ROW INSERT Triggers */ /* BEFORE ROW INSERT Triggers */
if (has_before_insert_row_trig) if (has_before_insert_row_trig)
{ {
slot = ExecBRInsertTriggers(estate, resultRelInfo, slot); if (!ExecBRInsertTriggers(estate, resultRelInfo, slot))
skip_tuple = true; /* "do nothing" */
if (slot == NULL) /* "do nothing" */
skip_tuple = true;
else /* trigger might have changed tuple */
tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
} }
if (!skip_tuple) if (!skip_tuple)
...@@ -2990,9 +2983,6 @@ CopyFrom(CopyState cstate) ...@@ -2990,9 +2983,6 @@ CopyFrom(CopyState cstate)
if (slot == NULL) /* "do nothing" */ if (slot == NULL) /* "do nothing" */
continue; /* next tuple please */ continue; /* next tuple please */
/* FDW might have changed tuple */
tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
/* /*
* AFTER ROW Triggers might reference the tableoid * AFTER ROW Triggers might reference the tableoid
* column, so (re-)initialize tts_tableOid before * column, so (re-)initialize tts_tableOid before
...@@ -3002,6 +2992,7 @@ CopyFrom(CopyState cstate) ...@@ -3002,6 +2992,7 @@ CopyFrom(CopyState cstate)
} }
else else
{ {
tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
heap_insert(resultRelInfo->ri_RelationDesc, tuple, heap_insert(resultRelInfo->ri_RelationDesc, tuple,
mycid, hi_options, bistate); mycid, hi_options, bistate);
ItemPointerCopy(&tuple->t_self, &slot->tts_tid); ItemPointerCopy(&tuple->t_self, &slot->tts_tid);
...@@ -3018,7 +3009,7 @@ CopyFrom(CopyState cstate) ...@@ -3018,7 +3009,7 @@ CopyFrom(CopyState cstate)
NIL); NIL);
/* AFTER ROW INSERT Triggers */ /* AFTER ROW INSERT Triggers */
ExecARInsertTriggers(estate, resultRelInfo, tuple, ExecARInsertTriggers(estate, resultRelInfo, slot,
recheckIndexes, cstate->transition_capture); recheckIndexes, cstate->transition_capture);
list_free(recheckIndexes); list_free(recheckIndexes);
...@@ -3158,7 +3149,7 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid, ...@@ -3158,7 +3149,7 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
ExecInsertIndexTuples(myslot, &(bufferedTuples[i]->t_self), ExecInsertIndexTuples(myslot, &(bufferedTuples[i]->t_self),
estate, false, NULL, NIL); estate, false, NULL, NIL);
ExecARInsertTriggers(estate, resultRelInfo, ExecARInsertTriggers(estate, resultRelInfo,
bufferedTuples[i], myslot,
recheckIndexes, cstate->transition_capture); recheckIndexes, cstate->transition_capture);
list_free(recheckIndexes); list_free(recheckIndexes);
} }
...@@ -3175,8 +3166,9 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid, ...@@ -3175,8 +3166,9 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
for (i = 0; i < nBufferedTuples; i++) for (i = 0; i < nBufferedTuples; i++)
{ {
cstate->cur_lineno = firstBufferedLineNo + i; cstate->cur_lineno = firstBufferedLineNo + i;
ExecStoreHeapTuple(bufferedTuples[i], myslot, false);
ExecARInsertTriggers(estate, resultRelInfo, ExecARInsertTriggers(estate, resultRelInfo,
bufferedTuples[i], myslot,
NIL, cstate->transition_capture); NIL, cstate->transition_capture);
} }
} }
......
...@@ -8921,8 +8921,6 @@ validateForeignKeyConstraint(char *conname, ...@@ -8921,8 +8921,6 @@ validateForeignKeyConstraint(char *conname,
trigdata.tg_trigtuple = tuple; trigdata.tg_trigtuple = tuple;
trigdata.tg_newtuple = NULL; trigdata.tg_newtuple = NULL;
trigdata.tg_trigger = &trig; trigdata.tg_trigger = &trig;
trigdata.tg_trigtuplebuf = scan->rs_cbuf;
trigdata.tg_newtuplebuf = InvalidBuffer;
fcinfo->context = (Node *) &trigdata; fcinfo->context = (Node *) &trigdata;
......
This diff is collapsed.
...@@ -975,9 +975,6 @@ InitPlan(QueryDesc *queryDesc, int eflags) ...@@ -975,9 +975,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
* Initialize the executor's tuple table to empty. * Initialize the executor's tuple table to empty.
*/ */
estate->es_tupleTable = NIL; estate->es_tupleTable = NIL;
estate->es_trig_tuple_slot = NULL;
estate->es_trig_oldtup_slot = NULL;
estate->es_trig_newtup_slot = NULL;
/* mark EvalPlanQual not active */ /* mark EvalPlanQual not active */
estate->es_epqTuple = NULL; estate->es_epqTuple = NULL;
...@@ -1324,6 +1321,9 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo, ...@@ -1324,6 +1321,9 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
resultRelInfo->ri_projectReturning = NULL; resultRelInfo->ri_projectReturning = NULL;
resultRelInfo->ri_onConflictArbiterIndexes = NIL; resultRelInfo->ri_onConflictArbiterIndexes = NIL;
resultRelInfo->ri_onConflict = NULL; resultRelInfo->ri_onConflict = NULL;
resultRelInfo->ri_ReturningSlot = NULL;
resultRelInfo->ri_TrigOldSlot = NULL;
resultRelInfo->ri_TrigNewSlot = NULL;
/* /*
* Partition constraint, which also includes the partition constraint of * Partition constraint, which also includes the partition constraint of
......
...@@ -403,10 +403,8 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot) ...@@ -403,10 +403,8 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot)
if (resultRelInfo->ri_TrigDesc && if (resultRelInfo->ri_TrigDesc &&
resultRelInfo->ri_TrigDesc->trig_insert_before_row) resultRelInfo->ri_TrigDesc->trig_insert_before_row)
{ {
slot = ExecBRInsertTriggers(estate, resultRelInfo, slot); if (!ExecBRInsertTriggers(estate, resultRelInfo, slot))
skip_tuple = true; /* "do nothing" */
if (slot == NULL) /* "do nothing" */
skip_tuple = true;
} }
if (!skip_tuple) if (!skip_tuple)
...@@ -432,7 +430,7 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot) ...@@ -432,7 +430,7 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot)
NIL); NIL);
/* AFTER ROW INSERT Triggers */ /* AFTER ROW INSERT Triggers */
ExecARInsertTriggers(estate, resultRelInfo, tuple, ExecARInsertTriggers(estate, resultRelInfo, slot,
recheckIndexes, NULL); recheckIndexes, NULL);
/* /*
...@@ -475,11 +473,10 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, ...@@ -475,11 +473,10 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
if (resultRelInfo->ri_TrigDesc && if (resultRelInfo->ri_TrigDesc &&
resultRelInfo->ri_TrigDesc->trig_update_before_row) resultRelInfo->ri_TrigDesc->trig_update_before_row)
{ {
slot = ExecBRUpdateTriggers(estate, epqstate, resultRelInfo, if (!ExecBRUpdateTriggers(estate, epqstate, resultRelInfo,
&hsearchslot->tuple->t_self, NULL, slot); &hsearchslot->tuple->t_self,
NULL, slot))
if (slot == NULL) /* "do nothing" */ skip_tuple = true; /* "do nothing" */
skip_tuple = true;
} }
if (!skip_tuple) if (!skip_tuple)
...@@ -507,7 +504,8 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, ...@@ -507,7 +504,8 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
/* AFTER ROW UPDATE Triggers */ /* AFTER ROW UPDATE Triggers */
ExecARUpdateTriggers(estate, resultRelInfo, ExecARUpdateTriggers(estate, resultRelInfo,
&hsearchslot->tuple->t_self, NULL, tuple, &(tuple->t_self),
NULL, slot,
recheckIndexes, NULL); recheckIndexes, NULL);
list_free(recheckIndexes); list_free(recheckIndexes);
...@@ -540,8 +538,9 @@ ExecSimpleRelationDelete(EState *estate, EPQState *epqstate, ...@@ -540,8 +538,9 @@ ExecSimpleRelationDelete(EState *estate, EPQState *epqstate,
resultRelInfo->ri_TrigDesc->trig_delete_before_row) resultRelInfo->ri_TrigDesc->trig_delete_before_row)
{ {
skip_tuple = !ExecBRDeleteTriggers(estate, epqstate, resultRelInfo, skip_tuple = !ExecBRDeleteTriggers(estate, epqstate, resultRelInfo,
&hsearchslot->tuple->t_self, NULL, &hsearchslot->tuple->t_self,
NULL); NULL, NULL);
} }
if (!skip_tuple) if (!skip_tuple)
......
...@@ -119,6 +119,7 @@ tts_virtual_clear(TupleTableSlot *slot) ...@@ -119,6 +119,7 @@ tts_virtual_clear(TupleTableSlot *slot)
slot->tts_nvalid = 0; slot->tts_nvalid = 0;
slot->tts_flags |= TTS_FLAG_EMPTY; slot->tts_flags |= TTS_FLAG_EMPTY;
ItemPointerSetInvalid(&slot->tts_tid);
} }
/* /*
...@@ -314,6 +315,7 @@ tts_heap_clear(TupleTableSlot *slot) ...@@ -314,6 +315,7 @@ tts_heap_clear(TupleTableSlot *slot)
slot->tts_nvalid = 0; slot->tts_nvalid = 0;
slot->tts_flags |= TTS_FLAG_EMPTY; slot->tts_flags |= TTS_FLAG_EMPTY;
ItemPointerSetInvalid(&slot->tts_tid);
hslot->off = 0; hslot->off = 0;
hslot->tuple = NULL; hslot->tuple = NULL;
} }
...@@ -477,6 +479,7 @@ tts_minimal_clear(TupleTableSlot *slot) ...@@ -477,6 +479,7 @@ tts_minimal_clear(TupleTableSlot *slot)
slot->tts_nvalid = 0; slot->tts_nvalid = 0;
slot->tts_flags |= TTS_FLAG_EMPTY; slot->tts_flags |= TTS_FLAG_EMPTY;
ItemPointerSetInvalid(&slot->tts_tid);
mslot->off = 0; mslot->off = 0;
mslot->mintuple = NULL; mslot->mintuple = NULL;
} }
...@@ -658,6 +661,7 @@ tts_buffer_heap_clear(TupleTableSlot *slot) ...@@ -658,6 +661,7 @@ tts_buffer_heap_clear(TupleTableSlot *slot)
slot->tts_nvalid = 0; slot->tts_nvalid = 0;
slot->tts_flags |= TTS_FLAG_EMPTY; slot->tts_flags |= TTS_FLAG_EMPTY;
ItemPointerSetInvalid(&slot->tts_tid);
bslot->base.tuple = NULL; bslot->base.tuple = NULL;
bslot->base.off = 0; bslot->base.off = 0;
bslot->buffer = InvalidBuffer; bslot->buffer = InvalidBuffer;
......
...@@ -131,9 +131,6 @@ CreateExecutorState(void) ...@@ -131,9 +131,6 @@ CreateExecutorState(void)
estate->es_tuple_routing_result_relations = NIL; estate->es_tuple_routing_result_relations = NIL;
estate->es_trig_target_relations = NIL; estate->es_trig_target_relations = NIL;
estate->es_trig_tuple_slot = NULL;
estate->es_trig_oldtup_slot = NULL;
estate->es_trig_newtup_slot = NULL;
estate->es_param_list_info = NULL; estate->es_param_list_info = NULL;
estate->es_param_exec_vals = NULL; estate->es_param_exec_vals = NULL;
...@@ -1102,3 +1099,69 @@ ExecCleanTargetListLength(List *targetlist) ...@@ -1102,3 +1099,69 @@ ExecCleanTargetListLength(List *targetlist)
} }
return len; return len;
} }
/*
* Return a relInfo's tuple slot for a trigger's OLD tuples.
*/
TupleTableSlot *
ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo)
{
if (relInfo->ri_TrigOldSlot == NULL)
{
Relation rel = relInfo->ri_RelationDesc;
MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
relInfo->ri_TrigOldSlot =
ExecInitExtraTupleSlot(estate,
RelationGetDescr(rel),
&TTSOpsBufferHeapTuple);
MemoryContextSwitchTo(oldcontext);
}
return relInfo->ri_TrigOldSlot;
}
/*
* Return a relInfo's tuple slot for a trigger's NEW tuples.
*/
TupleTableSlot *
ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo)
{
if (relInfo->ri_TrigNewSlot == NULL)
{
Relation rel = relInfo->ri_RelationDesc;
MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
relInfo->ri_TrigNewSlot =
ExecInitExtraTupleSlot(estate,
RelationGetDescr(rel),
&TTSOpsBufferHeapTuple);
MemoryContextSwitchTo(oldcontext);
}
return relInfo->ri_TrigNewSlot;
}
/*
* Return a relInfo's tuple slot for processing returning tuples.
*/
TupleTableSlot *
ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo)
{
if (relInfo->ri_ReturningSlot == NULL)
{
Relation rel = relInfo->ri_RelationDesc;
MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
relInfo->ri_ReturningSlot =
ExecInitExtraTupleSlot(estate,
RelationGetDescr(rel),
&TTSOpsBufferHeapTuple);
MemoryContextSwitchTo(oldcontext);
}
return relInfo->ri_ReturningSlot;
}
This diff is collapsed.
...@@ -196,11 +196,6 @@ create_estate_for_relation(LogicalRepRelMapEntry *rel) ...@@ -196,11 +196,6 @@ create_estate_for_relation(LogicalRepRelMapEntry *rel)
estate->es_output_cid = GetCurrentCommandId(true); estate->es_output_cid = GetCurrentCommandId(true);
/* Triggers might need a slot */
if (resultRelInfo->ri_TrigDesc)
estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL,
&TTSOpsVirtual);
/* Prepare to catch AFTER triggers. */ /* Prepare to catch AFTER triggers. */
AfterTriggerBeginQuery(); AfterTriggerBeginQuery();
......
This diff is collapsed.
...@@ -35,8 +35,8 @@ typedef struct TriggerData ...@@ -35,8 +35,8 @@ typedef struct TriggerData
HeapTuple tg_trigtuple; HeapTuple tg_trigtuple;
HeapTuple tg_newtuple; HeapTuple tg_newtuple;
Trigger *tg_trigger; Trigger *tg_trigger;
Buffer tg_trigtuplebuf; TupleTableSlot *tg_trigslot;
Buffer tg_newtuplebuf; TupleTableSlot *tg_newslot;
Tuplestorestate *tg_oldtable; Tuplestorestate *tg_oldtable;
Tuplestorestate *tg_newtable; Tuplestorestate *tg_newtable;
} TriggerData; } TriggerData;
...@@ -77,9 +77,9 @@ typedef struct TransitionCaptureState ...@@ -77,9 +77,9 @@ typedef struct TransitionCaptureState
* format to parent format after they have already been converted in the * format to parent format after they have already been converted in the
* opposite direction during routing. In that case we bypass conversion * opposite direction during routing. In that case we bypass conversion
* and allow the inserting code (copy.c and nodeModifyTable.c) to provide * and allow the inserting code (copy.c and nodeModifyTable.c) to provide
* the original tuple directly. * a slot containing the original tuple directly.
*/ */
HeapTuple tcs_original_insert_tuple; TupleTableSlot *tcs_original_insert_tuple;
/* /*
* Private data including the tuplestore(s) into which to insert tuples. * Private data including the tuplestore(s) into which to insert tuples.
...@@ -186,15 +186,15 @@ extern void ExecBSInsertTriggers(EState *estate, ...@@ -186,15 +186,15 @@ extern void ExecBSInsertTriggers(EState *estate,
extern void ExecASInsertTriggers(EState *estate, extern void ExecASInsertTriggers(EState *estate,
ResultRelInfo *relinfo, ResultRelInfo *relinfo,
TransitionCaptureState *transition_capture); TransitionCaptureState *transition_capture);
extern TupleTableSlot *ExecBRInsertTriggers(EState *estate, extern bool ExecBRInsertTriggers(EState *estate,
ResultRelInfo *relinfo, ResultRelInfo *relinfo,
TupleTableSlot *slot); TupleTableSlot *slot);
extern void ExecARInsertTriggers(EState *estate, extern void ExecARInsertTriggers(EState *estate,
ResultRelInfo *relinfo, ResultRelInfo *relinfo,
HeapTuple trigtuple, TupleTableSlot *slot,
List *recheckIndexes, List *recheckIndexes,
TransitionCaptureState *transition_capture); TransitionCaptureState *transition_capture);
extern TupleTableSlot *ExecIRInsertTriggers(EState *estate, extern bool ExecIRInsertTriggers(EState *estate,
ResultRelInfo *relinfo, ResultRelInfo *relinfo,
TupleTableSlot *slot); TupleTableSlot *slot);
extern void ExecBSDeleteTriggers(EState *estate, extern void ExecBSDeleteTriggers(EState *estate,
...@@ -221,7 +221,7 @@ extern void ExecBSUpdateTriggers(EState *estate, ...@@ -221,7 +221,7 @@ extern void ExecBSUpdateTriggers(EState *estate,
extern void ExecASUpdateTriggers(EState *estate, extern void ExecASUpdateTriggers(EState *estate,
ResultRelInfo *relinfo, ResultRelInfo *relinfo,
TransitionCaptureState *transition_capture); TransitionCaptureState *transition_capture);
extern TupleTableSlot *ExecBRUpdateTriggers(EState *estate, extern bool ExecBRUpdateTriggers(EState *estate,
EPQState *epqstate, EPQState *epqstate,
ResultRelInfo *relinfo, ResultRelInfo *relinfo,
ItemPointer tupleid, ItemPointer tupleid,
...@@ -231,10 +231,10 @@ extern void ExecARUpdateTriggers(EState *estate, ...@@ -231,10 +231,10 @@ extern void ExecARUpdateTriggers(EState *estate,
ResultRelInfo *relinfo, ResultRelInfo *relinfo,
ItemPointer tupleid, ItemPointer tupleid,
HeapTuple fdw_trigtuple, HeapTuple fdw_trigtuple,
HeapTuple newtuple, TupleTableSlot *slot,
List *recheckIndexes, List *recheckIndexes,
TransitionCaptureState *transition_capture); TransitionCaptureState *transition_capture);
extern TupleTableSlot *ExecIRUpdateTriggers(EState *estate, extern bool ExecIRUpdateTriggers(EState *estate,
ResultRelInfo *relinfo, ResultRelInfo *relinfo,
HeapTuple trigtuple, HeapTuple trigtuple,
TupleTableSlot *slot); TupleTableSlot *slot);
...@@ -258,9 +258,9 @@ extern bool AfterTriggerPendingOnRel(Oid relid); ...@@ -258,9 +258,9 @@ extern bool AfterTriggerPendingOnRel(Oid relid);
* in utils/adt/ri_triggers.c * in utils/adt/ri_triggers.c
*/ */
extern bool RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel, extern bool RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel,
HeapTuple old_row, HeapTuple new_row); TupleTableSlot *old_slot, TupleTableSlot *new_slot);
extern bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel, extern bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel,
HeapTuple old_row, HeapTuple new_row); TupleTableSlot *old_slot, TupleTableSlot *new_slot);
extern bool RI_Initial_Check(Trigger *trigger, extern bool RI_Initial_Check(Trigger *trigger,
Relation fk_rel, Relation pk_rel); Relation fk_rel, Relation pk_rel);
......
...@@ -560,6 +560,10 @@ extern Datum GetAttributeByNum(HeapTupleHeader tuple, AttrNumber attrno, ...@@ -560,6 +560,10 @@ extern Datum GetAttributeByNum(HeapTupleHeader tuple, AttrNumber attrno,
extern int ExecTargetListLength(List *targetlist); extern int ExecTargetListLength(List *targetlist);
extern int ExecCleanTargetListLength(List *targetlist); extern int ExecCleanTargetListLength(List *targetlist);
extern TupleTableSlot *ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo);
extern TupleTableSlot *ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo);
extern TupleTableSlot *ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo);
/* /*
* prototypes from functions in execIndexing.c * prototypes from functions in execIndexing.c
*/ */
......
...@@ -427,6 +427,11 @@ typedef struct ResultRelInfo ...@@ -427,6 +427,11 @@ typedef struct ResultRelInfo
/* optional runtime measurements for triggers */ /* optional runtime measurements for triggers */
Instrumentation *ri_TrigInstrument; Instrumentation *ri_TrigInstrument;
/* On-demand created slots for triggers / returning processing */
TupleTableSlot *ri_ReturningSlot; /* for trigger output tuples */
TupleTableSlot *ri_TrigOldSlot; /* for a trigger's old tuple */
TupleTableSlot *ri_TrigNewSlot; /* for a trigger's new tuple */
/* FDW callback functions, if foreign table */ /* FDW callback functions, if foreign table */
struct FdwRoutine *ri_FdwRoutine; struct FdwRoutine *ri_FdwRoutine;
...@@ -524,9 +529,6 @@ typedef struct EState ...@@ -524,9 +529,6 @@ typedef struct EState
/* Stuff used for firing triggers: */ /* Stuff used for firing triggers: */
List *es_trig_target_relations; /* trigger-only ResultRelInfos */ List *es_trig_target_relations; /* trigger-only ResultRelInfos */
TupleTableSlot *es_trig_tuple_slot; /* for trigger output tuples */
TupleTableSlot *es_trig_oldtup_slot; /* for TriggerEnabled */
TupleTableSlot *es_trig_newtup_slot; /* for TriggerEnabled */
/* Parameter info: */ /* Parameter info: */
ParamListInfo es_param_list_info; /* values of external params */ ParamListInfo es_param_list_info; /* values of external params */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment