diff options
| author | Bruce Momjian | 2001-05-09 21:10:39 +0000 |
|---|---|---|
| committer | Bruce Momjian | 2001-05-09 21:10:39 +0000 |
| commit | 8678929c22111863e9d6b836232dc4f69c52d9ae (patch) | |
| tree | c4c42d45a8e338d010be40b03627a812dc2e8df5 /src/test | |
| parent | a0458a91bfc14c77ca7672bab618820a6a8f565c (diff) | |
This patch should catch cases where the types
in referencing and referenced columns of an fk constraint
aren't comparable using '=' at constraint definition time
rather than insert/update time.
Stephan Szabo
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/regress/expected/alter_table.out | 57 | ||||
| -rw-r--r-- | src/test/regress/expected/foreign_key.out | 250 | ||||
| -rw-r--r-- | src/test/regress/sql/alter_table.sql | 36 | ||||
| -rw-r--r-- | src/test/regress/sql/foreign_key.sql | 156 |
4 files changed, 499 insertions, 0 deletions
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index 082a0be4782..dab0c7f9c5c 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -313,3 +313,60 @@ 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" DROP TABLE tmp2; +-- Foreign key adding test with mixed types +CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +CREATE TABLE FKTABLE (ftest1 text); +-- This next should fail, because text=int does not exist +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable; +NOTICE: ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'text' and 'int4' + You will have to retype this query using an explicit cast +-- This should also fail for the same reason, but here we +-- give the column name +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable(ptest1); +NOTICE: ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'text' and 'int4' + You will have to retype this query using an explicit cast +-- This should succeed, even though they are different types +-- because varchar=int does exist +DROP TABLE FKTABLE; +CREATE TABLE FKTABLE (ftest1 varchar); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable; +NOTICE: ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s) +-- As should this +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable(ptest1); +NOTICE: ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s) +DROP TABLE pktable; +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "fktable" +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "fktable" +DROP TABLE fktable; +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, PRIMARY KEY(ptest1, ptest2)); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +-- This should fail, because we just chose really odd types +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 datetime); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) references pktable; +NOTICE: ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'cidr' and 'int4' + You will have to retype this query using an explicit cast +-- Again, so should this... +DROP TABLE FKTABLE; +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 datetime); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) references pktable(ptest1, ptest2); +NOTICE: ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'cidr' and 'int4' + You will have to retype this query using an explicit cast +-- This fails because we mixed up the column ordering +DROP TABLE FKTABLE; +CREATE TABLE FKTABLE (ftest1 int, ftest2 text); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) references pktable(ptest2, ptest1); +NOTICE: ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'int4' and 'text' + You will have to retype this query using an explicit cast +-- As does this... +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest2, ftest1) references pktable(ptest1, ptest2); +NOTICE: ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'text' and 'int4' + You will have to retype this query using an explicit cast +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out index 075b6aa2f87..990c59c90c9 100644 --- a/src/test/regress/expected/foreign_key.out +++ b/src/test/regress/expected/foreign_key.out @@ -712,3 +712,253 @@ ERROR: UNIQUE constraint matching given keys for referenced table "pktable" not DROP TABLE FKTABLE_FAIL1; ERROR: table "fktable_fail1" does not exist DROP TABLE PKTABLE; +-- +-- Tests for mismatched types +-- +-- Basic one column, two table setup +CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +-- This next should fail, because text=int does not exist +CREATE TABLE FKTABLE (ftest1 text REFERENCES pktable); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'text' and 'int4' + You will have to retype this query using an explicit cast +-- This should also fail for the same reason, but here we +-- give the column name +CREATE TABLE FKTABLE (ftest1 text REFERENCES pktable(ptest1)); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'text' and 'int4' + You will have to retype this query using an explicit cast +-- This should succeed, even though they are different types +-- because varchar=int does exist +CREATE TABLE FKTABLE (ftest1 varchar REFERENCES pktable); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +DROP TABLE FKTABLE; +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" +-- As should this +CREATE TABLE FKTABLE (ftest1 varchar REFERENCES pktable(ptest1)); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +DROP TABLE FKTABLE; +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" +DROP TABLE PKTABLE; +-- Two columns, two tables +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, PRIMARY KEY(ptest1, ptest2)); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +-- This should fail, because we just chose really odd types +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 datetime, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'cidr' and 'int4' + You will have to retype this query using an explicit cast +-- Again, so should this... +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 datetime, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2)); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'cidr' and 'int4' + You will have to retype this query using an explicit cast +-- This fails because we mixed up the column ordering +CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'text' and 'int4' + You will have to retype this query using an explicit cast +-- As does this... +CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest1, ptest2)); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'text' and 'int4' + You will have to retype this query using an explicit cast +-- And again.. +CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest2, ptest1)); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'int4' and 'text' + You will have to retype this query using an explicit cast +-- This works... +CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest2, ptest1)); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +DROP TABLE FKTABLE; +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" +-- As does this +CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2)); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +DROP TABLE FKTABLE; +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" +DROP TABLE PKTABLE; +-- Two columns, same table +-- Make sure this still works... +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES pktable(ptest1, ptest2)); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +DROP TABLE PKTABLE; +-- And this, +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES pktable); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +DROP TABLE PKTABLE; +-- This shouldn't (mixed up columns) +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES pktable(ptest2, ptest1)); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'int4' and 'text' + You will have to retype this query using an explicit cast +-- Nor should this... (same reason, we have 4,3 referencing 1,2 which mismatches types +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4, +ptest3) REFERENCES pktable(ptest1, ptest2)); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'text' and 'int4' + You will have to retype this query using an explicit cast +-- Not this one either... Same as the last one except we didn't defined the columns being referenced. +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4, +ptest3) REFERENCES pktable); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'text' and 'int4' + You will have to retype this query using an explicit cast +-- +-- Now some cases with inheritance +-- Basic 2 table case: 1 column of matching types. +create table pktable_base (base1 int not null); +create table pktable (ptest1 int, primary key(base1), unique(base1, ptest1)) inherits (pktable_base); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +NOTICE: CREATE TABLE/UNIQUE will create implicit index 'pktable_base1_key' for table 'pktable' +create table fktable (ftest1 int references pktable(base1)); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +-- now some ins, upd, del +insert into pktable(base1) values (1); +insert into pktable(base1) values (2); +-- let's insert a non-existant fktable value +insert into fktable(ftest1) values (3); +ERROR: <unnamed> referential integrity violation - key referenced from fktable not found in pktable +-- let's make a valid row for that +insert into pktable(base1) values (3); +insert into fktable(ftest1) values (3); +-- let's try removing a row that should fail from pktable +delete from pktable where base1>2; +ERROR: <unnamed> referential integrity violation - key in pktable still referenced from fktable +-- okay, let's try updating all of the base1 values to *4 +-- which should fail. +update pktable set base1=base1*4; +ERROR: <unnamed> referential integrity violation - key in pktable still referenced from fktable +-- okay, let's try an update that should work. +update pktable set base1=base1*4 where base1<3; +-- and a delete that should work +delete from pktable where base1>3; +-- cleanup +drop table fktable; +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" +delete from pktable; +-- Now 2 columns 2 tables, matching types +create table fktable (ftest1 int, ftest2 int, foreign key(ftest1, ftest2) references pktable(base1, ptest1)); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +-- now some ins, upd, del +insert into pktable(base1, ptest1) values (1, 1); +insert into pktable(base1, ptest1) values (2, 2); +-- let's insert a non-existant fktable value +insert into fktable(ftest1, ftest2) values (3, 1); +ERROR: <unnamed> referential integrity violation - key referenced from fktable not found in pktable +-- let's make a valid row for that +insert into pktable(base1,ptest1) values (3, 1); +insert into fktable(ftest1, ftest2) values (3, 1); +-- let's try removing a row that should fail from pktable +delete from pktable where base1>2; +ERROR: <unnamed> referential integrity violation - key in pktable still referenced from fktable +-- okay, let's try updating all of the base1 values to *4 +-- which should fail. +update pktable set base1=base1*4; +ERROR: <unnamed> referential integrity violation - key in pktable still referenced from fktable +-- okay, let's try an update that should work. +update pktable set base1=base1*4 where base1<3; +-- and a delete that should work +delete from pktable where base1>3; +-- cleanup +drop table fktable; +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" +NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" +drop table pktable; +drop table pktable_base; +-- Now we'll do one all in 1 table with 2 columns of matching types +create table pktable_base(base1 int not null, base2 int); +create table pktable(ptest1 int, ptest2 int, primary key(base1, ptest1), foreign key(base2, ptest2) references + pktable(base1, ptest1)) inherits (pktable_base); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +insert into pktable (base1, ptest1, base2, ptest2) values (1, 1, 1, 1); +insert into pktable (base1, ptest1, base2, ptest2) values (2, 1, 1, 1); +insert into pktable (base1, ptest1, base2, ptest2) values (2, 2, 2, 1); +insert into pktable (base1, ptest1, base2, ptest2) values (1, 3, 2, 2); +-- fails (3,2) isn't in base1, ptest1 +insert into pktable (base1, ptest1, base2, ptest2) values (2, 3, 3, 2); +ERROR: <unnamed> referential integrity violation - key referenced from pktable not found in pktable +-- fails (2,2) is being referenced +delete from pktable where base1=2; +ERROR: <unnamed> referential integrity violation - key in pktable still referenced from pktable +-- fails (1,1) is being referenced (twice) +update pktable set base1=3 where base1=1; +ERROR: <unnamed> referential integrity violation - key in pktable still referenced from pktable +-- this sequence of two deletes will work, since after the first there will be no (2,*) references +delete from pktable where base2=2; +delete from pktable where base1=2; +drop table pktable; +drop table pktable_base; +-- 2 columns (2 tables), mismatched types +create table pktable_base(base1 int not null); +create table pktable(ptest1 text, primary key(base1, ptest1)) inherits (pktable_base); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +-- just generally bad types (with and without column references on the referenced table) +create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'cidr' and 'int4' + You will have to retype this query using an explicit cast +create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable(base1, ptest1)); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'cidr' and 'int4' + You will have to retype this query using an explicit cast +-- let's mix up which columns reference which +create table fktable(ftest1 int, ftest2 text, foreign key(ftest2, ftest1) references pktable); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'text' and 'int4' + You will have to retype this query using an explicit cast +create table fktable(ftest1 int, ftest2 text, foreign key(ftest2, ftest1) references pktable(base1, ptest1)); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'text' and 'int4' + You will have to retype this query using an explicit cast +create table fktable(ftest1 int, ftest2 text, foreign key(ftest1, ftest2) references pktable(ptest1, base1)); +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'int4' and 'text' + You will have to retype this query using an explicit cast +drop table pktable; +drop table pktable_base; +-- 2 columns (1 table), mismatched types +create table pktable_base(base1 int not null, base2 int); +create table pktable(ptest1 text, ptest2 text[], primary key(base1, ptest1), foreign key(base2, ptest2) references + pktable(base1, ptest1)) inherits (pktable_base); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types '_text' and 'text' + You will have to retype this query using an explicit cast +create table pktable(ptest1 text, ptest2 text, primary key(base1, ptest1), foreign key(base2, ptest2) references + pktable(ptest1, base1)) inherits (pktable_base); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'int4' and 'text' + You will have to retype this query using an explicit cast +create table pktable(ptest1 text, ptest2 text, primary key(base1, ptest1), foreign key(ptest2, base2) references + pktable(base1, ptest1)) inherits (pktable_base); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'text' and 'int4' + You will have to retype this query using an explicit cast +create table pktable(ptest1 text, ptest2 text, primary key(base1, ptest1), foreign key(ptest2, base2) references + pktable(base1, ptest1)) inherits (pktable_base); +NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' +NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +ERROR: Unable to identify an operator '=' for types 'text' and 'int4' + You will have to retype this query using an explicit cast +drop table pktable; +ERROR: table "pktable" does not exist +drop table pktable_base; diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql index f90710f8d96..f0ac095c535 100644 --- a/src/test/regress/sql/alter_table.sql +++ b/src/test/regress/sql/alter_table.sql @@ -212,3 +212,39 @@ DROP TABLE tmp3; DROP TABLE tmp2; +-- Foreign key adding test with mixed types + +CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY); +CREATE TABLE FKTABLE (ftest1 text); +-- This next should fail, because text=int does not exist +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable; +-- This should also fail for the same reason, but here we +-- give the column name +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable(ptest1); +-- This should succeed, even though they are different types +-- because varchar=int does exist +DROP TABLE FKTABLE; +CREATE TABLE FKTABLE (ftest1 varchar); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable; +-- As should this +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable(ptest1); +DROP TABLE pktable; +DROP TABLE fktable; + +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, PRIMARY KEY(ptest1, ptest2)); +-- This should fail, because we just chose really odd types +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 datetime); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) references pktable; +-- Again, so should this... +DROP TABLE FKTABLE; +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 datetime); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) references pktable(ptest1, ptest2); +-- This fails because we mixed up the column ordering +DROP TABLE FKTABLE; +CREATE TABLE FKTABLE (ftest1 int, ftest2 text); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) references pktable(ptest2, ptest1); +-- As does this... +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest2, ftest1) references pktable(ptest1, ptest2); + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; diff --git a/src/test/regress/sql/foreign_key.sql b/src/test/regress/sql/foreign_key.sql index 91ff0aafe58..587fd850f72 100644 --- a/src/test/regress/sql/foreign_key.sql +++ b/src/test/regress/sql/foreign_key.sql @@ -425,3 +425,159 @@ CREATE TABLE FKTABLE_FAIL1 (ftest1 int REFERENCES pktable(ptest1)); DROP TABLE FKTABLE_FAIL1; DROP TABLE PKTABLE; + +-- +-- Tests for mismatched types +-- +-- Basic one column, two table setup +CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY); +-- This next should fail, because text=int does not exist +CREATE TABLE FKTABLE (ftest1 text REFERENCES pktable); +-- This should also fail for the same reason, but here we +-- give the column name +CREATE TABLE FKTABLE (ftest1 text REFERENCES pktable(ptest1)); +-- This should succeed, even though they are different types +-- because varchar=int does exist +CREATE TABLE FKTABLE (ftest1 varchar REFERENCES pktable); +DROP TABLE FKTABLE; +-- As should this +CREATE TABLE FKTABLE (ftest1 varchar REFERENCES pktable(ptest1)); +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; + +-- Two columns, two tables +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, PRIMARY KEY(ptest1, ptest2)); +-- This should fail, because we just chose really odd types +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 datetime, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable); +-- Again, so should this... +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 datetime, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2)); +-- This fails because we mixed up the column ordering +CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable); +-- As does this... +CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest1, ptest2)); +-- And again.. +CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest2, ptest1)); +-- This works... +CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest2, ptest1)); +DROP TABLE FKTABLE; +-- As does this +CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2)); +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; + +-- Two columns, same table +-- Make sure this still works... +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES pktable(ptest1, ptest2)); +DROP TABLE PKTABLE; +-- And this, +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES pktable); +DROP TABLE PKTABLE; +-- This shouldn't (mixed up columns) +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES pktable(ptest2, ptest1)); +-- Nor should this... (same reason, we have 4,3 referencing 1,2 which mismatches types +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4, +ptest3) REFERENCES pktable(ptest1, ptest2)); +-- Not this one either... Same as the last one except we didn't defined the columns being referenced. +CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4, +ptest3) REFERENCES pktable); + +-- +-- Now some cases with inheritance +-- Basic 2 table case: 1 column of matching types. +create table pktable_base (base1 int not null); +create table pktable (ptest1 int, primary key(base1), unique(base1, ptest1)) inherits (pktable_base); +create table fktable (ftest1 int references pktable(base1)); +-- now some ins, upd, del +insert into pktable(base1) values (1); +insert into pktable(base1) values (2); +-- let's insert a non-existant fktable value +insert into fktable(ftest1) values (3); +-- let's make a valid row for that +insert into pktable(base1) values (3); +insert into fktable(ftest1) values (3); +-- let's try removing a row that should fail from pktable +delete from pktable where base1>2; +-- okay, let's try updating all of the base1 values to *4 +-- which should fail. +update pktable set base1=base1*4; +-- okay, let's try an update that should work. +update pktable set base1=base1*4 where base1<3; +-- and a delete that should work +delete from pktable where base1>3; +-- cleanup +drop table fktable; +delete from pktable; + +-- Now 2 columns 2 tables, matching types +create table fktable (ftest1 int, ftest2 int, foreign key(ftest1, ftest2) references pktable(base1, ptest1)); +-- now some ins, upd, del +insert into pktable(base1, ptest1) values (1, 1); +insert into pktable(base1, ptest1) values (2, 2); +-- let's insert a non-existant fktable value +insert into fktable(ftest1, ftest2) values (3, 1); +-- let's make a valid row for that +insert into pktable(base1,ptest1) values (3, 1); +insert into fktable(ftest1, ftest2) values (3, 1); +-- let's try removing a row that should fail from pktable +delete from pktable where base1>2; +-- okay, let's try updating all of the base1 values to *4 +-- which should fail. +update pktable set base1=base1*4; +-- okay, let's try an update that should work. +update pktable set base1=base1*4 where base1<3; +-- and a delete that should work +delete from pktable where base1>3; +-- cleanup +drop table fktable; +drop table pktable; +drop table pktable_base; + +-- Now we'll do one all in 1 table with 2 columns of matching types +create table pktable_base(base1 int not null, base2 int); +create table pktable(ptest1 int, ptest2 int, primary key(base1, ptest1), foreign key(base2, ptest2) references + pktable(base1, ptest1)) inherits (pktable_base); +insert into pktable (base1, ptest1, base2, ptest2) values (1, 1, 1, 1); +insert into pktable (base1, ptest1, base2, ptest2) values (2, 1, 1, 1); +insert into pktable (base1, ptest1, base2, ptest2) values (2, 2, 2, 1); +insert into pktable (base1, ptest1, base2, ptest2) values (1, 3, 2, 2); +-- fails (3,2) isn't in base1, ptest1 +insert into pktable (base1, ptest1, base2, ptest2) values (2, 3, 3, 2); +-- fails (2,2) is being referenced +delete from pktable where base1=2; +-- fails (1,1) is being referenced (twice) +update pktable set base1=3 where base1=1; +-- this sequence of two deletes will work, since after the first there will be no (2,*) references +delete from pktable where base2=2; +delete from pktable where base1=2; +drop table pktable; +drop table pktable_base; + +-- 2 columns (2 tables), mismatched types +create table pktable_base(base1 int not null); +create table pktable(ptest1 text, primary key(base1, ptest1)) inherits (pktable_base); +-- just generally bad types (with and without column references on the referenced table) +create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable); +create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable(base1, ptest1)); +-- let's mix up which columns reference which +create table fktable(ftest1 int, ftest2 text, foreign key(ftest2, ftest1) references pktable); +create table fktable(ftest1 int, ftest2 text, foreign key(ftest2, ftest1) references pktable(base1, ptest1)); +create table fktable(ftest1 int, ftest2 text, foreign key(ftest1, ftest2) references pktable(ptest1, base1)); +drop table pktable; +drop table pktable_base; + +-- 2 columns (1 table), mismatched types +create table pktable_base(base1 int not null, base2 int); +create table pktable(ptest1 text, ptest2 text[], primary key(base1, ptest1), foreign key(base2, ptest2) references + pktable(base1, ptest1)) inherits (pktable_base); +create table pktable(ptest1 text, ptest2 text, primary key(base1, ptest1), foreign key(base2, ptest2) references + pktable(ptest1, base1)) inherits (pktable_base); +create table pktable(ptest1 text, ptest2 text, primary key(base1, ptest1), foreign key(ptest2, base2) references + pktable(base1, ptest1)) inherits (pktable_base); +create table pktable(ptest1 text, ptest2 text, primary key(base1, ptest1), foreign key(ptest2, base2) references + pktable(base1, ptest1)) inherits (pktable_base); +drop table pktable; +drop table pktable_base; + |
