LCOV - code coverage report
Current view: top level - src/backend/utils/adt - trigfuncs.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 20 24 83.3 %
Date: 2019-09-19 02:07:14 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-2019, 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/builtins.h"
      19             : #include "utils/rel.h"
      20             : 
      21             : 
      22             : /*
      23             :  * suppress_redundant_updates_trigger
      24             :  *
      25             :  * This trigger function will inhibit an update from being done
      26             :  * if the OLD and NEW records are identical.
      27             :  */
      28             : Datum
      29          20 : suppress_redundant_updates_trigger(PG_FUNCTION_ARGS)
      30             : {
      31          20 :     TriggerData *trigdata = (TriggerData *) fcinfo->context;
      32             :     HeapTuple   newtuple,
      33             :                 oldtuple,
      34             :                 rettuple;
      35             :     HeapTupleHeader newheader,
      36             :                 oldheader;
      37             : 
      38             :     /* make sure it's called as a trigger */
      39          20 :     if (!CALLED_AS_TRIGGER(fcinfo))
      40           0 :         ereport(ERROR,
      41             :                 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
      42             :                  errmsg("suppress_redundant_updates_trigger: must be called as trigger")));
      43             : 
      44             :     /* and that it's called on update */
      45          20 :     if (!TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
      46           0 :         ereport(ERROR,
      47             :                 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
      48             :                  errmsg("suppress_redundant_updates_trigger: must be called on update")));
      49             : 
      50             :     /* and that it's called before update */
      51          20 :     if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event))
      52           0 :         ereport(ERROR,
      53             :                 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
      54             :                  errmsg("suppress_redundant_updates_trigger: must be called before update")));
      55             : 
      56             :     /* and that it's called for each row */
      57          20 :     if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
      58           0 :         ereport(ERROR,
      59             :                 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
      60             :                  errmsg("suppress_redundant_updates_trigger: must be called for each row")));
      61             : 
      62             :     /* get tuple data, set default result */
      63          20 :     rettuple = newtuple = trigdata->tg_newtuple;
      64          20 :     oldtuple = trigdata->tg_trigtuple;
      65             : 
      66          20 :     newheader = newtuple->t_data;
      67          20 :     oldheader = oldtuple->t_data;
      68             : 
      69             :     /* if the tuple payload is the same ... */
      70          36 :     if (newtuple->t_len == oldtuple->t_len &&
      71          32 :         newheader->t_hoff == oldheader->t_hoff &&
      72          32 :         (HeapTupleHeaderGetNatts(newheader) ==
      73          32 :          HeapTupleHeaderGetNatts(oldheader)) &&
      74          32 :         ((newheader->t_infomask & ~HEAP_XACT_MASK) ==
      75          32 :          (oldheader->t_infomask & ~HEAP_XACT_MASK)) &&
      76          16 :         memcmp(((char *) newheader) + SizeofHeapTupleHeader,
      77             :                ((char *) oldheader) + SizeofHeapTupleHeader,
      78          16 :                newtuple->t_len - SizeofHeapTupleHeader) == 0)
      79             :     {
      80             :         /* ... then suppress the update */
      81           8 :         rettuple = NULL;
      82             :     }
      83             : 
      84          20 :     return PointerGetDatum(rettuple);
      85             : }

Generated by: LCOV version 1.13