LCOV - code coverage report
Current view: top level - contrib/spi - autoinc.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 76 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 3 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*
       2              :  * contrib/spi/autoinc.c
       3              :  */
       4              : #include "postgres.h"
       5              : 
       6              : #include "access/htup_details.h"
       7              : #include "catalog/pg_type.h"
       8              : #include "commands/sequence.h"
       9              : #include "commands/trigger.h"
      10              : #include "executor/spi.h"
      11              : #include "utils/builtins.h"
      12              : #include "utils/rel.h"
      13              : 
      14            0 : PG_MODULE_MAGIC_EXT(
      15              :                                         .name = "autoinc",
      16              :                                         .version = PG_VERSION
      17              : );
      18              : 
      19            0 : PG_FUNCTION_INFO_V1(autoinc);
      20              : 
      21              : Datum
      22            0 : autoinc(PG_FUNCTION_ARGS)
      23              : {
      24            0 :         TriggerData *trigdata = (TriggerData *) fcinfo->context;
      25            0 :         Trigger    *trigger;            /* to get trigger name */
      26            0 :         int                     nargs;                  /* # of arguments */
      27            0 :         int                *chattrs;            /* attnums of attributes to change */
      28            0 :         int                     chnattrs = 0;   /* # of above */
      29            0 :         Datum      *newvals;            /* vals of above */
      30            0 :         bool       *newnulls;           /* null flags for above */
      31            0 :         char      **args;                       /* arguments */
      32            0 :         char       *relname;            /* triggered relation name */
      33            0 :         Relation        rel;                    /* triggered relation */
      34            0 :         HeapTuple       rettuple = NULL;
      35            0 :         TupleDesc       tupdesc;                /* tuple description */
      36            0 :         bool            isnull;
      37            0 :         int                     i;
      38              : 
      39            0 :         if (!CALLED_AS_TRIGGER(fcinfo))
      40              :                 /* internal error */
      41            0 :                 elog(ERROR, "not fired by trigger manager");
      42            0 :         if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
      43              :                 /* internal error */
      44            0 :                 elog(ERROR, "must be fired for row");
      45            0 :         if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event))
      46              :                 /* internal error */
      47            0 :                 elog(ERROR, "must be fired before event");
      48              : 
      49            0 :         if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
      50            0 :                 rettuple = trigdata->tg_trigtuple;
      51            0 :         else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
      52            0 :                 rettuple = trigdata->tg_newtuple;
      53              :         else
      54              :                 /* internal error */
      55            0 :                 elog(ERROR, "cannot process DELETE events");
      56              : 
      57            0 :         rel = trigdata->tg_relation;
      58            0 :         relname = SPI_getrelname(rel);
      59              : 
      60            0 :         trigger = trigdata->tg_trigger;
      61              : 
      62            0 :         nargs = trigger->tgnargs;
      63            0 :         if (nargs <= 0 || nargs % 2 != 0)
      64              :                 /* internal error */
      65            0 :                 elog(ERROR, "autoinc (%s): even number gt 0 of arguments was expected", relname);
      66              : 
      67            0 :         args = trigger->tgargs;
      68            0 :         tupdesc = rel->rd_att;
      69              : 
      70            0 :         chattrs = (int *) palloc(nargs / 2 * sizeof(int));
      71            0 :         newvals = (Datum *) palloc(nargs / 2 * sizeof(Datum));
      72            0 :         newnulls = (bool *) palloc(nargs / 2 * sizeof(bool));
      73              : 
      74            0 :         for (i = 0; i < nargs;)
      75              :         {
      76            0 :                 int                     attnum = SPI_fnumber(tupdesc, args[i]);
      77            0 :                 int32           val;
      78            0 :                 Datum           seqname;
      79              : 
      80            0 :                 if (attnum <= 0)
      81            0 :                         ereport(ERROR,
      82              :                                         (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
      83              :                                          errmsg("\"%s\" has no attribute \"%s\"",
      84              :                                                         relname, args[i])));
      85              : 
      86            0 :                 if (SPI_gettypeid(tupdesc, attnum) != INT4OID)
      87            0 :                         ereport(ERROR,
      88              :                                         (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
      89              :                                          errmsg("attribute \"%s\" of \"%s\" must be type INT4",
      90              :                                                         args[i], relname)));
      91              : 
      92            0 :                 val = DatumGetInt32(SPI_getbinval(rettuple, tupdesc, attnum, &isnull));
      93              : 
      94            0 :                 if (!isnull && val != 0)
      95              :                 {
      96            0 :                         i += 2;
      97            0 :                         continue;
      98              :                 }
      99              : 
     100            0 :                 i++;
     101            0 :                 chattrs[chnattrs] = attnum;
     102            0 :                 seqname = CStringGetTextDatum(args[i]);
     103            0 :                 newvals[chnattrs] = DirectFunctionCall1(nextval, seqname);
     104              :                 /* nextval now returns int64; coerce down to int32 */
     105            0 :                 newvals[chnattrs] = Int32GetDatum((int32) DatumGetInt64(newvals[chnattrs]));
     106            0 :                 if (DatumGetInt32(newvals[chnattrs]) == 0)
     107              :                 {
     108            0 :                         newvals[chnattrs] = DirectFunctionCall1(nextval, seqname);
     109            0 :                         newvals[chnattrs] = Int32GetDatum((int32) DatumGetInt64(newvals[chnattrs]));
     110            0 :                 }
     111            0 :                 newnulls[chnattrs] = false;
     112            0 :                 pfree(DatumGetTextPP(seqname));
     113            0 :                 chnattrs++;
     114            0 :                 i++;
     115            0 :         }
     116              : 
     117            0 :         if (chnattrs > 0)
     118              :         {
     119            0 :                 rettuple = heap_modify_tuple_by_cols(rettuple, tupdesc,
     120            0 :                                                                                          chnattrs, chattrs,
     121            0 :                                                                                          newvals, newnulls);
     122            0 :         }
     123              : 
     124            0 :         pfree(relname);
     125            0 :         pfree(chattrs);
     126            0 :         pfree(newvals);
     127            0 :         pfree(newnulls);
     128              : 
     129            0 :         return PointerGetDatum(rettuple);
     130            0 : }
        

Generated by: LCOV version 2.3.2-1