the destination partition.
The possibility of surprising outcomes should be considered when all these
triggers affect the row being moved. As far as <literal>AFTER ROW</literal>
triggers are concerned, <literal>AFTER</literal> <command>DELETE</command>
and <literal>AFTER</literal> <command>INSERT</command> triggers are
applied; but <literal>AFTER</literal> <command>UPDATE</command> triggers
are not applied because the <command>UPDATE</command> has been converted to
a <command>DELETE</command> and an <command>INSERT</command>. As far as
statement-level triggers are concerned, none of the
<command>DELETE</command> or <command>INSERT</command> triggers are fired,
even if row movement occurs; only the <command>UPDATE</command> triggers
defined on the target table used in the <command>UPDATE</command> statement
will be fired.
</para>
<para>
No separate triggers are defined for <command>MERGE</command>. Instead,
statement-level or row-level <command>UPDATE</command>,
<command>DELETE</command>, and <command>INSERT</command> triggers are fired
depending on (for statement-level triggers) what actions are specified in
the <command>MERGE</command> query and (for row-level triggers) what
actions are performed.
</para>
<para>
While running a <command>MERGE</command> command, statement-level
<literal>BEFORE</literal> and <literal>AFTER</literal> triggers are
fired for events specified in the actions of the <command>MERGE</command>
command, irrespective of whether or not the action is ultimately performed.
This is the same as an <command>UPDATE</command> statement that updates
no rows, yet statement-level triggers are fired.
The row-level triggers are fired only when a row is actually updated,
inserted or deleted. So it's perfectly legal that while statement-level
triggers are fired for certain types of action, no row-level triggers
are fired for the same kind of action.
</para>
<para>
Trigger functions invoked by per-statement triggers should always
return <symbol>NULL</symbol>. Trigger functions invoked by per-row
triggers can return a table row (a value of
type <structname>HeapTuple</structname>) to the calling executor,
if they choose. A row-level trigger fired before an operation has
the following choices:
<itemizedlist>
<listitem>
<para>
It can return <symbol>NULL</symbol> to skip the operation for the
current row. This instructs the executor to not perform the
row-level operation that invoked the trigger (the insertion,
modification, or deletion of a particular table row).
</para>
</listitem>
<listitem>
<para>
For row-level <command>INSERT</command>
and <command>UPDATE</command> triggers only, the returned row
becomes the row that will be inserted or will replace the row
being updated. This allows the trigger function to modify the
row being inserted or updated.
</para>
</listitem>
</itemizedlist>
A row-level <literal>BEFORE</literal> trigger that does not intend to cause
either of these behaviors must be careful to return as its result the same
row that was passed in (that is, the <varname>NEW</varname> row
for <command>INSERT</command> and <command>UPDATE</command>
triggers, the <varname>OLD</varname> row for
<command>DELETE</command> triggers).
</para>
<para>
A row-level <literal>INSTEAD OF</literal> trigger should either return
<symbol>NULL</symbol> to indicate that it did not modify any data from
the view's underlying base tables, or it should return the view
row that was passed in (the <varname>NEW</varname> row
for <command>INSERT</command> and <command>UPDATE</command>
operations, or the <varname>OLD</varname> row for
<command>DELETE</command> operations). A nonnull return value is
used to signal