1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-15 19:21:59 +03:00

Arrange to print the relevant key values when reporting a foreign-key

violation.  Also, factor out some duplicate code in the RI triggers.
Patch by Dmitry Tkach, reviewed by Stephan Szabo and Tom Lane.
This commit is contained in:
Tom Lane
2003-03-15 21:19:40 +00:00
parent 35911088ff
commit 48dfa0d057
4 changed files with 452 additions and 596 deletions

File diff suppressed because it is too large Load Diff

View File

@ -326,7 +326,7 @@ ERROR: ALTER TABLE: column "b" referenced in foreign key constraint does not ex
-- Try (and fail) to add constraint due to invalid data -- Try (and fail) to add constraint due to invalid data
ALTER TABLE tmp3 add constraint tmpconstr foreign key (a) references tmp2 match full; ALTER TABLE tmp3 add constraint tmpconstr foreign key (a) references tmp2 match full;
NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s) NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: tmpconstr referential integrity violation - key referenced from tmp3 not found in tmp2 ERROR: tmpconstr referential integrity violation - key (a)=(5) referenced from tmp3 not found in tmp2
-- Delete failing row -- Delete failing row
DELETE FROM tmp3 where a=5; DELETE FROM tmp3 where a=5;
-- Try (and succeed) -- Try (and succeed)

View File

@ -248,7 +248,7 @@ SELECT a,b,c,substring(d for 30), length(d) from clstr_tst;
-- Verify that foreign key link still works -- Verify that foreign key link still works
INSERT INTO clstr_tst (b, c) VALUES (1111, 'this should fail'); INSERT INTO clstr_tst (b, c) VALUES (1111, 'this should fail');
ERROR: clstr_tst_con referential integrity violation - key referenced from clstr_tst not found in clstr_tst_s ERROR: clstr_tst_con referential integrity violation - key (b)=(1111) referenced from clstr_tst not found in clstr_tst_s
SELECT conname FROM pg_constraint WHERE conrelid = 'clstr_tst'::regclass; SELECT conname FROM pg_constraint WHERE conrelid = 'clstr_tst'::regclass;
conname conname
---------------- ----------------

View File

@ -22,7 +22,7 @@ INSERT INTO FKTABLE VALUES (3, 4);
INSERT INTO FKTABLE VALUES (NULL, 1); INSERT INTO FKTABLE VALUES (NULL, 1);
-- Insert a failed row into FK TABLE -- Insert a failed row into FK TABLE
INSERT INTO FKTABLE VALUES (100, 2); INSERT INTO FKTABLE VALUES (100, 2);
ERROR: $1 referential integrity violation - key referenced from fktable not found in pktable ERROR: $1 referential integrity violation - key (ftest1)=(100) referenced from fktable not found in pktable
-- Check FKTABLE -- Check FKTABLE
SELECT * FROM FKTABLE; SELECT * FROM FKTABLE;
ftest1 | ftest2 ftest1 | ftest2
@ -80,9 +80,9 @@ INSERT INTO FKTABLE VALUES (3, 6, 12);
INSERT INTO FKTABLE VALUES (NULL, NULL, 0); INSERT INTO FKTABLE VALUES (NULL, NULL, 0);
-- Insert failed rows into FK TABLE -- Insert failed rows into FK TABLE
INSERT INTO FKTABLE VALUES (100, 2, 4); INSERT INTO FKTABLE VALUES (100, 2, 4);
ERROR: constrname referential integrity violation - key referenced from fktable not found in pktable ERROR: constrname referential integrity violation - key (ftest1,ftest2)=(100,2) referenced from fktable not found in pktable
INSERT INTO FKTABLE VALUES (2, 2, 4); INSERT INTO FKTABLE VALUES (2, 2, 4);
ERROR: constrname referential integrity violation - key referenced from fktable not found in pktable ERROR: constrname referential integrity violation - key (ftest1,ftest2)=(2,2) referenced from fktable not found in pktable
INSERT INTO FKTABLE VALUES (NULL, 2, 4); INSERT INTO FKTABLE VALUES (NULL, 2, 4);
ERROR: constrname referential integrity violation - MATCH FULL doesn't allow mixing of NULL and NON-NULL key values ERROR: constrname referential integrity violation - MATCH FULL doesn't allow mixing of NULL and NON-NULL key values
INSERT INTO FKTABLE VALUES (1, NULL, 4); INSERT INTO FKTABLE VALUES (1, NULL, 4);
@ -165,9 +165,9 @@ INSERT INTO FKTABLE VALUES (3, 6, 12);
INSERT INTO FKTABLE VALUES (NULL, NULL, 0); INSERT INTO FKTABLE VALUES (NULL, NULL, 0);
-- Insert failed rows into FK TABLE -- Insert failed rows into FK TABLE
INSERT INTO FKTABLE VALUES (100, 2, 4); INSERT INTO FKTABLE VALUES (100, 2, 4);
ERROR: constrname2 referential integrity violation - key referenced from fktable not found in pktable ERROR: constrname2 referential integrity violation - key (ftest1,ftest2)=(100,2) referenced from fktable not found in pktable
INSERT INTO FKTABLE VALUES (2, 2, 4); INSERT INTO FKTABLE VALUES (2, 2, 4);
ERROR: constrname2 referential integrity violation - key referenced from fktable not found in pktable ERROR: constrname2 referential integrity violation - key (ftest1,ftest2)=(2,2) referenced from fktable not found in pktable
INSERT INTO FKTABLE VALUES (NULL, 2, 4); INSERT INTO FKTABLE VALUES (NULL, 2, 4);
ERROR: constrname2 referential integrity violation - MATCH FULL doesn't allow mixing of NULL and NON-NULL key values ERROR: constrname2 referential integrity violation - MATCH FULL doesn't allow mixing of NULL and NON-NULL key values
INSERT INTO FKTABLE VALUES (1, NULL, 4); INSERT INTO FKTABLE VALUES (1, NULL, 4);
@ -250,7 +250,7 @@ INSERT INTO FKTABLE VALUES (3, 4);
INSERT INTO FKTABLE VALUES (NULL, 1); INSERT INTO FKTABLE VALUES (NULL, 1);
-- Insert a failed row into FK TABLE -- Insert a failed row into FK TABLE
INSERT INTO FKTABLE VALUES (100, 2); INSERT INTO FKTABLE VALUES (100, 2);
ERROR: $1 referential integrity violation - key referenced from fktable not found in pktable ERROR: $1 referential integrity violation - key (ftest1)=(100) referenced from fktable not found in pktable
-- Check FKTABLE -- Check FKTABLE
SELECT * FROM FKTABLE; SELECT * FROM FKTABLE;
ftest1 | ftest2 ftest1 | ftest2
@ -274,7 +274,7 @@ SELECT * FROM PKTABLE;
-- Delete a row from PK TABLE (should fail) -- Delete a row from PK TABLE (should fail)
DELETE FROM PKTABLE WHERE ptest1=1; DELETE FROM PKTABLE WHERE ptest1=1;
ERROR: $1 referential integrity violation - key in pktable still referenced from fktable ERROR: $1 referential integrity violation - key (ptest1)=(1) in pktable still referenced from fktable
-- Delete a row from PK TABLE (should succeed) -- Delete a row from PK TABLE (should succeed)
DELETE FROM PKTABLE WHERE ptest1=5; DELETE FROM PKTABLE WHERE ptest1=5;
-- Check PKTABLE for deletes -- Check PKTABLE for deletes
@ -289,7 +289,7 @@ SELECT * FROM PKTABLE;
-- Update a row from PK TABLE (should fail) -- Update a row from PK TABLE (should fail)
UPDATE PKTABLE SET ptest1=0 WHERE ptest1=2; UPDATE PKTABLE SET ptest1=0 WHERE ptest1=2;
ERROR: $1 referential integrity violation - key in pktable still referenced from fktable ERROR: $1 referential integrity violation - key (ptest1)=(2) in pktable still referenced from fktable
-- Update a row from PK TABLE (should succeed) -- Update a row from PK TABLE (should succeed)
UPDATE PKTABLE SET ptest1=0 WHERE ptest1=4; UPDATE PKTABLE SET ptest1=0 WHERE ptest1=4;
-- Check PKTABLE for updates -- Check PKTABLE for updates
@ -324,7 +324,7 @@ INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4);
INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5);
-- Insert a failed values -- Insert a failed values
INSERT INTO FKTABLE VALUES (1, 2, 7, 6); INSERT INTO FKTABLE VALUES (1, 2, 7, 6);
ERROR: constrname3 referential integrity violation - key referenced from fktable not found in pktable ERROR: constrname3 referential integrity violation - key (ftest1,ftest2,ftest3)=(1,2,7) referenced from fktable not found in pktable
-- Show FKTABLE -- Show FKTABLE
SELECT * from FKTABLE; SELECT * from FKTABLE;
ftest1 | ftest2 | ftest3 | ftest4 ftest1 | ftest2 | ftest3 | ftest4
@ -338,12 +338,12 @@ SELECT * from FKTABLE;
-- Try to update something that should fail -- Try to update something that should fail
UPDATE PKTABLE set ptest2=5 where ptest2=2; UPDATE PKTABLE set ptest2=5 where ptest2=2;
ERROR: constrname3 referential integrity violation - key in pktable still referenced from fktable ERROR: constrname3 referential integrity violation - key (ptest1,ptest2,ptest3)=(1,2,3) in pktable still referenced from fktable
-- Try to update something that should succeed -- Try to update something that should succeed
UPDATE PKTABLE set ptest1=1 WHERE ptest2=3; UPDATE PKTABLE set ptest1=1 WHERE ptest2=3;
-- Try to delete something that should fail -- Try to delete something that should fail
DELETE FROM PKTABLE where ptest1=1 and ptest2=2 and ptest3=3; DELETE FROM PKTABLE where ptest1=1 and ptest2=2 and ptest3=3;
ERROR: constrname3 referential integrity violation - key in pktable still referenced from fktable ERROR: constrname3 referential integrity violation - key (ptest1,ptest2,ptest3)=(1,2,3) in pktable still referenced from fktable
-- Try to delete something that should work -- Try to delete something that should work
DELETE FROM PKTABLE where ptest1=2; DELETE FROM PKTABLE where ptest1=2;
-- Show PKTABLE and FKTABLE -- Show PKTABLE and FKTABLE
@ -387,7 +387,7 @@ INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4);
INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5);
-- Insert a failed values -- Insert a failed values
INSERT INTO FKTABLE VALUES (1, 2, 7, 6); INSERT INTO FKTABLE VALUES (1, 2, 7, 6);
ERROR: constrname3 referential integrity violation - key referenced from fktable not found in pktable ERROR: constrname3 referential integrity violation - key (ftest1,ftest2,ftest3)=(1,2,7) referenced from fktable not found in pktable
-- Show FKTABLE -- Show FKTABLE
SELECT * from FKTABLE; SELECT * from FKTABLE;
ftest1 | ftest2 | ftest3 | ftest4 ftest1 | ftest2 | ftest3 | ftest4
@ -485,7 +485,7 @@ INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4);
INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5);
-- Insert a failed values -- Insert a failed values
INSERT INTO FKTABLE VALUES (1, 2, 7, 6); INSERT INTO FKTABLE VALUES (1, 2, 7, 6);
ERROR: constrname3 referential integrity violation - key referenced from fktable not found in pktable ERROR: constrname3 referential integrity violation - key (ftest1,ftest2,ftest3)=(1,2,7) referenced from fktable not found in pktable
-- Show FKTABLE -- Show FKTABLE
SELECT * from FKTABLE; SELECT * from FKTABLE;
ftest1 | ftest2 | ftest3 | ftest4 ftest1 | ftest2 | ftest3 | ftest4
@ -591,7 +591,7 @@ INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4);
INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5);
-- Insert a failed values -- Insert a failed values
INSERT INTO FKTABLE VALUES (1, 2, 7, 6); INSERT INTO FKTABLE VALUES (1, 2, 7, 6);
ERROR: constrname3 referential integrity violation - key referenced from fktable not found in pktable ERROR: constrname3 referential integrity violation - key (ftest1,ftest2,ftest3)=(1,2,7) referenced from fktable not found in pktable
-- Show FKTABLE -- Show FKTABLE
SELECT * from FKTABLE; SELECT * from FKTABLE;
ftest1 | ftest2 | ftest3 | ftest4 ftest1 | ftest2 | ftest3 | ftest4
@ -607,7 +607,7 @@ SELECT * from FKTABLE;
-- Try to update something that will fail -- Try to update something that will fail
UPDATE PKTABLE set ptest2=5 where ptest2=2; UPDATE PKTABLE set ptest2=5 where ptest2=2;
ERROR: constrname3 referential integrity violation - key referenced from fktable not found in pktable ERROR: constrname3 referential integrity violation - key (ftest1,ftest2,ftest3)=(1,-1,3) referenced from fktable not found in pktable
-- Try to update something that will set default -- Try to update something that will set default
UPDATE PKTABLE set ptest1=0, ptest2=5, ptest3=10 where ptest2=2; UPDATE PKTABLE set ptest1=0, ptest2=5, ptest3=10 where ptest2=2;
UPDATE PKTABLE set ptest2=10 where ptest2=4; UPDATE PKTABLE set ptest2=10 where ptest2=4;
@ -819,17 +819,17 @@ insert into pktable(base1) values (1);
insert into pktable(base1) values (2); insert into pktable(base1) values (2);
-- let's insert a non-existant fktable value -- let's insert a non-existant fktable value
insert into fktable(ftest1) values (3); insert into fktable(ftest1) values (3);
ERROR: $1 referential integrity violation - key referenced from fktable not found in pktable ERROR: $1 referential integrity violation - key (ftest1)=(3) referenced from fktable not found in pktable
-- let's make a valid row for that -- let's make a valid row for that
insert into pktable(base1) values (3); insert into pktable(base1) values (3);
insert into fktable(ftest1) values (3); insert into fktable(ftest1) values (3);
-- let's try removing a row that should fail from pktable -- let's try removing a row that should fail from pktable
delete from pktable where base1>2; delete from pktable where base1>2;
ERROR: $1 referential integrity violation - key in pktable still referenced from fktable ERROR: $1 referential integrity violation - key (base1)=(3) in pktable still referenced from fktable
-- okay, let's try updating all of the base1 values to *4 -- okay, let's try updating all of the base1 values to *4
-- which should fail. -- which should fail.
update pktable set base1=base1*4; update pktable set base1=base1*4;
ERROR: $1 referential integrity violation - key in pktable still referenced from fktable ERROR: $1 referential integrity violation - key (base1)=(3) in pktable still referenced from fktable
-- okay, let's try an update that should work. -- okay, let's try an update that should work.
update pktable set base1=base1*4 where base1<3; update pktable set base1=base1*4 where base1<3;
-- and a delete that should work -- and a delete that should work
@ -845,17 +845,17 @@ insert into pktable(base1, ptest1) values (1, 1);
insert into pktable(base1, ptest1) values (2, 2); insert into pktable(base1, ptest1) values (2, 2);
-- let's insert a non-existant fktable value -- let's insert a non-existant fktable value
insert into fktable(ftest1, ftest2) values (3, 1); insert into fktable(ftest1, ftest2) values (3, 1);
ERROR: $1 referential integrity violation - key referenced from fktable not found in pktable ERROR: $1 referential integrity violation - key (ftest1,ftest2)=(3,1) referenced from fktable not found in pktable
-- let's make a valid row for that -- let's make a valid row for that
insert into pktable(base1,ptest1) values (3, 1); insert into pktable(base1,ptest1) values (3, 1);
insert into fktable(ftest1, ftest2) values (3, 1); insert into fktable(ftest1, ftest2) values (3, 1);
-- let's try removing a row that should fail from pktable -- let's try removing a row that should fail from pktable
delete from pktable where base1>2; delete from pktable where base1>2;
ERROR: $1 referential integrity violation - key in pktable still referenced from fktable ERROR: $1 referential integrity violation - key (base1,ptest1)=(3,1) in pktable still referenced from fktable
-- okay, let's try updating all of the base1 values to *4 -- okay, let's try updating all of the base1 values to *4
-- which should fail. -- which should fail.
update pktable set base1=base1*4; update pktable set base1=base1*4;
ERROR: $1 referential integrity violation - key in pktable still referenced from fktable ERROR: $1 referential integrity violation - key (base1,ptest1)=(3,1) in pktable still referenced from fktable
-- okay, let's try an update that should work. -- okay, let's try an update that should work.
update pktable set base1=base1*4 where base1<3; update pktable set base1=base1*4 where base1<3;
-- and a delete that should work -- and a delete that should work
@ -876,13 +876,13 @@ insert into pktable (base1, ptest1, base2, ptest2) values (2, 2, 2, 1);
insert into pktable (base1, ptest1, base2, ptest2) values (1, 3, 2, 2); insert into pktable (base1, ptest1, base2, ptest2) values (1, 3, 2, 2);
-- fails (3,2) isn't in base1, ptest1 -- fails (3,2) isn't in base1, ptest1
insert into pktable (base1, ptest1, base2, ptest2) values (2, 3, 3, 2); insert into pktable (base1, ptest1, base2, ptest2) values (2, 3, 3, 2);
ERROR: $1 referential integrity violation - key referenced from pktable not found in pktable ERROR: $1 referential integrity violation - key (base2,ptest2)=(3,2) referenced from pktable not found in pktable
-- fails (2,2) is being referenced -- fails (2,2) is being referenced
delete from pktable where base1=2; delete from pktable where base1=2;
ERROR: $1 referential integrity violation - key in pktable still referenced from pktable ERROR: $1 referential integrity violation - key (base1,ptest1)=(2,2) in pktable still referenced from pktable
-- fails (1,1) is being referenced (twice) -- fails (1,1) is being referenced (twice)
update pktable set base1=3 where base1=1; update pktable set base1=3 where base1=1;
ERROR: $1 referential integrity violation - key referenced from pktable not found in pktable ERROR: $1 referential integrity violation - key (base2,ptest2)=(1,1) referenced from pktable not found in pktable
-- this sequence of two deletes will work, since after the first there will be no (2,*) references -- 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 base2=2;
delete from pktable where base1=2; delete from pktable where base1=2;
@ -963,7 +963,7 @@ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'fktable_pkey' fo
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
-- default to immediate: should fail -- default to immediate: should fail
INSERT INTO fktable VALUES (5, 10); INSERT INTO fktable VALUES (5, 10);
ERROR: $1 referential integrity violation - key referenced from fktable not found in pktable ERROR: $1 referential integrity violation - key (fk)=(10) referenced from fktable not found in pktable
-- explicitely defer the constraint -- explicitely defer the constraint
BEGIN; BEGIN;
SET CONSTRAINTS ALL DEFERRED; SET CONSTRAINTS ALL DEFERRED;
@ -993,7 +993,7 @@ BEGIN;
SET CONSTRAINTS ALL IMMEDIATE; SET CONSTRAINTS ALL IMMEDIATE;
-- should fail -- should fail
INSERT INTO fktable VALUES (500, 1000); INSERT INTO fktable VALUES (500, 1000);
ERROR: $1 referential integrity violation - key referenced from fktable not found in pktable ERROR: $1 referential integrity violation - key (fk)=(1000) referenced from fktable not found in pktable
COMMIT; COMMIT;
DROP TABLE fktable, pktable; DROP TABLE fktable, pktable;
-- tricky behavior: according to SQL99, if a deferred constraint is set -- tricky behavior: according to SQL99, if a deferred constraint is set
@ -1017,7 +1017,7 @@ SET CONSTRAINTS ALL DEFERRED;
INSERT INTO fktable VALUES (1000, 2000); INSERT INTO fktable VALUES (1000, 2000);
-- should cause transaction abort, due to preceding error -- should cause transaction abort, due to preceding error
SET CONSTRAINTS ALL IMMEDIATE; SET CONSTRAINTS ALL IMMEDIATE;
ERROR: $1 referential integrity violation - key referenced from fktable not found in pktable ERROR: $1 referential integrity violation - key (fk)=(2000) referenced from fktable not found in pktable
INSERT INTO pktable VALUES (2000, 3); -- too late INSERT INTO pktable VALUES (2000, 3); -- too late
ERROR: current transaction is aborted, queries ignored until end of transaction block ERROR: current transaction is aborted, queries ignored until end of transaction block
COMMIT; COMMIT;