1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

Add temporal FOREIGN KEY contraints

Add PERIOD clause to foreign key constraint definitions.  This is
supported for range and multirange types.  Temporal foreign keys check
for range containment instead of equality.

This feature matches the behavior of the SQL standard temporal foreign
keys, but it works on PostgreSQL's native ranges instead of SQL's
"periods", which don't exist in PostgreSQL (yet).

Reference actions ON {UPDATE,DELETE} {CASCADE,SET NULL,SET DEFAULT}
are not supported yet.

Author: Paul A. Jungwirth <pj@illuminatedcomputing.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: jian he <jian.universality@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CA+renyUApHgSZF9-nd-a0+OPGharLQLO=mDHcY4_qQ0+noCUVg@mail.gmail.com
This commit is contained in:
Peter Eisentraut
2024-03-24 07:37:13 +01:00
parent b1fe8efdf1
commit 34768ee361
16 changed files with 2790 additions and 118 deletions

View File

@ -2728,7 +2728,8 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
</para>
<para>
This constraint is defined with <literal>WITHOUT OVERLAPS</literal>
(for primary keys and unique constraints).
(for primary keys and unique constraints) or <literal>PERIOD</literal>
(for foreign keys).
</para></entry>
</row>

View File

@ -81,7 +81,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
UNIQUE [ NULLS [ NOT ] DISTINCT ] ( <replaceable class="parameter">column_name</replaceable> [, ... ] [, <replaceable class="parameter">column_name</replaceable> WITHOUT OVERLAPS ] ) <replaceable class="parameter">index_parameters</replaceable> |
PRIMARY KEY ( <replaceable class="parameter">column_name</replaceable> [, ... ] [, <replaceable class="parameter">column_name</replaceable> WITHOUT OVERLAPS ] ) <replaceable class="parameter">index_parameters</replaceable> |
EXCLUDE [ USING <replaceable class="parameter">index_method</replaceable> ] ( <replaceable class="parameter">exclude_element</replaceable> WITH <replaceable class="parameter">operator</replaceable> [, ... ] ) <replaceable class="parameter">index_parameters</replaceable> [ WHERE ( <replaceable class="parameter">predicate</replaceable> ) ] |
FOREIGN KEY ( <replaceable class="parameter">column_name</replaceable> [, ... ] ) REFERENCES <replaceable class="parameter">reftable</replaceable> [ ( <replaceable class="parameter">refcolumn</replaceable> [, ... ] ) ]
FOREIGN KEY ( <replaceable class="parameter">column_name</replaceable> [, ... ] [, PERIOD <replaceable class="parameter">column_name</replaceable> ] ) REFERENCES <replaceable class="parameter">reftable</replaceable> [ ( <replaceable class="parameter">refcolumn</replaceable> [, ... ] [, PERIOD <replaceable class="parameter">column_name</replaceable> ] ) ]
[ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE <replaceable
class="parameter">referential_action</replaceable> ] [ ON UPDATE <replaceable class="parameter">referential_action</replaceable> ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
@ -1152,8 +1152,8 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
<varlistentry id="sql-createtable-parms-references">
<term><literal>REFERENCES <replaceable class="parameter">reftable</replaceable> [ ( <replaceable class="parameter">refcolumn</replaceable> ) ] [ MATCH <replaceable class="parameter">matchtype</replaceable> ] [ ON DELETE <replaceable class="parameter">referential_action</replaceable> ] [ ON UPDATE <replaceable class="parameter">referential_action</replaceable> ]</literal> (column constraint)</term>
<term><literal>FOREIGN KEY ( <replaceable class="parameter">column_name</replaceable> [, ... ] )
REFERENCES <replaceable class="parameter">reftable</replaceable> [ ( <replaceable class="parameter">refcolumn</replaceable> [, ... ] ) ]
<term><literal>FOREIGN KEY ( <replaceable class="parameter">column_name</replaceable> [, ... ] [, PERIOD <replaceable class="parameter">column_name</replaceable> ] )
REFERENCES <replaceable class="parameter">reftable</replaceable> [ ( <replaceable class="parameter">refcolumn</replaceable> [, ... ] [, PERIOD <replaceable class="parameter">column_name</replaceable> ] ) ]
[ MATCH <replaceable class="parameter">matchtype</replaceable> ]
[ ON DELETE <replaceable class="parameter">referential_action</replaceable> ]
[ ON UPDATE <replaceable class="parameter">referential_action</replaceable> ]</literal>
@ -1169,7 +1169,30 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
primary key of the <replaceable class="parameter">reftable</replaceable>
is used. Otherwise, the <replaceable class="parameter">refcolumn</replaceable>
list must refer to the columns of a non-deferrable unique or primary key
constraint or be the columns of a non-partial unique index. The user
constraint or be the columns of a non-partial unique index.
</para>
<para>
If the last column is marked with <literal>PERIOD</literal>, it is
treated in a special way. While the non-<literal>PERIOD</literal>
columns are compared for equality (and there must be at least one of
them), the <literal>PERIOD</literal> column is not. Instead, the
constraint is considered satisfied if the referenced table has matching
records (based on the non-<literal>PERIOD</literal> parts of the key)
whose combined <literal>PERIOD</literal> values completely cover the
referencing record's. In other words, the reference must have a
referent for its entire duration. This column must be a range or
multirange type. In addition, the referenced table must have a primary
key or unique constraint declared with <literal>WITHOUT
OVERLAPS</literal>. Finally, if one side of the foreign key uses
<literal>PERIOD</literal>, the other side must too. If the <replaceable
class="parameter">refcolumn</replaceable> list is omitted, the
<literal>WITHOUT OVERLAPS</literal> part of the primary key is treated
as if marked with <literal>PERIOD</literal>.
</para>
<para>
The user
must have <literal>REFERENCES</literal> permission on the referenced
table (either the whole table, or the specific referenced columns). The
addition of a foreign key constraint requires a
@ -1243,6 +1266,10 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
values of the referencing column(s) to the new values of the
referenced columns, respectively.
</para>
<para>
In a temporal foreign key, this option is not supported.
</para>
</listitem>
</varlistentry>
@ -1254,6 +1281,10 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
referencing columns, to null. A subset of columns can only be
specified for <literal>ON DELETE</literal> actions.
</para>
<para>
In a temporal foreign key, this option is not supported.
</para>
</listitem>
</varlistentry>
@ -1267,6 +1298,10 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
(There must be a row in the referenced table matching the default
values, if they are not null, or the operation will fail.)
</para>
<para>
In a temporal foreign key, this option is not supported.
</para>
</listitem>
</varlistentry>
</variablelist>