WHERE sh.slunit = un.un_name) rsh,
(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) rsl
WHERE rsl.sl_color = rsh.slcolor
AND rsl.sl_len_cm >= rsh.slminlen_cm
AND rsl.sl_len_cm <= rsh.slmaxlen_cm) shoe_ready
WHERE shoe_ready.total_avail > 2;
</programlisting>
</para>
<para>
This might look inefficient, but the planner will collapse this into a
single-level query tree by <quote>pulling up</quote> the subqueries,
and then it will plan the joins just as if we'd written them out
manually. So collapsing the query tree is an optimization that the
rewrite system doesn't have to concern itself with.
</para>
</sect2>
<sect2 id="rules-views-non-select">
<title>View Rules in Non-<command>SELECT</command> Statements</title>
<para>
Two details of the query tree aren't touched in the description of
view rules above. These are the command type and the result relation.
In fact, the command type is not needed by view rules, but the result
relation may affect the way in which the query rewriter works, because
special care needs to be taken if the result relation is a view.
</para>
<para>
There are only a few differences between a query tree for a
<command>SELECT</command> and one for any other
command. Obviously, they have a different command type and for a
command other than a <command>SELECT</command>, the result
relation points to the range-table entry where the result should
go. Everything else is absolutely the same. So having two tables
<literal>t1</literal> and <literal>t2</literal> with columns <literal>a</literal> and
<literal>b</literal>, the query trees for the two statements:
<programlisting>
SELECT t2.b FROM t1, t2 WHERE t1.a = t2.a;
UPDATE t1 SET b = t2.b FROM t2 WHERE t1.a = t2.a;
</programlisting>
are nearly identical. In particular:
<itemizedlist>
<listitem>
<para>
The range tables contain entries for the tables <literal>t1</literal> and <literal>t2</literal>.
</para>
</listitem>
<listitem>
<para>
The target lists contain one variable that points to column
<literal>b</literal> of the range table entry for table <literal>t2</literal>.
</para>
</listitem>
<listitem>
<para>
The qualification expressions compare the columns <literal>a</literal> of both
range-table entries for equality.
</para>
</listitem>
<listitem>
<para>
The join trees show a simple join between <literal>t1</literal> and <literal>t2</literal>.
</para>
</listitem>
</itemizedlist>
</para>
<para>
The consequence is, that both query trees result in similar
execution plans: They are both joins over the two tables. For the
<command>UPDATE</command> the missing columns from <literal>t1</literal> are added to
the target list by the planner and the final query tree will read
as:
<programlisting>
UPDATE t1 SET a = t1.a, b = t2.b FROM t2 WHERE t1.a = t2.a;
</programlisting>
and thus the executor run over the join will produce exactly the
same result set as:
<programlisting>
SELECT t1.a, t2.b FROM t1, t2 WHERE t1.a = t2.a;
</programlisting>
But there is a little problem in
<command>UPDATE</command>: the part of the executor plan that does
the join does not care what the results from the join are
meant for. It just produces a result set of rows. The fact that
one is a <command>SELECT</command> command and the other is an
<command>UPDATE</command> is handled higher up in the executor, where
it knows