aboutsummaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/intro.sgml2
-rw-r--r--doc/src/sgml/ref/alter_table.sgml8
-rw-r--r--doc/src/sgml/ref/alter_view.sgml9
-rw-r--r--doc/src/sgml/ref/create_rule.sgml25
-rw-r--r--doc/src/sgml/ref/create_view.sgml125
-rw-r--r--doc/src/sgml/rules.sgml47
6 files changed, 175 insertions, 41 deletions
diff --git a/doc/src/sgml/intro.sgml b/doc/src/sgml/intro.sgml
index 4d3f93f3174..f0dba6f56fb 100644
--- a/doc/src/sgml/intro.sgml
+++ b/doc/src/sgml/intro.sgml
@@ -110,7 +110,7 @@
<simpara>triggers</simpara>
</listitem>
<listitem>
- <simpara>views</simpara>
+ <simpara>updatable views</simpara>
</listitem>
<listitem>
<simpara>transactional integrity</simpara>
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index 356419e2d08..5437626c3fe 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -147,11 +147,9 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable>
<listitem>
<para>
These forms set or remove the default value for a column.
- The default values only apply to subsequent <command>INSERT</command>
- commands; they do not cause rows already in the table to change.
- Defaults can also be created for views, in which case they are
- inserted into <command>INSERT</> statements on the view before
- the view's <literal>ON INSERT</literal> rule is applied.
+ Default values only apply in subsequent <command>INSERT</command>
+ or <command>UPDATE</> commands; they do not cause rows already in the
+ table to change.
</para>
</listitem>
</varlistentry>
diff --git a/doc/src/sgml/ref/alter_view.sgml b/doc/src/sgml/ref/alter_view.sgml
index 521f05b84a1..0e2b140241e 100644
--- a/doc/src/sgml/ref/alter_view.sgml
+++ b/doc/src/sgml/ref/alter_view.sgml
@@ -80,10 +80,11 @@ ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RESET
<listitem>
<para>
These forms set or remove the default value for a column.
- A default value associated with a view column is
- inserted into <command>INSERT</> statements on the view before
- the view's <literal>ON INSERT</literal> rule is applied, if
- the <command>INSERT</> does not specify a value for the column.
+ A view column's default value is substituted into any
+ <command>INSERT</> or <command>UPDATE</> command whose target is the
+ view, before applying any rules or triggers for the view. The view's
+ default will therefore take precedence over any default values from
+ underlying relations.
</para>
</listitem>
</varlistentry>
diff --git a/doc/src/sgml/ref/create_rule.sgml b/doc/src/sgml/ref/create_rule.sgml
index d4c33921290..381ea3ed6b4 100644
--- a/doc/src/sgml/ref/create_rule.sgml
+++ b/doc/src/sgml/ref/create_rule.sgml
@@ -45,10 +45,10 @@ CREATE [ OR REPLACE ] RULE <replaceable class="parameter">name</replaceable> AS
additional commands to be executed when a given command on a given
table is executed. Alternatively, an <literal>INSTEAD</literal>
rule can replace a given command by another, or cause a command
- not to be executed at all. Rules are used to implement table
+ not to be executed at all. Rules are used to implement SQL
views as well. It is important to realize that a rule is really
a command transformation mechanism, or command macro. The
- transformation happens before the execution of the commands starts.
+ transformation happens before the execution of the command starts.
If you actually want an operation that fires independently for each
physical row, you probably want to use a trigger, not a rule.
More information about the rules system is in <xref linkend="rules">.
@@ -73,13 +73,11 @@ CREATE [ OR REPLACE ] RULE <replaceable class="parameter">name</replaceable> AS
sufficient for your purposes) to replace update actions on the view
with appropriate updates on other tables. If you want to support
<command>INSERT RETURNING</> and so on, then be sure to put a suitable
- <literal>RETURNING</> clause into each of these rules. Alternatively,
- an updatable view can be implemented using <literal>INSTEAD OF</>
- triggers (see <xref linkend="sql-createtrigger">).
+ <literal>RETURNING</> clause into each of these rules.
</para>
<para>
- There is a catch if you try to use conditional rules for view
+ There is a catch if you try to use conditional rules for complex view
updates: there <emphasis>must</> be an unconditional
<literal>INSTEAD</literal> rule for each action you wish to allow
on the view. If the rule is conditional, or is not
@@ -95,6 +93,21 @@ CREATE [ OR REPLACE ] RULE <replaceable class="parameter">name</replaceable> AS
<literal>INSTEAD NOTHING</literal> action. (This method does not
currently work to support <literal>RETURNING</> queries, however.)
</para>
+
+ <note>
+ <para>
+ A view that is simple enough to be automatically updatable (see <xref
+ linkend="sql-createview">) does not require a user-created rule in
+ order to be updatable. While you can create an explicit rule anyway,
+ the automatic update transformation will generally outperform an
+ explicit rule.
+ </para>
+
+ <para>
+ Another alternative worth considering is to use <literal>INSTEAD OF</>
+ triggers (see <xref linkend="sql-createtrigger">) in place of rules.
+ </para>
+ </note>
</refsect1>
<refsect1>
diff --git a/doc/src/sgml/ref/create_view.sgml b/doc/src/sgml/ref/create_view.sgml
index 9e3bc2954f2..abbde94772c 100644
--- a/doc/src/sgml/ref/create_view.sgml
+++ b/doc/src/sgml/ref/create_view.sgml
@@ -128,17 +128,6 @@ CREATE [ OR REPLACE ] [ TEMP | TEMPORARY ] VIEW <replaceable class="PARAMETER">n
<title>Notes</title>
<para>
- Currently, views are read only: the system will not allow an insert,
- update, or delete on a view. You can get the effect of an updatable
- view by creating <literal>INSTEAD</> triggers on the view, which
- must convert attempted inserts, etc. on the view into
- appropriate actions on other tables. For more information see
- <xref linkend="sql-createtrigger">. Another possibility is to create
- rules (see <xref linkend="sql-createrule">), but in practice triggers
- are easier to understand and use correctly.
- </para>
-
- <para>
Use the <xref linkend="sql-dropview">
statement to drop views.
</para>
@@ -175,6 +164,105 @@ CREATE VIEW vista AS SELECT text 'Hello World' AS hello;
to replace it (this includes being a member of the owning role).
</para>
+ <refsect2 id="SQL-CREATEVIEW-updatable-views">
+ <title id="SQL-CREATEVIEW-updatable-views-title">Updatable Views</title>
+
+ <indexterm zone="sql-createview-updatable-views">
+ <primary>updatable views</primary>
+ </indexterm>
+
+ <para>
+ Simple views are automatically updatable: the system will allow
+ <command>INSERT</>, <command>UPDATE</> and <command>DELETE</> statements
+ to be used on the view in the same way as on a regular table. A view is
+ automatically updatable if it satisfies all of the following conditions:
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ The view must have exactly one entry in its <literal>FROM</> list,
+ which must be a table or another updatable view.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ The view definition must not contain <literal>WITH</>,
+ <literal>DISTINCT</>, <literal>GROUP BY</>, <literal>HAVING</>,
+ <literal>LIMIT</>, or <literal>OFFSET</> clauses at the top level.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ The view definition must not contain set operations (<literal>UNION</>,
+ <literal>INTERSECT</> or <literal>EXCEPT</>) at the top level.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ All columns in the view's select list must be simple references to
+ columns of the underlying relation. They cannot be expressions,
+ literals or functions. System columns cannot be referenced, either.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ No column of the underlying relation can appear more than once in
+ the view's select list.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ The view must not have the <literal>security_barrier</> property.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ If the view is automatically updatable the system will convert any
+ <command>INSERT</>, <command>UPDATE</> or <command>DELETE</> statement
+ on the view into the corresponding statement on the underlying base
+ relation.
+ </para>
+
+ <para>
+ If an automatically updatable view contains a <literal>WHERE</>
+ condition, the condition restricts which rows of the base relation are
+ available to be modified by <command>UPDATE</> and <command>DELETE</>
+ statements on the view. However, an <command>UPDATE</> is allowed to
+ change a row so that it no longer satisfies the <literal>WHERE</>
+ condition, and thus is no longer visible through the view. Similarly,
+ an <command>INSERT</> command can potentially insert base-relation rows
+ that do not satisfy the <literal>WHERE</> condition and thus are not
+ visible through the view.
+ </para>
+
+ <para>
+ A more complex view that does not satisfy all these conditions is
+ read-only by default: the system will not allow an insert, update, or
+ delete on the view. You can get the effect of an updatable view by
+ creating <literal>INSTEAD OF</> triggers on the view, which must
+ convert attempted inserts, etc. on the view into appropriate actions
+ on other tables. For more information see <xref
+ linkend="sql-createtrigger">. Another possibility is to create rules
+ (see <xref linkend="sql-createrule">), but in practice triggers are
+ easier to understand and use correctly.
+ </para>
+
+ <para>
+ Note that the user performing the insert, update or delete on the view
+ must have the corresponding insert, update or delete privilege on the
+ view. In addition the view's owner must have the relevant privileges on
+ the underlying base relations, but the user performing the update does
+ not need any permissions on the underlying base relations (see
+ <xref linkend="rules-privileges">).
+ </para>
+ </refsect2>
</refsect1>
<refsect1>
@@ -217,11 +305,15 @@ CREATE VIEW <replaceable class="parameter">name</replaceable> [ ( <replaceable c
<term><literal>CHECK OPTION</literal></term>
<listitem>
<para>
- This option has to do with updatable views. All
- <command>INSERT</> and <command>UPDATE</> commands on the view
- will be checked to ensure data satisfy the view-defining
- condition (that is, the new data would be visible through the
- view). If they do not, the update will be rejected.
+ This option controls the behavior of automatically updatable views.
+ When given, <command>INSERT</> and <command>UPDATE</> commands on
+ the view will be checked to ensure new rows satisfy the
+ view-defining condition (that is, the new rows would be visible
+ through the view). If they do not, the update will be rejected.
+ Without <literal>CHECK OPTION</literal>, <command>INSERT</> and
+ <command>UPDATE</> commands on the view are allowed to create rows
+ that are not visible through the view. (The latter behavior is the
+ only one currently provided by <productname>PostgreSQL</>.)
</para>
</listitem>
</varlistentry>
@@ -252,6 +344,7 @@ CREATE VIEW <replaceable class="parameter">name</replaceable> [ ( <replaceable c
<command>CREATE OR REPLACE VIEW</command> is a
<productname>PostgreSQL</productname> language extension.
So is the concept of a temporary view.
+ The <literal>WITH</> clause is an extension as well.
</para>
</refsect1>
diff --git a/doc/src/sgml/rules.sgml b/doc/src/sgml/rules.sgml
index cc02ada7c71..5811de7942f 100644
--- a/doc/src/sgml/rules.sgml
+++ b/doc/src/sgml/rules.sgml
@@ -808,13 +808,28 @@ SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
<para>
What happens if a view is named as the target relation for an
<command>INSERT</command>, <command>UPDATE</command>, or
- <command>DELETE</command>? Simply doing the substitutions
+ <command>DELETE</command>? Doing the substitutions
described above would give a query tree in which the result
relation points at a subquery range-table entry, which will not
- work. Instead, the rewriter assumes that the operation will be
- handled by an <literal>INSTEAD OF</> trigger on the view.
- (If there is no such trigger, the executor will throw an error
- when execution starts.) Rewriting works slightly differently
+ work. There are several ways in which <productname>PostgreSQL</>
+ can support the appearance of updating a view, however.
+</para>
+
+<para>
+ If the subquery selects from a single base relation and is simple
+ enough, the rewriter can automatically replace the subquery with the
+ underlying base relation so that the <command>INSERT</command>,
+ <command>UPDATE</command>, or <command>DELETE</command> is applied to
+ the base relation in the appropriate way. Views that are
+ <quote>simple enough</> for this are called <firstterm>automatically
+ updatable</>. For detailed information on the kinds of view that can
+ be automatically updated, see <xref linkend="sql-createview">.
+</para>
+
+<para>
+ Alternatively, the operation may be handled by a user-provided
+ <literal>INSTEAD OF</> trigger on the view.
+ Rewriting works slightly differently
in this case. For <command>INSERT</command>, the rewriter does
nothing at all with the view, leaving it as the result relation
for the query. For <command>UPDATE</command> and
@@ -842,10 +857,8 @@ SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
</para>
<para>
- If there are no <literal>INSTEAD OF</> triggers to update the view,
- the executor will throw an error, because it cannot automatically
- update a view by itself. To change this, we can define rules that
- modify the behavior of <command>INSERT</command>,
+ Another possibility is for the user to define <literal>INSTEAD</>
+ 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
@@ -860,6 +873,22 @@ SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
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>, or <command>DELETE</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</> rules or <literal>INSTEAD OF</>
+ 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>