From: dan Date: Mon, 12 Oct 2009 08:41:49 +0000 (+0000) Subject: Add further test cases to e_fkey.test. X-Git-Tag: fts3-refactor~111 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e506deb255fdb24f4799fffedfac93e9ae8c2607;p=thirdparty%2Fsqlite.git Add further test cases to e_fkey.test. FossilOrigin-Name: d61cc0e1a1e8b4bf49016d3d14554f9c20f86f6b --- diff --git a/manifest b/manifest index 9206185401..2b3e7d3aca 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sto\se_fkey.test. -D 2009-10-10T15:49:49 +C Add\sfurther\stest\scases\sto\se_fkey.test. +D 2009-10-12T08:41:50 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 4ca3f1dd6efa2075bcb27f4dc43eef749877740d F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -319,7 +319,7 @@ F test/descidx2.test 1310ed1326cdfed4ea2c55169631579f082d174f F test/descidx3.test 3394ad4d089335cac743c36a14129d6d931c316f F test/diskfull.test 0cede7ef9d8f415d9d3944005c76be7589bb5ebb F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376 -F test/e_fkey.test 4eed4c548dce094df9979b5f2c054e33fbce83e3 +F test/e_fkey.test f9fcab098eefc9eefe8624b730a48611dfeeface F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea F test/enc2.test 6d91a5286f59add0cfcbb2d0da913b76f2242398 F test/enc3.test 5c550d59ff31dccdba5d1a02ae11c7047d77c041 @@ -756,7 +756,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 89c548acf4691bad3d90400026267d4c6a55cde1 -R 7de7b5a6379d79285bcb46eab489900a +P 5ec07feea47e727824b8b48236b5cce80539a455 +R ec48fda10fcfca9f54309367518982c3 U dan -Z 8b7ccd9ba2e7265c9f40169de47aa9c5 +Z 4e3c8e06ad003cd47ba138558d63cec3 diff --git a/manifest.uuid b/manifest.uuid index c98cdf91ab..ae13414164 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5ec07feea47e727824b8b48236b5cce80539a455 \ No newline at end of file +d61cc0e1a1e8b4bf49016d3d14554f9c20f86f6b \ No newline at end of file diff --git a/test/e_fkey.test b/test/e_fkey.test index 3784429aef..04b825db7e 100644 --- a/test/e_fkey.test +++ b/test/e_fkey.test @@ -23,6 +23,352 @@ execsql "PRAGMA foreign_keys = ON" ### SECTION 1: Introduction to Foreign Key Constraints ########################################################################### +#------------------------------------------------------------------------- +# /* EV: R-04042-24825 */ +# +# Verify that the syntax in the first example in section 1 is valid. +# +do_test e_fkey-38.1 { + execsql { + CREATE TABLE artist( + artistid INTEGER PRIMARY KEY, + artistname TEXT + ); + CREATE TABLE track( + trackid INTEGER, + trackname TEXT, + trackartist INTEGER, + FOREIGN KEY(trackartist) REFERENCES artist(artistid) + ); + } +} {} + +#------------------------------------------------------------------------- +# /* EV: R-61362-32087 */ +# +# Attempting to insert a row into the 'track' table that corresponds +# to no row in the 'artist' table fails. +# +do_test e_fkey-39.1 { + catchsql { INSERT INTO track VALUES(1, 'track 1', 1) } +} {1 {foreign key constraint failed}} +do_test e_fkey-39.2 { + execsql { INSERT INTO artist VALUES(2, 'artist 1') } + catchsql { INSERT INTO track VALUES(1, 'track 1', 1) } +} {1 {foreign key constraint failed}} +do_test e_fkey-39.2 { + execsql { INSERT INTO track VALUES(1, 'track 1', 2) } +} {} + +#------------------------------------------------------------------------- +# /* EV: R-24401-52400 */ +# +# Attempting to delete a row from the 'artist' table while there are +# dependent rows in the track table also fails. +# +do_test e_fkey-40.1 { + catchsql { DELETE FROM artist WHERE artistid = 2 } +} {1 {foreign key constraint failed}} +do_test e_fkey-40.2 { + execsql { + DELETE FROM track WHERE trackartist = 2; + DELETE FROM artist WHERE artistid = 2; + } +} {} + +#------------------------------------------------------------------------- +# /* EV: R-23980-48859 */ +# +# If the foreign key column (trackartist) in table 'track' is set to NULL, +# there is no requirement for a matching row in the 'artist' table. +# +do_test e_fkey-41.1 { + execsql { + INSERT INTO track VALUES(1, 'track 1', NULL); + INSERT INTO track VALUES(2, 'track 2', NULL); + } +} {} +do_test e_fkey-41.2 { + execsql { SELECT * FROM artist } +} {} +do_test e_fkey-41.3 { + # Setting the trackid to a non-NULL value fails, of course. + catchsql { UPDATE track SET trackartist = 5 WHERE trackid = 1 } +} {1 {foreign key constraint failed}} +do_test e_fkey-41.4 { + execsql { + INSERT INTO artist VALUES(5, 'artist 5'); + UPDATE track SET trackartist = 5 WHERE trackid = 1; + } + catchsql { DELETE FROM artist WHERE artistid = 5} +} {1 {foreign key constraint failed}} +do_test e_fkey-41.5 { + execsql { + UPDATE track SET trackartist = NULL WHERE trackid = 1; + DELETE FROM artist WHERE artistid = 5; + } +} {} + +#------------------------------------------------------------------------- +# /* EV: R-52486-21352 */ +# +# Test that the following is true fo all rows in the track table: +# +# trackartist IS NULL OR +# EXISTS(SELECT 1 FROM artist WHERE artistid=trackartist) +# + +# This procedure executes a test case to check that statement +# R-52486-21352 is true after executing the SQL statement passed. +# as the second argument. +proc test_r52486_21352 {tn sql} { + set res [catchsql $sql] + set results { + {0 {}} + {1 {PRIMARY KEY must be unique}} + {1 {foreign key constraint failed}} + } + if {[lsearch $results $res]<0} { + error $res + } + + do_test e_fkey-42.$tn { + execsql { + SELECT count(*) FROM track WHERE NOT ( + trackartist IS NULL OR + EXISTS(SELECT 1 FROM artist WHERE artistid=trackartist) + ) + } + } {0} +} + +# Execute a series of random INSERT, UPDATE and DELETE operations +# (some of which may fail due to FK or PK constraint violations) on +# the two tables in the example schema. Test that R-52486-21352 +# is true after executing each operation. +# +set Template { + {INSERT INTO track VALUES($t, 'track $t', $a)} + {DELETE FROM track WHERE trackid = $t} + {UPDATE track SET trackartist = $a WHERE trackid = $t} + {INSERT INTO artist VALUES($a, 'artist $a')} + {DELETE FROM artist WHERE artistid = $a} + {UPDATE artist SET artistid = $a2 WHERE artistid = $a} +} +for {set i 0} {$i < 500} {incr i} { + set a [expr int(rand()*10)] + set a2 [expr int(rand()*10)] + set t [expr int(rand()*50)] + set sql [subst [lindex $Template [expr int(rand()*6)]]] + + test_r52486_21352 $i $sql +} + +#------------------------------------------------------------------------- +# /* EV: R-42412-59321 */ +# +# Check that a NOT NULL constraint can be added to the example schema +# to prohibit NULL child keys from being inserted. +# +drop_all_tables +do_test e_fkey-48.1 { + execsql { + CREATE TABLE artist( + artistid INTEGER PRIMARY KEY, + artistname TEXT + ); + CREATE TABLE track( + trackid INTEGER, + trackname TEXT, + trackartist INTEGER NOT NULL, + FOREIGN KEY(trackartist) REFERENCES artist(artistid) + ); + } +} {} +do_test e_fkey-48.2 { + catchsql { INSERT INTO track VALUES(14, 'Mr. Bojangles', NULL) } +} {1 {track.trackartist may not be NULL}} + +#------------------------------------------------------------------------- +# /* EV: R-01991-24099 */ +# +# Test an example from foreignkeys.html. +# +drop_all_tables +do_test e_fkey-43.1 { + execsql { + CREATE TABLE artist( + artistid INTEGER PRIMARY KEY, + artistname TEXT + ); + CREATE TABLE track( + trackid INTEGER, + trackname TEXT, + trackartist INTEGER, + FOREIGN KEY(trackartist) REFERENCES artist(artistid) + ); + INSERT INTO artist VALUES(1, 'Dean Martin'); + INSERT INTO artist VALUES(2, 'Frank Sinatra'); + INSERT INTO track VALUES(11, 'That''s Amore', 1); + INSERT INTO track VALUES(12, 'Christmas Blues', 1); + INSERT INTO track VALUES(13, 'My Way', 2); + } +} {} +do_test e_fkey-43.2 { + catchsql { INSERT INTO track VALUES(14, 'Mr. Bojangles', 3) } +} {1 {foreign key constraint failed}} +do_test e_fkey-43.3 { + execsql { INSERT INTO track VALUES(14, 'Mr. Bojangles', NULL) } +} {} +do_test e_fkey-43.4 { + catchsql { + UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles'; + } +} {1 {foreign key constraint failed}} +do_test e_fkey-43.5 { + execsql { + INSERT INTO artist VALUES(3, 'Sammy Davis Jr.'); + UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles'; + INSERT INTO track VALUES(15, 'Boogie Woogie', 3); + } +} {} + +#------------------------------------------------------------------------- +# /* EV: R-22377-02546 */ +# +# Test the second example from the first section of foreignkeys.html. +# +do_test e_fkey-44.1 { + catchsql { + DELETE FROM artist WHERE artistname = 'Frank Sinatra'; + } +} {1 {foreign key constraint failed}} +do_test e_fkey-44.2 { + execsql { + DELETE FROM track WHERE trackname = 'My Way'; + DELETE FROM artist WHERE artistname = 'Frank Sinatra'; + } +} {} +do_test e_fkey-44.3 { + catchsql { + UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin'; + } +} {1 {foreign key constraint failed}} +do_test e_fkey-44.4 { + execsql { + DELETE FROM track WHERE trackname IN('That''s Amore', 'Christmas Blues'); + UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin'; + } +} {} + + +#------------------------------------------------------------------------- +# /* EV: R-56032-24923 */ +# +# Test that a foreign key constraint is satisifed if "for each row in the child +# table either one or more of the child key columns are NULL, or there exists a +# row in the parent table for which each parent key column contains a value +# equal to the value in its associated child key column". +# +# /* EV: R-57765-12380 */ +# +# Test also that the comparison rules are used when testing if there +# is a matching row in the parent table of a foreign key constraint. +# +drop_all_tables +do_test e_fkey-45.1 { + execsql { + CREATE TABLE par(p PRIMARY KEY); + CREATE TABLE chi(c REFERENCES par); + + INSERT INTO par VALUES(1); + INSERT INTO par VALUES('1'); + INSERT INTO par VALUES(X'31'); + SELECT typeof(p) FROM par; + } +} {integer text blob} + +proc test_efkey_45 {tn isError sql} { + do_test e_fkey-45.$tn.1 " + catchsql {$sql} + " [lindex {{0 {}} {1 {foreign key constraint failed}}} $isError] + + do_test e_fkey-45.$tn.2 { + execsql { + SELECT * FROM chi WHERE c IS NOT NULL AND c NOT IN (SELECT p FROM par) + } + } {} +} + +test_efkey_45 1 0 "INSERT INTO chi VALUES(1)" +test_efkey_45 2 1 "INSERT INTO chi VALUES('1.0')" +test_efkey_45 3 0 "INSERT INTO chi VALUES('1')" +test_efkey_45 4 1 "DELETE FROM par WHERE p = '1'" +test_efkey_45 5 0 "DELETE FROM chi WHERE c = '1'" +test_efkey_45 6 0 "DELETE FROM par WHERE p = '1'" +test_efkey_45 7 1 "INSERT INTO chi VALUES('1')" +test_efkey_45 8 0 "INSERT INTO chi VALUES(X'31')" +test_efkey_45 9 1 "INSERT INTO chi VALUES(X'32')" + +#------------------------------------------------------------------------- +# /* EV: R-15796-47513 */ +# +# Specifically, test that when comparing child and parent key values the +# default collation sequence of the parent key column is used. +# +drop_all_tables +do_test e_fkey-46.1 { + execsql { + CREATE TABLE t1(a COLLATE nocase PRIMARY KEY); + CREATE TABLE t2(b REFERENCES t1); + } +} {} +do_test e_fkey-46.2 { + execsql { + INSERT INTO t1 VALUES('oNe'); + INSERT INTO t2 VALUES('one'); + INSERT INTO t2 VALUES('ONE'); + UPDATE t2 SET b = 'OnE'; + UPDATE t1 SET a = 'ONE'; + } +} {} +do_test e_fkey-46.3 { + catchsql { UPDATE t2 SET b = 'two' WHERE rowid = 1 } +} {1 {foreign key constraint failed}} +do_test e_fkey-46.4 { + catchsql { DELETE FROM t1 WHERE rowid = 1 } +} {1 {foreign key constraint failed}} + +#------------------------------------------------------------------------- +# /* EV: R-04240-13860 */ +# +# Specifically, test that when comparing child and parent key values the +# affinity of the parent key column is applied to the child key value +# before the comparison takes place. +# +drop_all_tables +do_test e_fkey-47.1 { + execsql { + CREATE TABLE t1(a NUMERIC PRIMARY KEY); + CREATE TABLE t2(b TEXT REFERENCES t1); + } +} {} +do_test e_fkey-47.2 { + execsql { + INSERT INTO t1 VALUES(1); + INSERT INTO t1 VALUES(2); + INSERT INTO t1 VALUES('three'); + INSERT INTO t2 VALUES('2.0'); + SELECT b, typeof(b) FROM t2; + } +} {2.0 text} +do_test e_fkey-47.3 { + execsql { SELECT typeof(a) FROM t1 } +} {integer integer text} +do_test e_fkey-47.4 { + catchsql { DELETE FROM t1 WHERE rowid = 2 } +} {1 {foreign key constraint failed}} + ########################################################################### ### SECTION 2: Enabling Foreign Key Support ########################################################################### @@ -35,12 +381,64 @@ execsql "PRAGMA foreign_keys = ON" ### SECTION 4.1: Composite Foreign Key Constraints ########################################################################### +#------------------------------------------------------------------------- +# /* EV: R-56396-15644 */ +# +# Test the example schema in the "Composite Foreign Key Constraints" +# section. +# +do_test e_fkey-36.1 { + execsql { + CREATE TABLE album( + albumartist TEXT, + albumname TEXT, + albumcover BINARY, + PRIMARY KEY(albumartist, albumname) + ); + CREATE TABLE song( + songid INTEGER, + songartist TEXT, + songalbum TEXT, + songname TEXT, + FOREIGN KEY(songartist, songalbum) REFERENCES album(albumartist,albumname) + ); + } +} {} + +do_test e_fkey-36.2 { + execsql { + INSERT INTO album VALUES('Elvis Presley', 'Elvis'' Christmas Album', NULL); + INSERT INTO song VALUES( + 1, 'Elvis Presley', 'Elvis'' Christmas Album', 'Here Comes Santa Clause' + ); + } +} {} +do_test e_fkey-36.3 { + catchsql { + INSERT INTO song VALUES(2, 'Elvis Presley', 'Elvis Is Back!', 'Fever'); + } +} {1 {foreign key constraint failed}} + +#------------------------------------------------------------------------- +# /* EV: R-33626-48418 */ +# +# Check that if any of the child key columns in the above schema are NULL, +# there is no requirement for a corresponding parent key. +# +do_test e_fkey-37.1 { + execsql { + INSERT INTO song VALUES(2, 'Elvis Presley', NULL, 'Fever'); + INSERT INTO song VALUES(3, NULL, 'Elvis Is Back', 'Soldier Boy'); + } +} {} + ########################################################################### ### SECTION 4.2: Deferred Foreign Key Constraints ########################################################################### #------------------------------------------------------------------------- # Note: R-35290-16460 is tested below. +# # TODO: R-30323-21917 #-------------------------------------------------------------------------