]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add further test cases to e_fkey.test.
authordan <dan@noemail.net>
Mon, 12 Oct 2009 08:41:49 +0000 (08:41 +0000)
committerdan <dan@noemail.net>
Mon, 12 Oct 2009 08:41:49 +0000 (08:41 +0000)
FossilOrigin-Name: d61cc0e1a1e8b4bf49016d3d14554f9c20f86f6b

manifest
manifest.uuid
test/e_fkey.test

index 92061854011011b81a3f6d6f911281166b6174b3..2b3e7d3aca8fff6762fc3930315f12e7373ee105 100644 (file)
--- 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
index c98cdf91abf93647b8e357f32cdc7baa7c276f83..ae134141646b4f45e82c8166409aea03cab189b2 100644 (file)
@@ -1 +1 @@
-5ec07feea47e727824b8b48236b5cce80539a455
\ No newline at end of file
+d61cc0e1a1e8b4bf49016d3d14554f9c20f86f6b
\ No newline at end of file
index 3784429aef8a85b95f6bc06111281362469c0e0c..04b825db7e73d513b7be26fafe58126f5682db16 100644 (file)
@@ -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
 
 #-------------------------------------------------------------------------