Home Explore Blog CI



postgresql

7th chunk of `doc/src/sgml/rules.sgml`
344f7cfe6c03d2aa3034417cf8b22e0774fdeb08973ed7130000000100000fa3
 | black    |    100 | cm      |       100
 sl7       |        7 | brown    |     60 | cm      |        60
 sl3       |        0 | black    |     35 | inch    |      88.9
 sl4       |        8 | black    |     40 | inch    |     101.6
 sl8       |        1 | brown    |     40 | inch    |     101.6
 sl5       |        4 | brown    |      1 | m       |       100
 sl6       |        0 | brown    |    0.9 | m       |        90
(8 rows)
</programlisting>
   </para>

   <para>
    This is the simplest <command>SELECT</command> you can do on our
    views, so we take this opportunity to explain the basics of view
    rules.  The <literal>SELECT * FROM shoelace</literal> was
    interpreted by the parser and produced the query tree:

<programlisting>
SELECT shoelace.sl_name, shoelace.sl_avail,
       shoelace.sl_color, shoelace.sl_len,
       shoelace.sl_unit, shoelace.sl_len_cm
  FROM shoelace shoelace;
</programlisting>

    and this is given to the rule system. The rule system walks through the
    range table and checks if there are rules
    for any relation. When processing the range table entry for
    <literal>shoelace</literal> (the only one up to now) it finds the
    <literal>_RETURN</literal> rule with the query tree:

<programlisting>
SELECT s.sl_name, s.sl_avail,
       s.sl_color, s.sl_len, s.sl_unit,
       s.sl_len * u.un_fact AS sl_len_cm
  FROM shoelace old, shoelace new,
       shoelace_data s, unit u
 WHERE s.sl_unit = u.un_name;
</programlisting>
</para>

<para>
    To expand the view, the rewriter simply creates a subquery range-table
    entry containing the rule's action query tree, and substitutes this
    range table entry for the original one that referenced the view.  The
    resulting rewritten query tree is almost the same as if you had typed:

<programlisting>
SELECT shoelace.sl_name, shoelace.sl_avail,
       shoelace.sl_color, shoelace.sl_len,
       shoelace.sl_unit, shoelace.sl_len_cm
  FROM (SELECT s.sl_name,
               s.sl_avail,
               s.sl_color,
               s.sl_len,
               s.sl_unit,
               s.sl_len * u.un_fact AS sl_len_cm
          FROM shoelace_data s, unit u
         WHERE s.sl_unit = u.un_name) shoelace;
</programlisting>

     There is one difference however: the subquery's range table has two
     extra entries <literal>shoelace old</literal> and <literal>shoelace new</literal>.  These entries don't
     participate directly in the query, since they aren't referenced by
     the subquery's join tree or target list.  The rewriter uses them
     to store the access privilege check information that was originally present
     in the range-table entry that referenced the view.  In this way, the
     executor will still check that the user has proper privileges to access
     the view, even though there's no direct use of the view in the rewritten
     query.
</para>

<para>
    That was the first rule applied.  The rule system will continue checking
    the remaining range-table entries in the top query (in this example there
    are no more), and it will recursively check the range-table entries in
    the added subquery to see if any of them reference views.  (But it
    won't expand <literal>old</literal> or <literal>new</literal> &mdash; otherwise we'd have infinite recursion!)
    In this example, there are no rewrite rules for <literal>shoelace_data</literal> or <literal>unit</literal>,
    so rewriting is complete and the above is the final result given to
    the planner.
</para>

<para>
    Now we want to write a query that finds out for which shoes currently in the store
    we have the matching shoelaces (color and length) and where the
    total number of exactly matching pairs is greater than or equal to two.

<programlisting>
SELECT * FROM shoe_ready WHERE total_avail &gt;= 2;

 shoename | sh_avail | sl_name | sl_avail | total_avail
----------+----------+---------+----------+-------------
 sh1      |        2 | sl1     |        5 |           2
 sh3

Title: Query Rewriting with View Rules
Summary
This section explains how the rule system in PostgreSQL rewrites queries that reference views, using the example of the shoelace view. It shows how the rewriter expands the view into a subquery and substitutes it into the original query, and how the system checks for access privileges and applies rewrite rules recursively. The example also demonstrates how to write a query that finds matching shoes and shoelaces with a total availability greater than or equal to two.