1# 2001 September 15 2# 3# The author disclaims copyright to this source code. In place of 4# a legal notice, here is a blessing: 5# 6# May you do good and not evil. 7# May you find forgiveness for yourself and forgive others. 8# May you share freely, never taking more than you give. 9# 10#*********************************************************************** 11# This file implements regression tests for SQLite library. The 12# focus of this script is database locks. 13# 14# $Id: trans.test,v 1.21 2004/06/09 19:03:55 drh Exp $ 15 16 17set testdir [file dirname $argv0] 18source $testdir/tester.tcl 19 20 21# Create several tables to work with. 22# 23do_test trans-1.0 { 24 execsql { 25 CREATE TABLE one(a int PRIMARY KEY, b text); 26 INSERT INTO one VALUES(1,'one'); 27 INSERT INTO one VALUES(2,'two'); 28 INSERT INTO one VALUES(3,'three'); 29 SELECT b FROM one ORDER BY a; 30 } 31} {one two three} 32do_test trans-1.1 { 33 execsql { 34 CREATE TABLE two(a int PRIMARY KEY, b text); 35 INSERT INTO two VALUES(1,'I'); 36 INSERT INTO two VALUES(5,'V'); 37 INSERT INTO two VALUES(10,'X'); 38 SELECT b FROM two ORDER BY a; 39 } 40} {I V X} 41do_test trans-1.9 { 42 sqlite altdb test.db 43 execsql {SELECT b FROM one ORDER BY a} altdb 44} {one two three} 45do_test trans-1.10 { 46 execsql {SELECT b FROM two ORDER BY a} altdb 47} {I V X} 48integrity_check trans-1.11 49 50# Basic transactions 51# 52do_test trans-2.1 { 53 set v [catch {execsql {BEGIN}} msg] 54 lappend v $msg 55} {0 {}} 56do_test trans-2.2 { 57 set v [catch {execsql {END}} msg] 58 lappend v $msg 59} {0 {}} 60do_test trans-2.3 { 61 set v [catch {execsql {BEGIN TRANSACTION}} msg] 62 lappend v $msg 63} {0 {}} 64do_test trans-2.4 { 65 set v [catch {execsql {COMMIT TRANSACTION}} msg] 66 lappend v $msg 67} {0 {}} 68do_test trans-2.5 { 69 set v [catch {execsql {BEGIN TRANSACTION 'foo'}} msg] 70 lappend v $msg 71} {0 {}} 72do_test trans-2.6 { 73 set v [catch {execsql {ROLLBACK TRANSACTION 'foo'}} msg] 74 lappend v $msg 75} {0 {}} 76do_test trans-2.10 { 77 execsql { 78 BEGIN; 79 SELECT a FROM one ORDER BY a; 80 SELECT a FROM two ORDER BY a; 81 END; 82 } 83} {1 2 3 1 5 10} 84integrity_check trans-2.11 85 86# Check the locking behavior 87# 88do_test trans-3.1 { 89 execsql { 90 BEGIN; 91 UPDATE one SET a = 0 WHERE 0; 92 SELECT a FROM one ORDER BY a; 93 } 94} {1 2 3} 95do_test trans-3.2 { 96 set v [catch {execsql { 97 SELECT a FROM two ORDER BY a; 98 } altdb} msg] 99 lappend v $msg 100} {1 {database is locked}} 101do_test trans-3.3 { 102 set v [catch {execsql { 103 SELECT a FROM one ORDER BY a; 104 } altdb} msg] 105 lappend v $msg 106} {1 {database is locked}} 107do_test trans-3.4 { 108 set v [catch {execsql { 109 INSERT INTO one VALUES(4,'four'); 110 }} msg] 111 lappend v $msg 112} {0 {}} 113do_test trans-3.5 { 114 set v [catch {execsql { 115 SELECT a FROM two ORDER BY a; 116 } altdb} msg] 117 lappend v $msg 118} {1 {database is locked}} 119do_test trans-3.6 { 120 set v [catch {execsql { 121 SELECT a FROM one ORDER BY a; 122 } altdb} msg] 123 lappend v $msg 124} {1 {database is locked}} 125do_test trans-3.7 { 126 set v [catch {execsql { 127 INSERT INTO two VALUES(4,'IV'); 128 }} msg] 129 lappend v $msg 130} {0 {}} 131do_test trans-3.8 { 132 set v [catch {execsql { 133 SELECT a FROM two ORDER BY a; 134 } altdb} msg] 135 lappend v $msg 136} {1 {database is locked}} 137do_test trans-3.9 { 138 set v [catch {execsql { 139 SELECT a FROM one ORDER BY a; 140 } altdb} msg] 141 lappend v $msg 142} {1 {database is locked}} 143do_test trans-3.10 { 144 execsql {END TRANSACTION} 145} {} 146do_test trans-3.11 { 147 set v [catch {execsql { 148 SELECT a FROM two ORDER BY a; 149 } altdb} msg] 150 lappend v $msg 151} {0 {1 4 5 10}} 152do_test trans-3.12 { 153 set v [catch {execsql { 154 SELECT a FROM one ORDER BY a; 155 } altdb} msg] 156 lappend v $msg 157} {0 {1 2 3 4}} 158do_test trans-3.13 { 159 set v [catch {execsql { 160 SELECT a FROM two ORDER BY a; 161 } db} msg] 162 lappend v $msg 163} {0 {1 4 5 10}} 164do_test trans-3.14 { 165 set v [catch {execsql { 166 SELECT a FROM one ORDER BY a; 167 } db} msg] 168 lappend v $msg 169} {0 {1 2 3 4}} 170integrity_check trans-3.15 171 172do_test trans-4.1 { 173 set v [catch {execsql { 174 COMMIT; 175 } db} msg] 176 lappend v $msg 177} {1 {cannot commit - no transaction is active}} 178do_test trans-4.2 { 179 set v [catch {execsql { 180 ROLLBACK; 181 } db} msg] 182 lappend v $msg 183} {1 {cannot rollback - no transaction is active}} 184do_test trans-4.3 { 185 set v [catch {execsql { 186 BEGIN TRANSACTION; 187 UPDATE two SET a = 0 WHERE 0; 188 SELECT a FROM two ORDER BY a; 189 } db} msg] 190 lappend v $msg 191} {0 {1 4 5 10}} 192do_test trans-4.4 { 193 set v [catch {execsql { 194 SELECT a FROM two ORDER BY a; 195 } altdb} msg] 196 lappend v $msg 197} {1 {database is locked}} 198do_test trans-4.5 { 199 set v [catch {execsql { 200 SELECT a FROM one ORDER BY a; 201 } altdb} msg] 202 lappend v $msg 203} {1 {database is locked}} 204do_test trans-4.6 { 205 set v [catch {execsql { 206 BEGIN TRANSACTION; 207 SELECT a FROM one ORDER BY a; 208 } db} msg] 209 lappend v $msg 210} {1 {cannot start a transaction within a transaction}} 211do_test trans-4.7 { 212 set v [catch {execsql { 213 SELECT a FROM two ORDER BY a; 214 } altdb} msg] 215 lappend v $msg 216} {1 {database is locked}} 217do_test trans-4.8 { 218 set v [catch {execsql { 219 SELECT a FROM one ORDER BY a; 220 } altdb} msg] 221 lappend v $msg 222} {1 {database is locked}} 223do_test trans-4.9 { 224 set v [catch {execsql { 225 END TRANSACTION; 226 SELECT a FROM two ORDER BY a; 227 } db} msg] 228 lappend v $msg 229} {0 {1 4 5 10}} 230do_test trans-4.10 { 231 set v [catch {execsql { 232 SELECT a FROM two ORDER BY a; 233 } altdb} msg] 234 lappend v $msg 235} {0 {1 4 5 10}} 236do_test trans-4.11 { 237 set v [catch {execsql { 238 SELECT a FROM one ORDER BY a; 239 } altdb} msg] 240 lappend v $msg 241} {0 {1 2 3 4}} 242integrity_check trans-4.12 243do_test trans-4.98 { 244 altdb close 245 execsql { 246 DROP TABLE one; 247 DROP TABLE two; 248 } 249} {} 250integrity_check trans-4.99 251 252# Check out the commit/rollback behavior of the database 253# 254do_test trans-5.1 { 255 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name} 256} {} 257do_test trans-5.2 { 258 execsql {BEGIN TRANSACTION} 259 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name} 260} {} 261do_test trans-5.3 { 262 execsql {CREATE TABLE one(a text, b int)} 263 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name} 264} {one} 265do_test trans-5.4 { 266 execsql {SELECT a,b FROM one ORDER BY b} 267} {} 268do_test trans-5.5 { 269 execsql {INSERT INTO one(a,b) VALUES('hello', 1)} 270 execsql {SELECT a,b FROM one ORDER BY b} 271} {hello 1} 272do_test trans-5.6 { 273 execsql {ROLLBACK} 274 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name} 275} {} 276do_test trans-5.7 { 277 set v [catch { 278 execsql {SELECT a,b FROM one ORDER BY b} 279 } msg] 280 lappend v $msg 281} {1 {no such table: one}} 282 283# Test commits and rollbacks of table CREATE TABLEs, CREATE INDEXs 284# DROP TABLEs and DROP INDEXs 285# 286do_test trans-5.8 { 287 execsql { 288 SELECT name fROM sqlite_master 289 WHERE type='table' OR type='index' 290 ORDER BY name 291 } 292} {} 293do_test trans-5.9 { 294 execsql { 295 BEGIN TRANSACTION; 296 CREATE TABLE t1(a int, b int, c int); 297 SELECT name fROM sqlite_master 298 WHERE type='table' OR type='index' 299 ORDER BY name; 300 } 301} {t1} 302do_test trans-5.10 { 303 execsql { 304 CREATE INDEX i1 ON t1(a); 305 SELECT name fROM sqlite_master 306 WHERE type='table' OR type='index' 307 ORDER BY name; 308 } 309} {i1 t1} 310do_test trans-5.11 { 311 execsql { 312 COMMIT; 313 SELECT name fROM sqlite_master 314 WHERE type='table' OR type='index' 315 ORDER BY name; 316 } 317} {i1 t1} 318do_test trans-5.12 { 319 execsql { 320 BEGIN TRANSACTION; 321 CREATE TABLE t2(a int, b int, c int); 322 CREATE INDEX i2a ON t2(a); 323 CREATE INDEX i2b ON t2(b); 324 DROP TABLE t1; 325 SELECT name fROM sqlite_master 326 WHERE type='table' OR type='index' 327 ORDER BY name; 328 } 329} {i2a i2b t2} 330do_test trans-5.13 { 331 execsql { 332 ROLLBACK; 333 SELECT name fROM sqlite_master 334 WHERE type='table' OR type='index' 335 ORDER BY name; 336 } 337} {i1 t1} 338do_test trans-5.14 { 339 execsql { 340 BEGIN TRANSACTION; 341 DROP INDEX i1; 342 SELECT name fROM sqlite_master 343 WHERE type='table' OR type='index' 344 ORDER BY name; 345 } 346} {t1} 347do_test trans-5.15 { 348 execsql { 349 ROLLBACK; 350 SELECT name fROM sqlite_master 351 WHERE type='table' OR type='index' 352 ORDER BY name; 353 } 354} {i1 t1} 355do_test trans-5.16 { 356 execsql { 357 BEGIN TRANSACTION; 358 DROP INDEX i1; 359 CREATE TABLE t2(x int, y int, z int); 360 CREATE INDEX i2x ON t2(x); 361 CREATE INDEX i2y ON t2(y); 362 INSERT INTO t2 VALUES(1,2,3); 363 SELECT name fROM sqlite_master 364 WHERE type='table' OR type='index' 365 ORDER BY name; 366 } 367} {i2x i2y t1 t2} 368do_test trans-5.17 { 369 execsql { 370 COMMIT; 371 SELECT name fROM sqlite_master 372 WHERE type='table' OR type='index' 373 ORDER BY name; 374 } 375} {i2x i2y t1 t2} 376do_test trans-5.18 { 377 execsql { 378 SELECT * FROM t2; 379 } 380} {1 2 3} 381do_test trans-5.19 { 382 execsql { 383 SELECT x FROM t2 WHERE y=2; 384 } 385} {1} 386do_test trans-5.20 { 387 execsql { 388 BEGIN TRANSACTION; 389 DROP TABLE t1; 390 DROP TABLE t2; 391 SELECT name fROM sqlite_master 392 WHERE type='table' OR type='index' 393 ORDER BY name; 394 } 395} {} 396do_test trans-5.21 { 397 set r [catch {execsql { 398 SELECT * FROM t2 399 }} msg] 400 lappend r $msg 401} {1 {no such table: t2}} 402do_test trans-5.22 { 403 execsql { 404 ROLLBACK; 405 SELECT name fROM sqlite_master 406 WHERE type='table' OR type='index' 407 ORDER BY name; 408 } 409} {i2x i2y t1 t2} 410do_test trans-5.23 { 411 execsql { 412 SELECT * FROM t2; 413 } 414} {1 2 3} 415integrity_check trans-5.23 416 417 418# Try to DROP and CREATE tables and indices with the same name 419# within a transaction. Make sure ROLLBACK works. 420# 421do_test trans-6.1 { 422 execsql2 { 423 INSERT INTO t1 VALUES(1,2,3); 424 BEGIN TRANSACTION; 425 DROP TABLE t1; 426 CREATE TABLE t1(p,q,r); 427 ROLLBACK; 428 SELECT * FROM t1; 429 } 430} {a 1 b 2 c 3} 431do_test trans-6.2 { 432 execsql2 { 433 INSERT INTO t1 VALUES(1,2,3); 434 BEGIN TRANSACTION; 435 DROP TABLE t1; 436 CREATE TABLE t1(p,q,r); 437 COMMIT; 438 SELECT * FROM t1; 439 } 440} {} 441do_test trans-6.3 { 442 execsql2 { 443 INSERT INTO t1 VALUES(1,2,3); 444 SELECT * FROM t1; 445 } 446} {p 1 q 2 r 3} 447do_test trans-6.4 { 448 execsql2 { 449 BEGIN TRANSACTION; 450 DROP TABLE t1; 451 CREATE TABLE t1(a,b,c); 452 INSERT INTO t1 VALUES(4,5,6); 453 SELECT * FROM t1; 454 DROP TABLE t1; 455 } 456} {a 4 b 5 c 6} 457do_test trans-6.5 { 458 execsql2 { 459 ROLLBACK; 460 SELECT * FROM t1; 461 } 462} {p 1 q 2 r 3} 463do_test trans-6.6 { 464 execsql2 { 465 BEGIN TRANSACTION; 466 DROP TABLE t1; 467 CREATE TABLE t1(a,b,c); 468 INSERT INTO t1 VALUES(4,5,6); 469 SELECT * FROM t1; 470 DROP TABLE t1; 471 } 472} {a 4 b 5 c 6} 473do_test trans-6.7 { 474 catchsql { 475 COMMIT; 476 SELECT * FROM t1; 477 } 478} {1 {no such table: t1}} 479 480# Repeat on a table with an automatically generated index. 481# 482do_test trans-6.10 { 483 execsql2 { 484 CREATE TABLE t1(a unique,b,c); 485 INSERT INTO t1 VALUES(1,2,3); 486 BEGIN TRANSACTION; 487 DROP TABLE t1; 488 CREATE TABLE t1(p unique,q,r); 489 ROLLBACK; 490 SELECT * FROM t1; 491 } 492} {a 1 b 2 c 3} 493do_test trans-6.11 { 494 execsql2 { 495 BEGIN TRANSACTION; 496 DROP TABLE t1; 497 CREATE TABLE t1(p unique,q,r); 498 COMMIT; 499 SELECT * FROM t1; 500 } 501} {} 502do_test trans-6.12 { 503 execsql2 { 504 INSERT INTO t1 VALUES(1,2,3); 505 SELECT * FROM t1; 506 } 507} {p 1 q 2 r 3} 508do_test trans-6.13 { 509 execsql2 { 510 BEGIN TRANSACTION; 511 DROP TABLE t1; 512 CREATE TABLE t1(a unique,b,c); 513 INSERT INTO t1 VALUES(4,5,6); 514 SELECT * FROM t1; 515 DROP TABLE t1; 516 } 517} {a 4 b 5 c 6} 518do_test trans-6.14 { 519 execsql2 { 520 ROLLBACK; 521 SELECT * FROM t1; 522 } 523} {p 1 q 2 r 3} 524do_test trans-6.15 { 525 execsql2 { 526 BEGIN TRANSACTION; 527 DROP TABLE t1; 528 CREATE TABLE t1(a unique,b,c); 529 INSERT INTO t1 VALUES(4,5,6); 530 SELECT * FROM t1; 531 DROP TABLE t1; 532 } 533} {a 4 b 5 c 6} 534do_test trans-6.16 { 535 catchsql { 536 COMMIT; 537 SELECT * FROM t1; 538 } 539} {1 {no such table: t1}} 540 541do_test trans-6.20 { 542 execsql { 543 CREATE TABLE t1(a integer primary key,b,c); 544 INSERT INTO t1 VALUES(1,-2,-3); 545 INSERT INTO t1 VALUES(4,-5,-6); 546 SELECT * FROM t1; 547 } 548} {1 -2 -3 4 -5 -6} 549do_test trans-6.21 { 550 execsql { 551 CREATE INDEX i1 ON t1(b); 552 SELECT * FROM t1 WHERE b<1; 553 } 554} {4 -5 -6 1 -2 -3} 555do_test trans-6.22 { 556 execsql { 557 BEGIN TRANSACTION; 558 DROP INDEX i1; 559 SELECT * FROM t1 WHERE b<1; 560 ROLLBACK; 561 } 562} {1 -2 -3 4 -5 -6} 563do_test trans-6.23 { 564 execsql { 565 SELECT * FROM t1 WHERE b<1; 566 } 567} {4 -5 -6 1 -2 -3} 568do_test trans-6.24 { 569 execsql { 570 BEGIN TRANSACTION; 571 DROP TABLE t1; 572 ROLLBACK; 573 SELECT * FROM t1 WHERE b<1; 574 } 575} {4 -5 -6 1 -2 -3} 576 577do_test trans-6.25 { 578 execsql { 579 BEGIN TRANSACTION; 580 DROP INDEX i1; 581 CREATE INDEX i1 ON t1(c); 582 SELECT * FROM t1 WHERE b<1; 583 } 584} {1 -2 -3 4 -5 -6} 585do_test trans-6.26 { 586 execsql { 587 SELECT * FROM t1 WHERE c<1; 588 } 589} {4 -5 -6 1 -2 -3} 590do_test trans-6.27 { 591 execsql { 592 ROLLBACK; 593 SELECT * FROM t1 WHERE b<1; 594 } 595} {4 -5 -6 1 -2 -3} 596do_test trans-6.28 { 597 execsql { 598 SELECT * FROM t1 WHERE c<1; 599 } 600} {1 -2 -3 4 -5 -6} 601 602# The following repeats steps 6.20 through 6.28, but puts a "unique" 603# constraint the first field of the table in order to generate an 604# automatic index. 605# 606do_test trans-6.30 { 607 execsql { 608 BEGIN TRANSACTION; 609 DROP TABLE t1; 610 CREATE TABLE t1(a int unique,b,c); 611 COMMIT; 612 INSERT INTO t1 VALUES(1,-2,-3); 613 INSERT INTO t1 VALUES(4,-5,-6); 614 SELECT * FROM t1 ORDER BY a; 615 } 616} {1 -2 -3 4 -5 -6} 617do_test trans-6.31 { 618 execsql { 619 CREATE INDEX i1 ON t1(b); 620 SELECT * FROM t1 WHERE b<1; 621 } 622} {4 -5 -6 1 -2 -3} 623do_test trans-6.32 { 624 execsql { 625 BEGIN TRANSACTION; 626 DROP INDEX i1; 627 SELECT * FROM t1 WHERE b<1; 628 ROLLBACK; 629 } 630} {1 -2 -3 4 -5 -6} 631do_test trans-6.33 { 632 execsql { 633 SELECT * FROM t1 WHERE b<1; 634 } 635} {4 -5 -6 1 -2 -3} 636do_test trans-6.34 { 637 execsql { 638 BEGIN TRANSACTION; 639 DROP TABLE t1; 640 ROLLBACK; 641 SELECT * FROM t1 WHERE b<1; 642 } 643} {4 -5 -6 1 -2 -3} 644 645do_test trans-6.35 { 646 execsql { 647 BEGIN TRANSACTION; 648 DROP INDEX i1; 649 CREATE INDEX i1 ON t1(c); 650 SELECT * FROM t1 WHERE b<1; 651 } 652} {1 -2 -3 4 -5 -6} 653do_test trans-6.36 { 654 execsql { 655 SELECT * FROM t1 WHERE c<1; 656 } 657} {4 -5 -6 1 -2 -3} 658do_test trans-6.37 { 659 execsql { 660 DROP INDEX i1; 661 SELECT * FROM t1 WHERE c<1; 662 } 663} {1 -2 -3 4 -5 -6} 664do_test trans-6.38 { 665 execsql { 666 ROLLBACK; 667 SELECT * FROM t1 WHERE b<1; 668 } 669} {4 -5 -6 1 -2 -3} 670do_test trans-6.39 { 671 execsql { 672 SELECT * FROM t1 WHERE c<1; 673 } 674} {1 -2 -3 4 -5 -6} 675integrity_check trans-6.40 676 677# Test to make sure rollback restores the database back to its original 678# state. 679# 680do_test trans-7.1 { 681 execsql {BEGIN} 682 for {set i 0} {$i<1000} {incr i} { 683 set r1 [expr {rand()}] 684 set r2 [expr {rand()}] 685 set r3 [expr {rand()}] 686 execsql "INSERT INTO t2 VALUES($r1,$r2,$r3)" 687 } 688 execsql {COMMIT} 689 set ::checksum [execsql {SELECT md5sum(x,y,z) FROM t2}] 690 set ::checksum2 [ 691 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master} 692 ] 693 execsql {SELECT count(*) FROM t2} 694} {1001} 695do_test trans-7.2 { 696 execsql {SELECT md5sum(x,y,z) FROM t2} 697} $checksum 698do_test trans-7.2.1 { 699 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master} 700} $checksum2 701do_test trans-7.3 { 702 execsql { 703 BEGIN; 704 DELETE FROM t2; 705 ROLLBACK; 706 SELECT md5sum(x,y,z) FROM t2; 707 } 708} $checksum 709do_test trans-7.4 { 710 execsql { 711 BEGIN; 712 INSERT INTO t2 SELECT * FROM t2; 713 ROLLBACK; 714 SELECT md5sum(x,y,z) FROM t2; 715 } 716} $checksum 717do_test trans-7.5 { 718 execsql { 719 BEGIN; 720 DELETE FROM t2; 721 ROLLBACK; 722 SELECT md5sum(x,y,z) FROM t2; 723 } 724} $checksum 725do_test trans-7.6 { 726 execsql { 727 BEGIN; 728 INSERT INTO t2 SELECT * FROM t2; 729 ROLLBACK; 730 SELECT md5sum(x,y,z) FROM t2; 731 } 732} $checksum 733do_test trans-7.7 { 734 execsql { 735 BEGIN; 736 CREATE TABLE t3 AS SELECT * FROM t2; 737 INSERT INTO t2 SELECT * FROM t3; 738 ROLLBACK; 739 SELECT md5sum(x,y,z) FROM t2; 740 } 741} $checksum 742do_test trans-7.8 { 743 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master} 744} $checksum2 745do_test trans-7.9 { 746 execsql { 747 BEGIN; 748 CREATE TEMP TABLE t3 AS SELECT * FROM t2; 749 INSERT INTO t2 SELECT * FROM t3; 750 ROLLBACK; 751 SELECT md5sum(x,y,z) FROM t2; 752 } 753} $checksum 754do_test trans-7.10 { 755 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master} 756} $checksum2 757do_test trans-7.11 { 758 execsql { 759 BEGIN; 760 CREATE TEMP TABLE t3 AS SELECT * FROM t2; 761 INSERT INTO t2 SELECT * FROM t3; 762 DROP INDEX i2x; 763 DROP INDEX i2y; 764 CREATE INDEX i3a ON t3(x); 765 ROLLBACK; 766 SELECT md5sum(x,y,z) FROM t2; 767 } 768} $checksum 769do_test trans-7.12 { 770 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master} 771} $checksum2 772do_test trans-7.13 { 773 execsql { 774 BEGIN; 775 DROP TABLE t2; 776 ROLLBACK; 777 SELECT md5sum(x,y,z) FROM t2; 778 } 779} $checksum 780do_test trans-7.14 { 781 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master} 782} $checksum2 783integrity_check trans-7.15 784 785# Arrange for another process to begin modifying the database but abort 786# and die in the middle of the modification. Then have this process read 787# the database. This process should detect the journal file and roll it 788# back. Verify that this happens correctly. 789# 790set fd [open test.tcl w] 791puts $fd { 792 sqlite db test.db 793 db eval { 794 PRAGMA default_cache_size=20; 795 BEGIN; 796 CREATE TABLE t3 AS SELECT * FROM t2; 797 DELETE FROM t2; 798 } 799 sqlite_abort 800} 801close $fd 802do_test trans-8.1 { 803 catch {exec [info nameofexec] test.tcl} 804 execsql {SELECT md5sum(x,y,z) FROM t2} 805} $checksum 806do_test trans-8.2 { 807 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master} 808} $checksum2 809integrity_check trans-8.3 810 811# In the following sequence of tests, compute the MD5 sum of the content 812# of a table, make lots of modifications to that table, then do a rollback. 813# Verify that after the rollback, the MD5 checksum is unchanged. 814# 815do_test trans-9.1 { 816 execsql { 817 PRAGMA default_cache_size=10; 818 } 819 db close 820 sqlite db test.db 821 execsql { 822 BEGIN; 823 CREATE TABLE t3(x TEXT); 824 INSERT INTO t3 VALUES(randstr(10,400)); 825 INSERT INTO t3 VALUES(randstr(10,400)); 826 INSERT INTO t3 SELECT randstr(10,400) FROM t3; 827 INSERT INTO t3 SELECT randstr(10,400) FROM t3; 828 INSERT INTO t3 SELECT randstr(10,400) FROM t3; 829 INSERT INTO t3 SELECT randstr(10,400) FROM t3; 830 INSERT INTO t3 SELECT randstr(10,400) FROM t3; 831 INSERT INTO t3 SELECT randstr(10,400) FROM t3; 832 INSERT INTO t3 SELECT randstr(10,400) FROM t3; 833 INSERT INTO t3 SELECT randstr(10,400) FROM t3; 834 INSERT INTO t3 SELECT randstr(10,400) FROM t3; 835 COMMIT; 836 SELECT count(*) FROM t3; 837 } 838} {1024} 839 840# The following procedure computes a "signature" for table "t3". If 841# T3 changes in any way, the signature should change. 842# 843# This is used to test ROLLBACK. We gather a signature for t3, then 844# make lots of changes to t3, then rollback and take another signature. 845# The two signatures should be the same. 846# 847proc signature {} { 848 return [db eval {SELECT count(*), md5sum(x) FROM t3}] 849} 850 851# Repeat the following group of tests 20 times for quick testing and 852# 40 times for full testing. Each iteration of the test makes table 853# t3 a little larger, and thus takes a little longer, so doing 40 tests 854# is more than 2.0 times slower than doing 20 tests. Considerably more. 855# 856if {[info exists ISQUICK]} { 857 set limit 20 858} else { 859 set limit 40 860} 861 862# Do rollbacks. Make sure the signature does not change. 863# 864for {set i 2} {$i<=$limit} {incr i} { 865 set ::sig [signature] 866 set cnt [lindex $::sig 0] 867 if {$i%2==0} { 868 execsql {PRAGMA synchronous=FULL} 869 } else { 870 execsql {PRAGMA synchronous=NORMAL} 871 } 872 do_test trans-9.$i.1-$cnt { 873 execsql { 874 BEGIN; 875 DELETE FROM t3 WHERE random()%10!=0; 876 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; 877 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; 878 ROLLBACK; 879 } 880 signature 881 } $sig 882 do_test trans-9.$i.2-$cnt { 883 execsql { 884 BEGIN; 885 DELETE FROM t3 WHERE random()%10!=0; 886 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; 887 DELETE FROM t3 WHERE random()%10!=0; 888 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; 889 ROLLBACK; 890 } 891 signature 892 } $sig 893 if {$i<$limit} { 894 do_test trans-9.$i.9-$cnt { 895 execsql { 896 INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0; 897 } 898 } {} 899 } 900 set ::pager_old_format 0 901} 902 903finish_test 904