aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-12-05 19:57:56 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-12-05 19:57:56 +0000
commit981a7d32d1326325caefa3e22df090e48f54cc6c (patch)
treefe6d1347a00c32f2da5f6fe98df76ff90c7d09f3
parent5ce8ab96f5ba00c061340c26e998f7a272455f6f (diff)
downloadpostgresql-981a7d32d1326325caefa3e22df090e48f54cc6c.tar.gz
postgresql-981a7d32d1326325caefa3e22df090e48f54cc6c.zip
From Stephan Szabo:
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.
-rw-r--r--src/backend/commands/command.c37
-rw-r--r--src/backend/parser/analyze.c61
-rw-r--r--src/test/regress/expected/alter_table.out10
-rw-r--r--src/test/regress/expected/foreign_key.out9
-rw-r--r--src/test/regress/sql/alter_table.sql13
-rw-r--r--src/test/regress/sql/foreign_key.sql7
6 files changed, 98 insertions, 39 deletions
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c
index 42f05f0761c..78a3d5e1a75 100644
--- a/src/backend/commands/command.c
+++ b/src/backend/commands/command.c
@@ -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);
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index dcd52347544..e4834158765 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -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);
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index d79a65c983a..082a0be4782 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -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"
diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out
index 41263247556..075b6aa2f87 100644
--- a/src/test/regress/expected/foreign_key.out
+++ b/src/test/regress/expected/foreign_key.out
@@ -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;
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index cb7b9a2a469..f90710f8d96 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -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;
diff --git a/src/test/regress/sql/foreign_key.sql b/src/test/regress/sql/foreign_key.sql
index ac29e50579c..91ff0aafe58 100644
--- a/src/test/regress/sql/foreign_key.sql
+++ b/src/test/regress/sql/foreign_key.sql
@@ -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;