Skip to content

Commit f177660

Browse files
committed
Include all columns in default names for foreign key constraints
When creating a name for a foreign key constraint when none is specified, use all column names instead of only the first one, similar to how it is already done for index names. Author: Paul Martinez <hellopfm@gmail.com> Reviewed-by: Peter Eisentraut <peter.eisentraut@2ndquadrant.com> Discussion: https://www.postgresql.org/message-id/flat/CAF+2_SFjky6XRfLNRXpkG97W6PRbOO_mjAxqXzAAimU=c7w7_A@mail.gmail.com
1 parent bbb96c3 commit f177660

File tree

7 files changed

+152
-76
lines changed

7 files changed

+152
-76
lines changed

src/backend/commands/indexcmds.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2109,7 +2109,8 @@ ChooseIndexName(const char *tabname, Oid namespaceId,
21092109
* We know that less than NAMEDATALEN characters will actually be used,
21102110
* so we can truncate the result once we've generated that many.
21112111
*
2112-
* XXX See also ChooseExtendedStatisticNameAddition.
2112+
* XXX See also ChooseForeignKeyConstraintNameAddition and
2113+
* ChooseExtendedStatisticNameAddition.
21132114
*/
21142115
static char *
21152116
ChooseIndexNameAddition(List *colnames)

src/backend/commands/statscmds.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,8 @@ ChooseExtendedStatisticName(const char *name1, const char *name2,
498498
* We know that less than NAMEDATALEN characters will actually be used,
499499
* so we can truncate the result once we've generated that many.
500500
*
501-
* XXX see also ChooseIndexNameAddition.
501+
* XXX see also ChooseForeignKeyConstraintNameAddition and
502+
* ChooseIndexNameAddition.
502503
*/
503504
static char *
504505
ChooseExtendedStatisticNameAddition(List *exprs)

src/backend/commands/tablecmds.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ static ObjectAddress ATExecAddConstraint(List **wqueue,
402402
AlteredTableInfo *tab, Relation rel,
403403
Constraint *newConstraint, bool recurse, bool is_readd,
404404
LOCKMODE lockmode);
405+
static char *ChooseForeignKeyConstraintNameAddition(List *colnames);
405406
static ObjectAddress ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
406407
IndexStmt *stmt, LOCKMODE lockmode);
407408
static ObjectAddress ATAddCheckConstraint(List **wqueue,
@@ -7191,7 +7192,7 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
71917192
else
71927193
newConstraint->conname =
71937194
ChooseConstraintName(RelationGetRelationName(rel),
7194-
strVal(linitial(newConstraint->fk_attrs)),
7195+
ChooseForeignKeyConstraintNameAddition(newConstraint->fk_attrs),
71957196
"fkey",
71967197
RelationGetNamespace(rel),
71977198
NIL);
@@ -7210,6 +7211,45 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
72107211
return address;
72117212
}
72127213

7214+
/*
7215+
* Generate the column-name portion of the constraint name for a new foreign
7216+
* key given the list of column names that reference the referenced
7217+
* table. This will be passed to ChooseConstraintName along with the parent
7218+
* table name and the "fkey" suffix.
7219+
*
7220+
* We know that less than NAMEDATALEN characters will actually be used, so we
7221+
* can truncate the result once we've generated that many.
7222+
*
7223+
* XXX see also ChooseExtendedStatisticNameAddition and
7224+
* ChooseIndexNameAddition.
7225+
*/
7226+
static char *
7227+
ChooseForeignKeyConstraintNameAddition(List *colnames)
7228+
{
7229+
char buf[NAMEDATALEN * 2];
7230+
int buflen = 0;
7231+
ListCell *lc;
7232+
7233+
buf[0] = '\0';
7234+
foreach(lc, colnames)
7235+
{
7236+
const char *name = strVal(lfirst(lc));
7237+
7238+
if (buflen > 0)
7239+
buf[buflen++] = '_'; /* insert _ between names */
7240+
7241+
/*
7242+
* At this point we have buflen <= NAMEDATALEN. name should be less
7243+
* than NAMEDATALEN already, but use strlcpy for paranoia.
7244+
*/
7245+
strlcpy(buf + buflen, name, NAMEDATALEN);
7246+
buflen += strlen(buf + buflen);
7247+
if (buflen >= NAMEDATALEN)
7248+
break;
7249+
}
7250+
return pstrdup(buf);
7251+
}
7252+
72137253
/*
72147254
* Add a check constraint to a single table and its children. Returns the
72157255
* address of the constraint added to the parent relation, if one gets added,

src/test/regress/expected/alter_table.out

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -655,26 +655,26 @@ CREATE TEMP TABLE PKTABLE (ptest1 int, ptest2 inet,
655655
-- This should fail, because we just chose really odd types
656656
CREATE TEMP TABLE FKTABLE (ftest1 cidr, ftest2 timestamp);
657657
ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) references pktable;
658-
ERROR: foreign key constraint "fktable_ftest1_fkey" cannot be implemented
658+
ERROR: foreign key constraint "fktable_ftest1_ftest2_fkey" cannot be implemented
659659
DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: cidr and integer.
660660
DROP TABLE FKTABLE;
661661
-- Again, so should this...
662662
CREATE TEMP TABLE FKTABLE (ftest1 cidr, ftest2 timestamp);
663663
ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2)
664664
references pktable(ptest1, ptest2);
665-
ERROR: foreign key constraint "fktable_ftest1_fkey" cannot be implemented
665+
ERROR: foreign key constraint "fktable_ftest1_ftest2_fkey" cannot be implemented
666666
DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: cidr and integer.
667667
DROP TABLE FKTABLE;
668668
-- This fails because we mixed up the column ordering
669669
CREATE TEMP TABLE FKTABLE (ftest1 int, ftest2 inet);
670670
ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2)
671671
references pktable(ptest2, ptest1);
672-
ERROR: foreign key constraint "fktable_ftest1_fkey" cannot be implemented
672+
ERROR: foreign key constraint "fktable_ftest1_ftest2_fkey" cannot be implemented
673673
DETAIL: Key columns "ftest1" and "ptest2" are of incompatible types: integer and inet.
674674
-- As does this...
675675
ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest2, ftest1)
676676
references pktable(ptest1, ptest2);
677-
ERROR: foreign key constraint "fktable_ftest2_fkey" cannot be implemented
677+
ERROR: foreign key constraint "fktable_ftest2_ftest1_fkey" cannot be implemented
678678
DETAIL: Key columns "ftest2" and "ptest1" are of incompatible types: inet and integer.
679679
DROP TABLE FKTABLE;
680680
DROP TABLE PKTABLE;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy