Home Explore Blog CI



postgresql

10th chunk of `doc/src/sgml/rules.sgml`
897d7a50821db8e4dd7447db2719fa6e9879c656ea4972ef0000000100000fa6
 </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>

Title: Query Planning and View Rules
Summary
This section discusses how the query planner handles view rules in non-SELECT statements, such as UPDATE commands. It explains that the planner adds the current tuple ID (CTID) to the target list to identify the rows to be updated, and how this allows the planner to access the original row and update it accordingly. The section also highlights the benefits of implementing views with the rule system, which provides the planner with all the necessary information to make informed decisions about query execution.