aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/trigger.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2021-03-30 20:01:27 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2021-03-30 20:01:31 -0400
commit65158f497a7d7523ad438b2034d01a560fafe6bd (patch)
treede4d0b2df57bf93cbd1d26be5a6533cc7fb79a89 /src/backend/commands/trigger.c
parent9ee7d533dacf8594057ced2d016250f09056c284 (diff)
downloadpostgresql-65158f497a7d7523ad438b2034d01a560fafe6bd.tar.gz
postgresql-65158f497a7d7523ad438b2034d01a560fafe6bd.zip
Remove small inefficiency in ExecARDeleteTriggers/ExecARUpdateTriggers.
Whilst poking at nodeModifyTable.c, I chanced to notice that while its calls to ExecBR*Triggers and ExecIR*Triggers are protected by tests to see if there are any relevant triggers to fire, its calls to ExecAR*Triggers are not; the latter functions do the equivalent tests themselves. This seems possibly reasonable given the more complex conditions involved, but what's less reasonable is that the ExecAR* functions aren't careful to do no work when there is no work to be done. ExecARInsertTriggers gets this right, but the other two will both force creation of a slot that the query may have no use for. ExecARUpdateTriggers additionally performed a usually-useless ExecClearTuple() on that slot. This is probably all pretty microscopic in real workloads, but a cycle shaved is a cycle earned.
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r--src/backend/commands/trigger.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 7383d5994eb..0ee318b3409 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -2546,11 +2546,12 @@ ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
TransitionCaptureState *transition_capture)
{
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
- TupleTableSlot *slot = ExecGetTriggerOldSlot(estate, relinfo);
if ((trigdesc && trigdesc->trig_delete_after_row) ||
(transition_capture && transition_capture->tcs_delete_old_table))
{
+ TupleTableSlot *slot = ExecGetTriggerOldSlot(estate, relinfo);
+
Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
if (fdw_trigtuple == NULL)
GetTupleForTrigger(estate,
@@ -2829,9 +2830,6 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
TransitionCaptureState *transition_capture)
{
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
- TupleTableSlot *oldslot = ExecGetTriggerOldSlot(estate, relinfo);
-
- ExecClearTuple(oldslot);
if ((trigdesc && trigdesc->trig_update_after_row) ||
(transition_capture &&
@@ -2844,6 +2842,8 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
* separately for DELETE and INSERT to capture transition table rows.
* In such case, either old tuple or new tuple can be NULL.
*/
+ TupleTableSlot *oldslot = ExecGetTriggerOldSlot(estate, relinfo);
+
if (fdw_trigtuple == NULL && ItemPointerIsValid(tupleid))
GetTupleForTrigger(estate,
NULL,
@@ -2854,6 +2854,8 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
NULL);
else if (fdw_trigtuple != NULL)
ExecForceStoreHeapTuple(fdw_trigtuple, oldslot, false);
+ else
+ ExecClearTuple(oldslot);
AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE,
true, oldslot, newslot, recheckIndexes,