moddatetime.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:3k
- /*
- moddatetime.c
- What is this?
- It is a function to be called from a trigger for the perpose of updating
- a modification datetime stamp in a record when that record is UPDATEd.
- Credits
- This is 95%+ based on autoinc.c, which I used as a starting point as I do
- not really know what I am doing. I also had help from
- Jan Wieck <jwieck@debis.com> who told me about the datetime_in("now") function.
- OH, me, I'm Terry Mackintosh <terry@terrym.com>
- */
- #include "executor/spi.h" /* this is what you need to work with SPI */
- #include "commands/trigger.h" /* -"- and triggers */
- HeapTuple moddatetime(void);
- HeapTuple
- moddatetime()
- {
- Trigger *trigger; /* to get trigger name */
- int nargs; /* # of arguments */
- int attnum; /* positional number of field to change */
- Datum newdt; /* The current datetime. */
- char **args; /* arguments */
- char *relname; /* triggered relation name */
- Relation rel; /* triggered relation */
- HeapTuple rettuple = NULL;
- TupleDesc tupdesc; /* tuple description */
- if (!CurrentTriggerData)
- elog(ERROR, "moddatetime: triggers are not initialized.");
- if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
- elog(ERROR, "moddatetime: can't process STATEMENT events.");
- if (TRIGGER_FIRED_AFTER(CurrentTriggerData->tg_event))
- elog(ERROR, "moddatetime: must be fired before event.");
- if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
- elog(ERROR, "moddatetime: must be fired before event.");
- else if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
- rettuple = CurrentTriggerData->tg_newtuple;
- else
- elog(ERROR, "moddatetime: can't process DELETE events.");
- rel = CurrentTriggerData->tg_relation;
- relname = SPI_getrelname(rel);
- trigger = CurrentTriggerData->tg_trigger;
- nargs = trigger->tgnargs;
- if (nargs != 1)
- elog(ERROR, "moddatetime (%s): A single argument was expected.", relname);
- args = trigger->tgargs;
- /* must be the field layout? */
- tupdesc = rel->rd_att;
- /* Why do this? */
- CurrentTriggerData = NULL;
- /* Get the current datetime. */
- newdt = datetime_in("now");
- /*
- * This gets the position in the turple of the field we want. args[0]
- * being the name of the field to update, as passed in from the
- * trigger.
- */
- attnum = SPI_fnumber(tupdesc, args[0]);
- /*
- * This is were we check to see if the feild we are suppost to update
- * even exits. The above function must return -1 if name not found?
- */
- if (attnum < 0)
- elog(ERROR, "moddatetime (%s): there is no attribute %s", relname,
- args[0]);
- /*
- * OK, this is where we make sure the datetime field that we are
- * modifying is really a datetime field. Hay, error checking, what a
- * novel idea !-)
- */
- if (SPI_gettypeid(tupdesc, attnum) != DATETIMEOID)
- elog(ERROR, "moddatetime (%s): attribute %s must be of DATETIME type",
- relname, args[0]);
- /* 1 is the number of items in the arrays attnum and newdt.
- attnum is the positional number of the field to be updated.
- newdt is the new datetime stamp.
- NOTE that attnum and newdt are not arrays, but then a 1 ellement array
- is not an array any more then they are. Thus, they can be considered a
- one element array.
- */
- rettuple = SPI_modifytuple(rel, rettuple, 1, &attnum, &newdt, NULL);
- if (rettuple == NULL)
- elog(ERROR, "moddatetime (%s): %d returned by SPI_modifytuple",
- relname, SPI_result);
- /* Clean up */
- pfree(relname);
- return (rettuple);
- }