| OLD | NEW |
| 1 # 2009 October 7 | 1 # 2009 October 7 |
| 2 # | 2 # |
| 3 # The author disclaims copyright to this source code. In place of | 3 # The author disclaims copyright to this source code. In place of |
| 4 # a legal notice, here is a blessing: | 4 # a legal notice, here is a blessing: |
| 5 # | 5 # |
| 6 # May you do good and not evil. | 6 # May you do good and not evil. |
| 7 # May you find forgiveness for yourself and forgive others. | 7 # May you find forgiveness for yourself and forgive others. |
| 8 # May you share freely, never taking more than you give. | 8 # May you share freely, never taking more than you give. |
| 9 # | 9 # |
| 10 #*********************************************************************** | 10 #*********************************************************************** |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 reset_db | 128 reset_db |
| 129 | 129 |
| 130 | 130 |
| 131 #------------------------------------------------------------------------- | 131 #------------------------------------------------------------------------- |
| 132 # EVIDENCE-OF: R-07280-60510 Assuming the library is compiled with | 132 # EVIDENCE-OF: R-07280-60510 Assuming the library is compiled with |
| 133 # foreign key constraints enabled, it must still be enabled by the | 133 # foreign key constraints enabled, it must still be enabled by the |
| 134 # application at runtime, using the PRAGMA foreign_keys command. | 134 # application at runtime, using the PRAGMA foreign_keys command. |
| 135 # | 135 # |
| 136 # This also tests that foreign key constraints are disabled by default. | 136 # This also tests that foreign key constraints are disabled by default. |
| 137 # | 137 # |
| 138 # EVIDENCE-OF: R-59578-04990 Foreign key constraints are disabled by | 138 # EVIDENCE-OF: R-44261-39702 Foreign key constraints are disabled by |
| 139 # default (for backwards compatibility), so must be enabled separately | 139 # default (for backwards compatibility), so must be enabled separately |
| 140 # for each database connection separately. | 140 # for each database connection. |
| 141 # | 141 # |
| 142 drop_all_tables | 142 drop_all_tables |
| 143 do_test e_fkey-4.1 { | 143 do_test e_fkey-4.1 { |
| 144 execsql { | 144 execsql { |
| 145 CREATE TABLE p(i PRIMARY KEY); | 145 CREATE TABLE p(i PRIMARY KEY); |
| 146 CREATE TABLE c(j REFERENCES p ON UPDATE CASCADE); | 146 CREATE TABLE c(j REFERENCES p ON UPDATE CASCADE); |
| 147 INSERT INTO p VALUES('hello'); | 147 INSERT INTO p VALUES('hello'); |
| 148 INSERT INTO c VALUES('hello'); | 148 INSERT INTO c VALUES('hello'); |
| 149 UPDATE p SET i = 'world'; | 149 UPDATE p SET i = 'world'; |
| 150 SELECT * FROM c; | 150 SELECT * FROM c; |
| 151 } | 151 } |
| 152 } {hello} | 152 } {hello} |
| 153 do_test e_fkey-4.2 { | 153 do_test e_fkey-4.2 { |
| 154 execsql { | 154 execsql { |
| 155 DELETE FROM c; | 155 DELETE FROM c; |
| 156 DELETE FROM p; | 156 DELETE FROM p; |
| 157 PRAGMA foreign_keys = ON; | 157 PRAGMA foreign_keys = ON; |
| 158 INSERT INTO p VALUES('hello'); | 158 INSERT INTO p VALUES('hello'); |
| 159 INSERT INTO c VALUES('hello'); | 159 INSERT INTO c VALUES('hello'); |
| 160 UPDATE p SET i = 'world'; | 160 UPDATE p SET i = 'world'; |
| 161 SELECT * FROM c; | 161 SELECT * FROM c; |
| 162 } | 162 } |
| 163 } {world} | 163 } {world} |
| 164 | 164 |
| 165 #------------------------------------------------------------------------- | 165 #------------------------------------------------------------------------- |
| 166 # EVIDENCE-OF: R-15278-54456 The application can can also use a PRAGMA | 166 # EVIDENCE-OF: R-08013-37737 The application can also use a PRAGMA |
| 167 # foreign_keys statement to determine if foreign keys are currently | 167 # foreign_keys statement to determine if foreign keys are currently |
| 168 # enabled. | 168 # enabled. |
| 169 |
| 169 # | 170 # |
| 170 # This also tests the example code in section 2 of foreignkeys.in. | 171 # This also tests the example code in section 2 of foreignkeys.in. |
| 171 # | 172 # |
| 172 # EVIDENCE-OF: R-11255-19907 | 173 # EVIDENCE-OF: R-11255-19907 |
| 173 # | 174 # |
| 174 reset_db | 175 reset_db |
| 175 do_test e_fkey-5.1 { | 176 do_test e_fkey-5.1 { |
| 176 execsql { PRAGMA foreign_keys } | 177 execsql { PRAGMA foreign_keys } |
| 177 } {0} | 178 } {0} |
| 178 do_test e_fkey-5.2 { | 179 do_test e_fkey-5.2 { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 204 CREATE TABLE t1(a UNIQUE, b); | 205 CREATE TABLE t1(a UNIQUE, b); |
| 205 CREATE TABLE t2(c, d REFERENCES t1(a)); | 206 CREATE TABLE t2(c, d REFERENCES t1(a)); |
| 206 INSERT INTO t1 VALUES(1, 2); | 207 INSERT INTO t1 VALUES(1, 2); |
| 207 INSERT INTO t2 VALUES(2, 1); | 208 INSERT INTO t2 VALUES(2, 1); |
| 208 BEGIN; | 209 BEGIN; |
| 209 PRAGMA foreign_keys = OFF; | 210 PRAGMA foreign_keys = OFF; |
| 210 } | 211 } |
| 211 catchsql { | 212 catchsql { |
| 212 DELETE FROM t1 | 213 DELETE FROM t1 |
| 213 } | 214 } |
| 214 } {1 {foreign key constraint failed}} | 215 } {1 {FOREIGN KEY constraint failed}} |
| 215 do_test e_fkey-6.2 { | 216 do_test e_fkey-6.2 { |
| 216 execsql { PRAGMA foreign_keys } | 217 execsql { PRAGMA foreign_keys } |
| 217 } {1} | 218 } {1} |
| 218 do_test e_fkey-6.3 { | 219 do_test e_fkey-6.3 { |
| 219 execsql { | 220 execsql { |
| 220 COMMIT; | 221 COMMIT; |
| 221 PRAGMA foreign_keys = OFF; | 222 PRAGMA foreign_keys = OFF; |
| 222 BEGIN; | 223 BEGIN; |
| 223 PRAGMA foreign_keys = ON; | 224 PRAGMA foreign_keys = ON; |
| 224 DELETE FROM t1; | 225 DELETE FROM t1; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 } | 259 } |
| 259 } {} | 260 } {} |
| 260 | 261 |
| 261 #------------------------------------------------------------------------- | 262 #------------------------------------------------------------------------- |
| 262 # EVIDENCE-OF: R-61362-32087 Attempting to insert a row into the track | 263 # EVIDENCE-OF: R-61362-32087 Attempting to insert a row into the track |
| 263 # table that does not correspond to any row in the artist table will | 264 # table that does not correspond to any row in the artist table will |
| 264 # fail, | 265 # fail, |
| 265 # | 266 # |
| 266 do_test e_fkey-8.1 { | 267 do_test e_fkey-8.1 { |
| 267 catchsql { INSERT INTO track VALUES(1, 'track 1', 1) } | 268 catchsql { INSERT INTO track VALUES(1, 'track 1', 1) } |
| 268 } {1 {foreign key constraint failed}} | 269 } {1 {FOREIGN KEY constraint failed}} |
| 269 do_test e_fkey-8.2 { | 270 do_test e_fkey-8.2 { |
| 270 execsql { INSERT INTO artist VALUES(2, 'artist 1') } | 271 execsql { INSERT INTO artist VALUES(2, 'artist 1') } |
| 271 catchsql { INSERT INTO track VALUES(1, 'track 1', 1) } | 272 catchsql { INSERT INTO track VALUES(1, 'track 1', 1) } |
| 272 } {1 {foreign key constraint failed}} | 273 } {1 {FOREIGN KEY constraint failed}} |
| 273 do_test e_fkey-8.2 { | 274 do_test e_fkey-8.2 { |
| 274 execsql { INSERT INTO track VALUES(1, 'track 1', 2) } | 275 execsql { INSERT INTO track VALUES(1, 'track 1', 2) } |
| 275 } {} | 276 } {} |
| 276 | 277 |
| 277 #------------------------------------------------------------------------- | 278 #------------------------------------------------------------------------- |
| 278 # Attempting to delete a row from the 'artist' table while there are | 279 # Attempting to delete a row from the 'artist' table while there are |
| 279 # dependent rows in the track table also fails. | 280 # dependent rows in the track table also fails. |
| 280 # | 281 # |
| 281 # EVIDENCE-OF: R-24401-52400 as will attempting to delete a row from the | 282 # EVIDENCE-OF: R-24401-52400 as will attempting to delete a row from the |
| 282 # artist table when there exist dependent rows in the track table | 283 # artist table when there exist dependent rows in the track table |
| 283 # | 284 # |
| 284 do_test e_fkey-9.1 { | 285 do_test e_fkey-9.1 { |
| 285 catchsql { DELETE FROM artist WHERE artistid = 2 } | 286 catchsql { DELETE FROM artist WHERE artistid = 2 } |
| 286 } {1 {foreign key constraint failed}} | 287 } {1 {FOREIGN KEY constraint failed}} |
| 287 do_test e_fkey-9.2 { | 288 do_test e_fkey-9.2 { |
| 288 execsql { | 289 execsql { |
| 289 DELETE FROM track WHERE trackartist = 2; | 290 DELETE FROM track WHERE trackartist = 2; |
| 290 DELETE FROM artist WHERE artistid = 2; | 291 DELETE FROM artist WHERE artistid = 2; |
| 291 } | 292 } |
| 292 } {} | 293 } {} |
| 293 | 294 |
| 294 #------------------------------------------------------------------------- | 295 #------------------------------------------------------------------------- |
| 295 # If the foreign key column (trackartist) in table 'track' is set to NULL, | 296 # If the foreign key column (trackartist) in table 'track' is set to NULL, |
| 296 # there is no requirement for a matching row in the 'artist' table. | 297 # there is no requirement for a matching row in the 'artist' table. |
| 297 # | 298 # |
| 298 # EVIDENCE-OF: R-23980-48859 There is one exception: if the foreign key | 299 # EVIDENCE-OF: R-23980-48859 There is one exception: if the foreign key |
| 299 # column in the track table is NULL, then no corresponding entry in the | 300 # column in the track table is NULL, then no corresponding entry in the |
| 300 # artist table is required. | 301 # artist table is required. |
| 301 # | 302 # |
| 302 do_test e_fkey-10.1 { | 303 do_test e_fkey-10.1 { |
| 303 execsql { | 304 execsql { |
| 304 INSERT INTO track VALUES(1, 'track 1', NULL); | 305 INSERT INTO track VALUES(1, 'track 1', NULL); |
| 305 INSERT INTO track VALUES(2, 'track 2', NULL); | 306 INSERT INTO track VALUES(2, 'track 2', NULL); |
| 306 } | 307 } |
| 307 } {} | 308 } {} |
| 308 do_test e_fkey-10.2 { | 309 do_test e_fkey-10.2 { |
| 309 execsql { SELECT * FROM artist } | 310 execsql { SELECT * FROM artist } |
| 310 } {} | 311 } {} |
| 311 do_test e_fkey-10.3 { | 312 do_test e_fkey-10.3 { |
| 312 # Setting the trackid to a non-NULL value fails, of course. | 313 # Setting the trackid to a non-NULL value fails, of course. |
| 313 catchsql { UPDATE track SET trackartist = 5 WHERE trackid = 1 } | 314 catchsql { UPDATE track SET trackartist = 5 WHERE trackid = 1 } |
| 314 } {1 {foreign key constraint failed}} | 315 } {1 {FOREIGN KEY constraint failed}} |
| 315 do_test e_fkey-10.4 { | 316 do_test e_fkey-10.4 { |
| 316 execsql { | 317 execsql { |
| 317 INSERT INTO artist VALUES(5, 'artist 5'); | 318 INSERT INTO artist VALUES(5, 'artist 5'); |
| 318 UPDATE track SET trackartist = 5 WHERE trackid = 1; | 319 UPDATE track SET trackartist = 5 WHERE trackid = 1; |
| 319 } | 320 } |
| 320 catchsql { DELETE FROM artist WHERE artistid = 5} | 321 catchsql { DELETE FROM artist WHERE artistid = 5} |
| 321 } {1 {foreign key constraint failed}} | 322 } {1 {FOREIGN KEY constraint failed}} |
| 322 do_test e_fkey-10.5 { | 323 do_test e_fkey-10.5 { |
| 323 execsql { | 324 execsql { |
| 324 UPDATE track SET trackartist = NULL WHERE trackid = 1; | 325 UPDATE track SET trackartist = NULL WHERE trackid = 1; |
| 325 DELETE FROM artist WHERE artistid = 5; | 326 DELETE FROM artist WHERE artistid = 5; |
| 326 } | 327 } |
| 327 } {} | 328 } {} |
| 328 | 329 |
| 329 #------------------------------------------------------------------------- | 330 #------------------------------------------------------------------------- |
| 330 # Test that the following is true fo all rows in the track table: | 331 # Test that the following is true fo all rows in the track table: |
| 331 # | 332 # |
| 332 # trackartist IS NULL OR | 333 # trackartist IS NULL OR |
| 333 # EXISTS(SELECT 1 FROM artist WHERE artistid=trackartist) | 334 # EXISTS(SELECT 1 FROM artist WHERE artistid=trackartist) |
| 334 # | 335 # |
| 335 # EVIDENCE-OF: R-52486-21352 Expressed in SQL, this means that for every | 336 # EVIDENCE-OF: R-52486-21352 Expressed in SQL, this means that for every |
| 336 # row in the track table, the following expression evaluates to true: | 337 # row in the track table, the following expression evaluates to true: |
| 337 # trackartist IS NULL OR EXISTS(SELECT 1 FROM artist WHERE | 338 # trackartist IS NULL OR EXISTS(SELECT 1 FROM artist WHERE |
| 338 # artistid=trackartist) | 339 # artistid=trackartist) |
| 339 | 340 |
| 340 # This procedure executes a test case to check that statement | 341 # This procedure executes a test case to check that statement |
| 341 # R-52486-21352 is true after executing the SQL statement passed. | 342 # R-52486-21352 is true after executing the SQL statement passed. |
| 342 # as the second argument. | 343 # as the second argument. |
| 343 proc test_r52486_21352 {tn sql} { | 344 proc test_r52486_21352 {tn sql} { |
| 344 set res [catchsql $sql] | 345 set res [catchsql $sql] |
| 345 set results { | 346 set results { |
| 346 {0 {}} | 347 {0 {}} |
| 347 {1 {PRIMARY KEY must be unique}} | 348 {1 {UNIQUE constraint failed: artist.artistid}} |
| 348 {1 {foreign key constraint failed}} | 349 {1 {FOREIGN KEY constraint failed}} |
| 349 } | 350 } |
| 350 if {[lsearch $results $res]<0} { | 351 if {[lsearch $results $res]<0} { |
| 351 error $res | 352 error $res |
| 352 } | 353 } |
| 353 | 354 |
| 354 do_test e_fkey-11.$tn { | 355 do_test e_fkey-11.$tn { |
| 355 execsql { | 356 execsql { |
| 356 SELECT count(*) FROM track WHERE NOT ( | 357 SELECT count(*) FROM track WHERE NOT ( |
| 357 trackartist IS NULL OR | 358 trackartist IS NULL OR |
| 358 EXISTS(SELECT 1 FROM artist WHERE artistid=trackartist) | 359 EXISTS(SELECT 1 FROM artist WHERE artistid=trackartist) |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 CREATE TABLE track( | 403 CREATE TABLE track( |
| 403 trackid INTEGER, | 404 trackid INTEGER, |
| 404 trackname TEXT, | 405 trackname TEXT, |
| 405 trackartist INTEGER NOT NULL, | 406 trackartist INTEGER NOT NULL, |
| 406 FOREIGN KEY(trackartist) REFERENCES artist(artistid) | 407 FOREIGN KEY(trackartist) REFERENCES artist(artistid) |
| 407 ); | 408 ); |
| 408 } | 409 } |
| 409 } {} | 410 } {} |
| 410 do_test e_fkey-12.2 { | 411 do_test e_fkey-12.2 { |
| 411 catchsql { INSERT INTO track VALUES(14, 'Mr. Bojangles', NULL) } | 412 catchsql { INSERT INTO track VALUES(14, 'Mr. Bojangles', NULL) } |
| 412 } {1 {track.trackartist may not be NULL}} | 413 } {1 {NOT NULL constraint failed: track.trackartist}} |
| 413 | 414 |
| 414 #------------------------------------------------------------------------- | 415 #------------------------------------------------------------------------- |
| 415 # EVIDENCE-OF: R-16127-35442 | 416 # EVIDENCE-OF: R-16127-35442 |
| 416 # | 417 # |
| 417 # Test an example from foreignkeys.html. | 418 # Test an example from foreignkeys.html. |
| 418 # | 419 # |
| 419 drop_all_tables | 420 drop_all_tables |
| 420 do_test e_fkey-13.1 { | 421 do_test e_fkey-13.1 { |
| 421 execsql { | 422 execsql { |
| 422 CREATE TABLE artist( | 423 CREATE TABLE artist( |
| 423 artistid INTEGER PRIMARY KEY, | 424 artistid INTEGER PRIMARY KEY, |
| 424 artistname TEXT | 425 artistname TEXT |
| 425 ); | 426 ); |
| 426 CREATE TABLE track( | 427 CREATE TABLE track( |
| 427 trackid INTEGER, | 428 trackid INTEGER, |
| 428 trackname TEXT, | 429 trackname TEXT, |
| 429 trackartist INTEGER, | 430 trackartist INTEGER, |
| 430 FOREIGN KEY(trackartist) REFERENCES artist(artistid) | 431 FOREIGN KEY(trackartist) REFERENCES artist(artistid) |
| 431 ); | 432 ); |
| 432 INSERT INTO artist VALUES(1, 'Dean Martin'); | 433 INSERT INTO artist VALUES(1, 'Dean Martin'); |
| 433 INSERT INTO artist VALUES(2, 'Frank Sinatra'); | 434 INSERT INTO artist VALUES(2, 'Frank Sinatra'); |
| 434 INSERT INTO track VALUES(11, 'That''s Amore', 1); | 435 INSERT INTO track VALUES(11, 'That''s Amore', 1); |
| 435 INSERT INTO track VALUES(12, 'Christmas Blues', 1); | 436 INSERT INTO track VALUES(12, 'Christmas Blues', 1); |
| 436 INSERT INTO track VALUES(13, 'My Way', 2); | 437 INSERT INTO track VALUES(13, 'My Way', 2); |
| 437 } | 438 } |
| 438 } {} | 439 } {} |
| 439 do_test e_fkey-13.2 { | 440 do_test e_fkey-13.2 { |
| 440 catchsql { INSERT INTO track VALUES(14, 'Mr. Bojangles', 3) } | 441 catchsql { INSERT INTO track VALUES(14, 'Mr. Bojangles', 3) } |
| 441 } {1 {foreign key constraint failed}} | 442 } {1 {FOREIGN KEY constraint failed}} |
| 442 do_test e_fkey-13.3 { | 443 do_test e_fkey-13.3 { |
| 443 execsql { INSERT INTO track VALUES(14, 'Mr. Bojangles', NULL) } | 444 execsql { INSERT INTO track VALUES(14, 'Mr. Bojangles', NULL) } |
| 444 } {} | 445 } {} |
| 445 do_test e_fkey-13.4 { | 446 do_test e_fkey-13.4 { |
| 446 catchsql { | 447 catchsql { |
| 447 UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles'; | 448 UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles'; |
| 448 } | 449 } |
| 449 } {1 {foreign key constraint failed}} | 450 } {1 {FOREIGN KEY constraint failed}} |
| 450 do_test e_fkey-13.5 { | 451 do_test e_fkey-13.5 { |
| 451 execsql { | 452 execsql { |
| 452 INSERT INTO artist VALUES(3, 'Sammy Davis Jr.'); | 453 INSERT INTO artist VALUES(3, 'Sammy Davis Jr.'); |
| 453 UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles'; | 454 UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles'; |
| 454 INSERT INTO track VALUES(15, 'Boogie Woogie', 3); | 455 INSERT INTO track VALUES(15, 'Boogie Woogie', 3); |
| 455 } | 456 } |
| 456 } {} | 457 } {} |
| 457 | 458 |
| 458 #------------------------------------------------------------------------- | 459 #------------------------------------------------------------------------- |
| 459 # EVIDENCE-OF: R-15958-50233 | 460 # EVIDENCE-OF: R-15958-50233 |
| 460 # | 461 # |
| 461 # Test the second example from the first section of foreignkeys.html. | 462 # Test the second example from the first section of foreignkeys.html. |
| 462 # | 463 # |
| 463 do_test e_fkey-14.1 { | 464 do_test e_fkey-14.1 { |
| 464 catchsql { | 465 catchsql { |
| 465 DELETE FROM artist WHERE artistname = 'Frank Sinatra'; | 466 DELETE FROM artist WHERE artistname = 'Frank Sinatra'; |
| 466 } | 467 } |
| 467 } {1 {foreign key constraint failed}} | 468 } {1 {FOREIGN KEY constraint failed}} |
| 468 do_test e_fkey-14.2 { | 469 do_test e_fkey-14.2 { |
| 469 execsql { | 470 execsql { |
| 470 DELETE FROM track WHERE trackname = 'My Way'; | 471 DELETE FROM track WHERE trackname = 'My Way'; |
| 471 DELETE FROM artist WHERE artistname = 'Frank Sinatra'; | 472 DELETE FROM artist WHERE artistname = 'Frank Sinatra'; |
| 472 } | 473 } |
| 473 } {} | 474 } {} |
| 474 do_test e_fkey-14.3 { | 475 do_test e_fkey-14.3 { |
| 475 catchsql { | 476 catchsql { |
| 476 UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin'; | 477 UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin'; |
| 477 } | 478 } |
| 478 } {1 {foreign key constraint failed}} | 479 } {1 {FOREIGN KEY constraint failed}} |
| 479 do_test e_fkey-14.4 { | 480 do_test e_fkey-14.4 { |
| 480 execsql { | 481 execsql { |
| 481 DELETE FROM track WHERE trackname IN('That''s Amore', 'Christmas Blues'); | 482 DELETE FROM track WHERE trackname IN('That''s Amore', 'Christmas Blues'); |
| 482 UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin'; | 483 UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin'; |
| 483 } | 484 } |
| 484 } {} | 485 } {} |
| 485 | 486 |
| 486 | 487 |
| 487 #------------------------------------------------------------------------- | 488 #------------------------------------------------------------------------- |
| 488 # EVIDENCE-OF: R-56032-24923 The foreign key constraint is satisfied if | 489 # EVIDENCE-OF: R-56032-24923 The foreign key constraint is satisfied if |
| (...skipping 17 matching lines...) Expand all Loading... |
| 506 INSERT INTO par VALUES(1); | 507 INSERT INTO par VALUES(1); |
| 507 INSERT INTO par VALUES('1'); | 508 INSERT INTO par VALUES('1'); |
| 508 INSERT INTO par VALUES(X'31'); | 509 INSERT INTO par VALUES(X'31'); |
| 509 SELECT typeof(p) FROM par; | 510 SELECT typeof(p) FROM par; |
| 510 } | 511 } |
| 511 } {integer text blob} | 512 } {integer text blob} |
| 512 | 513 |
| 513 proc test_efkey_45 {tn isError sql} { | 514 proc test_efkey_45 {tn isError sql} { |
| 514 do_test e_fkey-15.$tn.1 " | 515 do_test e_fkey-15.$tn.1 " |
| 515 catchsql {$sql} | 516 catchsql {$sql} |
| 516 " [lindex {{0 {}} {1 {foreign key constraint failed}}} $isError] | 517 " [lindex {{0 {}} {1 {FOREIGN KEY constraint failed}}} $isError] |
| 517 | 518 |
| 518 do_test e_fkey-15.$tn.2 { | 519 do_test e_fkey-15.$tn.2 { |
| 519 execsql { | 520 execsql { |
| 520 SELECT * FROM chi WHERE c IS NOT NULL AND c NOT IN (SELECT p FROM par) | 521 SELECT * FROM chi WHERE c IS NOT NULL AND c NOT IN (SELECT p FROM par) |
| 521 } | 522 } |
| 522 } {} | 523 } {} |
| 523 } | 524 } |
| 524 | 525 |
| 525 test_efkey_45 1 0 "INSERT INTO chi VALUES(1)" | 526 test_efkey_45 1 0 "INSERT INTO chi VALUES(1)" |
| 526 test_efkey_45 2 1 "INSERT INTO chi VALUES('1.0')" | 527 test_efkey_45 2 1 "INSERT INTO chi VALUES('1.0')" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 550 execsql { | 551 execsql { |
| 551 INSERT INTO t1 VALUES('oNe'); | 552 INSERT INTO t1 VALUES('oNe'); |
| 552 INSERT INTO t2 VALUES('one'); | 553 INSERT INTO t2 VALUES('one'); |
| 553 INSERT INTO t2 VALUES('ONE'); | 554 INSERT INTO t2 VALUES('ONE'); |
| 554 UPDATE t2 SET b = 'OnE'; | 555 UPDATE t2 SET b = 'OnE'; |
| 555 UPDATE t1 SET a = 'ONE'; | 556 UPDATE t1 SET a = 'ONE'; |
| 556 } | 557 } |
| 557 } {} | 558 } {} |
| 558 do_test e_fkey-16.3 { | 559 do_test e_fkey-16.3 { |
| 559 catchsql { UPDATE t2 SET b = 'two' WHERE rowid = 1 } | 560 catchsql { UPDATE t2 SET b = 'two' WHERE rowid = 1 } |
| 560 } {1 {foreign key constraint failed}} | 561 } {1 {FOREIGN KEY constraint failed}} |
| 561 do_test e_fkey-16.4 { | 562 do_test e_fkey-16.4 { |
| 562 catchsql { DELETE FROM t1 WHERE rowid = 1 } | 563 catchsql { DELETE FROM t1 WHERE rowid = 1 } |
| 563 } {1 {foreign key constraint failed}} | 564 } {1 {FOREIGN KEY constraint failed}} |
| 564 | 565 |
| 565 #------------------------------------------------------------------------- | 566 #------------------------------------------------------------------------- |
| 566 # Specifically, test that when comparing child and parent key values the | 567 # Specifically, test that when comparing child and parent key values the |
| 567 # affinity of the parent key column is applied to the child key value | 568 # affinity of the parent key column is applied to the child key value |
| 568 # before the comparison takes place. | 569 # before the comparison takes place. |
| 569 # | 570 # |
| 570 # EVIDENCE-OF: R-04240-13860 When comparing values, if the parent key | 571 # EVIDENCE-OF: R-04240-13860 When comparing values, if the parent key |
| 571 # column has an affinity, then that affinity is applied to the child key | 572 # column has an affinity, then that affinity is applied to the child key |
| 572 # value before the comparison is performed. | 573 # value before the comparison is performed. |
| 573 # | 574 # |
| (...skipping 11 matching lines...) Expand all Loading... |
| 585 INSERT INTO t1 VALUES('three'); | 586 INSERT INTO t1 VALUES('three'); |
| 586 INSERT INTO t2 VALUES('2.0'); | 587 INSERT INTO t2 VALUES('2.0'); |
| 587 SELECT b, typeof(b) FROM t2; | 588 SELECT b, typeof(b) FROM t2; |
| 588 } | 589 } |
| 589 } {2.0 text} | 590 } {2.0 text} |
| 590 do_test e_fkey-17.3 { | 591 do_test e_fkey-17.3 { |
| 591 execsql { SELECT typeof(a) FROM t1 } | 592 execsql { SELECT typeof(a) FROM t1 } |
| 592 } {integer integer text} | 593 } {integer integer text} |
| 593 do_test e_fkey-17.4 { | 594 do_test e_fkey-17.4 { |
| 594 catchsql { DELETE FROM t1 WHERE rowid = 2 } | 595 catchsql { DELETE FROM t1 WHERE rowid = 2 } |
| 595 } {1 {foreign key constraint failed}} | 596 } {1 {FOREIGN KEY constraint failed}} |
| 596 | 597 |
| 597 ########################################################################### | 598 ########################################################################### |
| 598 ### SECTION 3: Required and Suggested Database Indexes | 599 ### SECTION 3: Required and Suggested Database Indexes |
| 599 ########################################################################### | 600 ########################################################################### |
| 600 | 601 |
| 601 #------------------------------------------------------------------------- | 602 #------------------------------------------------------------------------- |
| 602 # A parent key must be either a PRIMARY KEY, subject to a UNIQUE | 603 # A parent key must be either a PRIMARY KEY, subject to a UNIQUE |
| 603 # constraint, or have a UNIQUE index created on it. | 604 # constraint, or have a UNIQUE index created on it. |
| 604 # | 605 # |
| 605 # EVIDENCE-OF: R-13435-26311 Usually, the parent key of a foreign key | 606 # EVIDENCE-OF: R-13435-26311 Usually, the parent key of a foreign key |
| (...skipping 14 matching lines...) Expand all Loading... |
| 620 do_test e_fkey-18.1 { | 621 do_test e_fkey-18.1 { |
| 621 execsql { | 622 execsql { |
| 622 CREATE TABLE t2(a REFERENCES t1(x)); | 623 CREATE TABLE t2(a REFERENCES t1(x)); |
| 623 } | 624 } |
| 624 } {} | 625 } {} |
| 625 proc test_efkey_57 {tn isError sql} { | 626 proc test_efkey_57 {tn isError sql} { |
| 626 catchsql { DROP TABLE t1 } | 627 catchsql { DROP TABLE t1 } |
| 627 execsql $sql | 628 execsql $sql |
| 628 do_test e_fkey-18.$tn { | 629 do_test e_fkey-18.$tn { |
| 629 catchsql { INSERT INTO t2 VALUES(NULL) } | 630 catchsql { INSERT INTO t2 VALUES(NULL) } |
| 630 } [lindex {{0 {}} {1 {foreign key mismatch}}} $isError] | 631 } [lindex {{0 {}} {/1 {foreign key mismatch - ".*" referencing ".*"}/}} \ |
| 632 $isError] |
| 631 } | 633 } |
| 632 test_efkey_57 2 0 { CREATE TABLE t1(x PRIMARY KEY) } | 634 test_efkey_57 2 0 { CREATE TABLE t1(x PRIMARY KEY) } |
| 633 test_efkey_57 3 0 { CREATE TABLE t1(x UNIQUE) } | 635 test_efkey_57 3 0 { CREATE TABLE t1(x UNIQUE) } |
| 634 test_efkey_57 4 0 { CREATE TABLE t1(x); CREATE UNIQUE INDEX t1i ON t1(x) } | 636 test_efkey_57 4 0 { CREATE TABLE t1(x); CREATE UNIQUE INDEX t1i ON t1(x) } |
| 635 test_efkey_57 5 1 { | 637 test_efkey_57 5 1 { |
| 636 CREATE TABLE t1(x); | 638 CREATE TABLE t1(x); |
| 637 CREATE UNIQUE INDEX t1i ON t1(x COLLATE nocase); | 639 CREATE UNIQUE INDEX t1i ON t1(x COLLATE nocase); |
| 638 } | 640 } |
| 639 test_efkey_57 6 1 { CREATE TABLE t1(x) } | 641 test_efkey_57 6 1 { CREATE TABLE t1(x) } |
| 640 test_efkey_57 7 1 { CREATE TABLE t1(x, y, PRIMARY KEY(x, y)) } | 642 test_efkey_57 7 1 { CREATE TABLE t1(x, y, PRIMARY KEY(x, y)) } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 do_test e_fkey-19.2 { | 693 do_test e_fkey-19.2 { |
| 692 execsql { | 694 execsql { |
| 693 INSERT INTO parent VALUES(1, 2, 3, 4, 5, 6); | 695 INSERT INTO parent VALUES(1, 2, 3, 4, 5, 6); |
| 694 INSERT INTO child1 VALUES('xxx', 1); | 696 INSERT INTO child1 VALUES('xxx', 1); |
| 695 INSERT INTO child2 VALUES('xxx', 2); | 697 INSERT INTO child2 VALUES('xxx', 2); |
| 696 INSERT INTO child3 VALUES(3, 4); | 698 INSERT INTO child3 VALUES(3, 4); |
| 697 } | 699 } |
| 698 } {} | 700 } {} |
| 699 do_test e_fkey-19.2 { | 701 do_test e_fkey-19.2 { |
| 700 catchsql { INSERT INTO child4 VALUES('xxx', 5) } | 702 catchsql { INSERT INTO child4 VALUES('xxx', 5) } |
| 701 } {1 {foreign key mismatch}} | 703 } {1 {foreign key mismatch - "child4" referencing "parent"}} |
| 702 do_test e_fkey-19.3 { | 704 do_test e_fkey-19.3 { |
| 703 catchsql { INSERT INTO child5 VALUES('xxx', 6) } | 705 catchsql { INSERT INTO child5 VALUES('xxx', 6) } |
| 704 } {1 {foreign key mismatch}} | 706 } {1 {foreign key mismatch - "child5" referencing "parent"}} |
| 705 do_test e_fkey-19.4 { | 707 do_test e_fkey-19.4 { |
| 706 catchsql { INSERT INTO child6 VALUES(2, 3) } | 708 catchsql { INSERT INTO child6 VALUES(2, 3) } |
| 707 } {1 {foreign key mismatch}} | 709 } {1 {foreign key mismatch - "child6" referencing "parent"}} |
| 708 do_test e_fkey-19.5 { | 710 do_test e_fkey-19.5 { |
| 709 catchsql { INSERT INTO child7 VALUES(3) } | 711 catchsql { INSERT INTO child7 VALUES(3) } |
| 710 } {1 {foreign key mismatch}} | 712 } {1 {foreign key mismatch - "child7" referencing "parent"}} |
| 711 | 713 |
| 712 #------------------------------------------------------------------------- | 714 #------------------------------------------------------------------------- |
| 713 # Test errors in the database schema that are detected while preparing | 715 # Test errors in the database schema that are detected while preparing |
| 714 # DML statements. The error text for these messages always matches | 716 # DML statements. The error text for these messages always matches |
| 715 # either "foreign key mismatch" or "no such table*" (using [string match]). | 717 # either "foreign key mismatch" or "no such table*" (using [string match]). |
| 716 # | 718 # |
| 717 # EVIDENCE-OF: R-45488-08504 If the database schema contains foreign key | 719 # EVIDENCE-OF: R-45488-08504 If the database schema contains foreign key |
| 718 # errors that require looking at more than one table definition to | 720 # errors that require looking at more than one table definition to |
| 719 # identify, then those errors are not detected when the tables are | 721 # identify, then those errors are not detected when the tables are |
| 720 # created. | 722 # created. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 CREATE TABLE p6(a PRIMARY KEY, b); | 760 CREATE TABLE p6(a PRIMARY KEY, b); |
| 759 CREATE TABLE c6(c, d, FOREIGN KEY(c, d) REFERENCES p6); | 761 CREATE TABLE c6(c, d, FOREIGN KEY(c, d) REFERENCES p6); |
| 760 | 762 |
| 761 CREATE TABLE p7(a, b, PRIMARY KEY(a, b)); | 763 CREATE TABLE p7(a, b, PRIMARY KEY(a, b)); |
| 762 CREATE TABLE c7(c, d REFERENCES p7); | 764 CREATE TABLE c7(c, d REFERENCES p7); |
| 763 } | 765 } |
| 764 } {} | 766 } {} |
| 765 | 767 |
| 766 foreach {tn tbl ptbl err} { | 768 foreach {tn tbl ptbl err} { |
| 767 2 c1 {} "no such table: main.nosuchtable" | 769 2 c1 {} "no such table: main.nosuchtable" |
| 768 3 c2 p2 "foreign key mismatch" | 770 3 c2 p2 "foreign key mismatch - \"c2\" referencing \"p2\"" |
| 769 4 c3 p3 "foreign key mismatch" | 771 4 c3 p3 "foreign key mismatch - \"c3\" referencing \"p3\"" |
| 770 5 c4 p4 "foreign key mismatch" | 772 5 c4 p4 "foreign key mismatch - \"c4\" referencing \"p4\"" |
| 771 6 c5 p5 "foreign key mismatch" | 773 6 c5 p5 "foreign key mismatch - \"c5\" referencing \"p5\"" |
| 772 7 c6 p6 "foreign key mismatch" | 774 7 c6 p6 "foreign key mismatch - \"c6\" referencing \"p6\"" |
| 773 8 c7 p7 "foreign key mismatch" | 775 8 c7 p7 "foreign key mismatch - \"c7\" referencing \"p7\"" |
| 774 } { | 776 } { |
| 775 do_test e_fkey-20.$tn.1 { | 777 do_test e_fkey-20.$tn.1 { |
| 776 catchsql "INSERT INTO $tbl VALUES('a', 'b')" | 778 catchsql "INSERT INTO $tbl VALUES('a', 'b')" |
| 777 } [list 1 $err] | 779 } [list 1 $err] |
| 778 do_test e_fkey-20.$tn.2 { | 780 do_test e_fkey-20.$tn.2 { |
| 779 catchsql "UPDATE $tbl SET c = ?, d = ?" | 781 catchsql "UPDATE $tbl SET c = ?, d = ?" |
| 780 } [list 1 $err] | 782 } [list 1 $err] |
| 781 do_test e_fkey-20.$tn.3 { | 783 do_test e_fkey-20.$tn.3 { |
| 782 catchsql "INSERT INTO $tbl SELECT ?, ?" | 784 catchsql "INSERT INTO $tbl SELECT ?, ?" |
| 783 } [list 1 $err] | 785 } [list 1 $err] |
| (...skipping 29 matching lines...) Expand all Loading... |
| 813 } | 815 } |
| 814 } {} | 816 } {} |
| 815 do_test e_fkey-21.2 { | 817 do_test e_fkey-21.2 { |
| 816 execsql { | 818 execsql { |
| 817 INSERT INTO parent2 VALUES('I', 'II'); | 819 INSERT INTO parent2 VALUES('I', 'II'); |
| 818 INSERT INTO child8 VALUES('I', 'II'); | 820 INSERT INTO child8 VALUES('I', 'II'); |
| 819 } | 821 } |
| 820 } {} | 822 } {} |
| 821 do_test e_fkey-21.3 { | 823 do_test e_fkey-21.3 { |
| 822 catchsql { INSERT INTO child9 VALUES('I') } | 824 catchsql { INSERT INTO child9 VALUES('I') } |
| 823 } {1 {foreign key mismatch}} | 825 } {1 {foreign key mismatch - "child9" referencing "parent2"}} |
| 824 do_test e_fkey-21.4 { | 826 do_test e_fkey-21.4 { |
| 825 catchsql { INSERT INTO child9 VALUES('II') } | 827 catchsql { INSERT INTO child9 VALUES('II') } |
| 826 } {1 {foreign key mismatch}} | 828 } {1 {foreign key mismatch - "child9" referencing "parent2"}} |
| 827 do_test e_fkey-21.5 { | 829 do_test e_fkey-21.5 { |
| 828 catchsql { INSERT INTO child9 VALUES(NULL) } | 830 catchsql { INSERT INTO child9 VALUES(NULL) } |
| 829 } {1 {foreign key mismatch}} | 831 } {1 {foreign key mismatch - "child9" referencing "parent2"}} |
| 830 do_test e_fkey-21.6 { | 832 do_test e_fkey-21.6 { |
| 831 catchsql { INSERT INTO child10 VALUES('I', 'II', 'III') } | 833 catchsql { INSERT INTO child10 VALUES('I', 'II', 'III') } |
| 832 } {1 {foreign key mismatch}} | 834 } {1 {foreign key mismatch - "child10" referencing "parent2"}} |
| 833 do_test e_fkey-21.7 { | 835 do_test e_fkey-21.7 { |
| 834 catchsql { INSERT INTO child10 VALUES(1, 2, 3) } | 836 catchsql { INSERT INTO child10 VALUES(1, 2, 3) } |
| 835 } {1 {foreign key mismatch}} | 837 } {1 {foreign key mismatch - "child10" referencing "parent2"}} |
| 836 do_test e_fkey-21.8 { | 838 do_test e_fkey-21.8 { |
| 837 catchsql { INSERT INTO child10 VALUES(NULL, NULL, NULL) } | 839 catchsql { INSERT INTO child10 VALUES(NULL, NULL, NULL) } |
| 838 } {1 {foreign key mismatch}} | 840 } {1 {foreign key mismatch - "child10" referencing "parent2"}} |
| 839 | 841 |
| 840 #------------------------------------------------------------------------- | 842 #------------------------------------------------------------------------- |
| 841 # Test errors that are reported when creating the child table. | 843 # Test errors that are reported when creating the child table. |
| 842 # Specifically: | 844 # Specifically: |
| 843 # | 845 # |
| 844 # * different number of child and parent key columns, and | 846 # * different number of child and parent key columns, and |
| 845 # * child columns that do not exist. | 847 # * child columns that do not exist. |
| 846 # | 848 # |
| 847 # EVIDENCE-OF: R-23682-59820 By contrast, if foreign key errors can be | 849 # EVIDENCE-OF: R-23682-59820 By contrast, if foreign key errors can be |
| 848 # recognized simply by looking at the definition of the child table and | 850 # recognized simply by looking at the definition of the child table and |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 888 execsql { | 890 execsql { |
| 889 CREATE TABLE p1(a, b, PRIMARY KEY(a, b)); | 891 CREATE TABLE p1(a, b, PRIMARY KEY(a, b)); |
| 890 CREATE TABLE p2(a, b PRIMARY KEY); | 892 CREATE TABLE p2(a, b PRIMARY KEY); |
| 891 CREATE TABLE c1(c, d, FOREIGN KEY(c, d) REFERENCES p1); | 893 CREATE TABLE c1(c, d, FOREIGN KEY(c, d) REFERENCES p1); |
| 892 CREATE TABLE c2(a, b REFERENCES p2); | 894 CREATE TABLE c2(a, b REFERENCES p2); |
| 893 } | 895 } |
| 894 } {} | 896 } {} |
| 895 proc test_efkey_60 {tn isError sql} { | 897 proc test_efkey_60 {tn isError sql} { |
| 896 do_test e_fkey-23.$tn " | 898 do_test e_fkey-23.$tn " |
| 897 catchsql {$sql} | 899 catchsql {$sql} |
| 898 " [lindex {{0 {}} {1 {foreign key constraint failed}}} $isError] | 900 " [lindex {{0 {}} {1 {FOREIGN KEY constraint failed}}} $isError] |
| 899 } | 901 } |
| 900 | 902 |
| 901 test_efkey_60 2 1 "INSERT INTO c1 VALUES(239, 231)" | 903 test_efkey_60 2 1 "INSERT INTO c1 VALUES(239, 231)" |
| 902 test_efkey_60 3 0 "INSERT INTO p1 VALUES(239, 231)" | 904 test_efkey_60 3 0 "INSERT INTO p1 VALUES(239, 231)" |
| 903 test_efkey_60 4 0 "INSERT INTO c1 VALUES(239, 231)" | 905 test_efkey_60 4 0 "INSERT INTO c1 VALUES(239, 231)" |
| 904 test_efkey_60 5 1 "INSERT INTO c2 VALUES(239, 231)" | 906 test_efkey_60 5 1 "INSERT INTO c2 VALUES(239, 231)" |
| 905 test_efkey_60 6 0 "INSERT INTO p2 VALUES(239, 231)" | 907 test_efkey_60 6 0 "INSERT INTO p2 VALUES(239, 231)" |
| 906 test_efkey_60 7 0 "INSERT INTO c2 VALUES(239, 231)" | 908 test_efkey_60 7 0 "INSERT INTO c2 VALUES(239, 231)" |
| 907 | 909 |
| 908 #------------------------------------------------------------------------- | 910 #------------------------------------------------------------------------- |
| (...skipping 16 matching lines...) Expand all Loading... |
| 925 CREATE TABLE c1(a, b, FOREIGN KEY(a, b) REFERENCES parent(x, y)); | 927 CREATE TABLE c1(a, b, FOREIGN KEY(a, b) REFERENCES parent(x, y)); |
| 926 CREATE TABLE c2(a, b, FOREIGN KEY(a, b) REFERENCES parent(x, y)); | 928 CREATE TABLE c2(a, b, FOREIGN KEY(a, b) REFERENCES parent(x, y)); |
| 927 CREATE TABLE c3(a, b, FOREIGN KEY(a, b) REFERENCES parent(x, y)); | 929 CREATE TABLE c3(a, b, FOREIGN KEY(a, b) REFERENCES parent(x, y)); |
| 928 CREATE INDEX c2i ON c2(a, b); | 930 CREATE INDEX c2i ON c2(a, b); |
| 929 CREATE UNIQUE INDEX c3i ON c2(b, a); | 931 CREATE UNIQUE INDEX c3i ON c2(b, a); |
| 930 } | 932 } |
| 931 } {} | 933 } {} |
| 932 proc test_efkey_61 {tn isError sql} { | 934 proc test_efkey_61 {tn isError sql} { |
| 933 do_test e_fkey-24.$tn " | 935 do_test e_fkey-24.$tn " |
| 934 catchsql {$sql} | 936 catchsql {$sql} |
| 935 " [lindex {{0 {}} {1 {foreign key constraint failed}}} $isError] | 937 " [lindex {{0 {}} {1 {FOREIGN KEY constraint failed}}} $isError] |
| 936 } | 938 } |
| 937 foreach {tn c} [list 2 c1 3 c2 4 c3] { | 939 foreach {tn c} [list 2 c1 3 c2 4 c3] { |
| 938 test_efkey_61 $tn.1 1 "INSERT INTO $c VALUES(1, 2)" | 940 test_efkey_61 $tn.1 1 "INSERT INTO $c VALUES(1, 2)" |
| 939 test_efkey_61 $tn.2 0 "INSERT INTO parent VALUES(1, 2)" | 941 test_efkey_61 $tn.2 0 "INSERT INTO parent VALUES(1, 2)" |
| 940 test_efkey_61 $tn.3 0 "INSERT INTO $c VALUES(1, 2)" | 942 test_efkey_61 $tn.3 0 "INSERT INTO $c VALUES(1, 2)" |
| 941 | 943 |
| 942 execsql "DELETE FROM $c ; DELETE FROM parent" | 944 execsql "DELETE FROM $c ; DELETE FROM parent" |
| 943 } | 945 } |
| 944 | 946 |
| 945 #------------------------------------------------------------------------- | 947 #------------------------------------------------------------------------- |
| (...skipping 20 matching lines...) Expand all Loading... |
| 966 trackartist INTEGER, | 968 trackartist INTEGER, |
| 967 FOREIGN KEY(trackartist) REFERENCES artist(artistid) | 969 FOREIGN KEY(trackartist) REFERENCES artist(artistid) |
| 968 ); | 970 ); |
| 969 } | 971 } |
| 970 } {} | 972 } {} |
| 971 do_execsql_test e_fkey-25.2 { | 973 do_execsql_test e_fkey-25.2 { |
| 972 PRAGMA foreign_keys = OFF; | 974 PRAGMA foreign_keys = OFF; |
| 973 EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1; | 975 EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1; |
| 974 EXPLAIN QUERY PLAN SELECT rowid FROM track WHERE trackartist = ?; | 976 EXPLAIN QUERY PLAN SELECT rowid FROM track WHERE trackartist = ?; |
| 975 } { | 977 } { |
| 976 0 0 0 {SCAN TABLE artist (~1000000 rows)} | 978 0 0 0 {SCAN TABLE artist} |
| 977 0 0 0 {SCAN TABLE track (~100000 rows)} | 979 0 0 0 {SCAN TABLE track} |
| 978 } | 980 } |
| 979 do_execsql_test e_fkey-25.3 { | 981 do_execsql_test e_fkey-25.3 { |
| 980 PRAGMA foreign_keys = ON; | 982 PRAGMA foreign_keys = ON; |
| 981 EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1; | 983 EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1; |
| 982 } { | 984 } { |
| 983 0 0 0 {SCAN TABLE artist (~1000000 rows)} | 985 0 0 0 {SCAN TABLE artist} |
| 984 0 0 0 {SCAN TABLE track (~100000 rows)} | 986 0 0 0 {SCAN TABLE track} |
| 985 } | 987 } |
| 986 do_test e_fkey-25.4 { | 988 do_test e_fkey-25.4 { |
| 987 execsql { | 989 execsql { |
| 988 INSERT INTO artist VALUES(5, 'artist 5'); | 990 INSERT INTO artist VALUES(5, 'artist 5'); |
| 989 INSERT INTO artist VALUES(6, 'artist 6'); | 991 INSERT INTO artist VALUES(6, 'artist 6'); |
| 990 INSERT INTO artist VALUES(7, 'artist 7'); | 992 INSERT INTO artist VALUES(7, 'artist 7'); |
| 991 INSERT INTO track VALUES(1, 'track 1', 5); | 993 INSERT INTO track VALUES(1, 'track 1', 5); |
| 992 INSERT INTO track VALUES(2, 'track 2', 6); | 994 INSERT INTO track VALUES(2, 'track 2', 6); |
| 993 } | 995 } |
| 994 } {} | 996 } {} |
| 995 | 997 |
| 996 do_test e_fkey-25.5 { | 998 do_test e_fkey-25.5 { |
| 997 concat \ | 999 concat \ |
| 998 [execsql { SELECT rowid FROM track WHERE trackartist = 5 }] \ | 1000 [execsql { SELECT rowid FROM track WHERE trackartist = 5 }] \ |
| 999 [catchsql { DELETE FROM artist WHERE artistid = 5 }] | 1001 [catchsql { DELETE FROM artist WHERE artistid = 5 }] |
| 1000 } {1 1 {foreign key constraint failed}} | 1002 } {1 1 {FOREIGN KEY constraint failed}} |
| 1001 | 1003 |
| 1002 do_test e_fkey-25.6 { | 1004 do_test e_fkey-25.6 { |
| 1003 concat \ | 1005 concat \ |
| 1004 [execsql { SELECT rowid FROM track WHERE trackartist = 7 }] \ | 1006 [execsql { SELECT rowid FROM track WHERE trackartist = 7 }] \ |
| 1005 [catchsql { DELETE FROM artist WHERE artistid = 7 }] | 1007 [catchsql { DELETE FROM artist WHERE artistid = 7 }] |
| 1006 } {0 {}} | 1008 } {0 {}} |
| 1007 | 1009 |
| 1008 do_test e_fkey-25.7 { | 1010 do_test e_fkey-25.7 { |
| 1009 concat \ | 1011 concat \ |
| 1010 [execsql { SELECT rowid FROM track WHERE trackartist = 6 }] \ | 1012 [execsql { SELECT rowid FROM track WHERE trackartist = 6 }] \ |
| 1011 [catchsql { DELETE FROM artist WHERE artistid = 6 }] | 1013 [catchsql { DELETE FROM artist WHERE artistid = 6 }] |
| 1012 } {2 1 {foreign key constraint failed}} | 1014 } {2 1 {FOREIGN KEY constraint failed}} |
| 1013 | 1015 |
| 1014 #------------------------------------------------------------------------- | 1016 #------------------------------------------------------------------------- |
| 1015 # EVIDENCE-OF: R-47936-10044 Or, more generally: | 1017 # EVIDENCE-OF: R-47936-10044 Or, more generally: |
| 1016 # SELECT rowid FROM <child-table> WHERE <child-key> = :parent_key_value | 1018 # SELECT rowid FROM <child-table> WHERE <child-key> = :parent_key_value |
| 1017 # | 1019 # |
| 1018 # Test that when a row is deleted from the parent table of an FK | 1020 # Test that when a row is deleted from the parent table of an FK |
| 1019 # constraint, the child table is queried for orphaned rows. The | 1021 # constraint, the child table is queried for orphaned rows. The |
| 1020 # query is equivalent to: | 1022 # query is equivalent to: |
| 1021 # | 1023 # |
| 1022 # SELECT rowid FROM <child-table> WHERE <child-key> = :parent_key_value | 1024 # SELECT rowid FROM <child-table> WHERE <child-key> = :parent_key_value |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1091 ); | 1093 ); |
| 1092 CREATE INDEX trackindex ON track(trackartist); | 1094 CREATE INDEX trackindex ON track(trackartist); |
| 1093 } | 1095 } |
| 1094 } {} | 1096 } {} |
| 1095 do_test e_fkey-27.2 { | 1097 do_test e_fkey-27.2 { |
| 1096 eqp { INSERT INTO artist VALUES(?, ?) } | 1098 eqp { INSERT INTO artist VALUES(?, ?) } |
| 1097 } {} | 1099 } {} |
| 1098 do_execsql_test e_fkey-27.3 { | 1100 do_execsql_test e_fkey-27.3 { |
| 1099 EXPLAIN QUERY PLAN UPDATE artist SET artistid = ?, artistname = ? | 1101 EXPLAIN QUERY PLAN UPDATE artist SET artistid = ?, artistname = ? |
| 1100 } { | 1102 } { |
| 1101 0 0 0 {SCAN TABLE artist (~1000000 rows)} | 1103 0 0 0 {SCAN TABLE artist} |
| 1102 0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?) (~10
rows)} | 1104 0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)} |
| 1103 0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?) (~10
rows)} | 1105 0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)} |
| 1104 } | 1106 } |
| 1105 do_execsql_test e_fkey-27.4 { | 1107 do_execsql_test e_fkey-27.4 { |
| 1106 EXPLAIN QUERY PLAN DELETE FROM artist | 1108 EXPLAIN QUERY PLAN DELETE FROM artist |
| 1107 } { | 1109 } { |
| 1108 0 0 0 {SCAN TABLE artist (~1000000 rows)} | 1110 0 0 0 {SCAN TABLE artist} |
| 1109 0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?) (~10
rows)} | 1111 0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)} |
| 1110 } | 1112 } |
| 1111 | 1113 |
| 1112 | 1114 |
| 1113 ########################################################################### | 1115 ########################################################################### |
| 1114 ### SECTION 4.1: Composite Foreign Key Constraints | 1116 ### SECTION 4.1: Composite Foreign Key Constraints |
| 1115 ########################################################################### | 1117 ########################################################################### |
| 1116 | 1118 |
| 1117 #------------------------------------------------------------------------- | 1119 #------------------------------------------------------------------------- |
| 1118 # Check that parent and child keys must have the same number of columns. | 1120 # Check that parent and child keys must have the same number of columns. |
| 1119 # | 1121 # |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1144 drop_all_tables | 1146 drop_all_tables |
| 1145 do_test e_fkey-28.$tn [list catchsql $sql] [list 1 $err] | 1147 do_test e_fkey-28.$tn [list catchsql $sql] [list 1 $err] |
| 1146 } | 1148 } |
| 1147 do_test e_fkey-28.8 { | 1149 do_test e_fkey-28.8 { |
| 1148 drop_all_tables | 1150 drop_all_tables |
| 1149 execsql { | 1151 execsql { |
| 1150 CREATE TABLE p(x PRIMARY KEY); | 1152 CREATE TABLE p(x PRIMARY KEY); |
| 1151 CREATE TABLE c(a, b, FOREIGN KEY(a,b) REFERENCES p); | 1153 CREATE TABLE c(a, b, FOREIGN KEY(a,b) REFERENCES p); |
| 1152 } | 1154 } |
| 1153 catchsql {DELETE FROM p} | 1155 catchsql {DELETE FROM p} |
| 1154 } {1 {foreign key mismatch}} | 1156 } {1 {foreign key mismatch - "c" referencing "p"}} |
| 1155 do_test e_fkey-28.9 { | 1157 do_test e_fkey-28.9 { |
| 1156 drop_all_tables | 1158 drop_all_tables |
| 1157 execsql { | 1159 execsql { |
| 1158 CREATE TABLE p(x, y, PRIMARY KEY(x,y)); | 1160 CREATE TABLE p(x, y, PRIMARY KEY(x,y)); |
| 1159 CREATE TABLE c(a REFERENCES p); | 1161 CREATE TABLE c(a REFERENCES p); |
| 1160 } | 1162 } |
| 1161 catchsql {DELETE FROM p} | 1163 catchsql {DELETE FROM p} |
| 1162 } {1 {foreign key mismatch}} | 1164 } {1 {foreign key mismatch - "c" referencing "p"}} |
| 1163 | 1165 |
| 1164 | 1166 |
| 1165 #------------------------------------------------------------------------- | 1167 #------------------------------------------------------------------------- |
| 1166 # EVIDENCE-OF: R-24676-09859 | 1168 # EVIDENCE-OF: R-24676-09859 |
| 1167 # | 1169 # |
| 1168 # Test the example schema in the "Composite Foreign Key Constraints" | 1170 # Test the example schema in the "Composite Foreign Key Constraints" |
| 1169 # section. | 1171 # section. |
| 1170 # | 1172 # |
| 1171 do_test e_fkey-29.1 { | 1173 do_test e_fkey-29.1 { |
| 1172 execsql { | 1174 execsql { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1191 INSERT INTO album VALUES('Elvis Presley', 'Elvis'' Christmas Album', NULL); | 1193 INSERT INTO album VALUES('Elvis Presley', 'Elvis'' Christmas Album', NULL); |
| 1192 INSERT INTO song VALUES( | 1194 INSERT INTO song VALUES( |
| 1193 1, 'Elvis Presley', 'Elvis'' Christmas Album', 'Here Comes Santa Clause' | 1195 1, 'Elvis Presley', 'Elvis'' Christmas Album', 'Here Comes Santa Clause' |
| 1194 ); | 1196 ); |
| 1195 } | 1197 } |
| 1196 } {} | 1198 } {} |
| 1197 do_test e_fkey-29.3 { | 1199 do_test e_fkey-29.3 { |
| 1198 catchsql { | 1200 catchsql { |
| 1199 INSERT INTO song VALUES(2, 'Elvis Presley', 'Elvis Is Back!', 'Fever'); | 1201 INSERT INTO song VALUES(2, 'Elvis Presley', 'Elvis Is Back!', 'Fever'); |
| 1200 } | 1202 } |
| 1201 } {1 {foreign key constraint failed}} | 1203 } {1 {FOREIGN KEY constraint failed}} |
| 1202 | 1204 |
| 1203 | 1205 |
| 1204 #------------------------------------------------------------------------- | 1206 #------------------------------------------------------------------------- |
| 1205 # EVIDENCE-OF: R-33626-48418 In SQLite, if any of the child key columns | 1207 # EVIDENCE-OF: R-33626-48418 In SQLite, if any of the child key columns |
| 1206 # (in this case songartist and songalbum) are NULL, then there is no | 1208 # (in this case songartist and songalbum) are NULL, then there is no |
| 1207 # requirement for a corresponding row in the parent table. | 1209 # requirement for a corresponding row in the parent table. |
| 1208 # | 1210 # |
| 1209 do_test e_fkey-30.1 { | 1211 do_test e_fkey-30.1 { |
| 1210 execsql { | 1212 execsql { |
| 1211 INSERT INTO song VALUES(2, 'Elvis Presley', NULL, 'Fever'); | 1213 INSERT INTO song VALUES(2, 'Elvis Presley', NULL, 'Fever'); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1232 do_test e_fkey-31.1 { | 1234 do_test e_fkey-31.1 { |
| 1233 execsql { | 1235 execsql { |
| 1234 CREATE TABLE king(a, b, PRIMARY KEY(a)); | 1236 CREATE TABLE king(a, b, PRIMARY KEY(a)); |
| 1235 CREATE TABLE prince(c REFERENCES king, d); | 1237 CREATE TABLE prince(c REFERENCES king, d); |
| 1236 } | 1238 } |
| 1237 } {} | 1239 } {} |
| 1238 | 1240 |
| 1239 do_test e_fkey-31.2 { | 1241 do_test e_fkey-31.2 { |
| 1240 # Execute a statement that violates the immediate FK constraint. | 1242 # Execute a statement that violates the immediate FK constraint. |
| 1241 catchsql { INSERT INTO prince VALUES(1, 2) } | 1243 catchsql { INSERT INTO prince VALUES(1, 2) } |
| 1242 } {1 {foreign key constraint failed}} | 1244 } {1 {FOREIGN KEY constraint failed}} |
| 1243 | 1245 |
| 1244 do_test e_fkey-31.3 { | 1246 do_test e_fkey-31.3 { |
| 1245 # This time, use a trigger to fix the constraint violation before the | 1247 # This time, use a trigger to fix the constraint violation before the |
| 1246 # statement has finished executing. Then execute the same statement as | 1248 # statement has finished executing. Then execute the same statement as |
| 1247 # in the previous test case. This time, no error. | 1249 # in the previous test case. This time, no error. |
| 1248 execsql { | 1250 execsql { |
| 1249 CREATE TRIGGER kt AFTER INSERT ON prince WHEN | 1251 CREATE TRIGGER kt AFTER INSERT ON prince WHEN |
| 1250 NOT EXISTS (SELECT a FROM king WHERE a = new.c) | 1252 NOT EXISTS (SELECT a FROM king WHERE a = new.c) |
| 1251 BEGIN | 1253 BEGIN |
| 1252 INSERT INTO king VALUES(new.c, NULL); | 1254 INSERT INTO king VALUES(new.c, NULL); |
| 1253 END | 1255 END |
| 1254 } | 1256 } |
| 1255 execsql { INSERT INTO prince VALUES(1, 2) } | 1257 execsql { INSERT INTO prince VALUES(1, 2) } |
| 1256 } {} | 1258 } {} |
| 1257 | 1259 |
| 1258 # Test that operating inside a transaction makes no difference to | 1260 # Test that operating inside a transaction makes no difference to |
| 1259 # immediate constraint violation handling. | 1261 # immediate constraint violation handling. |
| 1260 do_test e_fkey-31.4 { | 1262 do_test e_fkey-31.4 { |
| 1261 execsql { | 1263 execsql { |
| 1262 BEGIN; | 1264 BEGIN; |
| 1263 INSERT INTO prince VALUES(2, 3); | 1265 INSERT INTO prince VALUES(2, 3); |
| 1264 DROP TRIGGER kt; | 1266 DROP TRIGGER kt; |
| 1265 } | 1267 } |
| 1266 catchsql { INSERT INTO prince VALUES(3, 4) } | 1268 catchsql { INSERT INTO prince VALUES(3, 4) } |
| 1267 } {1 {foreign key constraint failed}} | 1269 } {1 {FOREIGN KEY constraint failed}} |
| 1268 do_test e_fkey-31.5 { | 1270 do_test e_fkey-31.5 { |
| 1269 execsql { | 1271 execsql { |
| 1270 COMMIT; | 1272 COMMIT; |
| 1271 SELECT * FROM king; | 1273 SELECT * FROM king; |
| 1272 } | 1274 } |
| 1273 } {1 {} 2 {}} | 1275 } {1 {} 2 {}} |
| 1274 | 1276 |
| 1275 #------------------------------------------------------------------------- | 1277 #------------------------------------------------------------------------- |
| 1276 # Test that if a deferred constraint is violated within a transaction, | 1278 # Test that if a deferred constraint is violated within a transaction, |
| 1277 # nothing happens immediately and the database is allowed to persist | 1279 # nothing happens immediately and the database is allowed to persist |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1288 # EVIDENCE-OF: R-55147-47664 For as long as the user has an open | 1290 # EVIDENCE-OF: R-55147-47664 For as long as the user has an open |
| 1289 # transaction, the database is allowed to exist in a state that violates | 1291 # transaction, the database is allowed to exist in a state that violates |
| 1290 # any number of deferred foreign key constraints. | 1292 # any number of deferred foreign key constraints. |
| 1291 # | 1293 # |
| 1292 # EVIDENCE-OF: R-29604-30395 However, COMMIT will fail as long as | 1294 # EVIDENCE-OF: R-29604-30395 However, COMMIT will fail as long as |
| 1293 # foreign key constraints remain in violation. | 1295 # foreign key constraints remain in violation. |
| 1294 # | 1296 # |
| 1295 proc test_efkey_34 {tn isError sql} { | 1297 proc test_efkey_34 {tn isError sql} { |
| 1296 do_test e_fkey-32.$tn " | 1298 do_test e_fkey-32.$tn " |
| 1297 catchsql {$sql} | 1299 catchsql {$sql} |
| 1298 " [lindex {{0 {}} {1 {foreign key constraint failed}}} $isError] | 1300 " [lindex {{0 {}} {1 {FOREIGN KEY constraint failed}}} $isError] |
| 1299 } | 1301 } |
| 1300 drop_all_tables | 1302 drop_all_tables |
| 1301 | 1303 |
| 1302 test_efkey_34 1 0 { | 1304 test_efkey_34 1 0 { |
| 1303 CREATE TABLE ll(k PRIMARY KEY); | 1305 CREATE TABLE ll(k PRIMARY KEY); |
| 1304 CREATE TABLE kk(c REFERENCES ll DEFERRABLE INITIALLY DEFERRED); | 1306 CREATE TABLE kk(c REFERENCES ll DEFERRABLE INITIALLY DEFERRED); |
| 1305 } | 1307 } |
| 1306 test_efkey_34 2 0 "BEGIN" | 1308 test_efkey_34 2 0 "BEGIN" |
| 1307 test_efkey_34 3 0 "INSERT INTO kk VALUES(5)" | 1309 test_efkey_34 3 0 "INSERT INTO kk VALUES(5)" |
| 1308 test_efkey_34 4 0 "INSERT INTO kk VALUES(10)" | 1310 test_efkey_34 4 0 "INSERT INTO kk VALUES(10)" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1319 # EVIDENCE-OF: R-56844-61705 If the current statement is not inside an | 1321 # EVIDENCE-OF: R-56844-61705 If the current statement is not inside an |
| 1320 # explicit transaction (a BEGIN/COMMIT/ROLLBACK block), then an implicit | 1322 # explicit transaction (a BEGIN/COMMIT/ROLLBACK block), then an implicit |
| 1321 # transaction is committed as soon as the statement has finished | 1323 # transaction is committed as soon as the statement has finished |
| 1322 # executing. In this case deferred constraints behave the same as | 1324 # executing. In this case deferred constraints behave the same as |
| 1323 # immediate constraints. | 1325 # immediate constraints. |
| 1324 # | 1326 # |
| 1325 drop_all_tables | 1327 drop_all_tables |
| 1326 proc test_efkey_35 {tn isError sql} { | 1328 proc test_efkey_35 {tn isError sql} { |
| 1327 do_test e_fkey-33.$tn " | 1329 do_test e_fkey-33.$tn " |
| 1328 catchsql {$sql} | 1330 catchsql {$sql} |
| 1329 " [lindex {{0 {}} {1 {foreign key constraint failed}}} $isError] | 1331 " [lindex {{0 {}} {1 {FOREIGN KEY constraint failed}}} $isError] |
| 1330 } | 1332 } |
| 1331 do_test e_fkey-33.1 { | 1333 do_test e_fkey-33.1 { |
| 1332 execsql { | 1334 execsql { |
| 1333 CREATE TABLE parent(x, y); | 1335 CREATE TABLE parent(x, y); |
| 1334 CREATE UNIQUE INDEX pi ON parent(x, y); | 1336 CREATE UNIQUE INDEX pi ON parent(x, y); |
| 1335 CREATE TABLE child(a, b, | 1337 CREATE TABLE child(a, b, |
| 1336 FOREIGN KEY(a, b) REFERENCES parent(x, y) DEFERRABLE INITIALLY DEFERRED | 1338 FOREIGN KEY(a, b) REFERENCES parent(x, y) DEFERRABLE INITIALLY DEFERRED |
| 1337 ); | 1339 ); |
| 1338 } | 1340 } |
| 1339 } {} | 1341 } {} |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1409 INSERT INTO c3 VALUES('g', 'h', 'i'); | 1411 INSERT INTO c3 VALUES('g', 'h', 'i'); |
| 1410 INSERT INTO c4 VALUES('j', 'k', 'l'); | 1412 INSERT INTO c4 VALUES('j', 'k', 'l'); |
| 1411 INSERT INTO c5 VALUES('m', 'n', 'o'); | 1413 INSERT INTO c5 VALUES('m', 'n', 'o'); |
| 1412 INSERT INTO c6 VALUES('p', 'q', 'r'); | 1414 INSERT INTO c6 VALUES('p', 'q', 'r'); |
| 1413 INSERT INTO c7 VALUES('s', 't', 'u'); | 1415 INSERT INTO c7 VALUES('s', 't', 'u'); |
| 1414 } | 1416 } |
| 1415 } {} | 1417 } {} |
| 1416 | 1418 |
| 1417 proc test_efkey_29 {tn sql isError} { | 1419 proc test_efkey_29 {tn sql isError} { |
| 1418 do_test e_fkey-34.$tn "catchsql {$sql}" [ | 1420 do_test e_fkey-34.$tn "catchsql {$sql}" [ |
| 1419 lindex {{0 {}} {1 {foreign key constraint failed}}} $isError | 1421 lindex {{0 {}} {1 {FOREIGN KEY constraint failed}}} $isError |
| 1420 ] | 1422 ] |
| 1421 } | 1423 } |
| 1422 test_efkey_29 2 "BEGIN" 0 | 1424 test_efkey_29 2 "BEGIN" 0 |
| 1423 test_efkey_29 3 "DELETE FROM parent WHERE x = 'a'" 1 | 1425 test_efkey_29 3 "DELETE FROM parent WHERE x = 'a'" 1 |
| 1424 test_efkey_29 4 "DELETE FROM parent WHERE x = 'd'" 1 | 1426 test_efkey_29 4 "DELETE FROM parent WHERE x = 'd'" 1 |
| 1425 test_efkey_29 5 "DELETE FROM parent WHERE x = 'g'" 1 | 1427 test_efkey_29 5 "DELETE FROM parent WHERE x = 'g'" 1 |
| 1426 test_efkey_29 6 "DELETE FROM parent WHERE x = 'j'" 1 | 1428 test_efkey_29 6 "DELETE FROM parent WHERE x = 'j'" 1 |
| 1427 test_efkey_29 7 "DELETE FROM parent WHERE x = 'm'" 1 | 1429 test_efkey_29 7 "DELETE FROM parent WHERE x = 'm'" 1 |
| 1428 test_efkey_29 8 "DELETE FROM parent WHERE x = 'p'" 1 | 1430 test_efkey_29 8 "DELETE FROM parent WHERE x = 'p'" 1 |
| 1429 test_efkey_29 9 "DELETE FROM parent WHERE x = 's'" 0 | 1431 test_efkey_29 9 "DELETE FROM parent WHERE x = 's'" 0 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1483 trackartist INTEGER REFERENCES artist(artistid) DEFERRABLE INITIALLY DEFER
RED | 1485 trackartist INTEGER REFERENCES artist(artistid) DEFERRABLE INITIALLY DEFER
RED |
| 1484 ); | 1486 ); |
| 1485 } | 1487 } |
| 1486 } {} | 1488 } {} |
| 1487 do_test e_fkey-35.2 { | 1489 do_test e_fkey-35.2 { |
| 1488 execsql { | 1490 execsql { |
| 1489 BEGIN; | 1491 BEGIN; |
| 1490 INSERT INTO track VALUES(1, 'White Christmas', 5); | 1492 INSERT INTO track VALUES(1, 'White Christmas', 5); |
| 1491 } | 1493 } |
| 1492 catchsql COMMIT | 1494 catchsql COMMIT |
| 1493 } {1 {foreign key constraint failed}} | 1495 } {1 {FOREIGN KEY constraint failed}} |
| 1494 do_test e_fkey-35.3 { | 1496 do_test e_fkey-35.3 { |
| 1495 execsql { | 1497 execsql { |
| 1496 INSERT INTO artist VALUES(5, 'Bing Crosby'); | 1498 INSERT INTO artist VALUES(5, 'Bing Crosby'); |
| 1497 COMMIT; | 1499 COMMIT; |
| 1498 } | 1500 } |
| 1499 } {} | 1501 } {} |
| 1500 | 1502 |
| 1501 #------------------------------------------------------------------------- | 1503 #------------------------------------------------------------------------- |
| 1502 # Verify that a nested savepoint may be released without satisfying | 1504 # Verify that a nested savepoint may be released without satisfying |
| 1503 # deferred foreign key constraints. | 1505 # deferred foreign key constraints. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1520 do_test e_fkey-36.2 { | 1522 do_test e_fkey-36.2 { |
| 1521 execsql { | 1523 execsql { |
| 1522 BEGIN; | 1524 BEGIN; |
| 1523 SAVEPOINT one; | 1525 SAVEPOINT one; |
| 1524 INSERT INTO t1 VALUES(4, 5); | 1526 INSERT INTO t1 VALUES(4, 5); |
| 1525 RELEASE one; | 1527 RELEASE one; |
| 1526 } | 1528 } |
| 1527 } {} | 1529 } {} |
| 1528 do_test e_fkey-36.3 { | 1530 do_test e_fkey-36.3 { |
| 1529 catchsql COMMIT | 1531 catchsql COMMIT |
| 1530 } {1 {foreign key constraint failed}} | 1532 } {1 {FOREIGN KEY constraint failed}} |
| 1531 do_test e_fkey-36.4 { | 1533 do_test e_fkey-36.4 { |
| 1532 execsql { | 1534 execsql { |
| 1533 UPDATE t1 SET a = 5 WHERE a = 4; | 1535 UPDATE t1 SET a = 5 WHERE a = 4; |
| 1534 COMMIT; | 1536 COMMIT; |
| 1535 } | 1537 } |
| 1536 } {} | 1538 } {} |
| 1537 | 1539 |
| 1538 | 1540 |
| 1539 #------------------------------------------------------------------------- | 1541 #------------------------------------------------------------------------- |
| 1540 # Check that a transaction savepoint (an outermost savepoint opened when | 1542 # Check that a transaction savepoint (an outermost savepoint opened when |
| 1541 # the database was in auto-commit mode) cannot be released without | 1543 # the database was in auto-commit mode) cannot be released without |
| 1542 # satisfying deferred foreign key constraints. It may be rolled back. | 1544 # satisfying deferred foreign key constraints. It may be rolled back. |
| 1543 # | 1545 # |
| 1544 # EVIDENCE-OF: R-44295-13823 A transaction savepoint (a non-nested | 1546 # EVIDENCE-OF: R-44295-13823 A transaction savepoint (a non-nested |
| 1545 # savepoint that was opened while there was not currently an open | 1547 # savepoint that was opened while there was not currently an open |
| 1546 # transaction), on the other hand, is subject to the same restrictions | 1548 # transaction), on the other hand, is subject to the same restrictions |
| 1547 # as a COMMIT - attempting to RELEASE it while the database is in such a | 1549 # as a COMMIT - attempting to RELEASE it while the database is in such a |
| 1548 # state will fail. | 1550 # state will fail. |
| 1549 # | 1551 # |
| 1550 do_test e_fkey-37.1 { | 1552 do_test e_fkey-37.1 { |
| 1551 execsql { | 1553 execsql { |
| 1552 SAVEPOINT one; | 1554 SAVEPOINT one; |
| 1553 SAVEPOINT two; | 1555 SAVEPOINT two; |
| 1554 INSERT INTO t1 VALUES(6, 7); | 1556 INSERT INTO t1 VALUES(6, 7); |
| 1555 RELEASE two; | 1557 RELEASE two; |
| 1556 } | 1558 } |
| 1557 } {} | 1559 } {} |
| 1558 do_test e_fkey-37.2 { | 1560 do_test e_fkey-37.2 { |
| 1559 catchsql {RELEASE one} | 1561 catchsql {RELEASE one} |
| 1560 } {1 {foreign key constraint failed}} | 1562 } {1 {FOREIGN KEY constraint failed}} |
| 1561 do_test e_fkey-37.3 { | 1563 do_test e_fkey-37.3 { |
| 1562 execsql { | 1564 execsql { |
| 1563 UPDATE t1 SET a = 7 WHERE a = 6; | 1565 UPDATE t1 SET a = 7 WHERE a = 6; |
| 1564 RELEASE one; | 1566 RELEASE one; |
| 1565 } | 1567 } |
| 1566 } {} | 1568 } {} |
| 1567 do_test e_fkey-37.4 { | 1569 do_test e_fkey-37.4 { |
| 1568 execsql { | 1570 execsql { |
| 1569 SAVEPOINT one; | 1571 SAVEPOINT one; |
| 1570 SAVEPOINT two; | 1572 SAVEPOINT two; |
| 1571 INSERT INTO t1 VALUES(9, 10); | 1573 INSERT INTO t1 VALUES(9, 10); |
| 1572 RELEASE two; | 1574 RELEASE two; |
| 1573 } | 1575 } |
| 1574 } {} | 1576 } {} |
| 1575 do_test e_fkey-37.5 { | 1577 do_test e_fkey-37.5 { |
| 1576 catchsql {RELEASE one} | 1578 catchsql {RELEASE one} |
| 1577 } {1 {foreign key constraint failed}} | 1579 } {1 {FOREIGN KEY constraint failed}} |
| 1578 do_test e_fkey-37.6 { | 1580 do_test e_fkey-37.6 { |
| 1579 execsql {ROLLBACK TO one ; RELEASE one} | 1581 execsql {ROLLBACK TO one ; RELEASE one} |
| 1580 } {} | 1582 } {} |
| 1581 | 1583 |
| 1582 #------------------------------------------------------------------------- | 1584 #------------------------------------------------------------------------- |
| 1583 # Test that if a COMMIT operation fails due to deferred foreign key | 1585 # Test that if a COMMIT operation fails due to deferred foreign key |
| 1584 # constraints, any nested savepoints remain open. | 1586 # constraints, any nested savepoints remain open. |
| 1585 # | 1587 # |
| 1586 # EVIDENCE-OF: R-37736-42616 If a COMMIT statement (or the RELEASE of a | 1588 # EVIDENCE-OF: R-37736-42616 If a COMMIT statement (or the RELEASE of a |
| 1587 # transaction SAVEPOINT) fails because the database is currently in a | 1589 # transaction SAVEPOINT) fails because the database is currently in a |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1598 execsql { | 1600 execsql { |
| 1599 BEGIN; | 1601 BEGIN; |
| 1600 INSERT INTO t1 VALUES(4, 4); | 1602 INSERT INTO t1 VALUES(4, 4); |
| 1601 SAVEPOINT one; | 1603 SAVEPOINT one; |
| 1602 INSERT INTO t1 VALUES(5, 6); | 1604 INSERT INTO t1 VALUES(5, 6); |
| 1603 SELECT * FROM t1; | 1605 SELECT * FROM t1; |
| 1604 } | 1606 } |
| 1605 } {1 1 2 2 3 3 4 4 5 6} | 1607 } {1 1 2 2 3 3 4 4 5 6} |
| 1606 do_test e_fkey-38.3 { | 1608 do_test e_fkey-38.3 { |
| 1607 catchsql COMMIT | 1609 catchsql COMMIT |
| 1608 } {1 {foreign key constraint failed}} | 1610 } {1 {FOREIGN KEY constraint failed}} |
| 1609 do_test e_fkey-38.4 { | 1611 do_test e_fkey-38.4 { |
| 1610 execsql { | 1612 execsql { |
| 1611 ROLLBACK TO one; | 1613 ROLLBACK TO one; |
| 1612 COMMIT; | 1614 COMMIT; |
| 1613 SELECT * FROM t1; | 1615 SELECT * FROM t1; |
| 1614 } | 1616 } |
| 1615 } {1 1 2 2 3 3 4 4} | 1617 } {1 1 2 2 3 3 4 4} |
| 1616 | 1618 |
| 1617 do_test e_fkey-38.5 { | 1619 do_test e_fkey-38.5 { |
| 1618 execsql { | 1620 execsql { |
| 1619 SAVEPOINT a; | 1621 SAVEPOINT a; |
| 1620 INSERT INTO t1 VALUES(5, 5); | 1622 INSERT INTO t1 VALUES(5, 5); |
| 1621 SAVEPOINT b; | 1623 SAVEPOINT b; |
| 1622 INSERT INTO t1 VALUES(6, 7); | 1624 INSERT INTO t1 VALUES(6, 7); |
| 1623 SAVEPOINT c; | 1625 SAVEPOINT c; |
| 1624 INSERT INTO t1 VALUES(7, 8); | 1626 INSERT INTO t1 VALUES(7, 8); |
| 1625 } | 1627 } |
| 1626 } {} | 1628 } {} |
| 1627 do_test e_fkey-38.6 { | 1629 do_test e_fkey-38.6 { |
| 1628 catchsql {RELEASE a} | 1630 catchsql {RELEASE a} |
| 1629 } {1 {foreign key constraint failed}} | 1631 } {1 {FOREIGN KEY constraint failed}} |
| 1630 do_test e_fkey-38.7 { | 1632 do_test e_fkey-38.7 { |
| 1631 execsql {ROLLBACK TO c} | 1633 execsql {ROLLBACK TO c} |
| 1632 catchsql {RELEASE a} | 1634 catchsql {RELEASE a} |
| 1633 } {1 {foreign key constraint failed}} | 1635 } {1 {FOREIGN KEY constraint failed}} |
| 1634 do_test e_fkey-38.8 { | 1636 do_test e_fkey-38.8 { |
| 1635 execsql { | 1637 execsql { |
| 1636 ROLLBACK TO b; | 1638 ROLLBACK TO b; |
| 1637 RELEASE a; | 1639 RELEASE a; |
| 1638 SELECT * FROM t1; | 1640 SELECT * FROM t1; |
| 1639 } | 1641 } |
| 1640 } {1 1 2 2 3 3 4 4 5 5} | 1642 } {1 1 2 2 3 3 4 4 5 5} |
| 1641 | 1643 |
| 1642 ########################################################################### | 1644 ########################################################################### |
| 1643 ### SECTION 4.3: ON DELETE and ON UPDATE Actions | 1645 ### SECTION 4.3: ON DELETE and ON UPDATE Actions |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1774 do_test e_fkey-41.2 { | 1776 do_test e_fkey-41.2 { |
| 1775 execsql { | 1777 execsql { |
| 1776 BEGIN; | 1778 BEGIN; |
| 1777 UPDATE parent SET p1='k' WHERE p1='j'; | 1779 UPDATE parent SET p1='k' WHERE p1='j'; |
| 1778 DELETE FROM parent WHERE p1='l'; | 1780 DELETE FROM parent WHERE p1='l'; |
| 1779 SELECT * FROM child; | 1781 SELECT * FROM child; |
| 1780 } | 1782 } |
| 1781 } {j k l m} | 1783 } {j k l m} |
| 1782 do_test e_fkey-41.3 { | 1784 do_test e_fkey-41.3 { |
| 1783 catchsql COMMIT | 1785 catchsql COMMIT |
| 1784 } {1 {foreign key constraint failed}} | 1786 } {1 {FOREIGN KEY constraint failed}} |
| 1785 do_test e_fkey-41.4 { | 1787 do_test e_fkey-41.4 { |
| 1786 execsql ROLLBACK | 1788 execsql ROLLBACK |
| 1787 } {} | 1789 } {} |
| 1788 | 1790 |
| 1789 #------------------------------------------------------------------------- | 1791 #------------------------------------------------------------------------- |
| 1790 # Test that "RESTRICT" means the application is prohibited from deleting | 1792 # Test that "RESTRICT" means the application is prohibited from deleting |
| 1791 # or updating a parent table row when there exists one or more child keys | 1793 # or updating a parent table row when there exists one or more child keys |
| 1792 # mapped to it. | 1794 # mapped to it. |
| 1793 # | 1795 # |
| 1794 # EVIDENCE-OF: R-04272-38653 The "RESTRICT" action means that the | 1796 # EVIDENCE-OF: R-04272-38653 The "RESTRICT" action means that the |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1812 do_test e_fkey-41.2 { | 1814 do_test e_fkey-41.2 { |
| 1813 execsql { | 1815 execsql { |
| 1814 INSERT INTO parent VALUES('a', 'b'); | 1816 INSERT INTO parent VALUES('a', 'b'); |
| 1815 INSERT INTO parent VALUES('c', 'd'); | 1817 INSERT INTO parent VALUES('c', 'd'); |
| 1816 INSERT INTO child1 VALUES('b', 'a'); | 1818 INSERT INTO child1 VALUES('b', 'a'); |
| 1817 INSERT INTO child2 VALUES('d', 'c'); | 1819 INSERT INTO child2 VALUES('d', 'c'); |
| 1818 } | 1820 } |
| 1819 } {} | 1821 } {} |
| 1820 do_test e_fkey-41.3 { | 1822 do_test e_fkey-41.3 { |
| 1821 catchsql { DELETE FROM parent WHERE p1 = 'a' } | 1823 catchsql { DELETE FROM parent WHERE p1 = 'a' } |
| 1822 } {1 {foreign key constraint failed}} | 1824 } {1 {FOREIGN KEY constraint failed}} |
| 1823 do_test e_fkey-41.4 { | 1825 do_test e_fkey-41.4 { |
| 1824 catchsql { UPDATE parent SET p2 = 'e' WHERE p1 = 'c' } | 1826 catchsql { UPDATE parent SET p2 = 'e' WHERE p1 = 'c' } |
| 1825 } {1 {foreign key constraint failed}} | 1827 } {1 {FOREIGN KEY constraint failed}} |
| 1826 | 1828 |
| 1827 #------------------------------------------------------------------------- | 1829 #------------------------------------------------------------------------- |
| 1828 # Test that RESTRICT is slightly different from NO ACTION for IMMEDIATE | 1830 # Test that RESTRICT is slightly different from NO ACTION for IMMEDIATE |
| 1829 # constraints, in that it is enforced immediately, not at the end of the | 1831 # constraints, in that it is enforced immediately, not at the end of the |
| 1830 # statement. | 1832 # statement. |
| 1831 # | 1833 # |
| 1832 # EVIDENCE-OF: R-37997-42187 The difference between the effect of a | 1834 # EVIDENCE-OF: R-37997-42187 The difference between the effect of a |
| 1833 # RESTRICT action and normal foreign key constraint enforcement is that | 1835 # RESTRICT action and normal foreign key constraint enforcement is that |
| 1834 # the RESTRICT action processing happens as soon as the field is updated | 1836 # the RESTRICT action processing happens as soon as the field is updated |
| 1835 # - not at the end of the current statement as it would with an | 1837 # - not at the end of the current statement as it would with an |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1849 INSERT INTO child2 VALUES('key2'); | 1851 INSERT INTO child2 VALUES('key2'); |
| 1850 | 1852 |
| 1851 CREATE TRIGGER parent_t AFTER UPDATE ON parent BEGIN | 1853 CREATE TRIGGER parent_t AFTER UPDATE ON parent BEGIN |
| 1852 UPDATE child1 set c = new.x WHERE c = old.x; | 1854 UPDATE child1 set c = new.x WHERE c = old.x; |
| 1853 UPDATE child2 set c = new.x WHERE c = old.x; | 1855 UPDATE child2 set c = new.x WHERE c = old.x; |
| 1854 END; | 1856 END; |
| 1855 } | 1857 } |
| 1856 } {} | 1858 } {} |
| 1857 do_test e_fkey-42.2 { | 1859 do_test e_fkey-42.2 { |
| 1858 catchsql { UPDATE parent SET x = 'key one' WHERE x = 'key1' } | 1860 catchsql { UPDATE parent SET x = 'key one' WHERE x = 'key1' } |
| 1859 } {1 {foreign key constraint failed}} | 1861 } {1 {FOREIGN KEY constraint failed}} |
| 1860 do_test e_fkey-42.3 { | 1862 do_test e_fkey-42.3 { |
| 1861 execsql { | 1863 execsql { |
| 1862 UPDATE parent SET x = 'key two' WHERE x = 'key2'; | 1864 UPDATE parent SET x = 'key two' WHERE x = 'key2'; |
| 1863 SELECT * FROM child2; | 1865 SELECT * FROM child2; |
| 1864 } | 1866 } |
| 1865 } {{key two}} | 1867 } {{key two}} |
| 1866 | 1868 |
| 1867 drop_all_tables | 1869 drop_all_tables |
| 1868 do_test e_fkey-42.4 { | 1870 do_test e_fkey-42.4 { |
| 1869 execsql { | 1871 execsql { |
| 1870 CREATE TABLE parent(x PRIMARY KEY); | 1872 CREATE TABLE parent(x PRIMARY KEY); |
| 1871 CREATE TABLE child1(c REFERENCES parent ON DELETE RESTRICT); | 1873 CREATE TABLE child1(c REFERENCES parent ON DELETE RESTRICT); |
| 1872 CREATE TABLE child2(c REFERENCES parent ON DELETE NO ACTION); | 1874 CREATE TABLE child2(c REFERENCES parent ON DELETE NO ACTION); |
| 1873 | 1875 |
| 1874 INSERT INTO parent VALUES('key1'); | 1876 INSERT INTO parent VALUES('key1'); |
| 1875 INSERT INTO parent VALUES('key2'); | 1877 INSERT INTO parent VALUES('key2'); |
| 1876 INSERT INTO child1 VALUES('key1'); | 1878 INSERT INTO child1 VALUES('key1'); |
| 1877 INSERT INTO child2 VALUES('key2'); | 1879 INSERT INTO child2 VALUES('key2'); |
| 1878 | 1880 |
| 1879 CREATE TRIGGER parent_t AFTER DELETE ON parent BEGIN | 1881 CREATE TRIGGER parent_t AFTER DELETE ON parent BEGIN |
| 1880 UPDATE child1 SET c = NULL WHERE c = old.x; | 1882 UPDATE child1 SET c = NULL WHERE c = old.x; |
| 1881 UPDATE child2 SET c = NULL WHERE c = old.x; | 1883 UPDATE child2 SET c = NULL WHERE c = old.x; |
| 1882 END; | 1884 END; |
| 1883 } | 1885 } |
| 1884 } {} | 1886 } {} |
| 1885 do_test e_fkey-42.5 { | 1887 do_test e_fkey-42.5 { |
| 1886 catchsql { DELETE FROM parent WHERE x = 'key1' } | 1888 catchsql { DELETE FROM parent WHERE x = 'key1' } |
| 1887 } {1 {foreign key constraint failed}} | 1889 } {1 {FOREIGN KEY constraint failed}} |
| 1888 do_test e_fkey-42.6 { | 1890 do_test e_fkey-42.6 { |
| 1889 execsql { | 1891 execsql { |
| 1890 DELETE FROM parent WHERE x = 'key2'; | 1892 DELETE FROM parent WHERE x = 'key2'; |
| 1891 SELECT * FROM child2; | 1893 SELECT * FROM child2; |
| 1892 } | 1894 } |
| 1893 } {{}} | 1895 } {{}} |
| 1894 | 1896 |
| 1895 drop_all_tables | 1897 drop_all_tables |
| 1896 do_test e_fkey-42.7 { | 1898 do_test e_fkey-42.7 { |
| 1897 execsql { | 1899 execsql { |
| 1898 CREATE TABLE parent(x PRIMARY KEY); | 1900 CREATE TABLE parent(x PRIMARY KEY); |
| 1899 CREATE TABLE child1(c REFERENCES parent ON DELETE RESTRICT); | 1901 CREATE TABLE child1(c REFERENCES parent ON DELETE RESTRICT); |
| 1900 CREATE TABLE child2(c REFERENCES parent ON DELETE NO ACTION); | 1902 CREATE TABLE child2(c REFERENCES parent ON DELETE NO ACTION); |
| 1901 | 1903 |
| 1902 INSERT INTO parent VALUES('key1'); | 1904 INSERT INTO parent VALUES('key1'); |
| 1903 INSERT INTO parent VALUES('key2'); | 1905 INSERT INTO parent VALUES('key2'); |
| 1904 INSERT INTO child1 VALUES('key1'); | 1906 INSERT INTO child1 VALUES('key1'); |
| 1905 INSERT INTO child2 VALUES('key2'); | 1907 INSERT INTO child2 VALUES('key2'); |
| 1906 } | 1908 } |
| 1907 } {} | 1909 } {} |
| 1908 do_test e_fkey-42.8 { | 1910 do_test e_fkey-42.8 { |
| 1909 catchsql { REPLACE INTO parent VALUES('key1') } | 1911 catchsql { REPLACE INTO parent VALUES('key1') } |
| 1910 } {1 {foreign key constraint failed}} | 1912 } {1 {FOREIGN KEY constraint failed}} |
| 1911 do_test e_fkey-42.9 { | 1913 do_test e_fkey-42.9 { |
| 1912 execsql { | 1914 execsql { |
| 1913 REPLACE INTO parent VALUES('key2'); | 1915 REPLACE INTO parent VALUES('key2'); |
| 1914 SELECT * FROM child2; | 1916 SELECT * FROM child2; |
| 1915 } | 1917 } |
| 1916 } {key2} | 1918 } {key2} |
| 1917 | 1919 |
| 1918 #------------------------------------------------------------------------- | 1920 #------------------------------------------------------------------------- |
| 1919 # Test that RESTRICT is enforced immediately, even for a DEFERRED constraint. | 1921 # Test that RESTRICT is enforced immediately, even for a DEFERRED constraint. |
| 1920 # | 1922 # |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1936 | 1938 |
| 1937 INSERT INTO parent VALUES('key1'); | 1939 INSERT INTO parent VALUES('key1'); |
| 1938 INSERT INTO parent VALUES('key2'); | 1940 INSERT INTO parent VALUES('key2'); |
| 1939 INSERT INTO child1 VALUES('key1'); | 1941 INSERT INTO child1 VALUES('key1'); |
| 1940 INSERT INTO child2 VALUES('key2'); | 1942 INSERT INTO child2 VALUES('key2'); |
| 1941 BEGIN; | 1943 BEGIN; |
| 1942 } | 1944 } |
| 1943 } {} | 1945 } {} |
| 1944 do_test e_fkey-43.2 { | 1946 do_test e_fkey-43.2 { |
| 1945 catchsql { UPDATE parent SET x = 'key one' WHERE x = 'key1' } | 1947 catchsql { UPDATE parent SET x = 'key one' WHERE x = 'key1' } |
| 1946 } {1 {foreign key constraint failed}} | 1948 } {1 {FOREIGN KEY constraint failed}} |
| 1947 do_test e_fkey-43.3 { | 1949 do_test e_fkey-43.3 { |
| 1948 execsql { UPDATE parent SET x = 'key two' WHERE x = 'key2' } | 1950 execsql { UPDATE parent SET x = 'key two' WHERE x = 'key2' } |
| 1949 } {} | 1951 } {} |
| 1950 do_test e_fkey-43.4 { | 1952 do_test e_fkey-43.4 { |
| 1951 catchsql COMMIT | 1953 catchsql COMMIT |
| 1952 } {1 {foreign key constraint failed}} | 1954 } {1 {FOREIGN KEY constraint failed}} |
| 1953 do_test e_fkey-43.5 { | 1955 do_test e_fkey-43.5 { |
| 1954 execsql { | 1956 execsql { |
| 1955 UPDATE child2 SET c = 'key two'; | 1957 UPDATE child2 SET c = 'key two'; |
| 1956 COMMIT; | 1958 COMMIT; |
| 1957 } | 1959 } |
| 1958 } {} | 1960 } {} |
| 1959 | 1961 |
| 1960 drop_all_tables | 1962 drop_all_tables |
| 1961 do_test e_fkey-43.6 { | 1963 do_test e_fkey-43.6 { |
| 1962 execsql { | 1964 execsql { |
| 1963 CREATE TABLE parent(x PRIMARY KEY); | 1965 CREATE TABLE parent(x PRIMARY KEY); |
| 1964 CREATE TABLE child1(c REFERENCES parent ON DELETE RESTRICT | 1966 CREATE TABLE child1(c REFERENCES parent ON DELETE RESTRICT |
| 1965 DEFERRABLE INITIALLY DEFERRED | 1967 DEFERRABLE INITIALLY DEFERRED |
| 1966 ); | 1968 ); |
| 1967 CREATE TABLE child2(c REFERENCES parent ON DELETE NO ACTION | 1969 CREATE TABLE child2(c REFERENCES parent ON DELETE NO ACTION |
| 1968 DEFERRABLE INITIALLY DEFERRED | 1970 DEFERRABLE INITIALLY DEFERRED |
| 1969 ); | 1971 ); |
| 1970 | 1972 |
| 1971 INSERT INTO parent VALUES('key1'); | 1973 INSERT INTO parent VALUES('key1'); |
| 1972 INSERT INTO parent VALUES('key2'); | 1974 INSERT INTO parent VALUES('key2'); |
| 1973 INSERT INTO child1 VALUES('key1'); | 1975 INSERT INTO child1 VALUES('key1'); |
| 1974 INSERT INTO child2 VALUES('key2'); | 1976 INSERT INTO child2 VALUES('key2'); |
| 1975 BEGIN; | 1977 BEGIN; |
| 1976 } | 1978 } |
| 1977 } {} | 1979 } {} |
| 1978 do_test e_fkey-43.7 { | 1980 do_test e_fkey-43.7 { |
| 1979 catchsql { DELETE FROM parent WHERE x = 'key1' } | 1981 catchsql { DELETE FROM parent WHERE x = 'key1' } |
| 1980 } {1 {foreign key constraint failed}} | 1982 } {1 {FOREIGN KEY constraint failed}} |
| 1981 do_test e_fkey-43.8 { | 1983 do_test e_fkey-43.8 { |
| 1982 execsql { DELETE FROM parent WHERE x = 'key2' } | 1984 execsql { DELETE FROM parent WHERE x = 'key2' } |
| 1983 } {} | 1985 } {} |
| 1984 do_test e_fkey-43.9 { | 1986 do_test e_fkey-43.9 { |
| 1985 catchsql COMMIT | 1987 catchsql COMMIT |
| 1986 } {1 {foreign key constraint failed}} | 1988 } {1 {FOREIGN KEY constraint failed}} |
| 1987 do_test e_fkey-43.10 { | 1989 do_test e_fkey-43.10 { |
| 1988 execsql { | 1990 execsql { |
| 1989 UPDATE child2 SET c = NULL; | 1991 UPDATE child2 SET c = NULL; |
| 1990 COMMIT; | 1992 COMMIT; |
| 1991 } | 1993 } |
| 1992 } {} | 1994 } {} |
| 1993 | 1995 |
| 1994 #------------------------------------------------------------------------- | 1996 #------------------------------------------------------------------------- |
| 1995 # Test SET NULL actions. | 1997 # Test SET NULL actions. |
| 1996 # | 1998 # |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2053 INSERT INTO pA(rowid, x) VALUES(3, X'ABCD'); | 2055 INSERT INTO pA(rowid, x) VALUES(3, X'ABCD'); |
| 2054 INSERT INTO pA(rowid, x) VALUES(4, X'1234'); | 2056 INSERT INTO pA(rowid, x) VALUES(4, X'1234'); |
| 2055 | 2057 |
| 2056 INSERT INTO cA VALUES(X'ABCD'); | 2058 INSERT INTO cA VALUES(X'ABCD'); |
| 2057 INSERT INTO cB VALUES(X'1234'); | 2059 INSERT INTO cB VALUES(X'1234'); |
| 2058 } | 2060 } |
| 2059 } {} | 2061 } {} |
| 2060 do_test e_fkey-45.2 { | 2062 do_test e_fkey-45.2 { |
| 2061 execsql { | 2063 execsql { |
| 2062 DELETE FROM pA WHERE rowid = 3; | 2064 DELETE FROM pA WHERE rowid = 3; |
| 2063 SELECT quote(x) FROM pA; | 2065 SELECT quote(x) FROM pA ORDER BY rowid; |
| 2064 } | 2066 } |
| 2065 } {X'0000' X'9999' X'1234'} | 2067 } {X'0000' X'9999' X'1234'} |
| 2066 do_test e_fkey-45.3 { | 2068 do_test e_fkey-45.3 { |
| 2067 execsql { SELECT quote(c) FROM cA } | 2069 execsql { SELECT quote(c) FROM cA } |
| 2068 } {X'0000'} | 2070 } {X'0000'} |
| 2069 do_test e_fkey-45.4 { | 2071 do_test e_fkey-45.4 { |
| 2070 execsql { | 2072 execsql { |
| 2071 UPDATE pA SET x = X'8765' WHERE rowid = 4; | 2073 UPDATE pA SET x = X'8765' WHERE rowid = 4; |
| 2072 SELECT quote(x) FROM pA; | 2074 SELECT quote(x) FROM pA ORDER BY rowid; |
| 2073 } | 2075 } |
| 2074 } {X'0000' X'9999' X'8765'} | 2076 } {X'0000' X'9999' X'8765'} |
| 2075 do_test e_fkey-45.5 { | 2077 do_test e_fkey-45.5 { |
| 2076 execsql { SELECT quote(c) FROM cB } | 2078 execsql { SELECT quote(c) FROM cB } |
| 2077 } {X'9999'} | 2079 } {X'9999'} |
| 2078 | 2080 |
| 2079 #------------------------------------------------------------------------- | 2081 #------------------------------------------------------------------------- |
| 2080 # Test ON DELETE CASCADE actions. | 2082 # Test ON DELETE CASCADE actions. |
| 2081 # | 2083 # |
| 2082 # EVIDENCE-OF: R-61376-57267 A "CASCADE" action propagates the delete or | 2084 # EVIDENCE-OF: R-61376-57267 A "CASCADE" action propagates the delete or |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2232 } {a two c} | 2234 } {a two c} |
| 2233 do_test e_fkey-49.3 { | 2235 do_test e_fkey-49.3 { |
| 2234 execsql { | 2236 execsql { |
| 2235 ROLLBACK; | 2237 ROLLBACK; |
| 2236 DELETE FROM parent WHERE a = 'A'; | 2238 DELETE FROM parent WHERE a = 'A'; |
| 2237 SELECT * FROM parent; | 2239 SELECT * FROM parent; |
| 2238 } | 2240 } |
| 2239 } {ONE two three} | 2241 } {ONE two three} |
| 2240 do_test e_fkey-49.4 { | 2242 do_test e_fkey-49.4 { |
| 2241 catchsql { UPDATE parent SET a = '' WHERE a = 'oNe' } | 2243 catchsql { UPDATE parent SET a = '' WHERE a = 'oNe' } |
| 2242 } {1 {foreign key constraint failed}} | 2244 } {1 {FOREIGN KEY constraint failed}} |
| 2243 | 2245 |
| 2244 | 2246 |
| 2245 #------------------------------------------------------------------------- | 2247 #------------------------------------------------------------------------- |
| 2246 # EVIDENCE-OF: R-11856-19836 | 2248 # EVIDENCE-OF: R-11856-19836 |
| 2247 # | 2249 # |
| 2248 # Test an example from the "ON DELETE and ON UPDATE Actions" section | 2250 # Test an example from the "ON DELETE and ON UPDATE Actions" section |
| 2249 # of foreignkeys.html. This example shows that adding an "ON DELETE DEFAULT" | 2251 # of foreignkeys.html. This example shows that adding an "ON DELETE DEFAULT" |
| 2250 # clause does not abrogate the need to satisfy the foreign key constraint | 2252 # clause does not abrogate the need to satisfy the foreign key constraint |
| 2251 # (R-28220-46694). | 2253 # (R-28220-46694). |
| 2252 # | 2254 # |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2267 trackid INTEGER, | 2269 trackid INTEGER, |
| 2268 trackname TEXT, | 2270 trackname TEXT, |
| 2269 trackartist INTEGER DEFAULT 0 REFERENCES artist(artistid) ON DELETE SET DE
FAULT | 2271 trackartist INTEGER DEFAULT 0 REFERENCES artist(artistid) ON DELETE SET DE
FAULT |
| 2270 ); | 2272 ); |
| 2271 INSERT INTO artist VALUES(3, 'Sammy Davis Jr.'); | 2273 INSERT INTO artist VALUES(3, 'Sammy Davis Jr.'); |
| 2272 INSERT INTO track VALUES(14, 'Mr. Bojangles', 3); | 2274 INSERT INTO track VALUES(14, 'Mr. Bojangles', 3); |
| 2273 } | 2275 } |
| 2274 } {} | 2276 } {} |
| 2275 do_test e_fkey-50.2 { | 2277 do_test e_fkey-50.2 { |
| 2276 catchsql { DELETE FROM artist WHERE artistname = 'Sammy Davis Jr.' } | 2278 catchsql { DELETE FROM artist WHERE artistname = 'Sammy Davis Jr.' } |
| 2277 } {1 {foreign key constraint failed}} | 2279 } {1 {FOREIGN KEY constraint failed}} |
| 2278 do_test e_fkey-50.3 { | 2280 do_test e_fkey-50.3 { |
| 2279 execsql { | 2281 execsql { |
| 2280 INSERT INTO artist VALUES(0, 'Unknown Artist'); | 2282 INSERT INTO artist VALUES(0, 'Unknown Artist'); |
| 2281 DELETE FROM artist WHERE artistname = 'Sammy Davis Jr.'; | 2283 DELETE FROM artist WHERE artistname = 'Sammy Davis Jr.'; |
| 2282 } | 2284 } |
| 2283 } {} | 2285 } {} |
| 2284 do_test e_fkey-50.4 { | 2286 do_test e_fkey-50.4 { |
| 2285 execsql { SELECT * FROM artist } | 2287 execsql { SELECT * FROM artist } |
| 2286 } {0 {Unknown Artist}} | 2288 } {0 {Unknown Artist}} |
| 2287 do_test e_fkey-50.5 { | 2289 do_test e_fkey-50.5 { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2318 INSERT INTO parent VALUES(new.x+old.x); | 2320 INSERT INTO parent VALUES(new.x+old.x); |
| 2319 END; | 2321 END; |
| 2320 | 2322 |
| 2321 INSERT INTO parent VALUES(1); | 2323 INSERT INTO parent VALUES(1); |
| 2322 INSERT INTO child VALUES(1); | 2324 INSERT INTO child VALUES(1); |
| 2323 } | 2325 } |
| 2324 } {} | 2326 } {} |
| 2325 do_test e_fkey-51.2 { | 2327 do_test e_fkey-51.2 { |
| 2326 execsql { | 2328 execsql { |
| 2327 UPDATE parent SET x = 22; | 2329 UPDATE parent SET x = 22; |
| 2328 SELECT * FROM parent UNION ALL SELECT 'xxx' UNION ALL SELECT a FROM child; | 2330 SELECT * FROM parent ORDER BY rowid; SELECT 'xxx' ; SELECT a FROM child; |
| 2329 } | 2331 } |
| 2330 } {22 21 23 xxx 22} | 2332 } {22 21 23 xxx 22} |
| 2331 do_test e_fkey-51.3 { | 2333 do_test e_fkey-51.3 { |
| 2332 execsql { | 2334 execsql { |
| 2333 DELETE FROM child; | 2335 DELETE FROM child; |
| 2334 DELETE FROM parent; | 2336 DELETE FROM parent; |
| 2335 INSERT INTO parent VALUES(-1); | 2337 INSERT INTO parent VALUES(-1); |
| 2336 INSERT INTO child VALUES(-1); | 2338 INSERT INTO child VALUES(-1); |
| 2337 UPDATE parent SET x = 22; | 2339 UPDATE parent SET x = 22; |
| 2338 SELECT * FROM parent UNION ALL SELECT 'xxx' UNION ALL SELECT a FROM child; | 2340 SELECT * FROM parent ORDER BY rowid; SELECT 'xxx' ; SELECT a FROM child; |
| 2339 } | 2341 } |
| 2340 } {22 23 21 xxx 23} | 2342 } {22 23 21 xxx 23} |
| 2341 | 2343 |
| 2342 | 2344 |
| 2343 #------------------------------------------------------------------------- | 2345 #------------------------------------------------------------------------- |
| 2344 # Verify that ON UPDATE actions only actually take place if the parent key | 2346 # Verify that ON UPDATE actions only actually take place if the parent key |
| 2345 # is set to a new value that is distinct from the old value. The default | 2347 # is set to a new value that is distinct from the old value. The default |
| 2346 # collation sequence and affinity are used to determine if the new value | 2348 # collation sequence and affinity are used to determine if the new value |
| 2347 # is 'distinct' from the old or not. | 2349 # is 'distinct' from the old or not. |
| 2348 # | 2350 # |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2631 # violated, the DROP TABLE statement fails and the table is not dropped. | 2633 # violated, the DROP TABLE statement fails and the table is not dropped. |
| 2632 # | 2634 # |
| 2633 do_test e_fkey-58.1 { | 2635 do_test e_fkey-58.1 { |
| 2634 execsql { | 2636 execsql { |
| 2635 DELETE FROM c1; | 2637 DELETE FROM c1; |
| 2636 DELETE FROM c2; | 2638 DELETE FROM c2; |
| 2637 DELETE FROM c3; | 2639 DELETE FROM c3; |
| 2638 } | 2640 } |
| 2639 execsql { INSERT INTO c5 VALUES('a', 'b') } | 2641 execsql { INSERT INTO c5 VALUES('a', 'b') } |
| 2640 catchsql { DROP TABLE p } | 2642 catchsql { DROP TABLE p } |
| 2641 } {1 {foreign key constraint failed}} | 2643 } {1 {FOREIGN KEY constraint failed}} |
| 2642 do_test e_fkey-58.2 { | 2644 do_test e_fkey-58.2 { |
| 2643 execsql { SELECT * FROM p } | 2645 execsql { SELECT * FROM p } |
| 2644 } {a b} | 2646 } {a b} |
| 2645 do_test e_fkey-58.3 { | 2647 do_test e_fkey-58.3 { |
| 2646 catchsql { | 2648 catchsql { |
| 2647 BEGIN; | 2649 BEGIN; |
| 2648 DROP TABLE p; | 2650 DROP TABLE p; |
| 2649 } | 2651 } |
| 2650 } {1 {foreign key constraint failed}} | 2652 } {1 {FOREIGN KEY constraint failed}} |
| 2651 do_test e_fkey-58.4 { | 2653 do_test e_fkey-58.4 { |
| 2652 execsql { | 2654 execsql { |
| 2653 SELECT * FROM p; | 2655 SELECT * FROM p; |
| 2654 SELECT * FROM c5; | 2656 SELECT * FROM c5; |
| 2655 ROLLBACK; | 2657 ROLLBACK; |
| 2656 } | 2658 } |
| 2657 } {a b a b} | 2659 } {a b a b} |
| 2658 | 2660 |
| 2659 #------------------------------------------------------------------------- | 2661 #------------------------------------------------------------------------- |
| 2660 # If a DEFERRED foreign key fails as a result of a DROP TABLE, attempting | 2662 # If a DEFERRED foreign key fails as a result of a DROP TABLE, attempting |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2674 } {} | 2676 } {} |
| 2675 do_test e_fkey-59.2 { | 2677 do_test e_fkey-59.2 { |
| 2676 execsql { INSERT INTO c7 VALUES('a', 'b') } | 2678 execsql { INSERT INTO c7 VALUES('a', 'b') } |
| 2677 execsql { | 2679 execsql { |
| 2678 BEGIN; | 2680 BEGIN; |
| 2679 DROP TABLE p; | 2681 DROP TABLE p; |
| 2680 } | 2682 } |
| 2681 } {} | 2683 } {} |
| 2682 do_test e_fkey-59.3 { | 2684 do_test e_fkey-59.3 { |
| 2683 catchsql COMMIT | 2685 catchsql COMMIT |
| 2684 } {1 {foreign key constraint failed}} | 2686 } {1 {FOREIGN KEY constraint failed}} |
| 2685 do_test e_fkey-59.4 { | 2687 do_test e_fkey-59.4 { |
| 2686 execsql { CREATE TABLE p(a, b, PRIMARY KEY(a, b)) } | 2688 execsql { CREATE TABLE p(a, b, PRIMARY KEY(a, b)) } |
| 2687 catchsql COMMIT | 2689 catchsql COMMIT |
| 2688 } {1 {foreign key constraint failed}} | 2690 } {1 {FOREIGN KEY constraint failed}} |
| 2689 do_test e_fkey-59.5 { | 2691 do_test e_fkey-59.5 { |
| 2690 execsql { INSERT INTO p VALUES('a', 'b') } | 2692 execsql { INSERT INTO p VALUES('a', 'b') } |
| 2691 execsql COMMIT | 2693 execsql COMMIT |
| 2692 } {} | 2694 } {} |
| 2693 | 2695 |
| 2694 #------------------------------------------------------------------------- | 2696 #------------------------------------------------------------------------- |
| 2695 # Any "foreign key mismatch" errors encountered while running an implicit | 2697 # Any "foreign key mismatch" errors encountered while running an implicit |
| 2696 # "DELETE FROM tbl" are ignored. | 2698 # "DELETE FROM tbl" are ignored. |
| 2697 # | 2699 # |
| 2698 # EVIDENCE-OF: R-57242-37005 Any "foreign key mismatch" errors | 2700 # EVIDENCE-OF: R-57242-37005 Any "foreign key mismatch" errors |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2722 execsql { | 2724 execsql { |
| 2723 BEGIN; | 2725 BEGIN; |
| 2724 DROP TABLE p; | 2726 DROP TABLE p; |
| 2725 SELECT * FROM c3; | 2727 SELECT * FROM c3; |
| 2726 ROLLBACK; | 2728 ROLLBACK; |
| 2727 } | 2729 } |
| 2728 } {{} 2} | 2730 } {{} 2} |
| 2729 do_test e_fkey-60.4 { | 2731 do_test e_fkey-60.4 { |
| 2730 execsql { CREATE TABLE nosuchtable(x PRIMARY KEY) } | 2732 execsql { CREATE TABLE nosuchtable(x PRIMARY KEY) } |
| 2731 catchsql { DELETE FROM p } | 2733 catchsql { DELETE FROM p } |
| 2732 } {1 {foreign key mismatch}} | 2734 } {1 {foreign key mismatch - "c2" referencing "p"}} |
| 2733 do_test e_fkey-60.5 { | 2735 do_test e_fkey-60.5 { |
| 2734 execsql { DROP TABLE c1 } | 2736 execsql { DROP TABLE c1 } |
| 2735 catchsql { DELETE FROM p } | 2737 catchsql { DELETE FROM p } |
| 2736 } {1 {foreign key mismatch}} | 2738 } {1 {foreign key mismatch - "c2" referencing "p"}} |
| 2737 do_test e_fkey-60.6 { | 2739 do_test e_fkey-60.6 { |
| 2738 execsql { DROP TABLE c2 } | 2740 execsql { DROP TABLE c2 } |
| 2739 execsql { DELETE FROM p } | 2741 execsql { DELETE FROM p } |
| 2740 } {} | 2742 } {} |
| 2741 | 2743 |
| 2742 #------------------------------------------------------------------------- | 2744 #------------------------------------------------------------------------- |
| 2743 # Test that the special behaviours of ALTER and DROP TABLE are only | 2745 # Test that the special behaviors of ALTER and DROP TABLE are only |
| 2744 # activated when foreign keys are enabled. Special behaviours are: | 2746 # activated when foreign keys are enabled. Special behaviors are: |
| 2745 # | 2747 # |
| 2746 # 1. ADD COLUMN not allowing a REFERENCES clause with a non-NULL | 2748 # 1. ADD COLUMN not allowing a REFERENCES clause with a non-NULL |
| 2747 # default value. | 2749 # default value. |
| 2748 # 2. Modifying foreign key definitions when a parent table is RENAMEd. | 2750 # 2. Modifying foreign key definitions when a parent table is RENAMEd. |
| 2749 # 3. Running an implicit DELETE FROM command as part of DROP TABLE. | 2751 # 3. Running an implicit DELETE FROM command as part of DROP TABLE. |
| 2750 # | 2752 # |
| 2751 # EVIDENCE-OF: R-54142-41346 The properties of the DROP TABLE and ALTER | 2753 # EVIDENCE-OF: R-54142-41346 The properties of the DROP TABLE and ALTER |
| 2752 # TABLE commands described above only apply if foreign keys are enabled. | 2754 # TABLE commands described above only apply if foreign keys are enabled. |
| 2753 # | 2755 # |
| 2754 do_test e_fkey-61.1.1 { | 2756 do_test e_fkey-61.1.1 { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2829 drop_all_tables | 2831 drop_all_tables |
| 2830 do_test e_fkey-62.$zMatch.1 { | 2832 do_test e_fkey-62.$zMatch.1 { |
| 2831 execsql " | 2833 execsql " |
| 2832 CREATE TABLE p(a, b, c, PRIMARY KEY(b, c)); | 2834 CREATE TABLE p(a, b, c, PRIMARY KEY(b, c)); |
| 2833 CREATE TABLE c(d, e, f, FOREIGN KEY(e, f) REFERENCES p MATCH $zMatch); | 2835 CREATE TABLE c(d, e, f, FOREIGN KEY(e, f) REFERENCES p MATCH $zMatch); |
| 2834 " | 2836 " |
| 2835 } {} | 2837 } {} |
| 2836 do_test e_fkey-62.$zMatch.2 { | 2838 do_test e_fkey-62.$zMatch.2 { |
| 2837 execsql { INSERT INTO p VALUES(1, 2, 3) } | 2839 execsql { INSERT INTO p VALUES(1, 2, 3) } |
| 2838 | 2840 |
| 2839 # MATCH SIMPLE behaviour: Allow any child key that contains one or more | 2841 # MATCH SIMPLE behavior: Allow any child key that contains one or more |
| 2840 # NULL value to be inserted. Non-NULL values do not have to map to any | 2842 # NULL value to be inserted. Non-NULL values do not have to map to any |
| 2841 # parent key values, so long as at least one field of the child key is | 2843 # parent key values, so long as at least one field of the child key is |
| 2842 # NULL. | 2844 # NULL. |
| 2843 execsql { INSERT INTO c VALUES('w', 2, 3) } | 2845 execsql { INSERT INTO c VALUES('w', 2, 3) } |
| 2844 execsql { INSERT INTO c VALUES('x', 'x', NULL) } | 2846 execsql { INSERT INTO c VALUES('x', 'x', NULL) } |
| 2845 execsql { INSERT INTO c VALUES('y', NULL, 'x') } | 2847 execsql { INSERT INTO c VALUES('y', NULL, 'x') } |
| 2846 execsql { INSERT INTO c VALUES('z', NULL, NULL) } | 2848 execsql { INSERT INTO c VALUES('z', NULL, NULL) } |
| 2847 | 2849 |
| 2848 # Check that the FK is enforced properly if there are no NULL values | 2850 # Check that the FK is enforced properly if there are no NULL values |
| 2849 # in the child key columns. | 2851 # in the child key columns. |
| 2850 catchsql { INSERT INTO c VALUES('a', 2, 4) } | 2852 catchsql { INSERT INTO c VALUES('a', 2, 4) } |
| 2851 } {1 {foreign key constraint failed}} | 2853 } {1 {FOREIGN KEY constraint failed}} |
| 2852 } | 2854 } |
| 2853 | 2855 |
| 2854 #------------------------------------------------------------------------- | 2856 #------------------------------------------------------------------------- |
| 2855 # Test that SQLite does not support the SET CONSTRAINT statement. And | 2857 # Test that SQLite does not support the SET CONSTRAINT statement. And |
| 2856 # that it is possible to create both immediate and deferred constraints. | 2858 # that it is possible to create both immediate and deferred constraints. |
| 2857 # | 2859 # |
| 2858 # EVIDENCE-OF: R-21599-16038 In SQLite, a foreign key constraint is | 2860 # EVIDENCE-OF: R-21599-16038 In SQLite, a foreign key constraint is |
| 2859 # permanently marked as deferred or immediate when it is created. | 2861 # permanently marked as deferred or immediate when it is created. |
| 2860 # | 2862 # |
| 2861 drop_all_tables | 2863 drop_all_tables |
| 2862 do_test e_fkey-62.1 { | 2864 do_test e_fkey-62.1 { |
| 2863 catchsql { SET CONSTRAINTS ALL IMMEDIATE } | 2865 catchsql { SET CONSTRAINTS ALL IMMEDIATE } |
| 2864 } {1 {near "SET": syntax error}} | 2866 } {1 {near "SET": syntax error}} |
| 2865 do_test e_fkey-62.2 { | 2867 do_test e_fkey-62.2 { |
| 2866 catchsql { SET CONSTRAINTS ALL DEFERRED } | 2868 catchsql { SET CONSTRAINTS ALL DEFERRED } |
| 2867 } {1 {near "SET": syntax error}} | 2869 } {1 {near "SET": syntax error}} |
| 2868 | 2870 |
| 2869 do_test e_fkey-62.3 { | 2871 do_test e_fkey-62.3 { |
| 2870 execsql { | 2872 execsql { |
| 2871 CREATE TABLE p(a, b, PRIMARY KEY(a, b)); | 2873 CREATE TABLE p(a, b, PRIMARY KEY(a, b)); |
| 2872 CREATE TABLE cd(c, d, | 2874 CREATE TABLE cd(c, d, |
| 2873 FOREIGN KEY(c, d) REFERENCES p DEFERRABLE INITIALLY DEFERRED); | 2875 FOREIGN KEY(c, d) REFERENCES p DEFERRABLE INITIALLY DEFERRED); |
| 2874 CREATE TABLE ci(c, d, | 2876 CREATE TABLE ci(c, d, |
| 2875 FOREIGN KEY(c, d) REFERENCES p DEFERRABLE INITIALLY IMMEDIATE); | 2877 FOREIGN KEY(c, d) REFERENCES p DEFERRABLE INITIALLY IMMEDIATE); |
| 2876 BEGIN; | 2878 BEGIN; |
| 2877 } | 2879 } |
| 2878 } {} | 2880 } {} |
| 2879 do_test e_fkey-62.4 { | 2881 do_test e_fkey-62.4 { |
| 2880 catchsql { INSERT INTO ci VALUES('x', 'y') } | 2882 catchsql { INSERT INTO ci VALUES('x', 'y') } |
| 2881 } {1 {foreign key constraint failed}} | 2883 } {1 {FOREIGN KEY constraint failed}} |
| 2882 do_test e_fkey-62.5 { | 2884 do_test e_fkey-62.5 { |
| 2883 catchsql { INSERT INTO cd VALUES('x', 'y') } | 2885 catchsql { INSERT INTO cd VALUES('x', 'y') } |
| 2884 } {0 {}} | 2886 } {0 {}} |
| 2885 do_test e_fkey-62.6 { | 2887 do_test e_fkey-62.6 { |
| 2886 catchsql { COMMIT } | 2888 catchsql { COMMIT } |
| 2887 } {1 {foreign key constraint failed}} | 2889 } {1 {FOREIGN KEY constraint failed}} |
| 2888 do_test e_fkey-62.7 { | 2890 do_test e_fkey-62.7 { |
| 2889 execsql { | 2891 execsql { |
| 2890 DELETE FROM cd; | 2892 DELETE FROM cd; |
| 2891 COMMIT; | 2893 COMMIT; |
| 2892 } | 2894 } |
| 2893 } {} | 2895 } {} |
| 2894 | 2896 |
| 2895 #------------------------------------------------------------------------- | 2897 #------------------------------------------------------------------------- |
| 2896 # Test that the maximum recursion depth of foreign key action programs is | 2898 # Test that the maximum recursion depth of foreign key action programs is |
| 2897 # governed by the SQLITE_MAX_TRIGGER_DEPTH and SQLITE_LIMIT_TRIGGER_DEPTH | 2899 # governed by the SQLITE_MAX_TRIGGER_DEPTH and SQLITE_LIMIT_TRIGGER_DEPTH |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2938 INSERT INTO t$i VALUES('xxx'); | 2940 INSERT INTO t$i VALUES('xxx'); |
| 2939 " | 2941 " |
| 2940 } | 2942 } |
| 2941 execsql COMMIT | 2943 execsql COMMIT |
| 2942 catchsql " | 2944 catchsql " |
| 2943 UPDATE t0 SET a = 'yyy'; | 2945 UPDATE t0 SET a = 'yyy'; |
| 2944 SELECT NOT (a='yyy') FROM t$limit; | 2946 SELECT NOT (a='yyy') FROM t$limit; |
| 2945 " | 2947 " |
| 2946 } | 2948 } |
| 2947 | 2949 |
| 2948 do_test e_fkey-63.1.1 { | 2950 # If the current build was created using clang with the -fsanitize=address |
| 2949 test_on_delete_recursion $SQLITE_MAX_TRIGGER_DEPTH | 2951 # switch, then the library uses considerably more stack space than usual. |
| 2950 } {0 0} | 2952 # So much more, that some of the following tests cause stack overflows |
| 2951 do_test e_fkey-63.1.2 { | 2953 # if they are run under this configuration. |
| 2952 test_on_delete_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1] | 2954 # |
| 2953 } {1 {too many levels of trigger recursion}} | 2955 if {[clang_sanitize_address]==0} { |
| 2954 do_test e_fkey-63.1.3 { | 2956 do_test e_fkey-63.1.1 { |
| 2955 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5 | 2957 test_on_delete_recursion $SQLITE_MAX_TRIGGER_DEPTH |
| 2956 test_on_delete_recursion 5 | 2958 } {0 0} |
| 2957 } {0 0} | 2959 do_test e_fkey-63.1.2 { |
| 2958 do_test e_fkey-63.1.4 { | 2960 test_on_delete_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1] |
| 2959 test_on_delete_recursion 6 | 2961 } {1 {too many levels of trigger recursion}} |
| 2960 } {1 {too many levels of trigger recursion}} | 2962 do_test e_fkey-63.1.3 { |
| 2961 do_test e_fkey-63.1.5 { | 2963 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5 |
| 2962 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000 | 2964 test_on_delete_recursion 5 |
| 2963 } {5} | 2965 } {0 0} |
| 2964 do_test e_fkey-63.2.1 { | 2966 do_test e_fkey-63.1.4 { |
| 2965 test_on_update_recursion $SQLITE_MAX_TRIGGER_DEPTH | 2967 test_on_delete_recursion 6 |
| 2966 } {0 0} | 2968 } {1 {too many levels of trigger recursion}} |
| 2967 do_test e_fkey-63.2.2 { | 2969 do_test e_fkey-63.1.5 { |
| 2968 test_on_update_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1] | 2970 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000 |
| 2969 } {1 {too many levels of trigger recursion}} | 2971 } {5} |
| 2970 do_test e_fkey-63.2.3 { | 2972 do_test e_fkey-63.2.1 { |
| 2971 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5 | 2973 test_on_update_recursion $SQLITE_MAX_TRIGGER_DEPTH |
| 2972 test_on_update_recursion 5 | 2974 } {0 0} |
| 2973 } {0 0} | 2975 do_test e_fkey-63.2.2 { |
| 2974 do_test e_fkey-63.2.4 { | 2976 test_on_update_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1] |
| 2975 test_on_update_recursion 6 | 2977 } {1 {too many levels of trigger recursion}} |
| 2976 } {1 {too many levels of trigger recursion}} | 2978 do_test e_fkey-63.2.3 { |
| 2977 do_test e_fkey-63.2.5 { | 2979 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5 |
| 2978 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000 | 2980 test_on_update_recursion 5 |
| 2979 } {5} | 2981 } {0 0} |
| 2982 do_test e_fkey-63.2.4 { |
| 2983 test_on_update_recursion 6 |
| 2984 } {1 {too many levels of trigger recursion}} |
| 2985 do_test e_fkey-63.2.5 { |
| 2986 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000 |
| 2987 } {5} |
| 2988 } |
| 2980 | 2989 |
| 2981 #------------------------------------------------------------------------- | 2990 #------------------------------------------------------------------------- |
| 2982 # The setting of the recursive_triggers pragma does not affect foreign | 2991 # The setting of the recursive_triggers pragma does not affect foreign |
| 2983 # key actions. | 2992 # key actions. |
| 2984 # | 2993 # |
| 2985 # EVIDENCE-OF: R-51769-32730 The PRAGMA recursive_triggers setting does | 2994 # EVIDENCE-OF: R-44355-00270 The PRAGMA recursive_triggers setting does |
| 2986 # not not affect the operation of foreign key actions. | 2995 # not affect the operation of foreign key actions. |
| 2987 # | 2996 # |
| 2988 foreach recursive_triggers_setting [list 0 1 ON OFF] { | 2997 foreach recursive_triggers_setting [list 0 1 ON OFF] { |
| 2989 drop_all_tables | 2998 drop_all_tables |
| 2990 execsql "PRAGMA recursive_triggers = $recursive_triggers_setting" | 2999 execsql "PRAGMA recursive_triggers = $recursive_triggers_setting" |
| 2991 | 3000 |
| 2992 do_test e_fkey-64.$recursive_triggers_setting.1 { | 3001 do_test e_fkey-64.$recursive_triggers_setting.1 { |
| 2993 execsql { | 3002 execsql { |
| 2994 CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1 ON DELETE CASCADE); | 3003 CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1 ON DELETE CASCADE); |
| 2995 INSERT INTO t1 VALUES(1, NULL); | 3004 INSERT INTO t1 VALUES(1, NULL); |
| 2996 INSERT INTO t1 VALUES(2, 1); | 3005 INSERT INTO t1 VALUES(2, 1); |
| 2997 INSERT INTO t1 VALUES(3, 2); | 3006 INSERT INTO t1 VALUES(3, 2); |
| 2998 INSERT INTO t1 VALUES(4, 3); | 3007 INSERT INTO t1 VALUES(4, 3); |
| 2999 INSERT INTO t1 VALUES(5, 4); | 3008 INSERT INTO t1 VALUES(5, 4); |
| 3000 SELECT count(*) FROM t1; | 3009 SELECT count(*) FROM t1; |
| 3001 } | 3010 } |
| 3002 } {5} | 3011 } {5} |
| 3003 do_test e_fkey-64.$recursive_triggers_setting.2 { | 3012 do_test e_fkey-64.$recursive_triggers_setting.2 { |
| 3004 execsql { SELECT count(*) FROM t1 WHERE a = 1 } | 3013 execsql { SELECT count(*) FROM t1 WHERE a = 1 } |
| 3005 } {1} | 3014 } {1} |
| 3006 do_test e_fkey-64.$recursive_triggers_setting.3 { | 3015 do_test e_fkey-64.$recursive_triggers_setting.3 { |
| 3007 execsql { | 3016 execsql { |
| 3008 DELETE FROM t1 WHERE a = 1; | 3017 DELETE FROM t1 WHERE a = 1; |
| 3009 SELECT count(*) FROM t1; | 3018 SELECT count(*) FROM t1; |
| 3010 } | 3019 } |
| 3011 } {0} | 3020 } {0} |
| 3012 } | 3021 } |
| 3013 | 3022 |
| 3014 finish_test | 3023 finish_test |
| OLD | NEW |