Re: insert rule doesn't see id field - Mailing list pgsql-sql
From | Ron Peterson |
---|---|
Subject | Re: insert rule doesn't see id field |
Date | |
Msg-id | 20030109215056.GA7798@mtholyoke.edu Whole thread Raw |
In response to | Re: insert rule doesn't see id field (dev@archonet.com) |
Responses |
Re: insert rule doesn't see id field
|
List | pgsql-sql |
On Thu, Jan 09, 2003 at 07:54:04PM -0000, dev@archonet.com wrote: > Sounds similar to the plpgsql example at: > > http://www.archonet.com/pgdocs/lock-field.html > > which silently discards changes. It's trivial (apart from quoting issues) > to write a trigger generator to customise the above in plpgsql (see the > Cookbook on techdocs.postgresql.org for examples) Ah - I wish I saw that earlier. Thanks for pointer. OTOH, I learned something... FWIW (probably just a good laugh): #include "executor/spi.h" /* this is what you need to work with SPI */ #include "commands/trigger.h" /* and triggers */ #include <ctype.h> /* tolower () */ #include <stdlib.h> extern Datum noupcols (PG_FUNCTION_ARGS); /* noupcols () -- revoke permission on column(s) e.g. CREATE FUNCTION noupcols () RETURNS opaque AS '/usr/lib/postgresql/lib/noupcols.so' LANGUAGE 'C'; CREATE TRIGGER person_noupcols BEFORE UPDATE ON person FOR EACH ROW EXECUTE PROCEDURE noupcols( 'name_last', 'id' ); Based on code from contrib/noup.c The approach adopted here is to set the values of all of the columns specified by noupcols to their old values. */ PG_FUNCTION_INFO_V1 (noupcols); Datum noupcols (PG_FUNCTION_ARGS) { TriggerData *trigdata = (TriggerData *) fcinfo->context; Trigger *trigger; /* to get trigger name */ Relation rel; /* triggered relation */ char **args; /* arguments: column names*/ int ncols; /* # of args specified in CREATE TRIGGER */ int *colindices; /*array of column indices to modify */ Datum *oldcolvals; /* old column values */ HeapTuple oldtuple =NULL; /* tuple before being modified */ HeapTuple newtuple = NULL; /* new tuple after user-specified update */ HeapTuple newnewtuple = NULL; /* tuple to return, after restoring newtuple's protected columns to their old values*/ TupleDesc tupdesc; /* tuple description */ bool isnull; /* to know is some columnNULL or not */ int ret; int i; if (!CALLED_AS_TRIGGER (fcinfo)) elog(ERROR, "noup: not fired by trigger manager"); if (TRIGGER_FIRED_FOR_STATEMENT (trigdata->tg_event)) elog (ERROR, "noup: can't process STATEMENT events"); if (TRIGGER_FIRED_BY_INSERT (trigdata->tg_event)) elog (ERROR, "noup: can't process INSERT events"); else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event)) elog (ERROR, "noup: can't process DELETE events"); oldtuple = trigdata->tg_trigtuple; newtuple = trigdata->tg_newtuple; trigger = trigdata->tg_trigger; rel = trigdata->tg_relation; tupdesc = rel->rd_att; ncols = trigger->tgnargs; args = trigger->tgargs; colindices = (int *) malloc (ncols * sizeof (int)); /* Connect to SPI manager */ if ((ret = SPI_connect()) < 0) elog (ERROR, "noupcol: SPI_connect returned %d", ret); /* Allocate space to place column values */ oldcolvals = (Datum*) palloc (ncols * sizeof (Datum)); /* For each column ... */ for (i = 0; i < ncols; i++) { /* get index of column in tuple */ colindices[i]= SPI_fnumber (tupdesc, args[i]); /* Bad guys may give us un-existing column in CREATE TRIGGER */ if (colindices < 0) { elog (ERROR,"noupcols: there is no attribute %s in relation %s", args[i], SPI_getrelname (rel)); pfree (oldcolvals); free (colindices); SPI_finish (); return PointerGetDatum(NULL); } /* Get previous value of column */ oldcolvals[i] = SPI_getbinval (oldtuple, tupdesc, colindices[i], &isnull); } /* Restore protected columns to their old values */ newnewtuple = SPI_modifytuple (rel, newtuple, ncols, colindices,oldcolvals, NULL); pfree (oldcolvals); free (colindices); SPI_finish (); if (SPI_result == SPI_ERROR_ARGUMENT) { elog (ERROR, "noupcols: bad argument to SPI_modifytuple\n"); returnPointerGetDatum (NULL); } if (SPI_result == SPI_ERROR_NOATTRIBUTE) { elog (ERROR, "noupcols: bad attribute value passed to SPI_modifytuple\n"); return PointerGetDatum (NULL); } return PointerGetDatum (newnewtuple); } -- Ron Peterson -o) Network & Systems Manager /\\ Mount Holyoke College _\_v http://www.mtholyoke.edu/~rpeterso ----