diff options
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r-- | src/backend/commands/trigger.c | 270 |
1 files changed, 75 insertions, 195 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 0d57d467484..cc50691aa00 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -84,8 +84,7 @@ static HeapTuple GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo, ItemPointer tid, LockTupleMode lockmode, - TupleTableSlot **newSlot, - HeapUpdateFailureData *hufdp); + TupleTableSlot **newSlot); static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, @@ -95,12 +94,6 @@ static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context); -static Tuplestorestate *AfterTriggerGetTransitionTable(int event, - HeapTuple oldtup, - HeapTuple newtup, - TransitionCaptureState *transition_capture); -static void TransitionTableAddTuple(HeapTuple heaptup, Tuplestorestate *tuplestore, - TupleConversionMap *map); static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, int event, bool row_trigger, HeapTuple oldtup, HeapTuple newtup, @@ -2736,8 +2729,7 @@ bool ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, - HeapTuple fdw_trigtuple, - HeapUpdateFailureData *hufdp) + HeapTuple fdw_trigtuple) { TriggerDesc *trigdesc = relinfo->ri_TrigDesc; bool result = true; @@ -2751,7 +2743,7 @@ ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, if (fdw_trigtuple == NULL) { trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid, - LockTupleExclusive, &newSlot, hufdp); + LockTupleExclusive, &newSlot); if (trigtuple == NULL) return false; } @@ -2822,7 +2814,6 @@ ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo, relinfo, tupleid, LockTupleExclusive, - NULL, NULL); else trigtuple = fdw_trigtuple; @@ -2960,8 +2951,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, - TupleTableSlot *slot, - HeapUpdateFailureData *hufdp) + TupleTableSlot *slot) { TriggerDesc *trigdesc = relinfo->ri_TrigDesc; HeapTuple slottuple = ExecMaterializeSlot(slot); @@ -2982,7 +2972,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, { /* get a copy of the on-disk tuple we are planning to update */ trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid, - lockmode, &newSlot, hufdp); + lockmode, &newSlot); if (trigtuple == NULL) return NULL; /* cancel the update action */ } @@ -3102,7 +3092,6 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, relinfo, tupleid, LockTupleExclusive, - NULL, NULL); else trigtuple = fdw_trigtuple; @@ -3251,8 +3240,7 @@ GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo, ItemPointer tid, LockTupleMode lockmode, - TupleTableSlot **newSlot, - HeapUpdateFailureData *hufdp) + TupleTableSlot **newSlot) { Relation relation = relinfo->ri_RelationDesc; HeapTupleData tuple; @@ -3278,11 +3266,6 @@ ltrmark:; estate->es_output_cid, lockmode, LockWaitBlock, false, &buffer, &hufd); - - /* Let the caller know about failure reason, if any. */ - if (hufdp) - *hufdp = hufd; - switch (test) { case HeapTupleSelfUpdated: @@ -3324,17 +3307,10 @@ ltrmark:; /* it was updated, so look at the updated version */ TupleTableSlot *epqslot; - /* - * If we're running MERGE then we must install the - * new tuple in the slot of the underlying join query and - * not the result relation itself. If the join does not - * yield any tuple, the caller will take the necessary - * action. - */ epqslot = EvalPlanQual(estate, epqstate, relation, - GetEPQRangeTableIndex(relinfo), + relinfo->ri_RangeTableIndex, lockmode, &hufd.ctid, hufd.xmax); @@ -3857,22 +3833,8 @@ struct AfterTriggersTableData bool before_trig_done; /* did we already queue BS triggers? */ bool after_trig_done; /* did we already queue AS triggers? */ AfterTriggerEventList after_trig_events; /* if so, saved list pointer */ - - /* - * We maintain separate transaction tables for UPDATE/INSERT/DELETE since - * MERGE can run all three actions in a single statement. Note that UPDATE - * needs both old and new transition tables whereas INSERT needs only new - * and DELETE needs only old. - */ - - /* "old" transition table for UPDATE, if any */ - Tuplestorestate *old_upd_tuplestore; - /* "new" transition table for UPDATE, if any */ - Tuplestorestate *new_upd_tuplestore; - /* "old" transition table for DELETE, if any */ - Tuplestorestate *old_del_tuplestore; - /* "new" transition table INSERT, if any */ - Tuplestorestate *new_ins_tuplestore; + Tuplestorestate *old_tuplestore; /* "old" transition table, if any */ + Tuplestorestate *new_tuplestore; /* "new" transition table, if any */ }; static AfterTriggersData afterTriggers; @@ -4339,19 +4301,13 @@ AfterTriggerExecute(AfterTriggerEvent event, { if (LocTriggerData.tg_trigger->tgoldtable) { - if (TRIGGER_FIRED_BY_UPDATE(evtshared->ats_event)) - LocTriggerData.tg_oldtable = evtshared->ats_table->old_upd_tuplestore; - else - LocTriggerData.tg_oldtable = evtshared->ats_table->old_del_tuplestore; + LocTriggerData.tg_oldtable = evtshared->ats_table->old_tuplestore; evtshared->ats_table->closed = true; } if (LocTriggerData.tg_trigger->tgnewtable) { - if (TRIGGER_FIRED_BY_INSERT(evtshared->ats_event)) - LocTriggerData.tg_newtable = evtshared->ats_table->new_ins_tuplestore; - else - LocTriggerData.tg_newtable = evtshared->ats_table->new_upd_tuplestore; + LocTriggerData.tg_newtable = evtshared->ats_table->new_tuplestore; evtshared->ats_table->closed = true; } } @@ -4686,10 +4642,8 @@ TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType) { TransitionCaptureState *state; - bool need_old_upd, - need_new_upd, - need_old_del, - need_new_ins; + bool need_old, + need_new; AfterTriggersTableData *table; MemoryContext oldcxt; ResourceOwner saveResourceOwner; @@ -4701,31 +4655,23 @@ MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType) switch (cmdType) { case CMD_INSERT: - need_old_upd = need_old_del = need_new_upd = false; - need_new_ins = trigdesc->trig_insert_new_table; + need_old = false; + need_new = trigdesc->trig_insert_new_table; break; case CMD_UPDATE: - need_old_upd = trigdesc->trig_update_old_table; - need_new_upd = trigdesc->trig_update_new_table; - need_old_del = need_new_ins = false; + need_old = trigdesc->trig_update_old_table; + need_new = trigdesc->trig_update_new_table; break; case CMD_DELETE: - need_old_del = trigdesc->trig_delete_old_table; - need_old_upd = need_new_upd = need_new_ins = false; - break; - case CMD_MERGE: - need_old_upd = trigdesc->trig_update_old_table; - need_new_upd = trigdesc->trig_update_new_table; - need_old_del = trigdesc->trig_delete_old_table; - need_new_ins = trigdesc->trig_insert_new_table; + need_old = trigdesc->trig_delete_old_table; + need_new = false; break; default: elog(ERROR, "unexpected CmdType: %d", (int) cmdType); - /* keep compiler quiet */ - need_old_upd = need_new_upd = need_old_del = need_new_ins = false; + need_old = need_new = false; /* keep compiler quiet */ break; } - if (!need_old_upd && !need_new_upd && !need_new_ins && !need_old_del) + if (!need_old && !need_new) return NULL; /* Check state, like AfterTriggerSaveEvent. */ @@ -4755,14 +4701,10 @@ MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType) saveResourceOwner = CurrentResourceOwner; CurrentResourceOwner = CurTransactionResourceOwner; - if (need_old_upd && table->old_upd_tuplestore == NULL) - table->old_upd_tuplestore = tuplestore_begin_heap(false, false, work_mem); - if (need_new_upd && table->new_upd_tuplestore == NULL) - table->new_upd_tuplestore = tuplestore_begin_heap(false, false, work_mem); - if (need_old_del && table->old_del_tuplestore == NULL) - table->old_del_tuplestore = tuplestore_begin_heap(false, false, work_mem); - if (need_new_ins && table->new_ins_tuplestore == NULL) - table->new_ins_tuplestore = tuplestore_begin_heap(false, false, work_mem); + if (need_old && table->old_tuplestore == NULL) + table->old_tuplestore = tuplestore_begin_heap(false, false, work_mem); + if (need_new && table->new_tuplestore == NULL) + table->new_tuplestore = tuplestore_begin_heap(false, false, work_mem); CurrentResourceOwner = saveResourceOwner; MemoryContextSwitchTo(oldcxt); @@ -4951,20 +4893,12 @@ AfterTriggerFreeQuery(AfterTriggersQueryData *qs) { AfterTriggersTableData *table = (AfterTriggersTableData *) lfirst(lc); - ts = table->old_upd_tuplestore; - table->old_upd_tuplestore = NULL; - if (ts) - tuplestore_end(ts); - ts = table->new_upd_tuplestore; - table->new_upd_tuplestore = NULL; - if (ts) - tuplestore_end(ts); - ts = table->old_del_tuplestore; - table->old_del_tuplestore = NULL; + ts = table->old_tuplestore; + table->old_tuplestore = NULL; if (ts) tuplestore_end(ts); - ts = table->new_ins_tuplestore; - table->new_ins_tuplestore = NULL; + ts = table->new_tuplestore; + table->new_tuplestore = NULL; if (ts) tuplestore_end(ts); } @@ -5735,84 +5669,6 @@ AfterTriggerPendingOnRel(Oid relid) return false; } -/* - * Get the transition table for the given event and depending on whether we are - * processing the old or the new tuple. - */ -static Tuplestorestate * -AfterTriggerGetTransitionTable(int event, - HeapTuple oldtup, - HeapTuple newtup, - TransitionCaptureState *transition_capture) -{ - Tuplestorestate *tuplestore = NULL; - bool delete_old_table = transition_capture->tcs_delete_old_table; - bool update_old_table = transition_capture->tcs_update_old_table; - bool update_new_table = transition_capture->tcs_update_new_table; - bool insert_new_table = transition_capture->tcs_insert_new_table;; - - /* - * For INSERT events newtup should be non-NULL, for DELETE events - * oldtup should be non-NULL, whereas for UPDATE events normally both - * oldtup and newtup are non-NULL. But for UPDATE events fired for - * capturing transition tuples during UPDATE partition-key row - * movement, oldtup is NULL when the event is for a row being inserted, - * whereas newtup is NULL when the event is for a row being deleted. - */ - Assert(!(event == TRIGGER_EVENT_DELETE && delete_old_table && - oldtup == NULL)); - Assert(!(event == TRIGGER_EVENT_INSERT && insert_new_table && - newtup == NULL)); - - /* - * We're called either for the newtup or the oldtup, but not both at the - * same time. - */ - Assert((oldtup != NULL) ^ (newtup != NULL)); - - if (oldtup != NULL) - { - if (event == TRIGGER_EVENT_DELETE && delete_old_table) - tuplestore = transition_capture->tcs_private->old_del_tuplestore; - else if (event == TRIGGER_EVENT_UPDATE && update_old_table) - tuplestore = transition_capture->tcs_private->old_upd_tuplestore; - } - - if (newtup != NULL) - { - if (event == TRIGGER_EVENT_INSERT && insert_new_table) - tuplestore = transition_capture->tcs_private->new_ins_tuplestore; - else if (event == TRIGGER_EVENT_UPDATE && update_new_table) - tuplestore = transition_capture->tcs_private->new_upd_tuplestore; - } - - return tuplestore; -} - -/* - * Add the given heap tuple to the given tuplestore, applying the conversion - * map if necessary. - */ -static void -TransitionTableAddTuple(HeapTuple heaptup, Tuplestorestate *tuplestore, - TupleConversionMap *map) -{ - /* - * Nothing needs to be done if we don't have a tuplestore. - */ - if (tuplestore == NULL) - return; - - if (map != NULL) - { - HeapTuple converted = do_convert_tuple(heaptup, map); - - tuplestore_puttuple(tuplestore, converted); - pfree(converted); - } - else - tuplestore_puttuple(tuplestore, heaptup); -} /* ---------- * AfterTriggerSaveEvent() @@ -5874,37 +5730,61 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, { HeapTuple original_insert_tuple = transition_capture->tcs_original_insert_tuple; TupleConversionMap *map = transition_capture->tcs_map; + bool delete_old_table = transition_capture->tcs_delete_old_table; + bool update_old_table = transition_capture->tcs_update_old_table; + bool update_new_table = transition_capture->tcs_update_new_table; + bool insert_new_table = transition_capture->tcs_insert_new_table;; /* - * Capture the old tuple in the appropriate transition table based on - * the event. + * For INSERT events newtup should be non-NULL, for DELETE events + * oldtup should be non-NULL, whereas for UPDATE events normally both + * oldtup and newtup are non-NULL. But for UPDATE events fired for + * capturing transition tuples during UPDATE partition-key row + * movement, oldtup is NULL when the event is for a row being inserted, + * whereas newtup is NULL when the event is for a row being deleted. */ - if (oldtup != NULL) + Assert(!(event == TRIGGER_EVENT_DELETE && delete_old_table && + oldtup == NULL)); + Assert(!(event == TRIGGER_EVENT_INSERT && insert_new_table && + newtup == NULL)); + + if (oldtup != NULL && + ((event == TRIGGER_EVENT_DELETE && delete_old_table) || + (event == TRIGGER_EVENT_UPDATE && update_old_table))) { - Tuplestorestate *tuplestore = - AfterTriggerGetTransitionTable(event, - oldtup, - NULL, - transition_capture); - TransitionTableAddTuple(oldtup, tuplestore, map); - } + Tuplestorestate *old_tuplestore; - /* - * Capture the new tuple in the appropriate transition table based on - * the event. - */ - if (newtup != NULL) + old_tuplestore = transition_capture->tcs_private->old_tuplestore; + + if (map != NULL) + { + HeapTuple converted = do_convert_tuple(oldtup, map); + + tuplestore_puttuple(old_tuplestore, converted); + pfree(converted); + } + else + tuplestore_puttuple(old_tuplestore, oldtup); + } + if (newtup != NULL && + ((event == TRIGGER_EVENT_INSERT && insert_new_table) || + (event == TRIGGER_EVENT_UPDATE && update_new_table))) { - Tuplestorestate *tuplestore = - AfterTriggerGetTransitionTable(event, - NULL, - newtup, - transition_capture); + Tuplestorestate *new_tuplestore; + + new_tuplestore = transition_capture->tcs_private->new_tuplestore; if (original_insert_tuple != NULL) - tuplestore_puttuple(tuplestore, original_insert_tuple); + tuplestore_puttuple(new_tuplestore, original_insert_tuple); + else if (map != NULL) + { + HeapTuple converted = do_convert_tuple(newtup, map); + + tuplestore_puttuple(new_tuplestore, converted); + pfree(converted); + } else - TransitionTableAddTuple(newtup, tuplestore, map); + tuplestore_puttuple(new_tuplestore, newtup); } /* |