doc: clarify handling of ON CONFLICT with triggers
authorBruce Momjian <bruce@momjian.us>
Fri, 8 Dec 2023 02:35:29 +0000 (21:35 -0500)
committerBruce Momjian <bruce@momjian.us>
Fri, 8 Dec 2023 02:35:50 +0000 (21:35 -0500)
The previous wording was confusing.  Also move partitioning mention to a
more logical location.

Reported-by: neil@fairwindsoft.com
Discussion: https://postgr.es/m/20170703200710.27956.64565@wrigleys.postgresql.org

Backpatch-through: master

doc/src/sgml/trigger.sgml

index 6e1f370b213b3099939ce206d8f71633362a7ca3..a5390ff64430e6150fa2e2f325d56f20c9252057 100644 (file)
    </para>
 
    <para>
-    A statement that targets a parent table in an inheritance or partitioning
-    hierarchy does not cause the statement-level triggers of affected child
-    tables to be fired; only the parent table's statement-level triggers are
-    fired.  However, row-level triggers of any affected child tables will be
-    fired.
+    If an <command>INSERT</command> contains an <literal>ON CONFLICT
+    DO UPDATE</literal> clause, it is possible for row-level
+    <literal>BEFORE</literal> <command>INSERT</command> and then
+    <literal>BEFORE</literal> <command>UPDATE</command> triggers
+    to be executed on triggered rows.  Such interactions can be
+    complex if the triggers are not idempotent because change made by
+    <literal>BEFORE</literal> <command>INSERT</command> triggers will be
+    seen by <literal>BEFORE</literal> <command>UPDATE</command> triggers,
+    including changes to <varname>EXCLUDED</varname> columns.
    </para>
 
    <para>
-    If an <command>INSERT</command> contains an <literal>ON CONFLICT
-    DO UPDATE</literal> clause, it is possible that the effects of
-    row-level <literal>BEFORE</literal> <command>INSERT</command> triggers and
-    row-level <literal>BEFORE</literal> <command>UPDATE</command> triggers can
-    both be applied in a way that is apparent from the final state of
-    the updated row, if an <varname>EXCLUDED</varname> column is referenced.
-    There need not be an <varname>EXCLUDED</varname> column reference for
-    both sets of row-level <literal>BEFORE</literal> triggers to execute,
-    though.  The
-    possibility of surprising outcomes should be considered when there
-    are both <literal>BEFORE</literal> <command>INSERT</command> and
-    <literal>BEFORE</literal> <command>UPDATE</command> row-level triggers
-    that change a row being inserted/updated (this can be
-    problematic even if the modifications are more or less equivalent, if
-    they're not also idempotent).  Note that statement-level
+    Note that statement-level
     <command>UPDATE</command> triggers are executed when <literal>ON
     CONFLICT DO UPDATE</literal> is specified, regardless of whether or not
     any rows were affected by the <command>UPDATE</command> (and
     triggers.
    </para>
 
+   <para>
+    A statement that targets a parent table in an inheritance or partitioning
+    hierarchy does not cause the statement-level triggers of affected child
+    tables to be fired; only the parent table's statement-level triggers are
+    fired.  However, row-level triggers of any affected child tables will be
+    fired.
+   </para>
+
    <para>
     If an <command>UPDATE</command> on a partitioned table causes a row to move
     to another partition, it will be performed as a <command>DELETE</command>