row has the same
effect as returning <literal>OK</literal>, that is the operation proceeds.
The trigger return value is ignored for all other types of triggers.
</para>
<tip>
<para>
The result list can be made from an array representation of the
modified tuple with the <literal>array get</literal> Tcl command.
</para>
</tip>
<para>
Here's a little example trigger function that forces an integer value
in a table to keep track of the number of updates that are performed on the
row. For new rows inserted, the value is initialized to 0 and then
incremented on every update operation.
<programlisting>
CREATE FUNCTION trigfunc_modcount() RETURNS trigger AS $$
switch $TG_op {
INSERT {
set NEW($1) 0
}
UPDATE {
set NEW($1) $OLD($1)
incr NEW($1)
}
default {
return OK
}
}
return [array get NEW]
$$ LANGUAGE pltcl;
CREATE TABLE mytab (num integer, description text, modcnt integer);
CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
FOR EACH ROW EXECUTE FUNCTION trigfunc_modcount('modcnt');
</programlisting>
Notice that the trigger function itself does not know the column
name; that's supplied from the trigger arguments. This lets the
trigger function be reused with different tables.
</para>
</sect1>
<sect1 id="pltcl-event-trigger">
<title>Event Trigger Functions in PL/Tcl</title>
<indexterm>
<primary>event trigger</primary>
<secondary>in PL/Tcl</secondary>
</indexterm>
<para>
Event trigger functions can be written in PL/Tcl.
<productname>PostgreSQL</productname> requires that a function that is
to be called as an event trigger must be declared as a function with no
arguments and a return type of <literal>event_trigger</literal>.
</para>
<para>
The information from the trigger manager is passed to the function body
in the following variables:
<variablelist>
<varlistentry>
<term><varname>$TG_event</varname></term>
<listitem>
<para>
The name of the event the trigger is fired for.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>$TG_tag</varname></term>
<listitem>
<para>
The command tag for which the trigger is fired.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
The return value of the trigger function is ignored.
</para>
<para>
Here's a little example event trigger function that simply raises
a <literal>NOTICE</literal> message each time a supported command is
executed:
<programlisting>
CREATE OR REPLACE FUNCTION tclsnitch() RETURNS event_trigger AS $$
elog NOTICE "tclsnitch: $TG_event $TG_tag"
$$ LANGUAGE pltcl;
CREATE EVENT TRIGGER tcl_a_snitch ON ddl_command_start EXECUTE FUNCTION tclsnitch();
</programlisting>
</para>
</sect1>
<sect1 id="pltcl-error-handling">
<title>Error Handling in PL/Tcl</title>
<indexterm>
<primary>exceptions</primary>
<secondary>in PL/Tcl</secondary>
</indexterm>
<para>
Tcl code within or called from a PL/Tcl function can raise an error,
either by executing some invalid operation or by generating an error
using the Tcl <function>error</function> command or
PL/Tcl's <function>elog</function> command. Such errors can be caught
within Tcl using the Tcl <function>catch</function> command. If an
error is not caught but is allowed to propagate out to the top level of
execution of the PL/Tcl function, it is reported as an SQL error in the
function's calling query.
</para>
<para>
Conversely, SQL errors that occur within PL/Tcl's
<function>spi_exec</function>, <function>spi_prepare</function>,
and <function>spi_execp</function>