Doc: mention foreign keys can reference unique indexes
authorDavid Rowley
Mon, 29 Jan 2024 21:15:51 +0000 (10:15 +1300)
committerDavid Rowley
Mon, 29 Jan 2024 21:15:51 +0000 (10:15 +1300)
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

doc/src/sgml/ddl.sgml
doc/src/sgml/ref/create_table.sgml
src/backend/commands/tablecmds.c

index 440a899d122a848e8cb0f26aee4160646418806d..11fa9c4a327b32b290d69c3c429ff28c166d6b76 100644 (file)
@@ -1181,16 +1181,16 @@ CREATE TABLE posts (
 
    
     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 DELETE of a row from the referenced table
-    or an UPDATE 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
+    DELETE of a row from the referenced table or an
+    UPDATE 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.
    
 
    
index 10ef699fab92016188d20fa335c874f017ea2403..6a15676d882adff63fa908cc2a46317544e162a3 100644 (file)
@@ -1137,10 +1137,11 @@ WITH ( MODULUS numeric_literal, REM
       column(s) of some row of the referenced table.  If the 
       class="parameter">refcolumn list is omitted, the
       primary key of the reftable
-      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 REFERENCES permission on the referenced table
-      (either the whole table, or the specific referenced columns).  The
+      is used.  Otherwise, the refcolumn
+      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 REFERENCES permission on the referenced
+      table (either the whole table, or the specific referenced columns).  The
       addition of a foreign key constraint requires a
       SHARE ROW EXCLUSIVE lock on the referenced table.
       Note that foreign key constraints cannot be defined between temporary
@@ -2277,13 +2278,19 @@ CREATE TABLE cities_partdef
   
 
   
-   Foreign<span class="marked">-Key Constraint Action</span>s
+   Foreign<span class="marked"> Key Constraint</span>s
 
    
-    The ability to specify column lists in the foreign-key actions
+    The ability to specify column lists in the foreign key actions
     SET DEFAULT and SET NULL is a
     PostgreSQL extension.
    
+
+   
+    It is a PostgreSQL extension that a
+    foreign key constraint may reference columns of a unique index instead of
+    columns of a primary key or unique constraint.
+   
   
 
   
index 25f3a3d1948eaf24d488b15b90180d9fc93da646..90a5238c4d4953b19d31267f335e7d5b6ff5c31b 100644 (file)
@@ -11443,15 +11443,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;