mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Offer triggers on foreign tables.
This covers all the SQL-standard trigger types supported for regular tables; it does not cover constraint triggers. The approach for acquiring the old row mirrors that for view INSTEAD OF triggers. For AFTER ROW triggers, we spool the foreign tuples to a tuplestore. This changes the FDW API contract; when deciding which columns to populate in the slot returned from data modification callbacks, writable FDWs will need to check for AFTER ROW triggers in addition to checking for a RETURNING clause. In support of the feature addition, refactor the TriggerFlags bits and the assembly of old tuples in ModifyTable. Ronan Dunklau, reviewed by KaiGai Kohei; some additional hacking by me.
This commit is contained in:
@ -308,7 +308,8 @@ AddForeignUpdateTargets (Query *parsetree,
|
||||
extra values to be fetched. Each such entry must be marked
|
||||
<structfield>resjunk</> = <literal>true</>, and must have a distinct
|
||||
<structfield>resname</> that will identify it at execution time.
|
||||
Avoid using names matching <literal>ctid<replaceable>N</></literal> or
|
||||
Avoid using names matching <literal>ctid<replaceable>N</></literal>,
|
||||
<literal>wholerow</literal>, or
|
||||
<literal>wholerow<replaceable>N</></literal>, as the core system can
|
||||
generate junk columns of these names.
|
||||
</para>
|
||||
@ -447,11 +448,12 @@ ExecForeignInsert (EState *estate,
|
||||
|
||||
<para>
|
||||
The data in the returned slot is used only if the <command>INSERT</>
|
||||
query has a <literal>RETURNING</> clause. Hence, the FDW could choose
|
||||
to optimize away returning some or all columns depending on the contents
|
||||
of the <literal>RETURNING</> clause. However, some slot must be
|
||||
returned to indicate success, or the query's reported row count will be
|
||||
wrong.
|
||||
query has a <literal>RETURNING</> clause or the foreign table has
|
||||
an <literal>AFTER ROW</> trigger. Triggers require all columns, but the
|
||||
FDW could choose to optimize away returning some or all columns depending
|
||||
on the contents of the <literal>RETURNING</> clause. Regardless, some
|
||||
slot must be returned to indicate success, or the query's reported row
|
||||
count will be wrong.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -492,11 +494,12 @@ ExecForeignUpdate (EState *estate,
|
||||
|
||||
<para>
|
||||
The data in the returned slot is used only if the <command>UPDATE</>
|
||||
query has a <literal>RETURNING</> clause. Hence, the FDW could choose
|
||||
to optimize away returning some or all columns depending on the contents
|
||||
of the <literal>RETURNING</> clause. However, some slot must be
|
||||
returned to indicate success, or the query's reported row count will be
|
||||
wrong.
|
||||
query has a <literal>RETURNING</> clause or the foreign table has
|
||||
an <literal>AFTER ROW</> trigger. Triggers require all columns, but the
|
||||
FDW could choose to optimize away returning some or all columns depending
|
||||
on the contents of the <literal>RETURNING</> clause. Regardless, some
|
||||
slot must be returned to indicate success, or the query's reported row
|
||||
count will be wrong.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -535,11 +538,12 @@ ExecForeignDelete (EState *estate,
|
||||
|
||||
<para>
|
||||
The data in the returned slot is used only if the <command>DELETE</>
|
||||
query has a <literal>RETURNING</> clause. Hence, the FDW could choose
|
||||
to optimize away returning some or all columns depending on the contents
|
||||
of the <literal>RETURNING</> clause. However, some slot must be
|
||||
returned to indicate success, or the query's reported row count will be
|
||||
wrong.
|
||||
query has a <literal>RETURNING</> clause or the foreign table has
|
||||
an <literal>AFTER ROW</> trigger. Triggers require all columns, but the
|
||||
FDW could choose to optimize away returning some or all columns depending
|
||||
on the contents of the <literal>RETURNING</> clause. Regardless, some
|
||||
slot must be returned to indicate success, or the query's reported row
|
||||
count will be wrong.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -43,9 +43,10 @@ CREATE [ CONSTRAINT ] TRIGGER <replaceable class="PARAMETER">name</replaceable>
|
||||
|
||||
<para>
|
||||
<command>CREATE TRIGGER</command> creates a new trigger. The
|
||||
trigger will be associated with the specified table or view and will
|
||||
execute the specified function <replaceable
|
||||
class="parameter">function_name</replaceable> when certain events occur.
|
||||
trigger will be associated with the specified table, view, or foreign table
|
||||
and will execute the specified
|
||||
function <replaceable class="parameter">function_name</replaceable> when
|
||||
certain events occur.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -93,7 +94,7 @@ CREATE [ CONSTRAINT ] TRIGGER <replaceable class="PARAMETER">name</replaceable>
|
||||
|
||||
<para>
|
||||
The following table summarizes which types of triggers may be used on
|
||||
tables and views:
|
||||
tables, views, and foreign tables:
|
||||
</para>
|
||||
|
||||
<informaltable id="supported-trigger-types">
|
||||
@ -110,8 +111,8 @@ CREATE [ CONSTRAINT ] TRIGGER <replaceable class="PARAMETER">name</replaceable>
|
||||
<row>
|
||||
<entry align="center" morerows="1"><literal>BEFORE</></entry>
|
||||
<entry align="center"><command>INSERT</>/<command>UPDATE</>/<command>DELETE</></entry>
|
||||
<entry align="center">Tables</entry>
|
||||
<entry align="center">Tables and views</entry>
|
||||
<entry align="center">Tables and foreign tables</entry>
|
||||
<entry align="center">Tables, views, and foreign tables</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry align="center"><command>TRUNCATE</></entry>
|
||||
@ -121,8 +122,8 @@ CREATE [ CONSTRAINT ] TRIGGER <replaceable class="PARAMETER">name</replaceable>
|
||||
<row>
|
||||
<entry align="center" morerows="1"><literal>AFTER</></entry>
|
||||
<entry align="center"><command>INSERT</>/<command>UPDATE</>/<command>DELETE</></entry>
|
||||
<entry align="center">Tables</entry>
|
||||
<entry align="center">Tables and views</entry>
|
||||
<entry align="center">Tables and foreign tables</entry>
|
||||
<entry align="center">Tables, views, and foreign tables</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry align="center"><command>TRUNCATE</></entry>
|
||||
@ -164,13 +165,13 @@ CREATE [ CONSTRAINT ] TRIGGER <replaceable class="PARAMETER">name</replaceable>
|
||||
<firstterm>constraint trigger</>. This is the same as a regular trigger
|
||||
except that the timing of the trigger firing can be adjusted using
|
||||
<xref linkend="SQL-SET-CONSTRAINTS">.
|
||||
Constraint triggers must be <literal>AFTER ROW</> triggers. They can
|
||||
be fired either at the end of the statement causing the triggering event,
|
||||
or at the end of the containing transaction; in the latter case they are
|
||||
said to be <firstterm>deferred</>. A pending deferred-trigger firing can
|
||||
also be forced to happen immediately by using <command>SET CONSTRAINTS</>.
|
||||
Constraint triggers are expected to raise an exception when the constraints
|
||||
they implement are violated.
|
||||
Constraint triggers must be <literal>AFTER ROW</> triggers on tables. They
|
||||
can be fired either at the end of the statement causing the triggering
|
||||
event, or at the end of the containing transaction; in the latter case they
|
||||
are said to be <firstterm>deferred</>. A pending deferred-trigger firing
|
||||
can also be forced to happen immediately by using <command>SET
|
||||
CONSTRAINTS</>. Constraint triggers are expected to raise an exception
|
||||
when the constraints they implement are violated.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -244,8 +245,8 @@ UPDATE OF <replaceable>column_name1</replaceable> [, <replaceable>column_name2</
|
||||
<term><replaceable class="parameter">table_name</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The name (optionally schema-qualified) of the table or view the trigger
|
||||
is for.
|
||||
The name (optionally schema-qualified) of the table, view, or foreign
|
||||
table the trigger is for.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -481,6 +482,14 @@ CREATE TRIGGER view_insert
|
||||
<refsect1 id="SQL-CREATETRIGGER-compatibility">
|
||||
<title>Compatibility</title>
|
||||
|
||||
<!--
|
||||
It's not clear whether SQL/MED contemplates triggers on foreign tables.
|
||||
Its <drop basic column definition> General Rules do mention the possibility
|
||||
of a reference from a trigger column list. On the other hand, nothing
|
||||
overrides the fact that CREATE TRIGGER only targets base tables. For now,
|
||||
do not document the compatibility status of triggers on foreign tables.
|
||||
-->
|
||||
|
||||
<para>
|
||||
The <command>CREATE TRIGGER</command> statement in
|
||||
<productname>PostgreSQL</productname> implements a subset of the
|
||||
|
@ -33,20 +33,21 @@
|
||||
<para>
|
||||
A trigger is a specification that the database should automatically
|
||||
execute a particular function whenever a certain type of operation is
|
||||
performed. Triggers can be attached to both tables and views.
|
||||
performed. Triggers can be attached to tables, views, and foreign tables.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
On tables, 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,
|
||||
On tables and foreign tables, 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.
|
||||
<command>UPDATE</command> triggers can moreover be set to fire only if
|
||||
certain columns are mentioned in the <literal>SET</literal> clause of the
|
||||
<command>UPDATE</command> 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.
|
||||
appropriate time to handle the event. Foreign tables do not support the
|
||||
TRUNCATE statement at all.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -111,10 +112,10 @@
|
||||
triggers fire immediately before a particular row is operated on,
|
||||
while row-level <literal>AFTER</> triggers fire at the end of the
|
||||
statement (but before any statement-level <literal>AFTER</> triggers).
|
||||
These types of triggers may only be defined on tables. Row-level
|
||||
<literal>INSTEAD OF</> triggers may only be defined on views, and fire
|
||||
immediately as each row in the view is identified as needing to be
|
||||
operated on.
|
||||
These types of triggers may only be defined on tables and foreign tables.
|
||||
Row-level <literal>INSTEAD OF</> triggers may only be defined on views,
|
||||
and fire immediately as each row in the view is identified as needing to
|
||||
be operated on.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -548,7 +549,8 @@ typedef struct TriggerData
|
||||
<command>DELETE</command> then this is what you should return
|
||||
from the function if you don't want to replace the row with
|
||||
a different one (in the case of <command>INSERT</command>) or
|
||||
skip the operation.
|
||||
skip the operation. For triggers on foreign tables, values of system
|
||||
columns herein are unspecified.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -563,7 +565,8 @@ typedef struct TriggerData
|
||||
<command>DELETE</command>. This is what you have to return
|
||||
from the function if the event is an <command>UPDATE</command>
|
||||
and you don't want to replace this row by a different one or
|
||||
skip the operation.
|
||||
skip the operation. For triggers on foreign tables, values of system
|
||||
columns herein are unspecified.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
Reference in New Issue
Block a user