Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres.h"
00017
00018 #include "catalog/pg_type.h"
00019 #include "executor/spi.h"
00020 #include "commands/trigger.h"
00021 #include "utils/rel.h"
00022 #include "utils/timestamp.h"
00023
00024 PG_MODULE_MAGIC;
00025
00026 extern Datum moddatetime(PG_FUNCTION_ARGS);
00027
00028 PG_FUNCTION_INFO_V1(moddatetime);
00029
00030 Datum
00031 moddatetime(PG_FUNCTION_ARGS)
00032 {
00033 TriggerData *trigdata = (TriggerData *) fcinfo->context;
00034 Trigger *trigger;
00035 int nargs;
00036 int attnum;
00037 Oid atttypid;
00038 Datum newdt;
00039 char **args;
00040 char *relname;
00041 Relation rel;
00042 HeapTuple rettuple = NULL;
00043 TupleDesc tupdesc;
00044
00045 if (!CALLED_AS_TRIGGER(fcinfo))
00046
00047 elog(ERROR, "moddatetime: not fired by trigger manager");
00048
00049 if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
00050
00051 elog(ERROR, "moddatetime: must be fired for row");
00052
00053 if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event))
00054
00055 elog(ERROR, "moddatetime: must be fired before event");
00056
00057 if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
00058
00059 elog(ERROR, "moddatetime: cannot process INSERT events");
00060 else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
00061 rettuple = trigdata->tg_newtuple;
00062 else
00063
00064 elog(ERROR, "moddatetime: cannot process DELETE events");
00065
00066 rel = trigdata->tg_relation;
00067 relname = SPI_getrelname(rel);
00068
00069 trigger = trigdata->tg_trigger;
00070
00071 nargs = trigger->tgnargs;
00072
00073 if (nargs != 1)
00074
00075 elog(ERROR, "moddatetime (%s): A single argument was expected", relname);
00076
00077 args = trigger->tgargs;
00078
00079 tupdesc = rel->rd_att;
00080
00081
00082
00083
00084
00085 attnum = SPI_fnumber(tupdesc, args[0]);
00086
00087
00088
00089
00090
00091 if (attnum < 0)
00092 ereport(ERROR,
00093 (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
00094 errmsg("\"%s\" has no attribute \"%s\"",
00095 relname, args[0])));
00096
00097
00098
00099
00100
00101 atttypid = SPI_gettypeid(tupdesc, attnum);
00102 if (atttypid == TIMESTAMPOID)
00103 newdt = DirectFunctionCall3(timestamp_in,
00104 CStringGetDatum("now"),
00105 ObjectIdGetDatum(InvalidOid),
00106 Int32GetDatum(-1));
00107 else if (atttypid == TIMESTAMPTZOID)
00108 newdt = DirectFunctionCall3(timestamptz_in,
00109 CStringGetDatum("now"),
00110 ObjectIdGetDatum(InvalidOid),
00111 Int32GetDatum(-1));
00112 else
00113 {
00114 ereport(ERROR,
00115 (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
00116 errmsg("attribute \"%s\" of \"%s\" must be type TIMESTAMP or TIMESTAMPTZ",
00117 args[0], relname)));
00118 newdt = (Datum) 0;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128 rettuple = SPI_modifytuple(rel, rettuple, 1, &attnum, &newdt, NULL);
00129
00130 if (rettuple == NULL)
00131
00132 elog(ERROR, "moddatetime (%s): %d returned by SPI_modifytuple",
00133 relname, SPI_result);
00134
00135
00136 pfree(relname);
00137
00138 return PointerGetDatum(rettuple);
00139 }