summaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
authorDean Rasheed2024-02-29 15:56:59 +0000
committerDean Rasheed2024-02-29 15:56:59 +0000
commit5f2e179bd31e5f5803005101eb12a8d7bf8db8f3 (patch)
tree838a9f273c1d3d825db322161c0b8cdf3fbb0ce1 /doc/src
parent8b29a119fdaa381d6f75105f539b1e658c0f8cdb (diff)
Support MERGE into updatable views.
This allows the target relation of MERGE to be an auto-updatable or trigger-updatable view, and includes support for WITH CHECK OPTION, security barrier views, and security invoker views. A trigger-updatable view must have INSTEAD OF triggers for every type of action (INSERT, UPDATE, and DELETE) mentioned in the MERGE command. An auto-updatable view must not have any INSTEAD OF triggers. Mixing auto-update and trigger-update actions (i.e., having a partial set of INSTEAD OF triggers) is not supported. Rule-updatable views are also not supported, since there is no rewriter support for non-SELECT rules with MERGE operations. Dean Rasheed, reviewed by Jian He and Alvaro Herrera. Discussion: https://postgr.es/m/CAEZATCVcB1g0nmxuEc-A+gGB0HnfcGQNGYH7gS=7rq0u0zOBXA@mail.gmail.com
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/ref/create_view.sgml42
-rw-r--r--doc/src/sgml/ref/merge.sgml22
-rw-r--r--doc/src/sgml/rules.sgml40
3 files changed, 66 insertions, 38 deletions
diff --git a/doc/src/sgml/ref/create_view.sgml b/doc/src/sgml/ref/create_view.sgml
index 3b26205f788..e8d9d3c8d0f 100644
--- a/doc/src/sgml/ref/create_view.sgml
+++ b/doc/src/sgml/ref/create_view.sgml
@@ -192,12 +192,14 @@ CREATE VIEW [ <replaceable>schema</replaceable> . ] <replaceable>view_name</repl
<listitem>
<para>
This option controls the behavior of automatically updatable views. When
- this option is specified, <command>INSERT</command> and <command>UPDATE</command>
+ this option is specified, <command>INSERT</command>,
+ <command>UPDATE</command>, and <command>MERGE</command>
commands on the view will be checked to ensure that new rows satisfy the
view-defining condition (that is, the new rows are checked to ensure that
they are visible through the view). If they are not, the update will be
rejected. If the <literal>CHECK OPTION</literal> is not specified,
- <command>INSERT</command> and <command>UPDATE</command> commands on the view are
+ <command>INSERT</command>, <command>UPDATE</command>, and
+ <command>MERGE</command> commands on the view are
allowed to create rows that are not visible through the view. The
following check options are supported:
@@ -247,7 +249,8 @@ CREATE VIEW [ <replaceable>schema</replaceable> . ] <replaceable>view_name</repl
<command>INSERT</command> or <command>UPDATE</command> command to be rewritten, then
all check options will be ignored in the rewritten query, including any
checks from automatically updatable views defined on top of the relation
- with the <literal>INSTEAD</literal> rule.
+ with the <literal>INSTEAD</literal> rule. <command>MERGE</command> is not
+ supported if the view or any of its base relations have rules.
</para>
</listitem>
</varlistentry>
@@ -360,7 +363,8 @@ CREATE VIEW vista AS SELECT text 'Hello World' AS hello;
<para>
Simple views are automatically updatable: the system will allow
- <command>INSERT</command>, <command>UPDATE</command> and <command>DELETE</command> statements
+ <command>INSERT</command>, <command>UPDATE</command>,
+ <command>DELETE</command>, and <command>MERGE</command> 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:
@@ -400,13 +404,15 @@ CREATE VIEW vista AS SELECT text 'Hello World' AS hello;
An automatically updatable view may contain a mix of updatable and
non-updatable columns. A column is updatable if it is a simple reference
to an updatable column of the underlying base relation; otherwise the
- column is read-only, and an error will be raised if an <command>INSERT</command>
- or <command>UPDATE</command> statement attempts to assign a value to it.
+ column is read-only, and an error will be raised if an
+ <command>INSERT</command>, <command>UPDATE</command>, or
+ <command>MERGE</command> statement attempts to assign a value to it.
</para>
<para>
If the view is automatically updatable the system will convert any
- <command>INSERT</command>, <command>UPDATE</command> or <command>DELETE</command> statement
+ <command>INSERT</command>, <command>UPDATE</command>,
+ <command>DELETE</command>, or <command>MERGE</command> statement
on the view into the corresponding statement on the underlying base
relation. <command>INSERT</command> statements that have an <literal>ON
CONFLICT UPDATE</literal> clause are fully supported.
@@ -415,17 +421,21 @@ CREATE VIEW vista AS SELECT text 'Hello World' AS hello;
<para>
If an automatically updatable view contains a <literal>WHERE</literal>
condition, the condition restricts which rows of the base relation are
- available to be modified by <command>UPDATE</command> and <command>DELETE</command>
- statements on the view. However, an <command>UPDATE</command> is allowed to
+ available to be modified by <command>UPDATE</command>,
+ <command>DELETE</command>, and <command>MERGE</command>
+ statements on the view. However, an <command>UPDATE</command> or
+ <command>MERGE</command> is allowed to
change a row so that it no longer satisfies the <literal>WHERE</literal>
condition, and thus is no longer visible through the view. Similarly,
- an <command>INSERT</command> command can potentially insert base-relation rows
+ an <command>INSERT</command> or <command>MERGE</command> command can
+ potentially insert base-relation rows
that do not satisfy the <literal>WHERE</literal> condition and thus are not
visible through the view (<literal>ON CONFLICT UPDATE</literal> may
similarly affect an existing row not visible through the view).
The <literal>CHECK OPTION</literal> may be used to prevent
- <command>INSERT</command> and <command>UPDATE</command> commands from creating
- such rows that are not visible through the view.
+ <command>INSERT</command>, <command>UPDATE</command>, and
+ <command>MERGE</command> commands from creating such rows that are not
+ visible through the view.
</para>
<para>
@@ -443,14 +453,16 @@ CREATE VIEW vista AS SELECT text 'Hello World' AS hello;
<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
+ read-only by default: the system will not allow an <command>INSERT</command>,
+ <command>UPDATE</command>, <command>DELETE</command>, or <command>MERGE</command>
+ on the view. You can get the effect of an updatable view by
creating <literal>INSTEAD OF</literal> 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.
+ easier to understand and use correctly. Also note that <command>MERGE</command>
+ is not supported on relations with rules.
</para>
<para>
diff --git a/doc/src/sgml/ref/merge.sgml b/doc/src/sgml/ref/merge.sgml
index bb34ef9b921..7a8ac40259c 100644
--- a/doc/src/sgml/ref/merge.sgml
+++ b/doc/src/sgml/ref/merge.sgml
@@ -132,9 +132,9 @@ DELETE
<term><replaceable class="parameter">target_table_name</replaceable></term>
<listitem>
<para>
- The name (optionally schema-qualified) of the target table to merge into.
- If <literal>ONLY</literal> is specified before the table name, matching
- rows are updated or deleted in the named table only. If
+ The name (optionally schema-qualified) of the target table or view to
+ merge into. If <literal>ONLY</literal> is specified before a table
+ name, matching rows are updated or deleted in the named table only. If
<literal>ONLY</literal> is not specified, matching rows are also updated
or deleted in any tables inheriting from the named table. Optionally,
<literal>*</literal> can be specified after the table name to explicitly
@@ -142,6 +142,16 @@ DELETE
<literal>ONLY</literal> keyword and <literal>*</literal> option do not
affect insert actions, which always insert into the named table only.
</para>
+
+ <para>
+ If <replaceable class="parameter">target_table_name</replaceable> is a
+ view, it must either be automatically updatable with no
+ <literal>INSTEAD OF</literal> triggers, or it must have
+ <literal>INSTEAD OF</literal> triggers for every type of action
+ (<literal>INSERT</literal>, <literal>UPDATE</literal>, and
+ <literal>DELETE</literal>) specified in the <literal>WHEN</literal>
+ clauses. Views with rules are not supported.
+ </para>
</listitem>
</varlistentry>
@@ -486,7 +496,11 @@ MERGE <replaceable class="parameter">total_count</replaceable>
the action's event type.
</para>
</listitem>
- </orderedlist></para>
+ </orderedlist>
+ If the target relation is a view with <literal>INSTEAD OF ROW</literal>
+ triggers for the action's event type, they are used to perform the
+ action instead.
+ </para>
</listitem>
</orderedlist></para>
</listitem>
diff --git a/doc/src/sgml/rules.sgml b/doc/src/sgml/rules.sgml
index d229b94d396..784c16e76ea 100644
--- a/doc/src/sgml/rules.sgml
+++ b/doc/src/sgml/rules.sgml
@@ -797,9 +797,9 @@ 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>? Doing the substitutions
- described above would give a query tree in which the result
+ <command>INSERT</command>, <command>UPDATE</command>,
+ <command>DELETE</command>, or <command>MERGE</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. There are several ways in which <productname>PostgreSQL</productname>
can support the appearance of updating a view, however.
@@ -813,11 +813,12 @@ SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
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</quote> for this are called <firstterm>automatically
- updatable</firstterm>. For detailed information on the kinds of view that can
- be automatically updated, see <xref linkend="sql-createview"/>.
+ <command>UPDATE</command>, <command>DELETE</command>, or
+ <command>MERGE</command> is applied to the base relation in the
+ appropriate way. Views that are <quote>simple enough</quote> for this
+ are called <firstterm>automatically updatable</firstterm>. For detailed
+ information on the kinds of view that can be automatically updated, see
+ <xref linkend="sql-createview"/>.
</para>
<para>
@@ -827,10 +828,10 @@ SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
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
- <command>DELETE</command>, it's still necessary to expand the
+ for the query. For <command>UPDATE</command>, <command>DELETE</command>,
+ and <command>MERGE</command>, it's still necessary to expand the
view query to produce the <quote>old</quote> rows that the command will
- attempt to update or delete. So the view is expanded as normal,
+ attempt to update, delete, or merge. So 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>
@@ -842,13 +843,13 @@ SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
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>
- or <command>DELETE</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.
+ 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>
@@ -857,7 +858,8 @@ SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
<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"/>.
+ of <xref linkend="rules-update"/>. Note that this will not work with
+ <command>MERGE</command>, which currently does not support rules.
</para>
<para>