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