Home Explore Blog CI



postgresql

20th chunk of `doc/src/sgml/rules.sgml`
2d825a8d7269d843e6cc640fc9ea047ce926e58b5d69c25b0000000100000fa0
 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>, and <literal>sl4</literal>).
    But <literal>sl3</literal> already has <literal>sl_avail = 0</literal>.   In this case, the original
    query trees qualification is different and that results
    in the extra query tree:

<programlisting>
INSERT INTO shoelace_log
SELECT shoelace_data.sl_name, 0,
       current_user, current_timestamp
  FROM shoelace_data
 WHERE 0 &lt;&gt; shoelace_data.sl_avail
   AND <emphasis>shoelace_data.sl_color = 'black'</emphasis>;
</programlisting>

    being generated by the rule.  This query tree will surely insert
    three new log entries. And that's absolutely correct.
</para>

<para>
    Here we can see why it is important that the original query tree
    is executed last.  If the <command>UPDATE</command> had been
    executed first, all the rows would have already been set to zero, so the
    logging <command>INSERT</command> would not find any row where
    <literal>0 &lt;&gt; shoelace_data.sl_avail</literal>.
</para>
</sect3>

</sect2>

<sect2 id="rules-update-views">
<title>Cooperation with Views</title>

<indexterm zone="rules-update-views"><primary>view</primary><secondary>updating</secondary></indexterm>

<para>
    A simple way to protect view relations from the mentioned
    possibility that someone can try to run <command>INSERT</command>,
    <command>UPDATE</command>, or <command>DELETE</command> on them is
    to let those query trees get thrown away.  So we could create the rules:

<programlisting>
CREATE RULE shoe_ins_protect AS ON INSERT TO shoe
    DO INSTEAD NOTHING;
CREATE RULE shoe_upd_protect AS ON UPDATE TO shoe
    DO INSTEAD NOTHING;
CREATE RULE shoe_del_protect AS ON DELETE TO shoe
    DO INSTEAD NOTHING;
</programlisting>

    If someone now tries to do any of these operations on the view
    relation <literal>shoe</literal>, the rule system will
    apply these rules. Since the rules have
    no actions and are <literal>INSTEAD</literal>, the resulting list of
    query trees will be empty and the whole query will become
    nothing because there is nothing left to be optimized or
    executed after the rule system is done with it.
</para>

<para>
    A more sophisticated way to use the rule system is to
    create rules that rewrite the query tree into one that
    does the right operation on the real tables. To do that
    on the <literal>shoelace</literal> view, we create
    the following rules:

<programlisting>
CREATE RULE shoelace_ins AS ON INSERT TO shoelace
    DO INSTEAD
    INSERT INTO shoelace_data VALUES (
           NEW.sl_name,
           NEW.sl_avail,
           NEW.sl_color,
           NEW.sl_len,
           NEW.sl_unit
    );

CREATE RULE shoelace_upd AS ON UPDATE TO shoelace
    DO INSTEAD
    UPDATE shoelace_data
       SET sl_name = NEW.sl_name,
           sl_avail = NEW.sl_avail,
           sl_color = NEW.sl_color,
           sl_len = NEW.sl_len,
           sl_unit = NEW.sl_unit
     WHERE sl_name = OLD.sl_name;

CREATE RULE shoelace_del AS ON DELETE TO shoelace

Title: Rules and View Updates
Summary
This section discusses how to use rules to control updates to views in PostgreSQL. It shows how to create rules that prevent updates to views by replacing the original query tree with an empty list, effectively doing nothing. It also demonstrates how to create more complex rules that rewrite the query tree to update the underlying tables instead of the view, using the 'INSTEAD' keyword to replace the original query with a new one that operates on the real tables.