</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 that this is an <command>UPDATE</command>, and it knows that
this result should go into table <literal>t1</literal>. But which of the rows
that are there has to be replaced by the new row?
</para>
<para>
To resolve this problem, another entry is added to the target list
in <command>UPDATE</command> (and also in
<command>DELETE</command>) statements: the current tuple ID
(<acronym>CTID</acronym>).<indexterm><primary>CTID</primary></indexterm>
This is a system column containing the
file block number and position in the block for the row. Knowing
the table, the <acronym>CTID</acronym> can be used to retrieve the
original row of <literal>t1</literal> to be updated. After adding the
<acronym>CTID</acronym> to the target list, the query actually looks like:
<programlisting>
SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
</programlisting>
Now another detail of <productname>PostgreSQL</productname> enters
the stage. Old table rows aren't overwritten, and this
is why <command>ROLLBACK</command> is fast. In an <command>UPDATE</command>,
the new result row is inserted into the table (after stripping the
<acronym>CTID</acronym>) and in the row header of the old row, which the
<acronym>CTID</acronym> pointed to, the <literal>cmax</literal> and
<literal>xmax</literal> entries are set to the current command counter
and current transaction ID. Thus the old row is hidden, and after
the transaction commits the vacuum cleaner can eventually remove
the dead row.
</para>
<para>
Knowing all that, we can simply apply view rules in absolutely
the same way to any command. There is no difference.
</para>
</sect2>
<sect2 id="rules-views-power">
<title>The Power of Views in <productname>PostgreSQL</productname></title>
<para>
The above demonstrates how the rule system incorporates view
definitions into the original query tree. In the second example, a
simple <command>SELECT</command> from one view created a final
query tree that is a join of 4 tables (<literal>unit</literal> was used twice with
different names).
</para>
<para>
The benefit of implementing views with the rule system is
that the planner has all
the information about which tables have to be scanned plus the
relationships between these tables plus the restrictive
qualifications from the views plus the qualifications from
the original query
in one single query tree. And this is still the situation
when the original query is already a join over views.
The planner has to decide which is
the best path to execute the query, and the more information
the planner has, the better this decision can be. And
the rule system as implemented in <productname>PostgreSQL</productname>
ensures that this is all information available about the query
up to that point.
</para>
</sect2>
<sect2 id="rules-views-update">
<title>Updating a View</title>