From a8f0bf643e693df066bb26da38be8c898de5de45 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 23 Sep 2009 12:06:52 +0000 Subject: [PATCH] Add extra tests for foreign key support. FossilOrigin-Name: 7d086afe69da4d03bd1de5408626858273f91e8f --- manifest | 16 +++---- manifest.uuid | 2 +- src/fkey.c | 10 ++--- test/fkey2.test | 100 ++++++++++++++++++++++++++++++++++++++++++ test/fkey_malloc.test | 57 +++++++++++++++++++++++- 5 files changed, 169 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index fa0d67b36e..0849f799c3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\smissing\scomments\sto\sfkey.c.\sAlso,\schange\sthe\sterminology\sused\sfor\scomments\sand\snames\sin\sfkey.c\sfrom\s"referenced/referencing"\sto\s"parent/child".\sThis\sis\sarguably\sless\scorrect,\sbut\sis\seasier\sto\sfollow. -D 2009-09-23T08:43:36 +C Add\sextra\stests\sfor\sforeign\skey\ssupport. +D 2009-09-23T12:06:52 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 4ca3f1dd6efa2075bcb27f4dc43eef749877740d F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -116,7 +116,7 @@ F src/date.c 657ff12ca0f1195b531561afacbb38b772d16638 F src/delete.c 15499f5d10047d38e68ce991b3f88cbddb6e0931 F src/expr.c 8a663240f374a5326ee157df3d27751f58b7676a F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff -F src/fkey.c da1a63c1cb22f4b93ceb743ab471a54648466732 +F src/fkey.c 320b318d3131139424ad36514cb376d326920610 F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606 F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32 F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7 @@ -330,8 +330,8 @@ F test/expr.test 80f3cf99f786ffbac19d2b0083673e7fc797030f F test/filectrl.test 8923a6dc7630f31c8a9dd3d3d740aa0922df7bf8 F test/filefmt.test 84e3d0fe9f12d0d2ac852465c6f8450aea0d6f43 F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da -F test/fkey2.test b752d0290886063b42b96584eca5ddeada4c3db1 -F test/fkey_malloc.test 91fb797bca97fd2cb170a3c7e2be7035e5f95244 +F test/fkey2.test 24668ccff4a2dc3177cc3271ffcbed158d90adca +F test/fkey_malloc.test a18bdb482c6a7b9a61865616a516584d17f04a04 F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7 F test/fts1b.test 5d8a01aefbecc8b7442b36c94c05eb7a845462d5 @@ -753,7 +753,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 71ac8e28e55ff0250ebe2fe239159ce2458d9165 -R 2ced32012b9c68891c37e1608fd90d15 +P 540c2d18e14c277b55f95729fbafc04ca66466b2 +R b1701f6c56797f01143914d74ba130c0 U dan -Z 2fdc28dc4452275cfa2178c7993f269c +Z 96e574304d094136cffd4148dd456947 diff --git a/manifest.uuid b/manifest.uuid index eab8d53d66..df45e300db 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -540c2d18e14c277b55f95729fbafc04ca66466b2 \ No newline at end of file +7d086afe69da4d03bd1de5408626858273f91e8f \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index 2dc93b66a2..fef04b7ace 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -407,11 +407,8 @@ static void fkScanChildren( pLeft->iTable = (pIdx ? (regData+pIdx->aiColumn[i]+1) : regData); } iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; - if( iCol<0 ){ - zCol = "rowid"; - }else{ - zCol = pFKey->pFrom->aCol[iCol].zName; - } + assert( iCol>=0 ); + zCol = pFKey->pFrom->aCol[iCol].zName; pRight = sqlite3Expr(db, TK_ID, zCol); pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); pWhere = sqlite3ExprAnd(db, pWhere, pEq); @@ -797,8 +794,9 @@ static Trigger *fkActionTrigger( Expr *pEq; /* tFromCol = OLD.tToCol */ iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; + assert( iFromCol>=0 ); tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid"; - tFromCol.z = iFromCol<0 ? "oid" : pFKey->pFrom->aCol[iFromCol].zName; + tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; tToCol.n = sqlite3Strlen30(tToCol.z); tFromCol.n = sqlite3Strlen30(tFromCol.z); diff --git a/test/fkey2.test b/test/fkey2.test index 8c6936e185..ad13906019 100644 --- a/test/fkey2.test +++ b/test/fkey2.test @@ -49,6 +49,12 @@ ifcapable {!foreignkey||!trigger} { # # fkey2-9.*: Test SET DEFAULT actions. # +# fkey2-10.*: Test errors. +# +# fkey2-11.*: Test CASCADE actions. +# +# fkey2-12.*: Test RESTRICT actions. +# # fkey2-genfkey.*: Tests that were used with the shell tool .genfkey # command. Recycled to test the built-in implementation. # @@ -518,6 +524,100 @@ do_test fkey2-9.1.5 { catchsql { DELETE FROM t1 } } {1 {foreign key constraint failed}} +#------------------------------------------------------------------------- +# The following tests, fkey2-10.*, test "foreign key mismatch" and +# other errors. +# + +set tn 1 +foreach zSql [list { + CREATE TABLE p(a PRIMARY KEY, b); + CREATE TABLE c(x REFERENCES p(c)); +}] { + drop_all_tables + + do_test fkey2-10.1.$tn { + execsql $zSql + catchsql { INSERT INTO c DEFAULT VALUES } + } {1 {foreign key mismatch}} +} + +# "rowid" cannot be used as part of a child key definition unless it +# happens to be the name of an explicitly declared column. +# +do_test fkey2-10.2.1 { + drop_all_tables + catchsql { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(c, d, FOREIGN KEY(rowid) REFERENCES t1(a)); + } +} {1 {unknown column "rowid" in foreign key definition}} +do_test fkey2-10.2.2 { + drop_all_tables + catchsql { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(rowid, d, FOREIGN KEY(rowid) REFERENCES t1(a)); + } +} {0 {}} + + +#------------------------------------------------------------------------- +# The following tests, fkey2-11.*, test CASCADE actions. +# +drop_all_tables +do_test fkey2-11.1.1 { + execsql { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(a) ON UPDATE CASCADE); + + INSERT INTO t1 VALUES(10, 100); + INSERT INTO t2 VALUES(10, 100); + UPDATE t1 SET a = 15; + SELECT * FROM t2; + } +} {15 100} + +#------------------------------------------------------------------------- +# The following tests, fkey2-12.*, test RESTRICT actions. +# +drop_all_tables +do_test fkey2-12.1.1 { + execsql { + CREATE TABLE t1(a, b PRIMARY KEY); + CREATE TABLE t2( + x REFERENCES t1 ON UPDATE RESTRICT DEFERRABLE INITIALLY DEFERRED + ); + INSERT INTO t1 VALUES(1, 'one'); + INSERT INTO t1 VALUES(2, 'two'); + INSERT INTO t1 VALUES(3, 'three'); + } +} {} + +do_test fkey2-12.1.2 { + execsql "BEGIN" + execsql "INSERT INTO t2 VALUES('two')" +} {} +do_test fkey2-12.1.3 { + execsql "UPDATE t1 SET b = 'four' WHERE b = 'one'" +} {} +do_test fkey2-12.1.4 { + catchsql "UPDATE t1 SET b = 'five' WHERE b = 'two'" +} {1 {foreign key constraint failed}} +do_test fkey2-12.1.5 { + execsql "DELETE FROM t1 WHERE b = 'two'" +} {} +do_test fkey2-12.1.6 { + catchsql "COMMIT" +} {1 {foreign key constraint failed}} +do_test fkey2-12.1.7 { + execsql { + INSERT INTO t1 VALUES(2, 'two'); + COMMIT; + } +} {} + + + #------------------------------------------------------------------------- # The following block of tests, those prefixed with "fkey2-genfkey.", are # the same tests that were used to test the ".genfkey" command provided diff --git a/test/fkey_malloc.test b/test/fkey_malloc.test index a8bf28c182..bd24bc7042 100644 --- a/test/fkey_malloc.test +++ b/test/fkey_malloc.test @@ -22,7 +22,7 @@ source $testdir/malloc_common.tcl do_malloc_test fkey_malloc-1 -sqlprep { PRAGMA foreign_keys = 1; - CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); CREATE TABLE t2(x REFERENCES t1 ON UPDATE CASCADE ON DELETE CASCADE); } -sqlbody { INSERT INTO t1 VALUES('aaa', 1); @@ -48,6 +48,61 @@ do_malloc_test fkey_malloc-2 -sqlprep { COMMIT; } +do_malloc_test fkey_malloc-3 -sqlprep { + PRAGMA foreign_keys = 1; + CREATE TABLE t1(x INTEGER PRIMARY KEY); + CREATE TABLE t2(y REFERENCES t1(rowid) ON UPDATE CASCADE); + CREATE TABLE t3(y DEFAULT 14 REFERENCES t1(x) ON UPDATE SET DEFAULT); + CREATE TABLE t4(y REFERENCES t1 ON UPDATE SET NULL); + INSERT INTO t1 VALUES(13); + INSERT INTO t2 VALUES(13); + INSERT INTO t3 VALUES(13); + INSERT INTO t4 VALUES(13); +} -sqlbody { + UPDATE t1 SET x = 14; +} + +proc catch_fk_error {zSql} { + set rc [catch {db eval $zSql} msg] + if {$rc==0} { + return $msg + } + if {[string match {*foreign key*} $msg]} { + return "" + } + if {$msg eq "out of memory"} { + error 1 + } + error $msg +} + +do_malloc_test fkey_malloc-4 -sqlprep { + PRAGMA foreign_keys = 1; + CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE); + CREATE TABLE t2(z REFERENCES t1(x), a REFERENCES t1(y)); + CREATE TABLE t3(x); + CREATE TABLE t4(z REFERENCES t3); + CREATE TABLE t5(x, y); + CREATE TABLE t6(z REFERENCES t5(x)); + CREATE INDEX i51 ON t5(x); + CREATE INDEX i52 ON t5(y, x); + INSERT INTO t1 VALUES(1, 2); +} -tclbody { + catch_fk_error {INSERT INTO t2 VALUES(1, 3)} + catch_fk_error {INSERT INTO t4 VALUES(2)} + catch_fk_error {INSERT INTO t6 VALUES(2)} +} + +do_malloc_test fkey_malloc-5 -sqlprep { + PRAGMA foreign_keys = 1; + CREATE TABLE t1(x, y, PRIMARY KEY(x, y)); + CREATE TABLE t2(a, b, FOREIGN KEY(a, b) REFERENCES t1 ON UPDATE CASCADE); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t2 VALUES(1, 2); +} -sqlbody { + UPDATE t1 SET x = 5; +} + finish_test