Skip to content

Commit fd262da

Browse files
committed
> Sure send it in, we can put it in contrib. > > > > > I wrote a
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 - rick@rpacorp.com Rick Poleshuck | Voice - (908) 653-1070 Fax - (908) 653-0265 | Mail - RPA Corporation | - 308 Elizabeth Avenue, Cranford, New Jersey 07016
1 parent 6e771e8 commit fd262da

File tree

3 files changed

+127
-0
lines changed

3 files changed

+127
-0
lines changed

contrib/noupdate/noup.c

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* noup.c -- functions to remove update permission from a column
3+
*/
4+
5+
#include "executor/spi.h" /* this is what you need to work with SPI */
6+
#include "commands/trigger.h" /* -"- and triggers */
7+
#include <ctype.h> /* tolower () */
8+
9+
HeapTuple noup(void);
10+
11+
/*
12+
* noup () -- revoke permission on column
13+
*
14+
* Though it's called without args You have to specify referenced
15+
* table/column while creating trigger:
16+
* EXECUTE PROCEDURE noup ('col').
17+
*/
18+
19+
HeapTuple /* have to return HeapTuple to Executor */
20+
noup()
21+
{
22+
Trigger *trigger; /* to get trigger name */
23+
int nargs; /* # of args specified in CREATE TRIGGER */
24+
char **args; /* arguments: column names and table name */
25+
int nkeys; /* # of key columns (= nargs / 2) */
26+
Datum *kvals; /* key values */
27+
Relation rel; /* triggered relation */
28+
HeapTuple tuple = NULL; /* tuple to return */
29+
TupleDesc tupdesc; /* tuple description */
30+
bool isnull; /* to know is some column NULL or not */
31+
int ret;
32+
int i;
33+
34+
/*
35+
* Some checks first...
36+
*/
37+
38+
/* Called by trigger manager ? */
39+
if (!CurrentTriggerData)
40+
elog(WARN, "noup: triggers are not initialized");
41+
42+
/* Should be called for ROW trigger */
43+
if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
44+
elog(WARN, "noup: can't process STATEMENT events");
45+
46+
/* Not should be called for INSERT */
47+
if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
48+
elog(WARN, "noup: can't process INSERT events");
49+
50+
/* Not should be called for DELETE */
51+
else if (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event))
52+
elog(WARN, "noup: can't process DELETE events");
53+
54+
/* check new Tuple */
55+
tuple = CurrentTriggerData->tg_newtuple;
56+
57+
trigger = CurrentTriggerData->tg_trigger;
58+
nargs = trigger->tgnargs;
59+
args = trigger->tgargs;
60+
61+
nkeys = nargs;
62+
rel = CurrentTriggerData->tg_relation;
63+
tupdesc = rel->rd_att;
64+
65+
/*
66+
* Setting CurrentTriggerData to NULL prevents direct calls to trigger
67+
* functions in queries. Normally, trigger functions have to be called
68+
* by trigger manager code only.
69+
*/
70+
CurrentTriggerData = NULL;
71+
72+
/* Connect to SPI manager */
73+
if ((ret = SPI_connect()) < 0)
74+
elog(WARN, "noup: SPI_connect returned %d", ret);
75+
76+
/*
77+
* We use SPI plan preparation feature, so allocate space to place key
78+
* values.
79+
*/
80+
kvals = (Datum *) palloc(nkeys * sizeof(Datum));
81+
82+
/* For each column in key ... */
83+
for (i = 0; i < nkeys; i++)
84+
{
85+
/* get index of column in tuple */
86+
int fnumber = SPI_fnumber(tupdesc, args[i]);
87+
88+
/* Bad guys may give us un-existing column in CREATE TRIGGER */
89+
if (fnumber < 0)
90+
elog(WARN, "noup: there is no attribute %s in relation %s",
91+
args[i], SPI_getrelname(rel));
92+
93+
/* Well, get binary (in internal format) value of column */
94+
kvals[i] = SPI_getbinval(tuple, tupdesc, fnumber, &isnull);
95+
96+
/*
97+
* If it's NOT NULL then cancel update
98+
*/
99+
if (!isnull)
100+
{
101+
102+
elog(WARN, "%s: update not allowed", args[i] );
103+
SPI_finish();
104+
return NULL;
105+
}
106+
107+
}
108+
109+
SPI_finish();
110+
return (tuple);
111+
}

contrib/noupdate/noup.example

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CREATE TABLE TEST ( COL1 INT, COL2 INT, COL3 INT );
2+
3+
CREATE TRIGGER BT BEFORE UPDATE ON TEST FOR EACH ROW
4+
EXECUTE PROCEDURE
5+
noup ('COL1');
6+
7+
-- Now Try
8+
INSERT INTO TEST VALUES (10,20,30);
9+
UPDATE TEST SET COL1 = 5;

contrib/noupdate/noup.source

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
DROP FUNCTION noup ();
2+
3+
CREATE FUNCTION noup ()
4+
RETURNS opaque
5+
AS '_OBJWD_/noup_DLSUFFIX_'
6+
LANGUAGE 'c'
7+
;

0 commit comments

Comments
 (0)