the view is expanded as normal,
but another unexpanded range-table entry is added to the query
to represent the view in its capacity as the result relation.
</para>
<para>
The problem that now arises is how to identify the rows to be
updated in the view. Recall that when the result relation
is a table, a special <acronym>CTID</acronym> entry is added to the target
list to identify the physical locations of the rows to be updated.
This does not work if the result relation is a view, because a view
does not have any <acronym>CTID</acronym>, since its rows do not have
actual physical locations. Instead, for an <command>UPDATE</command>,
<command>DELETE</command>, or <command>MERGE</command> operation, a
special <literal>wholerow</literal> entry is added to the target list,
which expands to include all columns from the view. The executor uses this
value to supply the <quote>old</quote> row to the
<literal>INSTEAD OF</literal> trigger. It is up to the trigger to work
out what to update based on the old and new row values.
</para>
<para>
Another possibility is for the user to define <literal>INSTEAD</literal>
rules that specify substitute actions for <command>INSERT</command>,
<command>UPDATE</command>, and <command>DELETE</command> commands on
a view. These rules will rewrite the command, typically into a command
that updates one or more tables, rather than views. That is the topic
of <xref linkend="rules-update"/>. Note that this will not work with
<command>MERGE</command>, which currently does not support rules on
the target relation other than <command>SELECT</command> rules.
</para>
<para>
Note that rules are evaluated first, rewriting the original query
before it is planned and executed. Therefore, if a view has
<literal>INSTEAD OF</literal> triggers as well as rules on <command>INSERT</command>,
<command>UPDATE</command>, or <command>DELETE</command>, then the rules will be
evaluated first, and depending on the result, the triggers may not be
used at all.
</para>
<para>
Automatic rewriting of an <command>INSERT</command>,
<command>UPDATE</command>, <command>DELETE</command>, or
<command>MERGE</command> query on a
simple view is always tried last. Therefore, if a view has rules or
triggers, they will override the default behavior of automatically
updatable views.
</para>
<para>
If there are no <literal>INSTEAD</literal> rules or <literal>INSTEAD OF</literal>
triggers for the view, and the rewriter cannot automatically rewrite
the query as an update on the underlying base relation, an error will
be thrown because the executor cannot update a view as such.
</para>
</sect2>
</sect1>
<sect1 id="rules-materializedviews">
<title>Materialized Views</title>
<indexterm zone="rules-materializedviews">
<primary>rule</primary>
<secondary>and materialized views</secondary>
</indexterm>
<indexterm zone="rules-materializedviews">
<primary>materialized view</primary>
<secondary>implementation through rules</secondary>
</indexterm>
<indexterm zone="rules-materializedviews">
<primary>view</primary>
<secondary>materialized</secondary>
</indexterm>
<para>
Materialized views in <productname>PostgreSQL</productname> use the
rule system like views do, but persist the results in a table-like form.
The main differences between:
<programlisting>
CREATE MATERIALIZED VIEW mymatview AS SELECT * FROM mytab;
</programlisting>
and:
<programlisting>
CREATE TABLE mymatview AS SELECT * FROM mytab;
</programlisting>
are that the materialized view cannot subsequently be directly updated
and that the query used to create the materialized view is stored in
exactly the same way that a view's query is stored, so that fresh data
can be generated for the materialized view with:
<programlisting>
REFRESH MATERIALIZED VIEW mymatview;
</programlisting>
The information