@@ -96,6 +96,12 @@ static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
9696 FmgrInfo * finfo ,
9797 Instrumentation * instr ,
9898 MemoryContext per_tuple_context );
99+ static Tuplestorestate * AfterTriggerGetTransitionTable (int event ,
100+ HeapTuple oldtup ,
101+ HeapTuple newtup ,
102+ TransitionCaptureState * transition_capture );
103+ static void TransitionTableAddTuple (HeapTuple heaptup , Tuplestorestate * tuplestore ,
104+ TupleConversionMap * map );
99105static void AfterTriggerSaveEvent (EState * estate , ResultRelInfo * relinfo ,
100106 int event , bool row_trigger ,
101107 HeapTuple oldtup , HeapTuple newtup ,
@@ -3846,6 +3852,14 @@ struct AfterTriggersTableData
38463852 bool before_trig_done ; /* did we already queue BS triggers? */
38473853 bool after_trig_done ; /* did we already queue AS triggers? */
38483854 AfterTriggerEventList after_trig_events ; /* if so, saved list pointer */
3855+
3856+ /*
3857+ * We maintain separate transaction tables for UPDATE/INSERT/DELETE since
3858+ * MERGE can run all three actions in a single statement. Note that UPDATE
3859+ * needs both old and new transition tables whereas INSERT needs only new
3860+ * and DELETE needs only old.
3861+ */
3862+
38493863 /* "old" transition table for UPDATE, if any */
38503864 Tuplestorestate * old_upd_tuplestore ;
38513865 /* "new" transition table for UPDATE, if any */
@@ -5716,6 +5730,84 @@ AfterTriggerPendingOnRel(Oid relid)
57165730 return false;
57175731}
57185732
5733+ /*
5734+ * Get the transition table for the given event and depending on whether we are
5735+ * processing the old or the new tuple.
5736+ */
5737+ static Tuplestorestate *
5738+ AfterTriggerGetTransitionTable (int event ,
5739+ HeapTuple oldtup ,
5740+ HeapTuple newtup ,
5741+ TransitionCaptureState * transition_capture )
5742+ {
5743+ Tuplestorestate * tuplestore = NULL ;
5744+ bool delete_old_table = transition_capture -> tcs_delete_old_table ;
5745+ bool update_old_table = transition_capture -> tcs_update_old_table ;
5746+ bool update_new_table = transition_capture -> tcs_update_new_table ;
5747+ bool insert_new_table = transition_capture -> tcs_insert_new_table ;;
5748+
5749+ /*
5750+ * For INSERT events newtup should be non-NULL, for DELETE events
5751+ * oldtup should be non-NULL, whereas for UPDATE events normally both
5752+ * oldtup and newtup are non-NULL. But for UPDATE events fired for
5753+ * capturing transition tuples during UPDATE partition-key row
5754+ * movement, oldtup is NULL when the event is for a row being inserted,
5755+ * whereas newtup is NULL when the event is for a row being deleted.
5756+ */
5757+ Assert (!(event == TRIGGER_EVENT_DELETE && delete_old_table &&
5758+ oldtup == NULL ));
5759+ Assert (!(event == TRIGGER_EVENT_INSERT && insert_new_table &&
5760+ newtup == NULL ));
5761+
5762+ /*
5763+ * We're called either for the newtup or the oldtup, but not both at the
5764+ * same time.
5765+ */
5766+ Assert ((oldtup != NULL ) ^ (newtup != NULL ));
5767+
5768+ if (oldtup != NULL )
5769+ {
5770+ if (event == TRIGGER_EVENT_DELETE && delete_old_table )
5771+ tuplestore = transition_capture -> tcs_private -> old_del_tuplestore ;
5772+ else if (event == TRIGGER_EVENT_UPDATE && update_old_table )
5773+ tuplestore = transition_capture -> tcs_private -> old_upd_tuplestore ;
5774+ }
5775+
5776+ if (newtup != NULL )
5777+ {
5778+ if (event == TRIGGER_EVENT_INSERT && insert_new_table )
5779+ tuplestore = transition_capture -> tcs_private -> new_ins_tuplestore ;
5780+ else if (event == TRIGGER_EVENT_UPDATE && update_new_table )
5781+ tuplestore = transition_capture -> tcs_private -> new_upd_tuplestore ;
5782+ }
5783+
5784+ return tuplestore ;
5785+ }
5786+
5787+ /*
5788+ * Add the given heap tuple to the given tuplestore, applying the conversion
5789+ * map if necessary.
5790+ */
5791+ static void
5792+ TransitionTableAddTuple (HeapTuple heaptup , Tuplestorestate * tuplestore ,
5793+ TupleConversionMap * map )
5794+ {
5795+ /*
5796+ * Nothing needs to be done if we don't have a tuplestore.
5797+ */
5798+ if (tuplestore == NULL )
5799+ return ;
5800+
5801+ if (map != NULL )
5802+ {
5803+ HeapTuple converted = do_convert_tuple (heaptup , map );
5804+
5805+ tuplestore_puttuple (tuplestore , converted );
5806+ pfree (converted );
5807+ }
5808+ else
5809+ tuplestore_puttuple (tuplestore , heaptup );
5810+ }
57195811
57205812/* ----------
57215813 * AfterTriggerSaveEvent()
@@ -5777,95 +5869,37 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
57775869 {
57785870 HeapTuple original_insert_tuple = transition_capture -> tcs_original_insert_tuple ;
57795871 TupleConversionMap * map = transition_capture -> tcs_map ;
5780- bool delete_old_table = transition_capture -> tcs_delete_old_table ;
5781- bool update_old_table = transition_capture -> tcs_update_old_table ;
5782- bool update_new_table = transition_capture -> tcs_update_new_table ;
5783- bool insert_new_table = transition_capture -> tcs_insert_new_table ;;
57845872
57855873 /*
5786- * For INSERT events newtup should be non-NULL, for DELETE events
5787- * oldtup should be non-NULL, whereas for UPDATE events normally both
5788- * oldtup and newtup are non-NULL. But for UPDATE events fired for
5789- * capturing transition tuples during UPDATE partition-key row
5790- * movement, oldtup is NULL when the event is for a row being inserted,
5791- * whereas newtup is NULL when the event is for a row being deleted.
5874+ * Capture the old tuple in the appropriate transition table based on
5875+ * the event.
57925876 */
5793- Assert (!(event == TRIGGER_EVENT_DELETE && delete_old_table &&
5794- oldtup == NULL ));
5795- Assert (!(event == TRIGGER_EVENT_INSERT && insert_new_table &&
5796- newtup == NULL ));
5797-
5798- if (oldtup != NULL &&
5799- (event == TRIGGER_EVENT_DELETE && delete_old_table ))
5877+ if (oldtup != NULL )
58005878 {
5801- Tuplestorestate * old_tuplestore ;
5802-
5803- old_tuplestore = transition_capture -> tcs_private -> old_del_tuplestore ;
5804-
5805- if (map != NULL )
5806- {
5807- HeapTuple converted = do_convert_tuple (oldtup , map );
5808-
5809- tuplestore_puttuple (old_tuplestore , converted );
5810- pfree (converted );
5811- }
5812- else
5813- tuplestore_puttuple (old_tuplestore , oldtup );
5879+ Tuplestorestate * tuplestore =
5880+ AfterTriggerGetTransitionTable (event ,
5881+ oldtup ,
5882+ NULL ,
5883+ transition_capture );
5884+ TransitionTableAddTuple (oldtup , tuplestore , map );
58145885 }
5815- if (oldtup != NULL &&
5816- (event == TRIGGER_EVENT_UPDATE && update_old_table ))
5817- {
5818- Tuplestorestate * old_tuplestore ;
5819-
5820- old_tuplestore = transition_capture -> tcs_private -> old_upd_tuplestore ;
5821-
5822- if (map != NULL )
5823- {
5824- HeapTuple converted = do_convert_tuple (oldtup , map );
58255886
5826- tuplestore_puttuple (old_tuplestore , converted );
5827- pfree (converted );
5828- }
5829- else
5830- tuplestore_puttuple (old_tuplestore , oldtup );
5831- }
5832- if (newtup != NULL &&
5833- (event == TRIGGER_EVENT_INSERT && insert_new_table ))
5834- {
5835- Tuplestorestate * new_tuplestore ;
5836-
5837- new_tuplestore = transition_capture -> tcs_private -> new_ins_tuplestore ;
5838-
5839- if (original_insert_tuple != NULL )
5840- tuplestore_puttuple (new_tuplestore , original_insert_tuple );
5841- else if (map != NULL )
5842- {
5843- HeapTuple converted = do_convert_tuple (newtup , map );
5844-
5845- tuplestore_puttuple (new_tuplestore , converted );
5846- pfree (converted );
5847- }
5848- else
5849- tuplestore_puttuple (new_tuplestore , newtup );
5850- }
5851- if (newtup != NULL &&
5852- (event == TRIGGER_EVENT_UPDATE && update_new_table ))
5887+ /*
5888+ * Capture the new tuple in the appropriate transition table based on
5889+ * the event.
5890+ */
5891+ if (newtup != NULL )
58535892 {
5854- Tuplestorestate * new_tuplestore ;
5855-
5856- new_tuplestore = transition_capture -> tcs_private -> new_upd_tuplestore ;
5893+ Tuplestorestate * tuplestore =
5894+ AfterTriggerGetTransitionTable (event ,
5895+ NULL ,
5896+ newtup ,
5897+ transition_capture );
58575898
58585899 if (original_insert_tuple != NULL )
5859- tuplestore_puttuple (new_tuplestore , original_insert_tuple );
5860- else if (map != NULL )
5861- {
5862- HeapTuple converted = do_convert_tuple (newtup , map );
5863-
5864- tuplestore_puttuple (new_tuplestore , converted );
5865- pfree (converted );
5866- }
5900+ tuplestore_puttuple (tuplestore , original_insert_tuple );
58675901 else
5868- tuplestore_puttuple ( new_tuplestore , newtup );
5902+ TransitionTableAddTuple ( newtup , tuplestore , map );
58695903 }
58705904
58715905 /*
0 commit comments