1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-03 20:02:46 +03:00

Support statement-level ON TRUNCATE triggers. Simon Riggs

This commit is contained in:
Tom Lane
2008-03-28 00:21:56 +00:00
parent 107b3d0c23
commit 7692d8d5b7
23 changed files with 454 additions and 83 deletions

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/plperl.sgml,v 2.67 2008/01/25 15:28:35 adunstan Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/plperl.sgml,v 2.68 2008/03/28 00:21:55 tgl Exp $ -->
<chapter id="plperl">
<title>PL/Perl - Perl Procedural Language</title>
@ -17,12 +17,14 @@
<ulink url="http://www.perl.com">Perl programming language</ulink>.
</para>
<para> The usual advantage to using PL/Perl is that this allows use,
<para>
The main advantage to using PL/Perl is that this allows use,
within stored functions, of the manyfold <quote>string
munging</quote> operators and functions available for Perl. Parsing
munging</quote> operators and functions available for Perl. Parsing
complex strings might be easier using Perl than it is with the
string functions and control structures provided in PL/pgSQL.</para>
string functions and control structures provided in PL/pgSQL.
</para>
<para>
To install PL/Perl in a particular database, use
<literal>createlang plperl <replaceable>dbname</></literal>.
@ -739,7 +741,8 @@ $$ LANGUAGE plperl;
<term><literal>$_TD-&gt;{event}</literal></term>
<listitem>
<para>
Trigger event: <literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>, or <literal>UNKNOWN</>
Trigger event: <literal>INSERT</>, <literal>UPDATE</>,
<literal>DELETE</>, <literal>TRUNCATE</>, or <literal>UNKNOWN</>
</para>
</listitem>
</varlistentry>
@ -822,14 +825,14 @@ $$ LANGUAGE plperl;
</para>
<para>
Triggers can return one of the following:
Row-level triggers can return one of the following:
<variablelist>
<varlistentry>
<term><literal>return;</literal></term>
<listitem>
<para>
Execute the statement
Execute the operation
</para>
</listitem>
</varlistentry>
@ -838,7 +841,7 @@ $$ LANGUAGE plperl;
<term><literal>"SKIP"</literal></term>
<listitem>
<para>
Don't execute the statement
Don't execute the operation
</para>
</listitem>
</varlistentry>

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.124 2008/03/23 00:24:19 tgl Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.125 2008/03/28 00:21:55 tgl Exp $ -->
<chapter id="plpgsql">
<title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title>
@ -2785,9 +2785,9 @@ RAISE EXCEPTION 'Nonexistent ID --> %', user_id;
<listitem>
<para>
Data type <type>text</type>; a string of
<literal>INSERT</literal>, <literal>UPDATE</literal>, or
<literal>DELETE</literal> telling for which operation the
trigger was fired.
<literal>INSERT</literal>, <literal>UPDATE</literal>,
<literal>DELETE</literal>, or <literal>TRUNCATE</>
telling for which operation the trigger was fired.
</para>
</listitem>
</varlistentry>

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpython.sgml,v 1.38 2007/02/01 00:28:17 momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpython.sgml,v 1.39 2008/03/28 00:21:55 tgl Exp $ -->
<chapter id="plpython">
<title>PL/Python - Python Procedural Language</title>
@ -381,31 +381,34 @@ $$ LANGUAGE plpythonu;
<para>
When a function is used as a trigger, the dictionary
<literal>TD</literal> contains trigger-related values. The trigger
rows are in <literal>TD["new"]</> and/or <literal>TD["old"]</>
depending on the trigger event. <literal>TD["event"]</> contains
<literal>TD</literal> contains trigger-related values.
<literal>TD["event"]</> contains
the event as a string (<literal>INSERT</>, <literal>UPDATE</>,
<literal>DELETE</>, or <literal>UNKNOWN</>).
<literal>DELETE</>, <literal>TRUNCATE</>, or <literal>UNKNOWN</>).
<literal>TD["when"]</> contains one of <literal>BEFORE</>,
<literal>AFTER</>, and <literal>UNKNOWN</>.
<literal>AFTER</>, or <literal>UNKNOWN</>.
<literal>TD["level"]</> contains one of <literal>ROW</>,
<literal>STATEMENT</>, and <literal>UNKNOWN</>.
<literal>STATEMENT</>, or <literal>UNKNOWN</>.
For a row-level trigger, the trigger
rows are in <literal>TD["new"]</> and/or <literal>TD["old"]</>
depending on the trigger event.
<literal>TD["name"]</> contains the trigger name,
<literal>TD["table_name"]</> contains the name of the table on which the trigger occurred,
<literal>TD["table_schema"]</> contains the schema of the table on which the trigger occurred,
<literal>TD["name"]</> contains the trigger name, and
<literal>TD["relid"]</> contains the OID of the table on
and <literal>TD["relid"]</> contains the OID of the table on
which the trigger occurred. If the <command>CREATE TRIGGER</> command
included arguments, they are available in <literal>TD["args"][0]</> to
<literal>TD["args"][(<replaceable>n</>-1)]</>.
<literal>TD["args"][<replaceable>n</>-1]</>.
</para>
<para>
If <literal>TD["when"]</literal> is <literal>BEFORE</>, you can
If <literal>TD["when"]</literal> is <literal>BEFORE</> and
<literal>TD["level"]</literal> is <literal>ROW</>, you can
return <literal>None</literal> or <literal>"OK"</literal> from the
Python function to indicate the row is unmodified,
<literal>"SKIP"</> to abort the event, or <literal>"MODIFY"</> to
indicate you've modified the row.
Otherwise the return value is ignored.
</para>
</sect1>

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/pltcl.sgml,v 2.47 2007/12/03 23:49:50 tgl Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/pltcl.sgml,v 2.48 2008/03/28 00:21:55 tgl Exp $ -->
<chapter id="pltcl">
<title>PL/Tcl - Tcl Procedural Language</title>
@ -569,7 +569,7 @@ SELECT 'doesn''t' AS ret
<listitem>
<para>
The string <literal>BEFORE</> or <literal>AFTER</> depending on the
type of trigger call.
type of trigger event.
</para>
</listitem>
</varlistentry>
@ -579,7 +579,7 @@ SELECT 'doesn''t' AS ret
<listitem>
<para>
The string <literal>ROW</> or <literal>STATEMENT</> depending on the
type of trigger call.
type of trigger event.
</para>
</listitem>
</varlistentry>
@ -588,8 +588,9 @@ SELECT 'doesn''t' AS ret
<term><varname>$TG_op</varname></term>
<listitem>
<para>
The string <literal>INSERT</>, <literal>UPDATE</>, or
<literal>DELETE</> depending on the type of trigger call.
The string <literal>INSERT</>, <literal>UPDATE</>,
<literal>DELETE</>, or <literal>TRUNCATE</> depending on the type of
trigger event.
</para>
</listitem>
</varlistentry>
@ -602,6 +603,7 @@ SELECT 'doesn''t' AS ret
row for <command>INSERT</> or <command>UPDATE</> actions, or
empty for <command>DELETE</>. The array is indexed by column
name. Columns that are null will not appear in the array.
This is not set for statement-level triggers.
</para>
</listitem>
</varlistentry>
@ -614,6 +616,7 @@ SELECT 'doesn''t' AS ret
row for <command>UPDATE</> or <command>DELETE</> actions, or
empty for <command>INSERT</>. The array is indexed by column
name. Columns that are null will not appear in the array.
This is not set for statement-level triggers.
</para>
</listitem>
</varlistentry>
@ -644,6 +647,7 @@ SELECT 'doesn''t' AS ret
only.) Needless to say that all this is only meaningful when the trigger
is <literal>BEFORE</> and <command>FOR EACH ROW</>; otherwise the return value is ignored.
</para>
<para>
Here's a little example trigger procedure that forces an integer value
in a table to keep track of the number of updates that are performed on the

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_trigger.sgml,v 1.47 2007/02/01 19:10:24 momjian Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/create_trigger.sgml,v 1.48 2008/03/28 00:21:55 tgl Exp $
PostgreSQL documentation
-->
@ -25,7 +25,7 @@ CREATE TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFORE | AFTE
EXECUTE PROCEDURE <replaceable class="PARAMETER">funcname</replaceable> ( <replaceable class="PARAMETER">arguments</replaceable> )
</synopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
@ -65,6 +65,12 @@ CREATE TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFORE | AFTE
EACH STATEMENT</literal> triggers).
</para>
<para>
In addition, triggers may be defined to fire for a
<command>TRUNCATE</command>, though only
<literal>FOR EACH STATEMENT</literal>.
</para>
<para>
If multiple triggers of the same kind are defined for the same event,
they will be fired in alphabetical order by name.
@ -80,7 +86,7 @@ CREATE TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFORE | AFTE
Refer to <xref linkend="triggers"> for more information about triggers.
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
@ -110,10 +116,10 @@ CREATE TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFORE | AFTE
<term><replaceable class="parameter">event</replaceable></term>
<listitem>
<para>
One of <command>INSERT</command>, <command>UPDATE</command>, or
<command>DELETE</command>; this specifies the event that will
fire the trigger. Multiple events can be specified using
<literal>OR</literal>.
One of <command>INSERT</command>, <command>UPDATE</command>,
<command>DELETE</command>, or <command>TRUNCATE</command>;
this specifies the event that will fire the trigger. Multiple
events can be specified using <literal>OR</literal>.
</para>
</listitem>
</varlistentry>
@ -179,6 +185,11 @@ CREATE TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFORE | AFTE
<literal>TRIGGER</literal> privilege on the table.
</para>
<para>
Use <xref linkend="sql-droptrigger"
endterm="sql-droptrigger-title"> to remove a trigger.
</para>
<para>
In <productname>PostgreSQL</productname> versions before 7.3, it was
necessary to declare trigger functions as returning the placeholder
@ -187,11 +198,6 @@ CREATE TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFORE | AFTE
declared as returning <type>opaque</>, but it will issue a notice and
change the function's declared return type to <type>trigger</>.
</para>
<para>
Use <xref linkend="sql-droptrigger"
endterm="sql-droptrigger-title"> to remove a trigger.
</para>
</refsect1>
<refsect1 id="R1-SQL-CREATETRIGGER-2">
@ -204,7 +210,7 @@ CREATE TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFORE | AFTE
<refsect1 id="SQL-CREATETRIGGER-compatibility">
<title>Compatibility</title>
<para>
The <command>CREATE TRIGGER</command> statement in
<productname>PostgreSQL</productname> implements a subset of the
@ -267,6 +273,12 @@ CREATE TRIGGER <replaceable class="PARAMETER">name</replaceable> { BEFORE | AFTE
<literal>OR</literal> is a <productname>PostgreSQL</> extension of
the SQL standard.
</para>
<para>
The ability to fire triggers for <command>TRUNCATE</command> is a
<productname>PostgreSQL</> extension of the SQL standard.
</para>
</refsect1>
<refsect1>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/truncate.sgml,v 1.24 2007/05/11 19:40:08 neilc Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/truncate.sgml,v 1.25 2008/03/28 00:21:55 tgl Exp $
PostgreSQL documentation
-->
@ -36,7 +36,7 @@ TRUNCATE [ TABLE ] <replaceable class="PARAMETER">name</replaceable> [, ...] [ C
operation. This is most useful on large tables.
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
@ -91,8 +91,16 @@ TRUNCATE [ TABLE ] <replaceable class="PARAMETER">name</replaceable> [, ...] [ C
</para>
<para>
<command>TRUNCATE</> will not run any <literal>ON DELETE</literal>
triggers that might exist for the tables.
<command>TRUNCATE</> will not fire any <literal>ON DELETE</literal>
triggers that might exist for the tables. But it will fire
<literal>ON TRUNCATE</literal> triggers.
If <literal>ON TRUNCATE</> triggers are defined for any of
the tables, then all <literal>BEFORE TRUNCATE</literal> triggers are
fired before any truncation happens, and all <literal>AFTER
TRUNCATE</literal> triggers are fired after the last truncation is
performed. The triggers will fire in the order that the tables are
to be processed (first those listed in the command, and then any
that were added due to cascading).
</para>
<warning>

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/trigger.sgml,v 1.51 2007/12/03 23:49:51 tgl Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/trigger.sgml,v 1.52 2008/03/28 00:21:55 tgl Exp $ -->
<chapter id="triggers">
<title>Triggers</title>
@ -36,14 +36,15 @@
performed. Triggers can be defined to execute either before or after any
<command>INSERT</command>, <command>UPDATE</command>, or
<command>DELETE</command> operation, either once per modified row,
or once per <acronym>SQL</acronym> statement.
If a trigger event occurs, the trigger's function is called
at the appropriate time to handle the event.
or once per <acronym>SQL</acronym> statement. Triggers can also fire
for <command>TRUNCATE</command> statements. If a trigger event occurs,
the trigger's function is called at the appropriate time to handle the
event.
</para>
<para>
The trigger function must be defined before the trigger itself can be
created. The trigger function must be declared as a
created. The trigger function must be declared as a
function taking no arguments and returning type <literal>trigger</>.
(The trigger function receives its input through a specially-passed
<structname>TriggerData</> structure, not in the form of ordinary function
@ -69,7 +70,8 @@
in the execution of any applicable per-statement triggers. These
two types of triggers are sometimes called <firstterm>row-level</>
triggers and <firstterm>statement-level</> triggers,
respectively.
respectively. Triggers on <command>TRUNCATE</command> may only be
defined at statement-level.
</para>
<para>
@ -398,6 +400,15 @@ typedef struct TriggerData
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>TRIGGER_FIRED_BY_TRUNCATE(tg_event)</literal></term>
<listitem>
<para>
Returns true if the trigger was fired by a <command>TRUNCATE</command> command.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</listitem>
@ -630,10 +641,10 @@ CREATE FUNCTION trigf() RETURNS trigger
AS '<replaceable>filename</>'
LANGUAGE C;
CREATE TRIGGER tbefore BEFORE INSERT OR UPDATE OR DELETE ON ttest
CREATE TRIGGER tbefore BEFORE INSERT OR UPDATE OR DELETE ON ttest
FOR EACH ROW EXECUTE PROCEDURE trigf();
CREATE TRIGGER tafter AFTER INSERT OR UPDATE OR DELETE ON ttest
CREATE TRIGGER tafter AFTER INSERT OR UPDATE OR DELETE ON ttest
FOR EACH ROW EXECUTE PROCEDURE trigf();
</programlisting>
</para>