Fix documentation on partitioning vs. foreign tables

1. The PARTITION OF clause of CREATE FOREIGN TABLE was not explained in
   the CREATE FOREIGN TABLE reference page.  Add it.
   (Postgres 10 onwards)

2. The limitation that tuple routing cannot target partitions that are
   foreign tables was not documented clearly enough.  Improve wording.
   (Postgres 10 onwards)

3. The UPDATE tuple re-routing concurrency behavior was explained in
   the DDL chapter, which doesn't seem the right place.  Move it to the
   UPDATE reference page instead.  (Postgres 11 onwards).

Authors: Amit Langote, David Rowley.
Reviewed-by: Etsuro Fujita.
Reported-by: Derek Hans
Discussion: https://postgr.es/m/CAGrP7a3Xc1Qy_B2WJcgAD8uQTS_NDcJn06O5mtS_Ne1nYhBsyw@mail.gmail.com
This commit is contained in:
Alvaro Herrera 2019-03-10 19:45:29 -03:00
parent bc2232f2f5
commit b16f8a2905
3 changed files with 42 additions and 28 deletions

View File

@ -3355,27 +3355,6 @@ ALTER TABLE measurement ATTACH PARTITION measurement_y2008m02
</para>
</listitem>
<listitem>
<para>
When an <command>UPDATE</command> causes a row to move from one
partition to another, there is a chance that another concurrent
<command>UPDATE</command> or <command>DELETE</command> will get a
serialization failure error. Suppose session 1 is performing an
<command>UPDATE</command> on a partition key, and meanwhile a concurrent
session 2 for which this row is visible performs an
<command>UPDATE</command> or <command>DELETE</command> operation on this
row. In such case, session 2's <command>UPDATE</command> or
<command>DELETE</command>, will detect the row movement and raise a
serialization failure error (which always returns with an SQLSTATE code
'40001'). Applications may wish to retry the transaction if this
occurs. In the usual case where the table is not partitioned, or where
there is no row movement, session 2 would have identified the newly
updated row and carried out the
<command>UPDATE</command>/<command>DELETE</command> on this new row
version.
</para>
</listitem>
<listitem>
<para>
<literal>BEFORE ROW</literal> triggers, if necessary, must be defined

View File

@ -160,6 +160,18 @@ CHECK ( <replaceable class="parameter">expression</replaceable> ) [ NO INHERIT ]
</listitem>
</varlistentry>
<varlistentry>
<term><literal>PARTITION OF <replaceable>parent_table</replaceable> FOR VALUES <replaceable class="parameter">partition_bound_spec</replaceable></literal></term>
<listitem>
<para>
This form can be used to create the foreign table as partition of
the given parent table with specified partition bound values.
See the similar form of
<xref linkend="sql-createtable"/> for more details.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>CONSTRAINT <replaceable class="parameter">constraint_name</replaceable></literal></term>
<listitem>
@ -308,6 +320,12 @@ CHECK ( <replaceable class="parameter">expression</replaceable> ) [ NO INHERIT ]
responsibility to ensure that the constraint definition matches
reality.
</para>
<para>
While rows can be moved from local partitions to a foreign-table partition
(provided the foreign data wrapper supports tuple routing), they cannot be
moved from a foreign-table partition to another partition.
</para>
</refsect1>
<refsect1 id="sql-createforeigntable-examples">

View File

@ -287,13 +287,30 @@ UPDATE <replaceable class="parameter">count</replaceable>
row satisfies its partition constraint, then the row is moved to that
partition. If there is no such partition, an error will occur. Behind the
scenes, the row movement is actually a <command>DELETE</command> and
<command>INSERT</command> operation. However, there is a possibility that a
concurrent <command>UPDATE</command> or <command>DELETE</command> on the
same row may miss this row. For details see the section
<xref linkend="ddl-partitioning-declarative-limitations"/>.
Currently, rows cannot be moved from a partition that is a
foreign table to some other partition, but they can be moved into a foreign
table if the foreign data wrapper supports it.
<command>INSERT</command> operation.
</para>
<para>
There is a possibility that a concurrent <command>UPDATE</command> or
<command>DELETE</command> on the row being moved will get a serialization
failure error. Suppose session 1 is performing an <command>UPDATE</command>
on a partition key, and meanwhile a concurrent session 2 for which this
row is visible performs an <command>UPDATE</command> or
<command>DELETE</command> operation on this row. In such case,
session 2's <command>UPDATE</command> or <command>DELETE</command> will
detect the row movement and raise a serialization failure error (which
always returns with an SQLSTATE code '40001'). Applications may wish to
retry the transaction if this occurs. In the usual case where the table
is not partitioned, or where there is no row movement, session 2 would
have identified the newly updated row and carried out the
<command>UPDATE</command>/<command>DELETE</command> on this new row
version.
</para>
<para>
Note that while rows can be moved from local partitions to a foreign-table
partition (provided the foreign data wrapper supports tuple routing), they
cannot be moved from a foreign-table partition to another partition.
</para>
</refsect1>