diff options
author | Vadim B. Mikheev | 1997-10-02 18:01:57 +0000 |
---|---|---|
committer | Vadim B. Mikheev | 1997-10-02 18:01:57 +0000 |
commit | d75206fdf59d1c0f49137e6b5dd65ea942da35ff (patch) | |
tree | ac13a5b7b6921bcc4ba5607904c60d6f95c96807 /contrib/spi/autoinc.c | |
parent | cd7c56eeeb83f6407d791186927667c4a415b204 (diff) |
General function for SERIAL/IDENTITY/AUTOINCREMENT feature.
Handle INSERT event in timetravel().
Diffstat (limited to 'contrib/spi/autoinc.c')
-rw-r--r-- | contrib/spi/autoinc.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/contrib/spi/autoinc.c b/contrib/spi/autoinc.c new file mode 100644 index 00000000000..2aceea60fa0 --- /dev/null +++ b/contrib/spi/autoinc.c @@ -0,0 +1,100 @@ + +#include "executor/spi.h" /* this is what you need to work with SPI */ +#include "commands/trigger.h" /* -"- and triggers */ + +HeapTuple autoinc(void); + +extern int4 nextval(struct varlena * seqin); + +HeapTuple +autoinc() +{ + Trigger *trigger; /* to get trigger name */ + int nargs; /* # of arguments */ + int *chattrs; /* attnums of attributes to change */ + int chnattrs = 0; /* # of above */ + Datum *newvals; /* vals of above */ + char **args; /* arguments */ + char *relname; /* triggered relation name */ + Relation rel; /* triggered relation */ + HeapTuple rettuple = NULL; + TupleDesc tupdesc; /* tuple description */ + bool isnull; + int i; + + if (!CurrentTriggerData) + elog(WARN, "autoinc: triggers are not initialized"); + if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event)) + elog(WARN, "autoinc: can't process STATEMENT events"); + if (TRIGGER_FIRED_AFTER(CurrentTriggerData->tg_event)) + elog(WARN, "autoinc: must be fired before event"); + + if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event)) + rettuple = CurrentTriggerData->tg_trigtuple; + else if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event)) + rettuple = CurrentTriggerData->tg_newtuple; + else + elog(WARN, "autoinc: can't process DELETE events"); + + rel = CurrentTriggerData->tg_relation; + relname = SPI_getrelname(rel); + + trigger = CurrentTriggerData->tg_trigger; + + nargs = trigger->tgnargs; + if (nargs <= 0 || nargs % 2 != 0) + elog(WARN, "autoinc (%s): even number gt 0 of arguments was expected", relname); + + args = trigger->tgargs; + tupdesc = rel->rd_att; + + CurrentTriggerData = NULL; + + chattrs = (int *) palloc (nargs/2 * sizeof (int)); + newvals = (Datum *) palloc (nargs/2 * sizeof (Datum)); + + for (i = 0; i < nargs; ) + { + struct varlena *seqname; + int attnum = SPI_fnumber (tupdesc, args[i]); + int32 val; + + if ( attnum < 0 ) + elog(WARN, "autoinc (%s): there is no attribute %s", relname, args[i]); + if (SPI_gettypeid (tupdesc, attnum) != INT4OID) + elog(WARN, "autoinc (%s): attribute %s must be of INT4 type", + relname, args[i]); + + val = DatumGetInt32 (SPI_getbinval (rettuple, tupdesc, attnum, &isnull)); + + if (!isnull && val != 0) + { + i += 2; + continue; + } + + i++; + chattrs[chnattrs] = attnum; + seqname = textin (args[i]); + newvals[chnattrs] = Int32GetDatum (nextval (seqname)); + if ( DatumGetInt32 (newvals[chnattrs]) == 0 ) + newvals[chnattrs] = Int32GetDatum (nextval (seqname)); + pfree (seqname); + chnattrs++; + i++; + } + + if (chnattrs > 0) + { + rettuple = SPI_modifytuple (rel, rettuple, chnattrs, chattrs, newvals, NULL); + if ( rettuple == NULL ) + elog (WARN, "autoinc (%s): %d returned by SPI_modifytuple", + relname, SPI_result); + } + + pfree (relname); + pfree (chattrs); + pfree (newvals); + + return (rettuple); +} |