LCOV - code coverage report
Current view: top level - src/backend/utils/adt - trigfuncs.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 20 24 83.3 %
Date: 2024-11-21 08:14:44 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * trigfuncs.c
       4             :  *    Builtin functions for useful trigger support.
       5             :  *
       6             :  *
       7             :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
       8             :  * Portions Copyright (c) 1994, Regents of the University of California
       9             :  *
      10             :  * src/backend/utils/adt/trigfuncs.c
      11             :  *
      12             :  *-------------------------------------------------------------------------
      13             :  */
      14             : #include "postgres.h"
      15             : 
      16             : #include "access/htup_details.h"
      17             : #include "commands/trigger.h"
      18             : #include "utils/fmgrprotos.h"
      19             : 
      20             : 
      21             : /*
      22             :  * suppress_redundant_updates_trigger
      23             :  *
      24             :  * This trigger function will inhibit an update from being done
      25             :  * if the OLD and NEW records are identical.
      26             :  */
      27             : Datum
      28          30 : suppress_redundant_updates_trigger(PG_FUNCTION_ARGS)
      29             : {
      30          30 :     TriggerData *trigdata = (TriggerData *) fcinfo->context;
      31             :     HeapTuple   newtuple,
      32             :                 oldtuple,
      33             :                 rettuple;
      34             :     HeapTupleHeader newheader,
      35             :                 oldheader;
      36             : 
      37             :     /* make sure it's called as a trigger */
      38          30 :     if (!CALLED_AS_TRIGGER(fcinfo))
      39           0 :         ereport(ERROR,
      40             :                 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
      41             :                  errmsg("suppress_redundant_updates_trigger: must be called as trigger")));
      42             : 
      43             :     /* and that it's called on update */
      44          30 :     if (!TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
      45           0 :         ereport(ERROR,
      46             :                 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
      47             :                  errmsg("suppress_redundant_updates_trigger: must be called on update")));
      48             : 
      49             :     /* and that it's called before update */
      50          30 :     if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event))
      51           0 :         ereport(ERROR,
      52             :                 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
      53             :                  errmsg("suppress_redundant_updates_trigger: must be called before update")));
      54             : 
      55             :     /* and that it's called for each row */
      56          30 :     if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
      57           0 :         ereport(ERROR,
      58             :                 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
      59             :                  errmsg("suppress_redundant_updates_trigger: must be called for each row")));
      60             : 
      61             :     /* get tuple data, set default result */
      62          30 :     rettuple = newtuple = trigdata->tg_newtuple;
      63          30 :     oldtuple = trigdata->tg_trigtuple;
      64             : 
      65          30 :     newheader = newtuple->t_data;
      66          30 :     oldheader = oldtuple->t_data;
      67             : 
      68             :     /* if the tuple payload is the same ... */
      69          30 :     if (newtuple->t_len == oldtuple->t_len &&
      70          24 :         newheader->t_hoff == oldheader->t_hoff &&
      71          24 :         (HeapTupleHeaderGetNatts(newheader) ==
      72          24 :          HeapTupleHeaderGetNatts(oldheader)) &&
      73          24 :         ((newheader->t_infomask & ~HEAP_XACT_MASK) ==
      74          24 :          (oldheader->t_infomask & ~HEAP_XACT_MASK)) &&
      75          24 :         memcmp(((char *) newheader) + SizeofHeapTupleHeader,
      76             :                ((char *) oldheader) + SizeofHeapTupleHeader,
      77          24 :                newtuple->t_len - SizeofHeapTupleHeader) == 0)
      78             :     {
      79             :         /* ... then suppress the update */
      80          12 :         rettuple = NULL;
      81             :     }
      82             : 
      83          30 :     return PointerGetDatum(rettuple);
      84             : }

Generated by: LCOV version 1.14