> Sure send it in, we can put it in contrib. > > > > > I wrote a
authorBruce Momjian
Tue, 16 Jun 1998 17:53:44 +0000 (17:53 +0000)
committerBruce Momjian
Tue, 16 Jun 1998 17:53:44 +0000 (17:53 +0000)
real small function to revoke update on a column. The function >
> doesn't do anything > > fancy like checking user ids.  > > > >
I copied most of it from the refint.c in the contrib directory.
> > > > Should I post this somewhere? It really isn't very big.
> >

Here it is...

--
| Email - [email protected]
Rick Poleshuck  | Voice - (908) 653-1070      Fax - (908) 653-0265
| Mail  - RPA Corporation |       - 308 Elizabeth
Avenue, Cranford, New Jersey  07016

contrib/noupdate/noup.c [new file with mode: 0644]
contrib/noupdate/noup.example [new file with mode: 0644]
contrib/noupdate/noup.source [new file with mode: 0644]

diff --git a/contrib/noupdate/noup.c b/contrib/noupdate/noup.c
new file mode 100644 (file)
index 0000000..efbe031
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * noup.c --   functions to remove update permission from a column
+ */
+
+#include "executor/spi.h"      /* this is what you need to work with SPI */
+#include "commands/trigger.h"  /* -"- and triggers */
+#include              /* tolower () */
+
+HeapTuple  noup(void);
+
+/*
+ * noup () -- revoke permission on column
+ *
+ * Though it's called without args You have to specify referenced
+ * table/column while creating trigger:  
+ * EXECUTE PROCEDURE noup ('col').
+ */
+
+HeapTuple                      /* have to return HeapTuple to Executor */
+noup()
+{
+   Trigger    *trigger;        /* to get trigger name */
+   int         nargs;          /* # of args specified in CREATE TRIGGER */
+   char      **args;           /* arguments: column names and table name */
+   int         nkeys;          /* # of key columns (= nargs / 2) */
+   Datum      *kvals;          /* key values */
+   Relation    rel;            /* triggered relation */
+   HeapTuple   tuple = NULL;   /* tuple to return */
+   TupleDesc   tupdesc;        /* tuple description */
+   bool        isnull;         /* to know is some column NULL or not */
+   int         ret;
+   int         i;
+
+   /*
+    * Some checks first...
+    */
+
+   /* Called by trigger manager ? */
+   if (!CurrentTriggerData)
+       elog(WARN, "noup: triggers are not initialized");
+
+   /* Should be called for ROW trigger */
+   if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
+       elog(WARN, "noup: can't process STATEMENT events");
+
+   /* Not should be called for INSERT */
+   if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
+       elog(WARN, "noup: can't process INSERT events");
+
+   /* Not should be called for DELETE */
+   else if (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event))
+       elog(WARN, "noup: can't process DELETE events");
+
+   /* check new Tuple */
+   tuple = CurrentTriggerData->tg_newtuple;
+
+   trigger = CurrentTriggerData->tg_trigger;
+   nargs = trigger->tgnargs;
+   args = trigger->tgargs;
+
+   nkeys = nargs;
+   rel = CurrentTriggerData->tg_relation;
+   tupdesc = rel->rd_att;
+
+   /*
+    * Setting CurrentTriggerData to NULL prevents direct calls to trigger
+    * functions in queries. Normally, trigger functions have to be called
+    * by trigger manager code only.
+    */
+   CurrentTriggerData = NULL;
+
+   /* Connect to SPI manager */
+   if ((ret = SPI_connect()) < 0)
+       elog(WARN, "noup: SPI_connect returned %d", ret);
+
+   /*
+    * We use SPI plan preparation feature, so allocate space to place key
+    * values.
+    */
+   kvals = (Datum *) palloc(nkeys * sizeof(Datum));
+
+   /* For each column in key ... */
+   for (i = 0; i < nkeys; i++)
+   {
+       /* get index of column in tuple */
+       int         fnumber = SPI_fnumber(tupdesc, args[i]);
+
+       /* Bad guys may give us un-existing column in CREATE TRIGGER */
+       if (fnumber < 0)
+           elog(WARN, "noup: there is no attribute %s in relation %s",
+                args[i], SPI_getrelname(rel));
+
+       /* Well, get binary (in internal format) value of column */
+       kvals[i] = SPI_getbinval(tuple, tupdesc, fnumber, &isnull);
+
+       /*
+        * If it's NOT NULL then cancel update
+        */
+       if (!isnull)
+       {
+   
+           elog(WARN, "%s: update not allowed", args[i] );
+           SPI_finish();
+           return NULL;
+       }
+
+   }
+
+   SPI_finish();
+   return (tuple);
+}
diff --git a/contrib/noupdate/noup.example b/contrib/noupdate/noup.example
new file mode 100644 (file)
index 0000000..62db1ee
--- /dev/null
@@ -0,0 +1,9 @@
+CREATE TABLE TEST ( COL1 INT, COL2 INT, COL3 INT );
+
+CREATE TRIGGER BT BEFORE UPDATE ON TEST FOR EACH ROW
+   EXECUTE PROCEDURE 
+   noup ('COL1');
+
+-- Now Try
+INSERT INTO TEST VALUES (10,20,30);
+UPDATE TEST SET COL1 = 5;
diff --git a/contrib/noupdate/noup.source b/contrib/noupdate/noup.source
new file mode 100644 (file)
index 0000000..0aa875d
--- /dev/null
@@ -0,0 +1,7 @@
+DROP FUNCTION noup ();
+
+CREATE FUNCTION noup ()
+   RETURNS opaque
+   AS '_OBJWD_/noup_DLSUFFIX_'
+   LANGUAGE 'c'
+;