Commit ac355d55 authored by Tom Lane's avatar Tom Lane

Move most of the error checking for foreign-key constraints out of

parse analysis and into the execution code (in tablecmds.c).  This
eliminates a lot of unreasonably complex code that needed to have two
or more execution paths in case it was dealing with a not-yet-created
table column vs. an already-existing one.  The execution code is always
dealing with already-created tables and so needs only one case.  This
also eliminates some potential race conditions (the table wasn't locked
between parse analysis and execution), makes it easy to fix the gripe
about wrong referenced-column names generating a misleading error message,
and lets us easily add a dependency from the foreign-key constraint to
the unique index that it requires the referenced table to have.  (Cf.
complaint from Kris Jurka 12-Sep-2002 on pgsql-bugs.)

Also, third try at building a deletion mechanism that is not sensitive
to the order in which pg_depend entries are visited.  Adding the above-
mentioned dependency exposed the folly of what dependency.c had been
doing: it failed for cases where B depends on C while both auto-depend
on A.  Dropping A should succeed in this case, but was failing if C
happened to be visited before B.  It appears the only solution is two
separate walks over the dependency tree.
parent e303a2db
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.229 2002/09/19 23:40:56 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.230 2002/09/22 00:37:09 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -1342,6 +1342,7 @@ StoreRelCheck(Relation rel, char *ccname, char *ccbin) ...@@ -1342,6 +1342,7 @@ StoreRelCheck(Relation rel, char *ccname, char *ccbin)
' ', ' ',
' ', ' ',
' ', ' ',
InvalidOid, /* no associated index */
expr, /* Tree form check constraint */ expr, /* Tree form check constraint */
ccbin, /* Binary form check constraint */ ccbin, /* Binary form check constraint */
ccsrc); /* Source form check constraint */ ccsrc); /* Source form check constraint */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.196 2002/09/04 20:31:14 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.197 2002/09/22 00:37:09 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -693,6 +693,7 @@ index_create(Oid heapRelationId, ...@@ -693,6 +693,7 @@ index_create(Oid heapRelationId,
' ', ' ',
' ', ' ',
' ', ' ',
InvalidOid, /* no associated index */
NULL, /* no check constraint */ NULL, /* no check constraint */
NULL, NULL,
NULL); NULL);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.6 2002/09/04 20:31:14 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.7 2002/09/22 00:37:09 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,7 @@ CreateConstraintEntry(const char *constraintName, ...@@ -53,6 +53,7 @@ CreateConstraintEntry(const char *constraintName,
char foreignUpdateType, char foreignUpdateType,
char foreignDeleteType, char foreignDeleteType,
char foreignMatchType, char foreignMatchType,
Oid indexRelId,
Node *conExpr, Node *conExpr,
const char *conBin, const char *conBin,
const char *conSrc) const char *conSrc)
...@@ -216,6 +217,21 @@ CreateConstraintEntry(const char *constraintName, ...@@ -216,6 +217,21 @@ CreateConstraintEntry(const char *constraintName,
} }
} }
if (OidIsValid(indexRelId))
{
/*
* Register normal dependency on the unique index that supports
* a foreign-key constraint.
*/
ObjectAddress relobject;
relobject.classId = RelOid_pg_class;
relobject.objectId = indexRelId;
relobject.objectSubId = 0;
recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
}
if (conExpr != NULL) if (conExpr != NULL)
{ {
/* /*
......
This diff is collapsed.
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_constraint.h,v 1.3 2002/09/04 20:31:37 momjian Exp $ * $Id: pg_constraint.h,v 1.4 2002/09/22 00:37:09 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -159,6 +159,7 @@ extern Oid CreateConstraintEntry(const char *constraintName, ...@@ -159,6 +159,7 @@ extern Oid CreateConstraintEntry(const char *constraintName,
char foreignUpdateType, char foreignUpdateType,
char foreignDeleteType, char foreignDeleteType,
char foreignMatchType, char foreignMatchType,
Oid indexRelId,
Node *conExpr, Node *conExpr,
const char *conBin, const char *conBin,
const char *conSrc); const char *conSrc);
......
...@@ -322,7 +322,7 @@ ERROR: ALTER TABLE: column "c" referenced in foreign key constraint does not ex ...@@ -322,7 +322,7 @@ ERROR: ALTER TABLE: column "c" referenced in foreign key constraint does not ex
-- Try (and fail) to add constraint due to invalide destination columns explicitly given -- Try (and fail) to add constraint due to invalide destination columns explicitly given
ALTER TABLE tmp3 add constraint tmpconstr foreign key(a) references tmp2(b) match full; ALTER TABLE tmp3 add constraint tmpconstr foreign key(a) references tmp2(b) match full;
NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s) NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: UNIQUE constraint matching given keys for referenced table "tmp2" not found ERROR: ALTER TABLE: column "b" referenced in foreign key constraint does not exist
-- Try (and fail) to add constraint due to invalid data -- Try (and fail) to add constraint due to invalid data
ALTER TABLE tmp3 add constraint tmpconstr foreign key (a) references tmp2 match full; ALTER TABLE tmp3 add constraint tmpconstr foreign key (a) references tmp2 match full;
NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s) NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
...@@ -908,10 +908,10 @@ NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s) ...@@ -908,10 +908,10 @@ NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: ALTER TABLE: column "........pg.dropped.1........" referenced in foreign key constraint does not exist ERROR: ALTER TABLE: column "........pg.dropped.1........" referenced in foreign key constraint does not exist
alter table atacc2 add foreign key (id) references atacc1(a); alter table atacc2 add foreign key (id) references atacc1(a);
NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s) NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: UNIQUE constraint matching given keys for referenced table "atacc1" not found ERROR: ALTER TABLE: column "a" referenced in foreign key constraint does not exist
alter table atacc2 add foreign key (id) references atacc1("........pg.dropped.1........"); alter table atacc2 add foreign key (id) references atacc1("........pg.dropped.1........");
NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s) NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: UNIQUE constraint matching given keys for referenced table "atacc1" not found ERROR: ALTER TABLE: column "........pg.dropped.1........" referenced in foreign key constraint does not exist
drop table atacc2; drop table atacc2;
create index "testing_idx" on atacc1(a); create index "testing_idx" on atacc1(a);
ERROR: DefineIndex: attribute "a" not found ERROR: DefineIndex: attribute "a" not found
......
...@@ -692,7 +692,7 @@ NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) ...@@ -692,7 +692,7 @@ NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: CREATE TABLE: column "ftest2" referenced in foreign key constraint does not exist ERROR: CREATE TABLE: column "ftest2" referenced in foreign key constraint does not exist
CREATE TABLE FKTABLE_FAIL2 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest1) REFERENCES PKTABLE(ptest2)); CREATE TABLE FKTABLE_FAIL2 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest1) REFERENCES PKTABLE(ptest2));
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: UNIQUE constraint matching given keys for referenced table "pktable" not found ERROR: CREATE TABLE: column "ptest2" referenced in foreign key constraint does not exist
DROP TABLE FKTABLE_FAIL1; DROP TABLE FKTABLE_FAIL1;
ERROR: table "fktable_fail1" does not exist ERROR: table "fktable_fail1" does not exist
DROP TABLE FKTABLE_FAIL2; DROP TABLE FKTABLE_FAIL2;
......
...@@ -548,7 +548,6 @@ DROP VIEW atestv1; ...@@ -548,7 +548,6 @@ DROP VIEW atestv1;
DROP VIEW atestv2; DROP VIEW atestv2;
-- this should cascade to drop atestv4 -- this should cascade to drop atestv4
DROP VIEW atestv3 CASCADE; DROP VIEW atestv3 CASCADE;
NOTICE: Drop cascades to rule _RETURN on view atestv3
NOTICE: Drop cascades to rule _RETURN on view atestv4 NOTICE: Drop cascades to rule _RETURN on view atestv4
NOTICE: Drop cascades to view atestv4 NOTICE: Drop cascades to view atestv4
-- this should complain "does not exist" -- this should complain "does not exist"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment