Doc: note that statement-level view triggers require an INSTEAD OF trigger.

If a view lacks an INSTEAD OF trigger, DML on it can only work by rewriting
the command into a command on the underlying base table(s).  Then we will
fire triggers attached to those table(s), not those for the view.  This
seems appropriate from a consistency standpoint, but nowhere was the
behavior explicitly documented, so let's do that.

There was some discussion of throwing an error or warning if a statement
trigger is created on a view without creating a row INSTEAD OF trigger.
But a simple implementation of that would result in dump/restore ordering
hazards.  Given that it's been like this all along, and we hadn't heard
a complaint till now, a documentation improvement seems sufficient.

Per bug #15106 from Pu Qun.  Back-patch to all supported branches.

Discussion: https://postgr.es/m/152083391168.1215.16892140713507052796@wrigleys.postgresql.org
This commit is contained in:
Tom Lane 2018-03-18 15:10:28 -04:00
parent 8d2814f274
commit a467832047
2 changed files with 22 additions and 3 deletions

View File

@ -499,6 +499,19 @@ UPDATE OF <replaceable>column_name1</replaceable> [, <replaceable>column_name2</
each affected row in a transition relation once and only once.
</para>
<para>
Statement-level triggers on a view are fired only if the action on the
view is handled by a row-level <literal>INSTEAD OF</literal> trigger.
If the action is handled by an <literal>INSTEAD</literal> rule, then
whatever statements are emitted by the rule are executed in place of the
original statement naming the view, so that the triggers that will be
fired are those on tables named in the replacement statements.
Similarly, if the view is automatically updatable, then the action is
handled by automatically rewriting the statement into an action on the
view's base table, so that the base table's statement-level triggers are
the ones that are fired.
</para>
<para>
Modifying a partitioned table or a table with inheritance children fires
statement-level triggers attached to the explicitly named table, but not

View File

@ -53,15 +53,21 @@
<para>
On views, triggers can be defined to execute instead of
<command>INSERT</command>, <command>UPDATE</command>, or
<command>DELETE</command> operations. <literal>INSTEAD OF</literal> triggers
<command>DELETE</command> operations.
Such <literal>INSTEAD OF</literal> triggers
are fired once for each row that needs to be modified in the view.
It is the responsibility of the
trigger's function to perform the necessary modifications to the
underlying base tables and, where appropriate, return the modified
trigger's function to perform the necessary modifications to the view's
underlying base table(s) and, where appropriate, return the modified
row as it will appear in the view. Triggers on views can also be defined
to execute once per <acronym>SQL</acronym> statement, before or after
<command>INSERT</command>, <command>UPDATE</command>, or
<command>DELETE</command> operations.
However, such triggers are fired only if there is also
an <literal>INSTEAD OF</literal> trigger on the view. Otherwise,
any statement targeting the view must be rewritten into a statement
affecting its underlying base table(s), and then the triggers
that will be fired are the ones attached to the base table(s).
</para>
<para>