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 <> 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