1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>37.3. Writing Trigger Functions in C</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="prev" href="trigger-datachanges.html" title="37.2. Visibility of Data Changes" /><link rel="next" href="trigger-example.html" title="37.4. A Complete Trigger Example" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">37.3. Writing Trigger Functions in C</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="trigger-datachanges.html" title="37.2. Visibility of Data Changes">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="triggers.html" title="Chapter 37. Triggers">Up</a></td><th width="60%" align="center">Chapter 37. Triggers</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="trigger-example.html" title="37.4. A Complete Trigger Example">Next</a></td></tr></table><hr /></div><div class="sect1" id="TRIGGER-INTERFACE"><div class="titlepage"><div><div><h2 class="title" style="clear: both">37.3. Writing Trigger Functions in C <a href="#TRIGGER-INTERFACE" class="id_link">#</a></h2></div></div></div><a id="id-1.8.4.7.2" class="indexterm"></a><a id="id-1.8.4.7.3" class="indexterm"></a><p>
3 This section describes the low-level details of the interface to a
4 trigger function. This information is only needed when writing
5 trigger functions in C. If you are using a higher-level language then
6 these details are handled for you. In most cases you should consider
7 using a procedural language before writing your triggers in C. The
8 documentation of each procedural language explains how to write a
9 trigger in that language.
11 Trigger functions must use the <span class="quote">“<span class="quote">version 1</span>”</span> function manager
14 When a function is called by the trigger manager, it is not passed
15 any normal arguments, but it is passed a <span class="quote">“<span class="quote">context</span>”</span>
16 pointer pointing to a <code class="structname">TriggerData</code> structure. C
17 functions can check whether they were called from the trigger
18 manager or not by executing the macro:
19 </p><pre class="programlisting">
20 CALLED_AS_TRIGGER(fcinfo)
23 </p><pre class="programlisting">
24 ((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
26 If this returns true, then it is safe to cast
27 <code class="literal">fcinfo->context</code> to type <code class="literal">TriggerData
28 *</code> and make use of the pointed-to
29 <code class="structname">TriggerData</code> structure. The function must
30 <span class="emphasis"><em>not</em></span> alter the <code class="structname">TriggerData</code>
31 structure or any of the data it points to.
33 <code class="structname">struct TriggerData</code> is defined in
34 <code class="filename">commands/trigger.h</code>:
36 </p><pre class="programlisting">
37 typedef struct TriggerData
40 TriggerEvent tg_event;
42 HeapTuple tg_trigtuple;
43 HeapTuple tg_newtuple;
45 TupleTableSlot *tg_trigslot;
46 TupleTableSlot *tg_newslot;
47 Tuplestorestate *tg_oldtable;
48 Tuplestorestate *tg_newtable;
49 const Bitmapset *tg_updatedcols;
53 where the members are defined as follows:
55 </p><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="structfield">type</code></span></dt><dd><p>
56 Always <code class="literal">T_TriggerData</code>.
57 </p></dd><dt><span class="term"><code class="structfield">tg_event</code></span></dt><dd><p>
58 Describes the event for which the function is called. You can use the
59 following macros to examine <code class="literal">tg_event</code>:
61 </p><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="literal">TRIGGER_FIRED_BEFORE(tg_event)</code></span></dt><dd><p>
62 Returns true if the trigger fired before the operation.
63 </p></dd><dt><span class="term"><code class="literal">TRIGGER_FIRED_AFTER(tg_event)</code></span></dt><dd><p>
64 Returns true if the trigger fired after the operation.
65 </p></dd><dt><span class="term"><code class="literal">TRIGGER_FIRED_INSTEAD(tg_event)</code></span></dt><dd><p>
66 Returns true if the trigger fired instead of the operation.
67 </p></dd><dt><span class="term"><code class="literal">TRIGGER_FIRED_FOR_ROW(tg_event)</code></span></dt><dd><p>
68 Returns true if the trigger fired for a row-level event.
69 </p></dd><dt><span class="term"><code class="literal">TRIGGER_FIRED_FOR_STATEMENT(tg_event)</code></span></dt><dd><p>
70 Returns true if the trigger fired for a statement-level event.
71 </p></dd><dt><span class="term"><code class="literal">TRIGGER_FIRED_BY_INSERT(tg_event)</code></span></dt><dd><p>
72 Returns true if the trigger was fired by an <code class="command">INSERT</code> command.
73 </p></dd><dt><span class="term"><code class="literal">TRIGGER_FIRED_BY_UPDATE(tg_event)</code></span></dt><dd><p>
74 Returns true if the trigger was fired by an <code class="command">UPDATE</code> command.
75 </p></dd><dt><span class="term"><code class="literal">TRIGGER_FIRED_BY_DELETE(tg_event)</code></span></dt><dd><p>
76 Returns true if the trigger was fired by a <code class="command">DELETE</code> command.
77 </p></dd><dt><span class="term"><code class="literal">TRIGGER_FIRED_BY_TRUNCATE(tg_event)</code></span></dt><dd><p>
78 Returns true if the trigger was fired by a <code class="command">TRUNCATE</code> command.
79 </p></dd></dl></div><p>
80 </p></dd><dt><span class="term"><code class="structfield">tg_relation</code></span></dt><dd><p>
81 A pointer to a structure describing the relation that the trigger fired for.
82 Look at <code class="filename">utils/rel.h</code> for details about
83 this structure. The most interesting things are
84 <code class="literal">tg_relation->rd_att</code> (descriptor of the relation
85 tuples) and <code class="literal">tg_relation->rd_rel->relname</code>
86 (relation name; the type is not <code class="type">char*</code> but
87 <code class="type">NameData</code>; use
88 <code class="literal">SPI_getrelname(tg_relation)</code> to get a <code class="type">char*</code> if you
89 need a copy of the name).
90 </p></dd><dt><span class="term"><code class="structfield">tg_trigtuple</code></span></dt><dd><p>
91 A pointer to the row for which the trigger was fired. This is
92 the row being inserted, updated, or deleted. If this trigger
93 was fired for an <code class="command">INSERT</code> or
94 <code class="command">DELETE</code> then this is what you should return
95 from the function if you don't want to replace the row with
96 a different one (in the case of <code class="command">INSERT</code>) or
97 skip the operation. For triggers on foreign tables, values of system
98 columns herein are unspecified.
99 </p></dd><dt><span class="term"><code class="structfield">tg_newtuple</code></span></dt><dd><p>
100 A pointer to the new version of the row, if the trigger was
101 fired for an <code class="command">UPDATE</code>, and <code class="symbol">NULL</code> if
102 it is for an <code class="command">INSERT</code> or a
103 <code class="command">DELETE</code>. This is what you have to return
104 from the function if the event is an <code class="command">UPDATE</code>
105 and you don't want to replace this row by a different one or
106 skip the operation. For triggers on foreign tables, values of system
107 columns herein are unspecified.
108 </p></dd><dt><span class="term"><code class="structfield">tg_trigger</code></span></dt><dd><p>
109 A pointer to a structure of type <code class="structname">Trigger</code>,
110 defined in <code class="filename">utils/reltrigger.h</code>:
112 </p><pre class="programlisting">
113 typedef struct Trigger
137 where <code class="structfield">tgname</code> is the trigger's name,
138 <code class="structfield">tgnargs</code> is the number of arguments in
139 <code class="structfield">tgargs</code>, and <code class="structfield">tgargs</code> is an array of
140 pointers to the arguments specified in the <code class="command">CREATE
141 TRIGGER</code> statement. The other members are for internal use
143 </p></dd><dt><span class="term"><code class="structfield">tg_trigslot</code></span></dt><dd><p>
144 The slot containing <code class="structfield">tg_trigtuple</code>,
145 or a <code class="symbol">NULL</code> pointer if there is no such tuple.
146 </p></dd><dt><span class="term"><code class="structfield">tg_newslot</code></span></dt><dd><p>
147 The slot containing <code class="structfield">tg_newtuple</code>,
148 or a <code class="symbol">NULL</code> pointer if there is no such tuple.
149 </p></dd><dt><span class="term"><code class="structfield">tg_oldtable</code></span></dt><dd><p>
150 A pointer to a structure of type <code class="structname">Tuplestorestate</code>
151 containing zero or more rows in the format specified by
152 <code class="structfield">tg_relation</code>, or a <code class="symbol">NULL</code> pointer
153 if there is no <code class="literal">OLD TABLE</code> transition relation.
154 </p></dd><dt><span class="term"><code class="structfield">tg_newtable</code></span></dt><dd><p>
155 A pointer to a structure of type <code class="structname">Tuplestorestate</code>
156 containing zero or more rows in the format specified by
157 <code class="structfield">tg_relation</code>, or a <code class="symbol">NULL</code> pointer
158 if there is no <code class="literal">NEW TABLE</code> transition relation.
159 </p></dd><dt><span class="term"><code class="structfield">tg_updatedcols</code></span></dt><dd><p>
160 For <code class="literal">UPDATE</code> triggers, a bitmap set indicating the
161 columns that were updated by the triggering command. Generic trigger
162 functions can use this to optimize actions by not having to deal with
163 columns that were not changed.
165 As an example, to determine whether a column with attribute number
166 <code class="varname">attnum</code> (1-based) is a member of this bitmap set,
167 call <code class="literal">bms_is_member(attnum -
168 FirstLowInvalidHeapAttributeNumber,
169 trigdata->tg_updatedcols))</code>.
171 For triggers other than <code class="literal">UPDATE</code> triggers, this will
172 be <code class="symbol">NULL</code>.
173 </p></dd></dl></div><p>
175 To allow queries issued through SPI to reference transition tables, see
176 <a class="xref" href="spi-spi-register-trigger-data.html" title="SPI_register_trigger_data"><span class="refentrytitle">SPI_register_trigger_data</span></a>.
178 A trigger function must return either a
179 <code class="structname">HeapTuple</code> pointer or a <code class="symbol">NULL</code> pointer
180 (<span class="emphasis"><em>not</em></span> an SQL null value, that is, do not set <em class="parameter"><code>isNull</code></em> true).
181 Be careful to return either
182 <code class="structfield">tg_trigtuple</code> or <code class="structfield">tg_newtuple</code>,
183 as appropriate, if you don't want to modify the row being operated on.
184 </p></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="trigger-datachanges.html" title="37.2. Visibility of Data Changes">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="triggers.html" title="Chapter 37. Triggers">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="trigger-example.html" title="37.4. A Complete Trigger Example">Next</a></td></tr><tr><td width="40%" align="left" valign="top">37.2. Visibility of Data Changes </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="40%" align="right" valign="top"> 37.4. A Complete Trigger Example</td></tr></table></div></body></html>