@@ -96,6 +96,12 @@ static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
96
96
FmgrInfo * finfo ,
97
97
Instrumentation * instr ,
98
98
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 );
99
105
static void AfterTriggerSaveEvent (EState * estate , ResultRelInfo * relinfo ,
100
106
int event , bool row_trigger ,
101
107
HeapTuple oldtup , HeapTuple newtup ,
@@ -3846,6 +3852,14 @@ struct AfterTriggersTableData
3846
3852
bool before_trig_done ; /* did we already queue BS triggers? */
3847
3853
bool after_trig_done ; /* did we already queue AS triggers? */
3848
3854
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
+
3849
3863
/* "old" transition table for UPDATE, if any */
3850
3864
Tuplestorestate * old_upd_tuplestore ;
3851
3865
/* "new" transition table for UPDATE, if any */
@@ -5716,6 +5730,84 @@ AfterTriggerPendingOnRel(Oid relid)
5716
5730
return false;
5717
5731
}
5718
5732
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
+ }
5719
5811
5720
5812
/* ----------
5721
5813
* AfterTriggerSaveEvent()
@@ -5777,95 +5869,37 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
5777
5869
{
5778
5870
HeapTuple original_insert_tuple = transition_capture -> tcs_original_insert_tuple ;
5779
5871
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 ;;
5784
5872
5785
5873
/*
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.
5792
5876
*/
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 )
5800
5878
{
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 );
5814
5885
}
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 );
5825
5886
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 )
5853
5892
{
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 );
5857
5898
5858
5899
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 );
5867
5901
else
5868
- tuplestore_puttuple ( new_tuplestore , newtup );
5902
+ TransitionTableAddTuple ( newtup , tuplestore , map );
5869
5903
}
5870
5904
5871
5905
/*
0 commit comments