summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorBruce Momjian2001-05-09 21:10:39 +0000
committerBruce Momjian2001-05-09 21:10:39 +0000
commit8678929c22111863e9d6b836232dc4f69c52d9ae (patch)
treec4c42d45a8e338d010be40b03627a812dc2e8df5 /src/test
parenta0458a91bfc14c77ca7672bab618820a6a8f565c (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.out57
-rw-r--r--src/test/regress/expected/foreign_key.out250
-rw-r--r--src/test/regress/sql/alter_table.sql36
-rw-r--r--src/test/regress/sql/foreign_key.sql156
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;
+