]> granicus.if.org Git - postgresql/commitdiff
From Stephan Szabo:
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 5 Dec 2000 19:57:56 +0000 (19:57 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 5 Dec 2000 19:57:56 +0000 (19:57 +0000)
I believe this should fix the issue that Philip Warner
noticed about the check for unique constraints meeting the
referenced keys of a foreign key constraint allowing the
specification of a subset of a foreign key instead of
rejecting it.  I also added tests for a base case of
this to the foreign key and alter table tests and patches
for expected output.

src/backend/commands/command.c
src/backend/parser/analyze.c
src/test/regress/expected/alter_table.out
src/test/regress/expected/foreign_key.out
src/test/regress/sql/alter_table.sql
src/test/regress/sql/foreign_key.sql

index 42f05f0761cf0c2c013d987d95368602c88b175b..78a3d5e1a75fe198f4c5b19d39cd21cb1b35ffc8 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.112 2000/11/16 22:30:19 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.113 2000/12/05 19:57:55 tgl Exp $
  *
  * NOTES
  *       The PerformAddAttribute() code, like most of the relation
@@ -1287,26 +1287,33 @@ AlterTableAddConstraint(char *relationName,
                                {
                                        List       *attrl;
 
-                                       /* go through the fkconstraint->pk_attrs list */
-                                       foreach(attrl, fkconstraint->pk_attrs)
-                                       {
-                                               Ident *attr=lfirst(attrl);
-                                               found = false;
-                                               for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
+                                       /* Make sure this index has the same number of keys -- It obviously
+                                        * won't match otherwise. */
+                                       for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++);
+                                       if (i!=length(fkconstraint->pk_attrs))
+                                               found=false;
+                                       else {
+                                               /* go through the fkconstraint->pk_attrs list */
+                                               foreach(attrl, fkconstraint->pk_attrs)
                                                {
-                                                       int pkattno = indexStruct->indkey[i];
-                                                       if (pkattno>0)
+                                                       Ident *attr=lfirst(attrl);
+                                                       found = false;
+                                                       for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
                                                        {
-                                                               char *name = NameStr(rel_attrs[pkattno-1]->attname);
-                                                               if (strcmp(name, attr->name)==0)
+                                                               int pkattno = indexStruct->indkey[i];
+                                                               if (pkattno>0)
                                                                {
-                                                                       found = true;
-                                                                       break;
+                                                                       char *name = NameStr(rel_attrs[pkattno-1]->attname);
+                                                                       if (strcmp(name, attr->name)==0)
+                                                                       {
+                                                                               found = true;
+                                                                               break;
+                                                                       }
                                                                }
                                                        }
+                                                       if (!found)
+                                                               break;
                                                }
-                                               if (!found)
-                                                       break;
                                        }
                                }
                                ReleaseSysCache(indexTuple);
index dcd523475440cce849e8e1110f57cc59fffea208..e4834158765d3da6e621fc366c8768e8ce29ed12 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $Id: analyze.c,v 1.169 2000/12/05 19:15:10 tgl Exp $
+ *     $Id: analyze.c,v 1.170 2000/12/05 19:57:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1209,18 +1209,26 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
                                                List *pkattrs;
                                                Ident *pkattr;
                                                if (ind->unique) {
-                                                       foreach(pkattrs, fkconstraint->pk_attrs) {
+                                                       int count=0;
+                                                       foreach(indparms, ind->indexParams) {
+                                                               count++;
+                                                       }
+                                                       if (count!=length(fkconstraint->pk_attrs))
                                                                found=0;
-                                                               pkattr=lfirst(pkattrs);
-                                                               foreach(indparms, ind->indexParams) {
-                                                                       indparm=lfirst(indparms);
-                                                                       if (strcmp(indparm->name, pkattr->name)==0) {
-                                                                               found=1;
-                                                                               break;
+                                                       else {
+                                                               foreach(pkattrs, fkconstraint->pk_attrs) {
+                                                                       found=0;
+                                                                       pkattr=lfirst(pkattrs);
+                                                                       foreach(indparms, ind->indexParams) {
+                                                                               indparm=lfirst(indparms);
+                                                                               if (strcmp(indparm->name, pkattr->name)==0) {
+                                                                                       found=1;
+                                                                                       break;
+                                                                               }
                                                                        }
+                                                                       if (!found)
+                                                                               break;
                                                                }
-                                                               if (!found)
-                                                                       break;
                                                        }
                                                }
                                                if (found)
@@ -2634,26 +2642,31 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint)
                {
                        List *attrl;
 
-                       /* go through the fkconstraint->pk_attrs list */
-                       foreach(attrl, fkconstraint->pk_attrs)
-                       {
-                               Ident *attr=lfirst(attrl);
-                               found = false;
-                               for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
+                       for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++);
+                       if (i!=length(fkconstraint->pk_attrs))
+                               found=false;
+                       else {
+                               /* go through the fkconstraint->pk_attrs list */
+                               foreach(attrl, fkconstraint->pk_attrs)
                                {
-                                       int             pkattno = indexStruct->indkey[i];
-                                       if (pkattno>0)
+                                       Ident *attr=lfirst(attrl);
+                                       found = false;
+                                       for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
                                        {
-                                               char *name = NameStr(pkrel_attrs[pkattno - 1]->attname);
-                                               if (strcmp(name, attr->name)==0)
+                                               int             pkattno = indexStruct->indkey[i];
+                                               if (pkattno>0)
                                                {
-                                                       found = true;
-                                                       break;
+                                                       char *name = NameStr(pkrel_attrs[pkattno - 1]->attname);
+                                                       if (strcmp(name, attr->name)==0)
+                                                       {
+                                                               found = true;
+                                                               break;
+                                                       }
                                                }
                                        }
+                                       if (!found)
+                                               break;
                                }
-                               if (!found)
-                                       break;
                        }
                }
                ReleaseSysCache(indexTuple);
index d79a65c983a9b7d361b12b63a775bafa7bacfd8e..082a0be4782128dcf1f1336bd68e39bb19ecd2a9 100644 (file)
@@ -273,6 +273,9 @@ SELECT unique1 FROM tenk1 WHERE unique1 < 5;
 CREATE TABLE tmp2 (a int primary key);
 NOTICE:  CREATE TABLE/PRIMARY KEY will create implicit index 'tmp2_pkey' for table 'tmp2'
 CREATE TABLE tmp3 (a int, b int);
+CREATE TABLE tmp4 (a int, b int, unique(a,b));
+NOTICE:  CREATE TABLE/UNIQUE will create implicit index 'tmp4_a_key' for table 'tmp4'
+CREATE TABLE tmp5 (a int, b int);
 -- Insert rows into tmp2 (pktable)
 INSERT INTO tmp2 values (1);
 INSERT INTO tmp2 values (2);
@@ -299,6 +302,13 @@ DELETE FROM tmp3 where a=5;
 -- Try (and succeed)
 ALTER TABLE tmp3 add constraint tmpconstr foreign key (a) references tmp2 match full;
 NOTICE:  ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s)
+-- Try (and fail) to create constraint from tmp5(a) to tmp4(a) - unique constraint on
+-- tmp4 is a,b
+ALTER TABLE tmp5 add constraint tmpconstr foreign key(a) references tmp4(a) match full;
+NOTICE:  ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s)
+ERROR:  UNIQUE constraint matching given keys for referenced table "tmp4" not found
+DROP TABLE tmp5;
+DROP TABLE tmp4;
 DROP TABLE tmp3;
 NOTICE:  DROP TABLE implicitly drops referential integrity trigger from table "tmp2"
 NOTICE:  DROP TABLE implicitly drops referential integrity trigger from table "tmp2"
index 412632475566ed6b64084f1f80cb7d613db55b50..075b6aa2f8706cc572fe244bfab05d9367e9b7a6 100644 (file)
@@ -703,3 +703,12 @@ ERROR:  table "fktable_fail1" does not exist
 DROP TABLE FKTABLE_FAIL2;
 ERROR:  table "fktable_fail2" does not exist
 DROP TABLE PKTABLE;
+-- Test for referencing column number smaller than referenced constraint
+CREATE TABLE PKTABLE (ptest1 int, ptest2 int, UNIQUE(ptest1, ptest2));
+NOTICE:  CREATE TABLE/UNIQUE will create implicit index 'pktable_ptest1_key' for table 'pktable'
+CREATE TABLE FKTABLE_FAIL1 (ftest1 int REFERENCES pktable(ptest1));
+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
+DROP TABLE FKTABLE_FAIL1;
+ERROR:  table "fktable_fail1" does not exist
+DROP TABLE PKTABLE;
index cb7b9a2a469e055b05b4a7fdda6e53202c314409..f90710f8d96ea623a22c247ab5dca1a42175ba2e 100644 (file)
@@ -169,6 +169,10 @@ CREATE TABLE tmp2 (a int primary key);
 
 CREATE TABLE tmp3 (a int, b int);
 
+CREATE TABLE tmp4 (a int, b int, unique(a,b));
+
+CREATE TABLE tmp5 (a int, b int);
+
 -- Insert rows into tmp2 (pktable)
 INSERT INTO tmp2 values (1);
 INSERT INTO tmp2 values (2);
@@ -195,6 +199,15 @@ DELETE FROM tmp3 where a=5;
 -- Try (and succeed)
 ALTER TABLE tmp3 add constraint tmpconstr foreign key (a) references tmp2 match full;
 
+-- Try (and fail) to create constraint from tmp5(a) to tmp4(a) - unique constraint on
+-- tmp4 is a,b
+
+ALTER TABLE tmp5 add constraint tmpconstr foreign key(a) references tmp4(a) match full;
+
+DROP TABLE tmp5;
+
+DROP TABLE tmp4;
+
 DROP TABLE tmp3;
 
 DROP TABLE tmp2;
index ac29e50579c7c24b6e945a8c51a6b3bf1ffad9c1..91ff0aafe58c0efd13c5cbeeddab7a41f1c4565f 100644 (file)
@@ -418,3 +418,10 @@ CREATE TABLE FKTABLE_FAIL2 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest1)
 DROP TABLE FKTABLE_FAIL1;
 DROP TABLE FKTABLE_FAIL2;
 DROP TABLE PKTABLE;
+
+-- Test for referencing column number smaller than referenced constraint
+CREATE TABLE PKTABLE (ptest1 int, ptest2 int, UNIQUE(ptest1, ptest2));
+CREATE TABLE FKTABLE_FAIL1 (ftest1 int REFERENCES pktable(ptest1));
+
+DROP TABLE FKTABLE_FAIL1;
+DROP TABLE PKTABLE;