Home Explore Blog CI



postgresql

19th chunk of `doc/src/sgml/rules.sgml`
97a9179d953dde1c9077f7b631938b1b741ad8018375aebf0000000100000faf
 changes:

<programlisting>
INSERT INTO shoelace_log VALUES (
       new.sl_name, new.sl_avail,
       current_user, current_timestamp )
  FROM shoelace_data new, shoelace_data old,
       shoelace_data shoelace_data
 <emphasis>WHERE new.sl_avail &lt;&gt; old.sl_avail</emphasis>;
</programlisting>

    (This looks even stranger, since <literal>INSERT ... VALUES</literal> doesn't have
    a <literal>WHERE</literal> clause either, but the planner and executor will have no
    difficulty with it.  They need to support this same functionality
    anyway for <literal>INSERT ... SELECT</literal>.)
   </para>

   <para>
    In step 3, the original query tree's qualification is added,
    restricting the result set further to only the rows that would have been touched
    by the original query:

<programlisting>
INSERT INTO shoelace_log VALUES (
       new.sl_name, new.sl_avail,
       current_user, current_timestamp )
  FROM shoelace_data new, shoelace_data old,
       shoelace_data shoelace_data
 WHERE new.sl_avail &lt;&gt; old.sl_avail
   <emphasis>AND shoelace_data.sl_name = 'sl7'</emphasis>;
</programlisting>
   </para>

   <para>
    Step 4 replaces references to <literal>NEW</literal> by the target list entries from the
    original query tree or by the matching variable references
    from the result relation:

<programlisting>
INSERT INTO shoelace_log VALUES (
       <emphasis>shoelace_data.sl_name</emphasis>, <emphasis>6</emphasis>,
       current_user, current_timestamp )
  FROM shoelace_data new, shoelace_data old,
       shoelace_data shoelace_data
 WHERE <emphasis>6</emphasis> &lt;&gt; old.sl_avail
   AND shoelace_data.sl_name = 'sl7';
</programlisting>

   </para>

   <para>
    Step 5 changes <literal>OLD</literal> references into result relation references:

<programlisting>
INSERT INTO shoelace_log VALUES (
       shoelace_data.sl_name, 6,
       current_user, current_timestamp )
  FROM shoelace_data new, shoelace_data old,
       shoelace_data shoelace_data
 WHERE 6 &lt;&gt; <emphasis>shoelace_data.sl_avail</emphasis>
   AND shoelace_data.sl_name = 'sl7';
</programlisting>
   </para>

   <para>
    That's it.  Since the rule is <literal>ALSO</literal>, we also output the
    original query tree.  In short, the output from the rule system
    is a list of two query trees that correspond to these statements:

<programlisting>
INSERT INTO shoelace_log VALUES (
       shoelace_data.sl_name, 6,
       current_user, current_timestamp )
  FROM shoelace_data
 WHERE 6 &lt;&gt; shoelace_data.sl_avail
   AND shoelace_data.sl_name = 'sl7';

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

    These are executed in this order, and that is exactly what
    the rule was meant to do.
   </para>

   <para>
    The substitutions and the added qualifications
    ensure that, if the original query would be, say:

<programlisting>
UPDATE shoelace_data SET sl_color = 'green'
 WHERE sl_name = 'sl7';
</programlisting>

    no log entry would get written.  In that case, the original query
    tree does not contain a target list entry for
    <literal>sl_avail</literal>, so <literal>NEW.sl_avail</literal> will get
    replaced by <literal>shoelace_data.sl_avail</literal>.  Thus, the extra
    command generated by the rule is:

<programlisting>
INSERT INTO shoelace_log VALUES (
       shoelace_data.sl_name, <emphasis>shoelace_data.sl_avail</emphasis>,
       current_user, current_timestamp )
  FROM shoelace_data
 WHERE <emphasis>shoelace_data.sl_avail</emphasis> &lt;&gt; shoelace_data.sl_avail
   AND shoelace_data.sl_name = 'sl7';
</programlisting>

    and that qualification will never be true.
   </para>

   <para>
    It will also work if the original query modifies multiple rows. So
    if someone issued the command:

<programlisting>
UPDATE shoelace_data SET sl_avail = 0
 WHERE sl_color = 'black';
</programlisting>

    four rows in fact get updated (<literal>sl1</literal>, <literal>sl2</literal>, <literal>sl3</literal>,

Title: Rule System Processing
Summary
This section describes the step-by-step processing of a rule system in PostgreSQL, specifically an update rule that logs changes to a column in a table. It demonstrates how the rule system modifies the original query tree to incorporate the rule's action and qualifications, resulting in a modified query tree that inserts log entries into a separate table. The example shows how the rule system handles various scenarios, including updates that do and do not modify the column being logged, as well as updates that modify multiple rows.