Home Explore Blog CI



postgresql

17th chunk of `doc/src/sgml/rules.sgml`
621c952efae9dac45d6210de7aa54053e367c9f0dd27c1b50000000100000fa4
 given and <literal>INSTEAD</literal></term>
      <listitem>
       <para>
        the query tree from the rule action with the rule
        qualification and the original query tree's qualification; and
        the original query tree with the negated rule qualification
        added
       </para>
      </listitem>
     </varlistentry>
    </variablelist>

    Finally, if the rule is <literal>ALSO</literal>, the unchanged original query tree is
    added to the list. Since only qualified <literal>INSTEAD</literal> rules already add the
    original query tree, we end up with either one or two output query trees
    for a rule with one action.
</para>

<para>
    For <literal>ON INSERT</literal> rules, the original query (if not suppressed by <literal>INSTEAD</literal>)
    is done before any actions added by rules.  This allows the actions to
    see the inserted row(s).  But for <literal>ON UPDATE</literal> and <literal>ON
    DELETE</literal> rules, the original query is done after the actions added by rules.
    This ensures that the actions can see the to-be-updated or to-be-deleted
    rows; otherwise, the actions might do nothing because they find no rows
    matching their qualifications.
</para>

<para>
    The query trees generated from rule actions are thrown into the
    rewrite system again, and maybe more rules get applied resulting
    in additional or fewer query trees.
    So a rule's actions must have either a different
    command type or a different result relation than the rule itself is
    on, otherwise this recursive process will end up in an infinite loop.
    (Recursive expansion of a rule will be detected and reported as an
    error.)
</para>

<para>
    The query trees found in the actions of the
    <structname>pg_rewrite</structname> system catalog are only
    templates. Since they can reference the range-table entries for
    <literal>NEW</literal> and <literal>OLD</literal>, some substitutions have to be made before they can be
    used. For any reference to <literal>NEW</literal>, the target list of the original
    query is searched for a corresponding entry. If found, that
    entry's expression replaces the reference. Otherwise, <literal>NEW</literal> means the
    same as <literal>OLD</literal> (for an <command>UPDATE</command>) or is replaced by
    a null value (for an <command>INSERT</command>). Any reference to <literal>OLD</literal> is
    replaced by a reference to the range-table entry that is the
    result relation.
</para>

<para>
    After the system is done applying update rules, it applies view rules to the
    produced query tree(s).  Views cannot insert new update actions so
    there is no need to apply update rules to the output of view rewriting.
</para>

<sect3 id="rules-update-how-first">
<title>A First Rule Step by Step</title>

<para>
    Say we want to trace changes to the <literal>sl_avail</literal> column in the
    <literal>shoelace_data</literal> relation. So we set up a log table
    and a rule that conditionally writes a log entry when an
    <command>UPDATE</command> is performed on
    <literal>shoelace_data</literal>.

<programlisting>
CREATE TABLE shoelace_log (
    sl_name    text,          -- shoelace changed
    sl_avail   integer,       -- new available value
    log_who    text,          -- who did it
    log_when   timestamp      -- when
);

CREATE RULE log_shoelace AS ON UPDATE TO shoelace_data
    WHERE NEW.sl_avail &lt;&gt; OLD.sl_avail
    DO INSERT INTO shoelace_log VALUES (
                                    NEW.sl_name,
                                    NEW.sl_avail,
                                    current_user,
                                    current_timestamp
                                );
</programlisting>
</para>

<para>
    Now someone does:

<programlisting>
UPDATE shoelace_data SET sl_avail = 6 WHERE sl_name = 'sl7';
</programlisting>

    and we look at the log table:

<programlisting>
SELECT * FROM shoelace_log;

 sl_name

Title: How Update Rules Work
Summary
This section continues to explain the behavior of update rules in PostgreSQL, including how the original query tree is modified or suppressed, and how the rule system applies update rules to produce one or two output query trees. It also covers the order of operations for ON INSERT, UPDATE, and DELETE rules, and how the query trees generated from rule actions are rewritten and expanded. Additionally, it discusses how the pg_rewrite system catalog is used to store query trees and how they are substituted with range-table entries for NEW and OLD. The section also introduces an example of creating a log table and a rule to trace changes to a specific column in a relation.