Doc: mention foreign keys can reference unique indexes

We seem to have only documented a foreign key can reference the columns of
a primary key or unique constraint.  Here we adjust the documentation
to mention columns in a non-partial unique index can be mentioned too.

The header comment for transformFkeyCheckAttrs() also didn't mention
unique indexes, so fix that too.  In passing make that header comment
reflect reality in the various other aspects where it deviated from it.

Bug: 18295
Reported-by: Gilles PARC
Author: Laurenz Albe, David Rowley
Discussion: https://www.postgresql.org/message-id/18295-0ed0fac5c9f7b17b%40postgresql.org
Backpatch-through: 12
This commit is contained in:
David Rowley 2024-01-30 10:15:17 +13:00
parent 97287bdfae
commit c85977d8fe
3 changed files with 32 additions and 21 deletions

View File

@ -1318,16 +1318,16 @@ CREATE TABLE posts (
<para>
A foreign key must reference columns that either are a primary key or
form a unique constraint. This means that the referenced columns always
have an index (the one underlying the primary key or unique constraint);
so checks on whether a referencing row has a match will be efficient.
Since a <command>DELETE</command> of a row from the referenced table
or an <command>UPDATE</command> of a referenced column will require
a scan of the referencing table for rows matching the old value, it
is often a good idea to index the referencing columns too. Because this
is not always needed, and there are many choices available on how
to index, declaration of a foreign key constraint does not
automatically create an index on the referencing columns.
form a unique constraint, or are columns from a non-partial unique index.
This means that the referenced columns always have an index to allow
efficient lookups on whether a referencing row has a match. Since a
<command>DELETE</command> of a row from the referenced table or an
<command>UPDATE</command> of a referenced column will require a scan of
the referencing table for rows matching the old value, it is often a good
idea to index the referencing columns too. Because this is not always
needed, and there are many choices available on how to index, the
declaration of a foreign key constraint does not automatically create an
index on the referencing columns.
</para>
<para>

View File

@ -1165,10 +1165,11 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
column(s) of some row of the referenced table. If the <replaceable
class="parameter">refcolumn</replaceable> list is omitted, the
primary key of the <replaceable class="parameter">reftable</replaceable>
is used. The referenced columns must be the columns of a non-deferrable
unique or primary key constraint in the referenced table. The user
must have <literal>REFERENCES</literal> permission on the referenced table
(either the whole table, or the specific referenced columns). The
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
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
<literal>SHARE ROW EXCLUSIVE</literal> lock on the referenced table.
Note that foreign key constraints cannot be defined between temporary
@ -2305,13 +2306,19 @@ CREATE TABLE cities_partdef
</refsect2>
<refsect2>
<title>Foreign-Key Constraint Actions</title>
<title>Foreign Key Constraints</title>
<para>
The ability to specify column lists in the foreign-key actions
The ability to specify column lists in the foreign key actions
<literal>SET DEFAULT</literal> and <literal>SET NULL</literal> is a
<productname>PostgreSQL</productname> extension.
</para>
<para>
It is a <productname>PostgreSQL</productname> extension that a
foreign key constraint may reference columns of a unique index instead of
columns of a primary key or unique constraint.
</para>
</refsect2>
<refsect2>

View File

@ -12117,15 +12117,19 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
/*
* transformFkeyCheckAttrs -
*
* Make sure that the attributes of a referenced table belong to a unique
* (or primary key) constraint. Return the OID of the index supporting
* the constraint, as well as the opclasses associated with the index
* columns.
* Validate that the 'attnums' columns in the 'pkrel' relation are valid to
* reference as part of a foreign key constraint.
*
* Returns the OID of the unique index supporting the constraint and
* populates the caller-provided 'opclasses' array with the opclasses
* associated with the index columns.
*
* Raises an ERROR on validation failure.
*/
static Oid
transformFkeyCheckAttrs(Relation pkrel,
int numattrs, int16 *attnums,
Oid *opclasses) /* output parameter */
Oid *opclasses)
{
Oid indexoid = InvalidOid;
bool found = false;