Header And Logo

PostgreSQL
| The world's most advanced open source database.

insert_username.c

Go to the documentation of this file.
00001 /*
00002  * insert_username.c
00003  * $Modified: Thu Oct 16 08:13:42 1997 by brook $
00004  * contrib/spi/insert_username.c
00005  *
00006  * insert user name in response to a trigger
00007  * usage:  insert_username (column_name)
00008  */
00009 #include "postgres.h"
00010 
00011 #include "catalog/pg_type.h"
00012 #include "commands/trigger.h"
00013 #include "executor/spi.h"
00014 #include "miscadmin.h"
00015 #include "utils/builtins.h"
00016 #include "utils/rel.h"
00017 
00018 PG_MODULE_MAGIC;
00019 
00020 extern Datum insert_username(PG_FUNCTION_ARGS);
00021 
00022 PG_FUNCTION_INFO_V1(insert_username);
00023 
00024 Datum
00025 insert_username(PG_FUNCTION_ARGS)
00026 {
00027     TriggerData *trigdata = (TriggerData *) fcinfo->context;
00028     Trigger    *trigger;        /* to get trigger name */
00029     int         nargs;          /* # of arguments */
00030     Datum       newval;         /* new value of column */
00031     char      **args;           /* arguments */
00032     char       *relname;        /* triggered relation name */
00033     Relation    rel;            /* triggered relation */
00034     HeapTuple   rettuple = NULL;
00035     TupleDesc   tupdesc;        /* tuple description */
00036     int         attnum;
00037 
00038     /* sanity checks from autoinc.c */
00039     if (!CALLED_AS_TRIGGER(fcinfo))
00040         /* internal error */
00041         elog(ERROR, "insert_username: not fired by trigger manager");
00042     if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
00043         /* internal error */
00044         elog(ERROR, "insert_username: must be fired for row");
00045     if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event))
00046         /* internal error */
00047         elog(ERROR, "insert_username: must be fired before event");
00048 
00049     if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
00050         rettuple = trigdata->tg_trigtuple;
00051     else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
00052         rettuple = trigdata->tg_newtuple;
00053     else
00054         /* internal error */
00055         elog(ERROR, "insert_username: cannot process DELETE events");
00056 
00057     rel = trigdata->tg_relation;
00058     relname = SPI_getrelname(rel);
00059 
00060     trigger = trigdata->tg_trigger;
00061 
00062     nargs = trigger->tgnargs;
00063     if (nargs != 1)
00064         /* internal error */
00065         elog(ERROR, "insert_username (%s): one argument was expected", relname);
00066 
00067     args = trigger->tgargs;
00068     tupdesc = rel->rd_att;
00069 
00070     attnum = SPI_fnumber(tupdesc, args[0]);
00071 
00072     if (attnum < 0)
00073         ereport(ERROR,
00074                 (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
00075                  errmsg("\"%s\" has no attribute \"%s\"", relname, args[0])));
00076 
00077     if (SPI_gettypeid(tupdesc, attnum) != TEXTOID)
00078         ereport(ERROR,
00079                 (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
00080                  errmsg("attribute \"%s\" of \"%s\" must be type TEXT",
00081                         args[0], relname)));
00082 
00083     /* create fields containing name */
00084     newval = CStringGetTextDatum(GetUserNameFromId(GetUserId()));
00085 
00086     /* construct new tuple */
00087     rettuple = SPI_modifytuple(rel, rettuple, 1, &attnum, &newval, NULL);
00088     if (rettuple == NULL)
00089         /* internal error */
00090         elog(ERROR, "insert_username (\"%s\"): %d returned by SPI_modifytuple",
00091              relname, SPI_result);
00092 
00093     pfree(relname);
00094 
00095     return PointerGetDatum(rettuple);
00096 }