Skip to content

Commit 3a46a45

Browse files
committed
Add API of sorts for transition table handling in trigger.c
Preparatory patch for further additions in this area, particularly to allow MERGE to have separate transition tables for each action. Author: Pavan Deolasee <pavan.deolasee@gmail.com> Reviewed-by: Álvaro Herrera <alvherre@alvh.no-ip.org> Discussion: https://postgr.es/m/CABOikdNj+8HEJ5D8tu56mrPkjHVRrBb2_cdKWwpiYNcjXgDw8g@mail.gmail.com Discussion: https://postgr.es/m/20201231134736.GA25392@alvherre.pgsql
1 parent 641f3df commit 3a46a45

File tree

1 file changed

+119
-53
lines changed

1 file changed

+119
-53
lines changed

src/backend/commands/trigger.c

Lines changed: 119 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3772,6 +3772,16 @@ static AfterTriggersTableData *GetAfterTriggersTableData(Oid relid,
37723772
CmdType cmdType);
37733773
static TupleTableSlot *GetAfterTriggersStoreSlot(AfterTriggersTableData *table,
37743774
TupleDesc tupdesc);
3775+
static Tuplestorestate *GetAfterTriggersTransitionTable(int event,
3776+
TupleTableSlot *oldslot,
3777+
TupleTableSlot *newslot,
3778+
TransitionCaptureState *transition_capture);
3779+
static void TransitionTableAddTuple(EState *estate,
3780+
TransitionCaptureState *transition_capture,
3781+
ResultRelInfo *relinfo,
3782+
TupleTableSlot *slot,
3783+
TupleTableSlot *original_insert_tuple,
3784+
Tuplestorestate *tuplestore);
37753785
static void AfterTriggerFreeQuery(AfterTriggersQueryData *qs);
37763786
static SetConstraintState SetConstraintStateCreate(int numalloc);
37773787
static SetConstraintState SetConstraintStateCopy(SetConstraintState state);
@@ -5158,6 +5168,92 @@ AfterTriggerEndSubXact(bool isCommit)
51585168
}
51595169
}
51605170

5171+
/*
5172+
* Get the transition table for the given event and depending on whether we are
5173+
* processing the old or the new tuple.
5174+
*/
5175+
static Tuplestorestate *
5176+
GetAfterTriggersTransitionTable(int event,
5177+
TupleTableSlot *oldslot,
5178+
TupleTableSlot *newslot,
5179+
TransitionCaptureState *transition_capture)
5180+
{
5181+
Tuplestorestate *tuplestore = NULL;
5182+
bool delete_old_table = transition_capture->tcs_delete_old_table;
5183+
bool update_old_table = transition_capture->tcs_update_old_table;
5184+
bool update_new_table = transition_capture->tcs_update_new_table;
5185+
bool insert_new_table = transition_capture->tcs_insert_new_table;
5186+
5187+
/*
5188+
* For INSERT events NEW should be non-NULL, for DELETE events OLD should
5189+
* be non-NULL, whereas for UPDATE events normally both OLD and NEW are
5190+
* non-NULL. But for UPDATE events fired for capturing transition tuples
5191+
* during UPDATE partition-key row movement, OLD is NULL when the event is
5192+
* for a row being inserted, whereas NEW is NULL when the event is for a
5193+
* row being deleted.
5194+
*/
5195+
Assert(!(event == TRIGGER_EVENT_DELETE && delete_old_table &&
5196+
TupIsNull(oldslot)));
5197+
Assert(!(event == TRIGGER_EVENT_INSERT && insert_new_table &&
5198+
TupIsNull(newslot)));
5199+
5200+
if (!TupIsNull(oldslot))
5201+
{
5202+
Assert(TupIsNull(newslot));
5203+
if (event == TRIGGER_EVENT_DELETE && delete_old_table)
5204+
tuplestore = transition_capture->tcs_private->old_tuplestore;
5205+
else if (event == TRIGGER_EVENT_UPDATE && update_old_table)
5206+
tuplestore = transition_capture->tcs_private->old_tuplestore;
5207+
}
5208+
else if (!TupIsNull(newslot))
5209+
{
5210+
Assert(TupIsNull(oldslot));
5211+
if (event == TRIGGER_EVENT_INSERT && insert_new_table)
5212+
tuplestore = transition_capture->tcs_private->new_tuplestore;
5213+
else if (event == TRIGGER_EVENT_UPDATE && update_new_table)
5214+
tuplestore = transition_capture->tcs_private->new_tuplestore;
5215+
}
5216+
5217+
return tuplestore;
5218+
}
5219+
5220+
/*
5221+
* Add the given heap tuple to the given tuplestore, applying the conversion
5222+
* map if necessary.
5223+
*
5224+
* If original_insert_tuple is given, we can add that tuple without conversion.
5225+
*/
5226+
static void
5227+
TransitionTableAddTuple(EState *estate,
5228+
TransitionCaptureState *transition_capture,
5229+
ResultRelInfo *relinfo,
5230+
TupleTableSlot *slot,
5231+
TupleTableSlot *original_insert_tuple,
5232+
Tuplestorestate *tuplestore)
5233+
{
5234+
TupleConversionMap *map;
5235+
5236+
/*
5237+
* Nothing needs to be done if we don't have a tuplestore.
5238+
*/
5239+
if (tuplestore == NULL)
5240+
return;
5241+
5242+
if (original_insert_tuple)
5243+
tuplestore_puttupleslot(tuplestore, original_insert_tuple);
5244+
else if ((map = ExecGetChildToRootMap(relinfo)) != NULL)
5245+
{
5246+
AfterTriggersTableData *table = transition_capture->tcs_private;
5247+
TupleTableSlot *storeslot;
5248+
5249+
storeslot = GetAfterTriggersStoreSlot(table, map->outdesc);
5250+
execute_attr_map_slot(map->attrMap, slot, storeslot);
5251+
tuplestore_puttupleslot(tuplestore, storeslot);
5252+
}
5253+
else
5254+
tuplestore_puttupleslot(tuplestore, slot);
5255+
}
5256+
51615257
/* ----------
51625258
* AfterTriggerEnlargeQueryState()
51635259
*
@@ -5650,7 +5746,6 @@ AfterTriggerPendingOnRel(Oid relid)
56505746
return false;
56515747
}
56525748

5653-
56545749
/* ----------
56555750
* AfterTriggerSaveEvent()
56565751
*
@@ -5709,68 +5804,39 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
57095804
*/
57105805
if (row_trigger && transition_capture != NULL)
57115806
{
5712-
TupleTableSlot *original_insert_tuple = transition_capture->tcs_original_insert_tuple;
5713-
TupleConversionMap *map = ExecGetChildToRootMap(relinfo);
5714-
bool delete_old_table = transition_capture->tcs_delete_old_table;
5715-
bool update_old_table = transition_capture->tcs_update_old_table;
5716-
bool update_new_table = transition_capture->tcs_update_new_table;
5717-
bool insert_new_table = transition_capture->tcs_insert_new_table;
57185807

57195808
/*
5720-
* For INSERT events NEW should be non-NULL, for DELETE events OLD
5721-
* should be non-NULL, whereas for UPDATE events normally both OLD and
5722-
* NEW are non-NULL. But for UPDATE events fired for capturing
5723-
* transition tuples during UPDATE partition-key row movement, OLD is
5724-
* NULL when the event is for a row being inserted, whereas NEW is
5725-
* NULL when the event is for a row being deleted.
5809+
* Capture the old tuple in the appropriate transition table based on
5810+
* the event.
57265811
*/
5727-
Assert(!(event == TRIGGER_EVENT_DELETE && delete_old_table &&
5728-
TupIsNull(oldslot)));
5729-
Assert(!(event == TRIGGER_EVENT_INSERT && insert_new_table &&
5730-
TupIsNull(newslot)));
5731-
5732-
if (!TupIsNull(oldslot) &&
5733-
((event == TRIGGER_EVENT_DELETE && delete_old_table) ||
5734-
(event == TRIGGER_EVENT_UPDATE && update_old_table)))
5812+
if (!TupIsNull(oldslot))
57355813
{
57365814
Tuplestorestate *old_tuplestore;
57375815

5738-
old_tuplestore = transition_capture->tcs_private->old_tuplestore;
5739-
5740-
if (map != NULL)
5741-
{
5742-
AfterTriggersTableData *table = transition_capture->tcs_private;
5743-
TupleTableSlot *storeslot;
5744-
5745-
storeslot = GetAfterTriggersStoreSlot(table, map->outdesc);
5746-
execute_attr_map_slot(map->attrMap, oldslot, storeslot);
5747-
tuplestore_puttupleslot(old_tuplestore, storeslot);
5748-
}
5749-
else
5750-
tuplestore_puttupleslot(old_tuplestore, oldslot);
5816+
old_tuplestore = GetAfterTriggersTransitionTable(event,
5817+
oldslot,
5818+
NULL,
5819+
transition_capture);
5820+
TransitionTableAddTuple(estate, transition_capture, relinfo,
5821+
oldslot, NULL, old_tuplestore);
57515822
}
5752-
if (!TupIsNull(newslot) &&
5753-
((event == TRIGGER_EVENT_INSERT && insert_new_table) ||
5754-
(event == TRIGGER_EVENT_UPDATE && update_new_table)))
5823+
5824+
/*
5825+
* Capture the new tuple in the appropriate transition table based on
5826+
* the event.
5827+
*/
5828+
if (!TupIsNull(newslot))
57555829
{
57565830
Tuplestorestate *new_tuplestore;
57575831

5758-
new_tuplestore = transition_capture->tcs_private->new_tuplestore;
5759-
5760-
if (original_insert_tuple != NULL)
5761-
tuplestore_puttupleslot(new_tuplestore,
5762-
original_insert_tuple);
5763-
else if (map != NULL)
5764-
{
5765-
AfterTriggersTableData *table = transition_capture->tcs_private;
5766-
TupleTableSlot *storeslot;
5767-
5768-
storeslot = GetAfterTriggersStoreSlot(table, map->outdesc);
5769-
execute_attr_map_slot(map->attrMap, newslot, storeslot);
5770-
tuplestore_puttupleslot(new_tuplestore, storeslot);
5771-
}
5772-
else
5773-
tuplestore_puttupleslot(new_tuplestore, newslot);
5832+
new_tuplestore = GetAfterTriggersTransitionTable(event,
5833+
NULL,
5834+
newslot,
5835+
transition_capture);
5836+
TransitionTableAddTuple(estate, transition_capture, relinfo,
5837+
newslot,
5838+
transition_capture->tcs_original_insert_tuple,
5839+
new_tuplestore);
57745840
}
57755841

57765842
/*

0 commit comments

Comments
 (0)