public inbox for [email protected]
help / color / mirror / Atom feedFrom: Alvaro Herrera <[email protected]>
Subject: [PATCH v14 1/3] Add API of sorts for transition table handling in trigger.c
Date: Wed, 2 Feb 2022 16:58:51 -0300
Preparatory patch for further additions in this area, particularly to
allow MERGE having separate transition tables for each action.
Author: Pavan Deolasee <[email protected]>
Reviewed-by: Álvaro Herrera <[email protected]>
Discussion: https://postgr.es/m/CABOikdNj+8HEJ5D8tu56mrPkjHVRrBb2_cdKWwpiYNcjXgDw8g@mail.gmail.com
Discussion: https://postgr.es/m/[email protected]
---
src/backend/commands/trigger.c | 170 +++++++++++++++++++++++----------
1 file changed, 118 insertions(+), 52 deletions(-)
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 1a9c1ac290..23af3f2269 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -94,6 +94,16 @@ static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
FmgrInfo *finfo,
Instrumentation *instr,
MemoryContext per_tuple_context);
+static Tuplestorestate *AfterTriggerGetTransitionTable(int event,
+ TupleTableSlot *oldslot,
+ TupleTableSlot *newslot,
+ TransitionCaptureState *transition_capture);
+static void TransitionTableAddTuple(EState *estate,
+ TransitionCaptureState *transition_capture,
+ ResultRelInfo *relinfo,
+ TupleTableSlot *slot,
+ TupleTableSlot *original_insert_tuple,
+ Tuplestorestate *tuplestore);
static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
int event, bool row_trigger,
TupleTableSlot *oldtup, TupleTableSlot *newtup,
@@ -5650,6 +5660,91 @@ 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,
+ TupleTableSlot *oldslot,
+ TupleTableSlot *newslot,
+ 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 NEW should be non-NULL, for DELETE events OLD
+ * should be non-NULL, whereas for UPDATE events normally both OLD and
+ * NEW are non-NULL. But for UPDATE events fired for capturing
+ * transition tuples during UPDATE partition-key row movement, OLD is
+ * NULL when the event is for a row being inserted, whereas NEW is
+ * NULL when the event is for a row being deleted.
+ */
+ Assert(!(event == TRIGGER_EVENT_DELETE && delete_old_table &&
+ TupIsNull(oldslot)));
+ Assert(!(event == TRIGGER_EVENT_INSERT && insert_new_table &&
+ TupIsNull(newslot)));
+
+ if (!TupIsNull(oldslot))
+ {
+ Assert(TupIsNull(newslot));
+ if (event == TRIGGER_EVENT_DELETE && delete_old_table)
+ tuplestore = transition_capture->tcs_private->old_tuplestore;
+ else if (event == TRIGGER_EVENT_UPDATE && update_old_table)
+ tuplestore = transition_capture->tcs_private->old_tuplestore;
+ }
+ else if (!TupIsNull(newslot))
+ {
+ Assert(TupIsNull(oldslot));
+ if (event == TRIGGER_EVENT_INSERT && insert_new_table)
+ tuplestore = transition_capture->tcs_private->new_tuplestore;
+ else if (event == TRIGGER_EVENT_UPDATE && update_new_table)
+ tuplestore = transition_capture->tcs_private->new_tuplestore;
+ }
+
+ return tuplestore;
+}
+
+/*
+ * Add the given heap tuple to the given tuplestore, applying the conversion
+ * map if necessary.
+ *
+ * If original_insert_tuple is given, we can add that tuple without conversion.
+ */
+static void
+TransitionTableAddTuple(EState *estate,
+ TransitionCaptureState *transition_capture,
+ ResultRelInfo *relinfo,
+ TupleTableSlot *slot,
+ TupleTableSlot *original_insert_tuple,
+ Tuplestorestate *tuplestore)
+{
+ TupleConversionMap *map;
+
+ /*
+ * Nothing needs to be done if we don't have a tuplestore.
+ */
+ if (tuplestore == NULL)
+ return;
+
+ if (original_insert_tuple)
+ tuplestore_puttupleslot(tuplestore, original_insert_tuple);
+ else if ((map = ExecGetChildToRootMap(relinfo)) != NULL)
+ {
+ AfterTriggersTableData *table = transition_capture->tcs_private;
+ TupleTableSlot *storeslot;
+
+ storeslot = GetAfterTriggersStoreSlot(table, map->outdesc);
+ execute_attr_map_slot(map->attrMap, slot, storeslot);
+ tuplestore_puttupleslot(tuplestore, storeslot);
+ }
+ else
+ tuplestore_puttupleslot(tuplestore, slot);
+}
/* ----------
* AfterTriggerSaveEvent()
@@ -5709,68 +5804,39 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
*/
if (row_trigger && transition_capture != NULL)
{
- TupleTableSlot *original_insert_tuple = transition_capture->tcs_original_insert_tuple;
- TupleConversionMap *map = ExecGetChildToRootMap(relinfo);
- 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 NEW should be non-NULL, for DELETE events OLD
- * should be non-NULL, whereas for UPDATE events normally both OLD and
- * NEW are non-NULL. But for UPDATE events fired for capturing
- * transition tuples during UPDATE partition-key row movement, OLD is
- * NULL when the event is for a row being inserted, whereas NEW is
- * NULL when the event is for a row being deleted.
+ * Capture the old tuple in the appropriate transition table based on
+ * the event.
*/
- Assert(!(event == TRIGGER_EVENT_DELETE && delete_old_table &&
- TupIsNull(oldslot)));
- Assert(!(event == TRIGGER_EVENT_INSERT && insert_new_table &&
- TupIsNull(newslot)));
-
- if (!TupIsNull(oldslot) &&
- ((event == TRIGGER_EVENT_DELETE && delete_old_table) ||
- (event == TRIGGER_EVENT_UPDATE && update_old_table)))
+ if (!TupIsNull(oldslot))
{
Tuplestorestate *old_tuplestore;
- old_tuplestore = transition_capture->tcs_private->old_tuplestore;
-
- if (map != NULL)
- {
- AfterTriggersTableData *table = transition_capture->tcs_private;
- TupleTableSlot *storeslot;
-
- storeslot = GetAfterTriggersStoreSlot(table, map->outdesc);
- execute_attr_map_slot(map->attrMap, oldslot, storeslot);
- tuplestore_puttupleslot(old_tuplestore, storeslot);
- }
- else
- tuplestore_puttupleslot(old_tuplestore, oldslot);
+ old_tuplestore = AfterTriggerGetTransitionTable(event,
+ oldslot,
+ NULL,
+ transition_capture);
+ TransitionTableAddTuple(estate, transition_capture, relinfo,
+ oldslot, NULL, old_tuplestore);
}
- if (!TupIsNull(newslot) &&
- ((event == TRIGGER_EVENT_INSERT && insert_new_table) ||
- (event == TRIGGER_EVENT_UPDATE && update_new_table)))
+
+ /*
+ * Capture the new tuple in the appropriate transition table based on
+ * the event.
+ */
+ if (!TupIsNull(newslot))
{
Tuplestorestate *new_tuplestore;
- new_tuplestore = transition_capture->tcs_private->new_tuplestore;
-
- if (original_insert_tuple != NULL)
- tuplestore_puttupleslot(new_tuplestore,
- original_insert_tuple);
- else if (map != NULL)
- {
- AfterTriggersTableData *table = transition_capture->tcs_private;
- TupleTableSlot *storeslot;
-
- storeslot = GetAfterTriggersStoreSlot(table, map->outdesc);
- execute_attr_map_slot(map->attrMap, newslot, storeslot);
- tuplestore_puttupleslot(new_tuplestore, storeslot);
- }
- else
- tuplestore_puttupleslot(new_tuplestore, newslot);
+ new_tuplestore = AfterTriggerGetTransitionTable(event,
+ NULL,
+ newslot,
+ transition_capture);
+ TransitionTableAddTuple(estate, transition_capture, relinfo,
+ newslot,
+ transition_capture->tcs_original_insert_tuple,
+ new_tuplestore);
}
/*
--
2.30.2
--tve4tfqa3b2wczcs
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v14-0002-Split-ExecUpdate-and-ExecDelete-in-reusable-piec.patch"
Content-Transfer-Encoding: 8bit
view thread (41+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH v14 1/3] Add API of sorts for transition table handling in trigger.c
In-Reply-To: <no-message-id-1860498@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox