mirror of https://github.com/postgres/postgres
Handle INSERT event in timetravel().pull/50/head
parent
cd7c56eeeb
commit
d75206fdf5
@ -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); |
||||
} |
@ -0,0 +1,35 @@ |
||||
DROP SEQUENCE next_id; |
||||
DROP TABLE ids; |
||||
|
||||
CREATE SEQUENCE next_id START -2 MINVALUE -2; |
||||
|
||||
CREATE TABLE ids ( |
||||
id int4, |
||||
idesc text |
||||
); |
||||
|
||||
CREATE TRIGGER ids_nextid |
||||
BEFORE INSERT OR UPDATE ON ids |
||||
FOR EACH ROW |
||||
EXECUTE PROCEDURE autoinc (id, next_id); |
||||
|
||||
INSERT INTO ids VALUES (0, 'first (-2 ?)'); |
||||
INSERT INTO ids VALUES (null, 'second (-1 ?)'); |
||||
INSERT INTO ids(idesc) VALUES ('third (1 ?!)'); |
||||
|
||||
SELECT * FROM ids; |
||||
|
||||
UPDATE ids SET id = null, idesc = 'first: -2 --> 2' |
||||
WHERE idesc = 'first (-2 ?)'; |
||||
UPDATE ids SET id = 0, idesc = 'second: -1 --> 3' |
||||
WHERE id = -1; |
||||
UPDATE ids SET id = 4, idesc = 'third: 1 --> 4' |
||||
WHERE id = 1; |
||||
|
||||
SELECT * FROM ids; |
||||
|
||||
SELECT 'Wasn''t it 4 ?' as nextval, nextval ('next_id') as value; |
||||
|
||||
insert into ids (idesc) select textcat (idesc, '. Copy.') from ids; |
||||
|
||||
SELECT * FROM ids; |
@ -0,0 +1,6 @@ |
||||
DROP FUNCTION autoinc(); |
||||
|
||||
CREATE FUNCTION autoinc() |
||||
RETURNS opaque |
||||
AS '_OBJWD_/autoinc_DLSUFFIX_' |
||||
LANGUAGE 'c'; |
Loading…
Reference in new issue