]> granicus.if.org Git - postgresql/blob - doc/src/sgml/trigger.sgml
Minor cleanup in markup, especially in the Output section.
[postgresql] / doc / src / sgml / trigger.sgml
1 <Chapter Id="triggers">
2 <Title>Triggers</Title>
3
4 <Para>
5    While the current version of <ProductName>Postgres</ProductName> has various client interfaces
6 such as Perl, Tcl, Python and C, it lacks an actual <FirstTerm>Procedural Language</FirstTerm>
7 (PL).  We hope to have a proper PL one day.  In the meantime it is possible
8 to call C functions as trigger actions.  Note that STATEMENT-level trigger
9 events are not supported in the current version.  You can currently specify
10 BEFORE or AFTER on INSERT, DELETE or UPDATE of a tuple as a trigger event.
11 </Para>
12
13 <Sect1>
14 <Title>Trigger Creation</Title>
15
16 <Para>
17    If a trigger event occurs, the trigger manager (called by the Executor)
18 initializes the global structure TriggerData *CurrentTriggerData (described
19 below) and calls the trigger function to handle the event.
20 </Para>
21
22 <Para>
23    The trigger function must be created before the trigger is created as a
24 function taking no arguments and returns opaque.
25 </Para>
26
27 <Para>
28    The syntax for creating triggers is as follows:
29
30 <ProgramListing>
31    CREATE TRIGGER &lt;trigger name&gt; &lt;BEFORE|AFTER&gt; &lt;INSERT|DELETE|UPDATE&gt;
32        ON &lt;relation name&gt; FOR EACH &lt;ROW|STATEMENT&gt;
33        EXECUTE PROCEDURE &lt;procedure name&gt; (&lt;function args&gt;);
34 </ProgramListing>
35 </Para>
36
37 <Para>
38    The name of the trigger is used if you ever have to delete the trigger.
39 It is used as an argument to the DROP TRIGGER command.
40 </Para>
41
42 <Para>
43    The next word determines whether the function is called before or after
44 the event.
45 </Para>
46
47 <Para>
48    The next element of the command determines on what event(s) will trigger
49 the function.  Multiple events can be specified separated by OR.
50 </Para>
51
52 <Para>
53    The relation name determines which table the event applies to.
54 </Para>
55
56 <Para>
57    The FOR EACH statement determines whether the trigger is fired for each
58 affected row or before (or after) the entire statement has completed.
59 </Para>
60
61 <Para>
62    The procedure name is the C function called.
63 </Para>
64
65 <Para>
66    The args are passed to the function in the CurrentTriggerData structure.
67 The purpose of passing arguments to the function is to allow different
68 triggers with similar requirements to call the same function.
69 </Para>
70
71 <Para>
72    Also, function may be used for triggering different relations (these
73 functions are named as "general trigger functions").
74 </Para>
75
76 <Para>
77    As example of using both features above, there could be a general
78 function that takes as its arguments two field names and puts the current
79 user in one and the current timestamp in the other. This allows triggers to
80 be written on INSERT events to automatically track creation of records in a
81 transaction table for example. It could also be used as a "last updated"
82 function if used in an UPDATE event.
83 </Para>
84
85 <Para>
86    Trigger functions return HeapTuple to the calling Executor.  This
87 is ignored for triggers fired after an INSERT, DELETE or UPDATE operation
88 but it allows BEFORE triggers to:
89
90    - return NULL to skip the operation for the current tuple (and so the
91      tuple will not be inserted/updated/deleted);
92    - return a pointer to another tuple (INSERT and UPDATE only) which will
93      be inserted (as the new version of the updated tuple if UPDATE) instead
94      of original tuple.
95 </Para>
96
97 <Para>
98    Note, that there is no initialization performed by the CREATE TRIGGER
99 handler.  This will be changed in the future.  Also, if more than one trigger
100 is defined for the same event on the same relation, the order of trigger
101 firing is unpredictable. This may be changed in the future.
102 </Para>
103
104 <Para>
105    If a trigger function executes SQL-queries (using SPI) then these queries
106 may fire triggers again. This is known as cascading triggers.  There is no
107 explicit limitation on the number of cascade levels.
108 </Para>
109
110 <Para>
111    If a trigger is fired by INSERT and inserts a new tuple in the same
112 relation then this trigger will be fired again.  Currently, there is nothing
113 provided for synchronization (etc) of these cases but this may change.  At
114 the moment, there is function funny_dup17() in the regress tests which uses
115 some techniques to stop recursion (cascading) on itself...
116 </Para>
117
118 </Sect1>
119
120 <Sect1>
121 <Title>Interaction with the Trigger Manager</Title>
122
123 <Para>
124    As mentioned above, when function is called by the trigger manager,
125 structure TriggerData *CurrentTriggerData is NOT NULL and initialized.  So
126 it is better to check CurrentTriggerData against being NULL at the start
127 and set it to NULL just after fetching the information to prevent calls to
128 a trigger function not from the trigger manager.
129 </Para>
130
131 <Para>
132    struct TriggerData is defined in src/include/commands/trigger.h:
133
134 <ProgramListing>
135 typedef struct TriggerData
136 {
137         TriggerEvent    tg_event;
138         Relation        tg_relation;
139         HeapTuple       tg_trigtuple;
140         HeapTuple       tg_newtuple;
141         Trigger         *tg_trigger;
142 } TriggerData;
143 </ProgramListing>
144
145 <ProgramListing>
146 tg_event 
147    describes event for which the function is called. You may use the
148    following macros to examine tg_event:
149
150    TRIGGER_FIRED_BEFORE(event) returns TRUE if trigger fired BEFORE;
151    TRIGGER_FIRED_AFTER(event) returns TRUE if trigger fired AFTER;
152    TRIGGER_FIRED_FOR_ROW(event) returns TRUE if trigger fired for
153                                 ROW-level event;
154    TRIGGER_FIRED_FOR_STATEMENT(event) returns TRUE if trigger fired for
155                                 STATEMENT-level event;
156    TRIGGER_FIRED_BY_INSERT(event) returns TRUE if trigger fired by INSERT;
157    TRIGGER_FIRED_BY_DELETE(event) returns TRUE if trigger fired by DELETE;
158    TRIGGER_FIRED_BY_UPDATE(event) returns TRUE if trigger fired by UPDATE.
159
160 tg_relation
161    is pointer to structure describing the triggered relation. Look at
162    src/include/utils/rel.h for details about this structure.  The most
163    interest things are tg_relation->rd_att (descriptor of the relation
164    tuples) and tg_relation->rd_rel->relname (relation's name. This is not
165    char*, but NameData.  Use SPI_getrelname(tg_relation) to get char* if
166    you need a copy of name).
167
168 tg_trigtuple
169    is a pointer to the tuple for which the trigger is fired. This is the tuple
170    being inserted (if INSERT), deleted (if DELETE) or updated (if UPDATE).
171    If INSERT/DELETE then this is what you are to return to Executor if 
172    you don't want to replace tuple with another one (INSERT) or skip the
173    operation.
174
175 tg_newtuple
176    is a pointer to the new version of tuple if UPDATE and NULL if this is
177    for an INSERT or a DELETE. This is what you are to return to Executor if
178    UPDATE and you don't want to replace this tuple with another one or skip
179    the operation.
180
181 tg_trigger
182    is pointer to structure Trigger defined in src/include/utils/rel.h:
183
184 typedef struct Trigger
185 {
186         char            *tgname;
187         Oid             tgfoid;
188         func_ptr        tgfunc;
189         int16           tgtype;
190         int16           tgnargs;
191         int16           tgattr[8];
192         char            **tgargs;
193 } Trigger;
194
195    tgname is the trigger's name, tgnargs is number of arguments in tgargs,
196    tgargs is an array of pointers to the arguments specified in the CREATE
197    TRIGGER statement. Other members are for internal use only.
198 </ProgramListing>
199 </Para>
200 </Sect1>
201
202 <Sect1>
203 <Title>Visibility of Data Changes</Title>
204
205 <Para>
206    <ProductName>Postgres</ProductName> data changes visibility rule: during a query execution, data
207 changes made by the query itself (via SQL-function, SPI-function, triggers)
208 are invisible to the query scan.  For example, in query
209
210 <ProgramListing>
211    INSERT INTO a SELECT * FROM a
212 </ProgramListing>
213
214    tuples inserted are invisible for SELECT' scan.  In effect, this
215 duplicates the database table within itself (subject to unique index
216 rules, of course) without recursing.
217 </Para>
218
219 <Para>
220    But keep in mind this notice about visibility in the SPI documentation:
221
222 <ProgramListing>
223    Changes made by query Q are visible by queries which are started after
224    query Q, no matter whether they are started inside Q (during the
225    execution of Q) or after Q is done.
226 </ProgramListing>
227 </Para>
228
229 <Para>
230    This is true for triggers as well so, though a tuple being inserted
231 (tg_trigtuple) is not visible to queries in a BEFORE trigger, this tuple
232 (just inserted) is visible to queries in an AFTER trigger, and to queries
233 in BEFORE/AFTER triggers fired after this!
234 </Para>
235 </Sect1>
236
237 <Sect1>
238 <Title>Examples</Title>
239
240 <Para>
241    There are more complex examples in in src/test/regress/regress.c and
242 in contrib/spi.
243 </Para>
244
245 <Para>
246    Here is a very simple example of trigger usage.  Function trigf reports
247 the number of tuples in the triggered relation ttest and skips the
248 operation if the query attempts to insert NULL into x (i.e - it acts as a
249 NOT NULL constraint but doesn't abort the transaction).
250
251 <ProgramListing>
252 #include "executor/spi.h"       /* this is what you need to work with SPI */
253 #include "commands/trigger.h"   /* -"- and triggers */
254
255 HeapTuple               trigf(void);
256
257 HeapTuple
258 trigf()
259 {
260         TupleDesc       tupdesc;
261         HeapTuple       rettuple;
262         char            *when;
263         bool            checknull = false;
264         bool            isnull;
265         int             ret, i;
266
267         if (!CurrentTriggerData)
268                 elog(WARN, "trigf: triggers are not initialized");
269         
270         /* tuple to return to Executor */
271         if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
272                 rettuple = CurrentTriggerData->tg_newtuple;
273         else
274                 rettuple = CurrentTriggerData->tg_trigtuple;
275         
276         /* check for NULLs ? */
277         if (!TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event) &&
278                 TRIGGER_FIRED_BEFORE(CurrentTriggerData->tg_event))
279                 checknull = true;
280         
281         if (TRIGGER_FIRED_BEFORE(CurrentTriggerData->tg_event))
282                 when = "before";
283         else
284                 when = "after ";
285         
286         tupdesc = CurrentTriggerData->tg_relation->rd_att;
287         CurrentTriggerData = NULL;
288         
289         /* Connect to SPI manager */
290         if ((ret = SPI_connect()) < 0)
291                 elog(WARN, "trigf (fired %s): SPI_connect returned %d", when, ret);
292         
293         /* Get number of tuples in relation */
294         ret = SPI_exec("select count(*) from ttest", 0);
295         
296         if (ret < 0)
297                 elog(WARN, "trigf (fired %s): SPI_exec returned %d", when, ret);
298         
299         i = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &amp;isnull);
300         
301         elog (NOTICE, "trigf (fired %s): there are %d tuples in ttest", when, i);
302         
303         SPI_finish();
304         
305         if (checknull)
306         {
307                 i = SPI_getbinval(rettuple, tupdesc, 1, &amp;isnull);
308                 if (isnull)
309                         rettuple = NULL;
310         }
311
312         return (rettuple);
313 }
314 </ProgramListing>
315 </Para>
316
317 <Para>
318    Now, compile and 
319 create table ttest (x int4);
320 create function trigf () returns opaque as 
321 '...path_to_so' language 'c';
322
323 <ProgramListing>
324 vac=> create trigger tbefore before insert or update or delete on ttest 
325 for each row execute procedure trigf();
326 CREATE
327 vac=> create trigger tafter after insert or update or delete on ttest 
328 for each row execute procedure trigf();
329 CREATE
330 vac=> insert into ttest values (null);
331 NOTICE:trigf (fired before): there are 0 tuples in ttest
332 INSERT 0 0
333
334 -- Insertion skipped and AFTER trigger is not fired
335
336 vac=> select * from ttest;
337 x
338 -
339 (0 rows)
340
341 vac=> insert into ttest values (1);
342 NOTICE:trigf (fired before): there are 0 tuples in ttest
343 NOTICE:trigf (fired after ): there are 1 tuples in ttest
344                                        ^^^^^^^^
345                              remember what we said about visibility.
346 INSERT 167793 1
347 vac=> select * from ttest;
348 x
349 -
350 1
351 (1 row)
352
353 vac=> insert into ttest select x * 2 from ttest;
354 NOTICE:trigf (fired before): there are 1 tuples in ttest
355 NOTICE:trigf (fired after ): there are 2 tuples in ttest
356                                        ^^^^^^^^
357                              remember what we said about visibility.
358 INSERT 167794 1
359 vac=> select * from ttest;
360 x
361 -
362 1
363 2
364 (2 rows)
365
366 vac=> update ttest set x = null where x = 2;
367 NOTICE:trigf (fired before): there are 2 tuples in ttest
368 UPDATE 0
369 vac=> update ttest set x = 4 where x = 2;
370 NOTICE:trigf (fired before): there are 2 tuples in ttest
371 NOTICE:trigf (fired after ): there are 2 tuples in ttest
372 UPDATE 1
373 vac=> select * from ttest;
374 x
375 -
376 1
377 4
378 (2 rows)
379
380 vac=> delete from ttest;
381 NOTICE:trigf (fired before): there are 2 tuples in ttest
382 NOTICE:trigf (fired after ): there are 1 tuples in ttest
383 NOTICE:trigf (fired before): there are 1 tuples in ttest
384 NOTICE:trigf (fired after ): there are 0 tuples in ttest
385                                        ^^^^^^^^
386                              remember what we said about visibility.
387 DELETE 2
388 vac=> select * from ttest;
389 x
390 -
391 (0 rows)
392 </ProgramListing>
393
394 </Para>
395 </Sect1>
396 </Chapter>