pgsql: Change the names generated for child foreign key constraints.

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: pgsql-committers(at)lists(dot)postgresql(dot)org
Subject: pgsql: Change the names generated for child foreign key constraints.
Date: 2025-04-23 16:03:09
Message-ID: E1u7cZ2-001Qcm-2H@gemulon.postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-committers

Change the names generated for child foreign key constraints.

When a foreign key constraint is placed on a partitioned table, we
actually make two pg_constraint entries associated with that table.
(I have my doubts about the wisdom of that, but it's been like that
since v12 and post-feature-freeze is no time to be messing with such
entrenched decisions.) The second "child" entry always had a name
generated according to the default rule, "table_column(s)_fkey[nnn]",
even if the primary entry had an unrelated user-specified name. The
trouble with doing that is that the default name could collide with
the user-specified name of some other constraint on the same table.
While we were willing to adjust the generated name to avoid
collisions, that only helps if it's made second; if it's made first
then creation of the other constraint would fail, potentially causing
dump/reload or pg_upgrade failures.

The core of the problem here is that we're infringing on user
namespace, so I doubt that there's any 100% solution other than to
find a way to not need the "child" entry. In the meantime, it seems
like it'd be an improvement to make the child's name be the name of
the parent constraint with an underscore and digit(s) appended as
necessary to make it unique. This rule can in theory fail in the same
way, but it seems much less probable; for one thing, this rule is
guaranteed not to match primary entries having auto-generated names.
(While an auto-generated primary name isn't user-specified to begin
with, it acts like that during dump/reload, so collisions against such
names are definitely possible.)

An additional bonus, visible in some of the regression test cases
that change here, arises from the fact that some error messages
cite the child constraint's name not the parent's. In the
previous approach the two names could be completely unrelated,
leading to user confusion --- the more so since psql's \d command
hides child constraints. With this approach it's hopefully much
clearer which constraint-the-user-knows-about is failing.

However, that does mean that there's user-visible behavior change
occurring here, making it seem like not something to back-patch.
I feel it's not too late for v18, though.

Reported-by: Kirill Reshke <reshkekirill(at)gmail(dot)com>
Author: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Reviewed-by: Alvaro Herrera <alvherre(at)kurilemu(dot)de>
Discussion: https://postgr.es/m/CALdSSPhGitjpTfzEMJN-Y2x+Q-5QChSxAsmSJ1-E8mQJLkHOqQ@mail.gmail.com

Branch
------
master

Details
-------
https://git.postgresql.org/pg/commitdiff/3db61db48ef5b8898f7e85f98548fdec79d76524

Modified Files
--------------
src/backend/catalog/pg_constraint.c | 9 ++-
src/backend/commands/tablecmds.c | 10 +--
.../expected/detach-partition-concurrently-2.out | 2 +-
.../expected/detach-partition-concurrently-4.out | 2 +-
src/test/isolation/expected/fk-partitioned-1.out | 14 ++--
src/test/isolation/expected/fk-partitioned-2.out | 4 +-
src/test/regress/expected/constraints.out | 6 +-
src/test/regress/expected/foreign_key.out | 82 +++++++++++-----------
src/test/regress/expected/without_overlaps.out | 8 +--
src/test/regress/sql/foreign_key.sql | 4 +-
10 files changed, 74 insertions(+), 67 deletions(-)

Browse pgsql-committers by date

  From Date Subject
Next Message Robert Haas 2025-04-23 16:12:11 Re: pgsql: Add function to get memory context stats for processes
Previous Message Nathan Bossart 2025-04-23 15:43:34 Re: vacuumdb --missing-stats-only and pg_upgrade from PG13