| 2924 | } |
| 2925 | |
| 2926 | void |
| 2927 | ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, |
| 2928 | ItemPointer tupleid, |
| 2929 | HeapTuple fdw_trigtuple, |
| 2930 | TupleTableSlot *newslot, |
| 2931 | List *recheckIndexes, |
| 2932 | TransitionCaptureState *transition_capture) |
| 2933 | { |
| 2934 | TriggerDesc *trigdesc = relinfo->ri_TrigDesc; |
| 2935 | |
| 2936 | if ((trigdesc && trigdesc->trig_update_after_row) || |
| 2937 | (transition_capture && |
| 2938 | (transition_capture->tcs_update_old_table || |
| 2939 | transition_capture->tcs_update_new_table))) |
| 2940 | { |
| 2941 | /* |
| 2942 | * Note: if the UPDATE is converted into a DELETE+INSERT as part of |
| 2943 | * update-partition-key operation, then this function is also called |
| 2944 | * separately for DELETE and INSERT to capture transition table rows. |
| 2945 | * In such case, either old tuple or new tuple can be NULL. |
| 2946 | */ |
| 2947 | TupleTableSlot *oldslot = ExecGetTriggerOldSlot(estate, relinfo); |
| 2948 | |
| 2949 | if (fdw_trigtuple == NULL && ItemPointerIsValid(tupleid)) |
| 2950 | GetTupleForTrigger(estate, |
| 2951 | NULL, |
| 2952 | relinfo, |
| 2953 | tupleid, |
| 2954 | LockTupleExclusive, |
| 2955 | oldslot, |
| 2956 | NULL); |
| 2957 | else if (fdw_trigtuple != NULL) |
| 2958 | ExecForceStoreHeapTuple(fdw_trigtuple, oldslot, false); |
| 2959 | else |
| 2960 | ExecClearTuple(oldslot); |
| 2961 | |
| 2962 | AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE, |
| 2963 | true, oldslot, newslot, recheckIndexes, |
| 2964 | ExecGetAllUpdatedCols(relinfo, estate), |
| 2965 | transition_capture); |
| 2966 | } |
| 2967 | } |
| 2968 | |
| 2969 | bool |
| 2970 | ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo, |
no test coverage detected