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.
This commit is contained in:
parent
5ce8ab96f5
commit
981a7d32d1
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* The PerformAddAttribute() code, like most of the relation
|
* The PerformAddAttribute() code, like most of the relation
|
||||||
@ -1287,6 +1287,12 @@ AlterTableAddConstraint(char *relationName,
|
|||||||
{
|
{
|
||||||
List *attrl;
|
List *attrl;
|
||||||
|
|
||||||
|
/* 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 */
|
/* go through the fkconstraint->pk_attrs list */
|
||||||
foreach(attrl, fkconstraint->pk_attrs)
|
foreach(attrl, fkconstraint->pk_attrs)
|
||||||
{
|
{
|
||||||
@ -1309,6 +1315,7 @@ AlterTableAddConstraint(char *relationName,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ReleaseSysCache(indexTuple);
|
ReleaseSysCache(indexTuple);
|
||||||
if (found)
|
if (found)
|
||||||
break;
|
break;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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,6 +1209,13 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
|
|||||||
List *pkattrs;
|
List *pkattrs;
|
||||||
Ident *pkattr;
|
Ident *pkattr;
|
||||||
if (ind->unique) {
|
if (ind->unique) {
|
||||||
|
int count=0;
|
||||||
|
foreach(indparms, ind->indexParams) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (count!=length(fkconstraint->pk_attrs))
|
||||||
|
found=0;
|
||||||
|
else {
|
||||||
foreach(pkattrs, fkconstraint->pk_attrs) {
|
foreach(pkattrs, fkconstraint->pk_attrs) {
|
||||||
found=0;
|
found=0;
|
||||||
pkattr=lfirst(pkattrs);
|
pkattr=lfirst(pkattrs);
|
||||||
@ -1223,6 +1230,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (found)
|
if (found)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2634,6 +2642,10 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint)
|
|||||||
{
|
{
|
||||||
List *attrl;
|
List *attrl;
|
||||||
|
|
||||||
|
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 */
|
/* go through the fkconstraint->pk_attrs list */
|
||||||
foreach(attrl, fkconstraint->pk_attrs)
|
foreach(attrl, fkconstraint->pk_attrs)
|
||||||
{
|
{
|
||||||
@ -2656,6 +2668,7 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ReleaseSysCache(indexTuple);
|
ReleaseSysCache(indexTuple);
|
||||||
if (found)
|
if (found)
|
||||||
break;
|
break;
|
||||||
|
@ -273,6 +273,9 @@ SELECT unique1 FROM tenk1 WHERE unique1 < 5;
|
|||||||
CREATE TABLE tmp2 (a int primary key);
|
CREATE TABLE tmp2 (a int primary key);
|
||||||
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'tmp2_pkey' for table 'tmp2'
|
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'tmp2_pkey' for table 'tmp2'
|
||||||
CREATE TABLE tmp3 (a int, b int);
|
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 rows into tmp2 (pktable)
|
||||||
INSERT INTO tmp2 values (1);
|
INSERT INTO tmp2 values (1);
|
||||||
INSERT INTO tmp2 values (2);
|
INSERT INTO tmp2 values (2);
|
||||||
@ -299,6 +302,13 @@ DELETE FROM tmp3 where a=5;
|
|||||||
-- Try (and succeed)
|
-- Try (and succeed)
|
||||||
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 ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s)
|
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;
|
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"
|
||||||
NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "tmp2"
|
NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "tmp2"
|
||||||
|
@ -703,3 +703,12 @@ ERROR: table "fktable_fail1" does not exist
|
|||||||
DROP TABLE FKTABLE_FAIL2;
|
DROP TABLE FKTABLE_FAIL2;
|
||||||
ERROR: table "fktable_fail2" does not exist
|
ERROR: table "fktable_fail2" does not exist
|
||||||
DROP TABLE PKTABLE;
|
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;
|
||||||
|
@ -169,6 +169,10 @@ CREATE TABLE tmp2 (a int primary key);
|
|||||||
|
|
||||||
CREATE TABLE tmp3 (a int, b int);
|
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 rows into tmp2 (pktable)
|
||||||
INSERT INTO tmp2 values (1);
|
INSERT INTO tmp2 values (1);
|
||||||
INSERT INTO tmp2 values (2);
|
INSERT INTO tmp2 values (2);
|
||||||
@ -195,6 +199,15 @@ DELETE FROM tmp3 where a=5;
|
|||||||
-- Try (and succeed)
|
-- Try (and succeed)
|
||||||
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;
|
||||||
|
|
||||||
|
-- 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 tmp3;
|
||||||
|
|
||||||
DROP TABLE tmp2;
|
DROP TABLE tmp2;
|
||||||
|
@ -418,3 +418,10 @@ CREATE TABLE FKTABLE_FAIL2 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest1)
|
|||||||
DROP TABLE FKTABLE_FAIL1;
|
DROP TABLE FKTABLE_FAIL1;
|
||||||
DROP TABLE FKTABLE_FAIL2;
|
DROP TABLE FKTABLE_FAIL2;
|
||||||
DROP TABLE PKTABLE;
|
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user