~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to contrib/noupdate/noup.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
extern Datum noup(PG_FUNCTION_ARGS);
 
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
PG_FUNCTION_INFO_V1(noup);
 
20
 
 
21
Datum
 
22
noup(PG_FUNCTION_ARGS)
 
23
{
 
24
        TriggerData *trigdata = (TriggerData *) fcinfo->context;
 
25
        Trigger    *trigger;            /* to get trigger name */
 
26
        int                     nargs;                  /* # of args specified in CREATE TRIGGER */
 
27
        char      **args;                       /* arguments: column names and table name */
 
28
        int                     nkeys;                  /* # of key columns (= nargs / 2) */
 
29
        Datum      *kvals;                      /* key values */
 
30
        Relation        rel;                    /* triggered relation */
 
31
        HeapTuple       tuple = NULL;   /* tuple to return */
 
32
        TupleDesc       tupdesc;                /* tuple description */
 
33
        bool            isnull;                 /* to know is some column NULL or not */
 
34
        int                     ret;
 
35
        int                     i;
 
36
 
 
37
        /*
 
38
         * Some checks first...
 
39
         */
 
40
 
 
41
        /* Called by trigger manager ? */
 
42
        if (!CALLED_AS_TRIGGER(fcinfo))
 
43
                /* internal error */
 
44
                elog(ERROR, "noup: not fired by trigger manager");
 
45
 
 
46
        /* Should be called for ROW trigger */
 
47
        if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
 
48
                /* internal error */
 
49
                elog(ERROR, "noup: can't process STATEMENT events");
 
50
 
 
51
        /* Should not be called for INSERT */
 
52
        if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
 
53
                /* internal error */
 
54
                elog(ERROR, "noup: can't process INSERT events");
 
55
 
 
56
        /* Should not be called for DELETE */
 
57
        else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
 
58
                /* internal error */
 
59
                elog(ERROR, "noup: can't process DELETE events");
 
60
 
 
61
        /* check new Tuple */
 
62
        tuple = trigdata->tg_newtuple;
 
63
 
 
64
        trigger = trigdata->tg_trigger;
 
65
        nargs = trigger->tgnargs;
 
66
        args = trigger->tgargs;
 
67
 
 
68
        nkeys = nargs;
 
69
        rel = trigdata->tg_relation;
 
70
        tupdesc = rel->rd_att;
 
71
 
 
72
        /* Connect to SPI manager */
 
73
        if ((ret = SPI_connect()) < 0)
 
74
                /* internal error */
 
75
                elog(ERROR, "noup: SPI_connect returned %d", ret);
 
76
 
 
77
        /*
 
78
         * We use SPI plan preparation feature, so allocate space to place key
 
79
         * values.
 
80
         */
 
81
        kvals = (Datum *) palloc(nkeys * sizeof(Datum));
 
82
 
 
83
        /* For each column in key ... */
 
84
        for (i = 0; i < nkeys; i++)
 
85
        {
 
86
                /* get index of column in tuple */
 
87
                int                     fnumber = SPI_fnumber(tupdesc, args[i]);
 
88
 
 
89
                /* Bad guys may give us un-existing column in CREATE TRIGGER */
 
90
                if (fnumber < 0)
 
91
                        /* internal error */
 
92
                        elog(ERROR, "noup: there is no attribute %s in relation %s",
 
93
                                 args[i], SPI_getrelname(rel));
 
94
 
 
95
                /* Well, get binary (in internal format) value of column */
 
96
                kvals[i] = SPI_getbinval(tuple, tupdesc, fnumber, &isnull);
 
97
 
 
98
                /*
 
99
                 * If it's NOT NULL then cancel update
 
100
                 */
 
101
                if (!isnull)
 
102
                {
 
103
                        elog(WARNING, "%s: update not allowed", args[i]);
 
104
                        SPI_finish();
 
105
                        return PointerGetDatum(NULL);
 
106
                }
 
107
 
 
108
        }
 
109
 
 
110
        SPI_finish();
 
111
        return PointerGetDatum(tuple);
 
112
}