mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
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
This commit is contained in:
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user