Home Explore Blog CI



postgresql

21th chunk of `doc/src/sgml/rules.sgml`
d2f76e93f48cdf01c15f4552c4dee3e2e6bfed7cb1cdccab0000000100000fb0
 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
    DO INSTEAD
    DELETE FROM shoelace_data
     WHERE sl_name = OLD.sl_name;
</programlisting>
   </para>

   <para>
    If you want to support <literal>RETURNING</literal> queries on the view,
    you need to make the rules include <literal>RETURNING</literal> clauses that
    compute the view rows.  This is usually pretty trivial for views on a
    single table, but it's a bit tedious for join views such as
    <literal>shoelace</literal>.  An example for the insert case is:

<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
    )
    RETURNING
           shoelace_data.*,
           (SELECT shoelace_data.sl_len * u.un_fact
            FROM unit u WHERE shoelace_data.sl_unit = u.un_name);
</programlisting>

    Note that this one rule supports both <command>INSERT</command> and
    <command>INSERT RETURNING</command> queries on the view &mdash; the
    <literal>RETURNING</literal> clause is simply ignored for <command>INSERT</command>.
   </para>

   <para>
    Note that in the <literal>RETURNING</literal> clause of a rule,
    <literal>OLD</literal> and <literal>NEW</literal> refer to the
    pseudorelations added as extra range table entries to the rewritten
    query, rather than old/new rows in the result relation.  Thus, for
    example, in a rule supporting <command>UPDATE</command> queries on this
    view, if the <literal>RETURNING</literal> clause contained
    <literal>old.sl_name</literal>, the old name would always be returned,
    regardless of whether the <literal>RETURNING</literal> clause in the
    query on the view specified <literal>OLD</literal> or <literal>NEW</literal>,
    which might be confusing.  To avoid this confusion, and support returning
    old and new values in queries on the view, the <literal>RETURNING</literal>
    clause in the rule definition should refer to entries from the result
    relation such as <literal>shoelace_data.sl_name</literal>, without
    specifying <literal>OLD</literal> or <literal>NEW</literal>.
   </para>

   <para>
    Now assume that once in a while, a pack of shoelaces arrives at
    the shop and a big parts list along with it.  But you don't want
    to manually update the <literal>shoelace</literal> view every
    time.  Instead we set up two little tables: one where you can
    insert the items from the part list, and one with a special
    trick. The creation commands for these are:

<programlisting>
CREATE TABLE shoelace_arrive (
    arr_name    text,
    arr_quant   integer
);

CREATE TABLE shoelace_ok (
    ok_name     text,
    ok_quant    integer
);

CREATE RULE shoelace_ok_ins AS ON INSERT TO shoelace_ok
    DO INSTEAD
    UPDATE shoelace
       SET sl_avail = sl_avail + NEW.ok_quant
     WHERE sl_name = NEW.ok_name;
</programlisting>

    Now you can fill the table <literal>shoelace_arrive</literal>

Title: Advanced Rule Systems for Views
Summary
This section discusses advanced techniques for using rule systems with views in PostgreSQL, including creating rules that rewrite query trees to operate on underlying tables, supporting RETURNING queries on views, and using rules to automate updates to views based on inserts into other tables, such as tracking inventory arrivals and updates.