1# 2005 December 30 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# 12# $Id: shared.test,v 1.21 2006/01/23 21:38:03 drh Exp $ 13 14set testdir [file dirname $argv0] 15source $testdir/tester.tcl 16db close 17 18ifcapable !shared_cache { 19 finish_test 20 return 21} 22 23set ::enable_shared_cache [sqlite3_enable_shared_cache 1] 24 25foreach av [list 0 1] { 26 27# Open the database connection and execute the auto-vacuum pragma 28file delete -force test.db 29sqlite3 db test.db 30 31ifcapable autovacuum { 32 do_test shared-[expr $av+1].1.0 { 33 execsql "pragma auto_vacuum=$::av" 34 execsql {pragma auto_vacuum} 35 } "$av" 36} else { 37 if {$av} { 38 db close 39 break 40 } 41} 42 43# $av is currently 0 if this loop iteration is to test with auto-vacuum turned 44# off, and 1 if it is turned on. Increment it so that (1 -> no auto-vacuum) 45# and (2 -> auto-vacuum). The sole reason for this is so that it looks nicer 46# when we use this variable as part of test-case names. 47# 48incr av 49 50# Test organization: 51# 52# shared-1.*: Simple test to verify basic sanity of table level locking when 53# two connections share a pager cache. 54# shared-2.*: Test that a read transaction can co-exist with a 55# write-transaction, including a simple test to ensure the 56# external locking protocol is still working. 57# shared-3.*: Simple test of read-uncommitted mode. 58# shared-4.*: Check that the schema is locked and unlocked correctly. 59# shared-5.*: Test that creating/dropping schema items works when databases 60# are attached in different orders to different handles. 61# shared-6.*: Locking, UNION ALL queries and sub-queries. 62# shared-7.*: Autovacuum and shared-cache. 63# shared-8.*: Tests related to the text encoding of shared-cache databases. 64# shared-9.*: TEMP triggers and shared-cache databases. 65# shared-10.*: Tests of sqlite3_close(). 66# shared-11.*: Test transaction locking. 67# 68 69do_test shared-$av.1.1 { 70 # Open a second database on the file test.db. It should use the same pager 71 # cache and schema as the original connection. Verify that only 1 file is 72 # opened. 73 sqlite3 db2 test.db 74 set ::sqlite_open_file_count 75} {1} 76do_test shared-$av.1.2 { 77 # Add a table and a single row of data via the first connection. 78 # Ensure that the second connection can see them. 79 execsql { 80 CREATE TABLE abc(a, b, c); 81 INSERT INTO abc VALUES(1, 2, 3); 82 } db 83 execsql { 84 SELECT * FROM abc; 85 } db2 86} {1 2 3} 87do_test shared-$av.1.3 { 88 # Have the first connection begin a transaction and obtain a read-lock 89 # on table abc. This should not prevent the second connection from 90 # querying abc. 91 execsql { 92 BEGIN; 93 SELECT * FROM abc; 94 } 95 execsql { 96 SELECT * FROM abc; 97 } db2 98} {1 2 3} 99do_test shared-$av.1.4 { 100 # Try to insert a row into abc via connection 2. This should fail because 101 # of the read-lock connection 1 is holding on table abc (obtained in the 102 # previous test case). 103 catchsql { 104 INSERT INTO abc VALUES(4, 5, 6); 105 } db2 106} {1 {database table is locked: abc}} 107do_test shared-$av.1.5 { 108 # Using connection 2 (the one without the open transaction), try to create 109 # a new table. This should fail because of the open read transaction 110 # held by connection 1. 111 catchsql { 112 CREATE TABLE def(d, e, f); 113 } db2 114} {1 {database table is locked: sqlite_master}} 115do_test shared-$av.1.6 { 116 # Upgrade connection 1's transaction to a write transaction. Create 117 # a new table - def - and insert a row into it. Because the connection 1 118 # transaction modifies the schema, it should not be possible for 119 # connection 2 to access the database at all until the connection 1 120 # has finished the transaction. 121 execsql { 122 CREATE TABLE def(d, e, f); 123 INSERT INTO def VALUES('IV', 'V', 'VI'); 124 } 125} {} 126do_test shared-$av.1.7 { 127 # Read from the sqlite_master table with connection 1 (inside the 128 # transaction). Then test that we can not do this with connection 2. This 129 # is because of the schema-modified lock established by connection 1 130 # in the previous test case. 131 execsql { 132 SELECT * FROM sqlite_master; 133 } 134 catchsql { 135 SELECT * FROM sqlite_master; 136 } db2 137} {1 {database schema is locked: main}} 138do_test shared-$av.1.8 { 139 # Commit the connection 1 transaction. 140 execsql { 141 COMMIT; 142 } 143} {} 144 145do_test shared-$av.2.1 { 146 # Open connection db3 to the database. Use a different path to the same 147 # file so that db3 does *not* share the same pager cache as db and db2 148 # (there should be two open file handles). 149 if {$::tcl_platform(platform)=="unix"} { 150 sqlite3 db3 ./test.db 151 } else { 152 sqlite3 db3 TEST.DB 153 } 154 set ::sqlite_open_file_count 155} {2} 156do_test shared-$av.2.2 { 157 # Start read transactions on db and db2 (the shared pager cache). Ensure 158 # db3 cannot write to the database. 159 execsql { 160 BEGIN; 161 SELECT * FROM abc; 162 } 163 execsql { 164 BEGIN; 165 SELECT * FROM abc; 166 } db2 167 catchsql { 168 INSERT INTO abc VALUES(1, 2, 3); 169 } db2 170} {1 {database table is locked: abc}} 171do_test shared-$av.2.3 { 172 # Turn db's transaction into a write-transaction. db3 should still be 173 # able to read from table def (but will not see the new row). Connection 174 # db2 should not be able to read def (because of the write-lock). 175 176# Todo: The failed "INSERT INTO abc ..." statement in the above test 177# has started a write-transaction on db2 (should this be so?). This 178# would prevent connection db from starting a write-transaction. So roll the 179# db2 transaction back and replace it with a new read transaction. 180 execsql { 181 ROLLBACK; 182 BEGIN; 183 SELECT * FROM abc; 184 } db2 185 186 execsql { 187 INSERT INTO def VALUES('VII', 'VIII', 'IX'); 188 } 189 concat [ 190 catchsql { SELECT * FROM def; } db3 191 ] [ 192 catchsql { SELECT * FROM def; } db2 193 ] 194} {0 {IV V VI} 1 {database table is locked: def}} 195do_test shared-$av.2.4 { 196 # Commit the open transaction on db. db2 still holds a read-transaction. 197 # This should prevent db3 from writing to the database, but not from 198 # reading. 199 execsql { 200 COMMIT; 201 } 202 concat [ 203 catchsql { SELECT * FROM def; } db3 204 ] [ 205 catchsql { INSERT INTO def VALUES('X', 'XI', 'XII'); } db3 206 ] 207} {0 {IV V VI VII VIII IX} 1 {database is locked}} 208 209catchsql COMMIT db2 210 211do_test shared-$av.3.1.1 { 212 # This test case starts a linear scan of table 'seq' using a 213 # read-uncommitted connection. In the middle of the scan, rows are added 214 # to the end of the seq table (ahead of the current cursor position). 215 # The uncommitted rows should be included in the results of the scan. 216 execsql " 217 CREATE TABLE seq(i PRIMARY KEY, x); 218 INSERT INTO seq VALUES(1, '[string repeat X 500]'); 219 INSERT INTO seq VALUES(2, '[string repeat X 500]'); 220 " 221 execsql {SELECT * FROM sqlite_master} db2 222 execsql {PRAGMA read_uncommitted = 1} db2 223 224 set ret [list] 225 db2 eval {SELECT i FROM seq ORDER BY i} { 226 if {$i < 4} { 227 set max [execsql {SELECT max(i) FROM seq}] 228 db eval { 229 INSERT INTO seq SELECT i + :max, x FROM seq; 230 } 231 } 232 lappend ret $i 233 } 234 set ret 235} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16} 236do_test shared-$av.3.1.2 { 237 # Another linear scan through table seq using a read-uncommitted connection. 238 # This time, delete each row as it is read. Should not affect the results of 239 # the scan, but the table should be empty after the scan is concluded 240 # (test 3.1.3 verifies this). 241 set ret [list] 242 db2 eval {SELECT i FROM seq} { 243 db eval {DELETE FROM seq WHERE i = :i} 244 lappend ret $i 245 } 246 set ret 247} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16} 248do_test shared-$av.3.1.3 { 249 execsql { 250 SELECT * FROM seq; 251 } 252} {} 253 254catch {db close} 255catch {db2 close} 256catch {db3 close} 257 258#-------------------------------------------------------------------------- 259# Tests shared-4.* test that the schema locking rules are applied 260# correctly. i.e.: 261# 262# 1. All transactions require a read-lock on the schemas of databases they 263# access. 264# 2. Transactions that modify a database schema require a write-lock on that 265# schema. 266# 3. It is not possible to compile a statement while another handle has a 267# write-lock on the schema. 268# 269 270# Open two database handles db and db2. Each has a single attach database 271# (as well as main): 272# 273# db.main -> ./test.db 274# db.test2 -> ./test2.db 275# db2.main -> ./test2.db 276# db2.test -> ./test.db 277# 278file delete -force test.db 279file delete -force test2.db 280file delete -force test2.db-journal 281sqlite3 db test.db 282sqlite3 db2 test2.db 283do_test shared-$av.4.1.1 { 284 set sqlite_open_file_count 285} {2} 286do_test shared-$av.4.1.2 { 287 execsql {ATTACH 'test2.db' AS test2} 288 set sqlite_open_file_count 289} {2} 290do_test shared-$av.4.1.3 { 291 execsql {ATTACH 'test.db' AS test} db2 292 set sqlite_open_file_count 293} {2} 294 295# Sanity check: Create a table in ./test.db via handle db, and test that handle 296# db2 can "see" the new table immediately. A handle using a seperate pager 297# cache would have to reload the database schema before this were possible. 298# 299do_test shared-$av.4.2.1 { 300 execsql { 301 CREATE TABLE abc(a, b, c); 302 CREATE TABLE def(d, e, f); 303 INSERT INTO abc VALUES('i', 'ii', 'iii'); 304 INSERT INTO def VALUES('I', 'II', 'III'); 305 } 306} {} 307do_test shared-$av.4.2.2 { 308 execsql { 309 SELECT * FROM test.abc; 310 } db2 311} {i ii iii} 312 313# Open a read-transaction and read from table abc via handle 2. Check that 314# handle 1 can read table abc. Check that handle 1 cannot modify table abc 315# or the database schema. Then check that handle 1 can modify table def. 316# 317do_test shared-$av.4.3.1 { 318 execsql { 319 BEGIN; 320 SELECT * FROM test.abc; 321 } db2 322} {i ii iii} 323do_test shared-$av.4.3.2 { 324 catchsql { 325 INSERT INTO abc VALUES('iv', 'v', 'vi'); 326 } 327} {1 {database table is locked: abc}} 328do_test shared-$av.4.3.3 { 329 catchsql { 330 CREATE TABLE ghi(g, h, i); 331 } 332} {1 {database table is locked: sqlite_master}} 333do_test shared-$av.4.3.3 { 334 catchsql { 335 INSERT INTO def VALUES('IV', 'V', 'VI'); 336 } 337} {0 {}} 338do_test shared-$av.4.3.4 { 339 # Cleanup: commit the transaction opened by db2. 340 execsql { 341 COMMIT 342 } db2 343} {} 344 345# Open a write-transaction using handle 1 and modify the database schema. 346# Then try to execute a compiled statement to read from the same 347# database via handle 2 (fails to get the lock on sqlite_master). Also 348# try to compile a read of the same database using handle 2 (also fails). 349# Finally, compile a read of the other database using handle 2. This 350# should also fail. 351# 352ifcapable compound { 353 do_test shared-$av.4.4.1.2 { 354 # Sanity check 1: Check that the schema is what we think it is when viewed 355 # via handle 1. 356 execsql { 357 CREATE TABLE test2.ghi(g, h, i); 358 SELECT 'test.db:'||name FROM sqlite_master 359 UNION ALL 360 SELECT 'test2.db:'||name FROM test2.sqlite_master; 361 } 362 } {test.db:abc test.db:def test2.db:ghi} 363 do_test shared-$av.4.4.1.2 { 364 # Sanity check 2: Check that the schema is what we think it is when viewed 365 # via handle 2. 366 execsql { 367 SELECT 'test2.db:'||name FROM sqlite_master 368 UNION ALL 369 SELECT 'test.db:'||name FROM test.sqlite_master; 370 } db2 371 } {test2.db:ghi test.db:abc test.db:def} 372} 373 374do_test shared-$av.4.4.2 { 375 set ::DB2 [sqlite3_connection_pointer db2] 376 set sql {SELECT * FROM abc} 377 set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY] 378 execsql { 379 BEGIN; 380 CREATE TABLE jkl(j, k, l); 381 } 382 sqlite3_step $::STMT1 383} {SQLITE_ERROR} 384do_test shared-$av.4.4.3 { 385 sqlite3_finalize $::STMT1 386} {SQLITE_LOCKED} 387do_test shared-$av.4.4.4 { 388 set rc [catch { 389 set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY] 390 } msg] 391 list $rc $msg 392} {1 {(6) database schema is locked: test}} 393do_test shared-$av.4.4.5 { 394 set rc [catch { 395 set ::STMT1 [sqlite3_prepare $::DB2 "SELECT * FROM ghi" -1 DUMMY] 396 } msg] 397 list $rc $msg 398} {1 {(6) database schema is locked: test}} 399 400 401catch {db2 close} 402catch {db close} 403 404#-------------------------------------------------------------------------- 405# Tests shared-5.* 406# 407foreach db [list test.db test1.db test2.db test3.db] { 408 file delete -force $db ${db}-journal 409} 410do_test shared-$av.5.1.1 { 411 sqlite3 db1 test.db 412 sqlite3 db2 test.db 413 execsql { 414 ATTACH 'test1.db' AS test1; 415 ATTACH 'test2.db' AS test2; 416 ATTACH 'test3.db' AS test3; 417 } db1 418 execsql { 419 ATTACH 'test3.db' AS test3; 420 ATTACH 'test2.db' AS test2; 421 ATTACH 'test1.db' AS test1; 422 } db2 423} {} 424do_test shared-$av.5.1.2 { 425 execsql { 426 CREATE TABLE test1.t1(a, b); 427 CREATE INDEX test1.i1 ON t1(a, b); 428 } db1 429} {} 430ifcapable view { 431 do_test shared-$av.5.1.3 { 432 execsql { 433 CREATE VIEW test1.v1 AS SELECT * FROM t1; 434 } db1 435 } {} 436} 437ifcapable trigger { 438 do_test shared-$av.5.1.4 { 439 execsql { 440 CREATE TRIGGER test1.trig1 AFTER INSERT ON t1 BEGIN 441 INSERT INTO t1 VALUES(new.a, new.b); 442 END; 443 } db1 444 } {} 445} 446do_test shared-$av.5.1.5 { 447 execsql { 448 DROP INDEX i1; 449 } db2 450} {} 451ifcapable view { 452 do_test shared-$av.5.1.6 { 453 execsql { 454 DROP VIEW v1; 455 } db2 456 } {} 457} 458ifcapable trigger { 459 do_test shared-$av.5.1.7 { 460 execsql { 461 DROP TRIGGER trig1; 462 } db2 463 } {} 464} 465do_test shared-$av.5.1.8 { 466 execsql { 467 DROP TABLE t1; 468 } db2 469} {} 470ifcapable compound { 471 do_test shared-$av.5.1.9 { 472 execsql { 473 SELECT * FROM sqlite_master UNION ALL SELECT * FROM test1.sqlite_master 474 } db1 475 } {} 476} 477 478#-------------------------------------------------------------------------- 479# Tests shared-6.* test that a query obtains all the read-locks it needs 480# before starting execution of the query. This means that there is no chance 481# some rows of data will be returned before a lock fails and SQLITE_LOCK 482# is returned. 483# 484do_test shared-$av.6.1.1 { 485 execsql { 486 CREATE TABLE t1(a, b); 487 CREATE TABLE t2(a, b); 488 INSERT INTO t1 VALUES(1, 2); 489 INSERT INTO t2 VALUES(3, 4); 490 } db1 491} {} 492ifcapable compound { 493 do_test shared-$av.6.1.2 { 494 execsql { 495 SELECT * FROM t1 UNION ALL SELECT * FROM t2; 496 } db2 497 } {1 2 3 4} 498} 499do_test shared-$av.6.1.3 { 500 # Establish a write lock on table t2 via connection db2. Then make a 501 # UNION all query using connection db1 that first accesses t1, followed 502 # by t2. If the locks are grabbed at the start of the statement (as 503 # they should be), no rows are returned. If (as was previously the case) 504 # they are grabbed as the tables are accessed, the t1 rows will be 505 # returned before the query fails. 506 # 507 execsql { 508 BEGIN; 509 INSERT INTO t2 VALUES(5, 6); 510 } db2 511 set ret [list] 512 catch { 513 db1 eval {SELECT * FROM t1 UNION ALL SELECT * FROM t2} { 514 lappend ret $a $b 515 } 516 } 517 set ret 518} {} 519do_test shared-$av.6.1.4 { 520 execsql { 521 COMMIT; 522 BEGIN; 523 INSERT INTO t1 VALUES(7, 8); 524 } db2 525 set ret [list] 526 catch { 527 db1 eval { 528 SELECT (CASE WHEN a>4 THEN (SELECT a FROM t1) ELSE 0 END) AS d FROM t2; 529 } { 530 lappend ret $d 531 } 532 } 533 set ret 534} {} 535 536catch {db1 close} 537catch {db2 close} 538foreach f [list test.db test2.db] { 539 file delete -force $f ${f}-journal 540} 541 542#-------------------------------------------------------------------------- 543# Tests shared-7.* test auto-vacuum does not invalidate cursors from 544# other shared-cache users when it reorganizes the database on 545# COMMIT. 546# 547do_test shared-$av.7.1 { 548 # This test case sets up a test database in auto-vacuum mode consisting 549 # of two tables, t1 and t2. Both have a single index. Table t1 is 550 # populated first (so consists of pages toward the start of the db file), 551 # t2 second (pages toward the end of the file). 552 sqlite3 db test.db 553 sqlite3 db2 test.db 554 execsql { 555 BEGIN; 556 CREATE TABLE t1(a PRIMARY KEY, b); 557 CREATE TABLE t2(a PRIMARY KEY, b); 558 } 559 set ::contents {} 560 for {set i 0} {$i < 100} {incr i} { 561 set a [string repeat "$i " 20] 562 set b [string repeat "$i " 20] 563 db eval { 564 INSERT INTO t1 VALUES(:a, :b); 565 } 566 lappend ::contents [list [expr $i+1] $a $b] 567 } 568 execsql { 569 INSERT INTO t2 SELECT * FROM t1; 570 COMMIT; 571 } 572} {} 573do_test shared-$av.7.2 { 574 # This test case deletes the contents of table t1 (the one at the start of 575 # the file) while many cursors are open on table t2 and it's index. All of 576 # the non-root pages will be moved from the end to the start of the file 577 # when the DELETE is committed - this test verifies that moving the pages 578 # does not disturb the open cursors. 579 # 580 581 proc lockrow {db tbl oids body} { 582 set ret [list] 583 db eval "SELECT oid AS i, a, b FROM $tbl ORDER BY a" { 584 if {$i==[lindex $oids 0]} { 585 set noids [lrange $oids 1 end] 586 if {[llength $noids]==0} { 587 set subret [eval $body] 588 } else { 589 set subret [lockrow $db $tbl $noids $body] 590 } 591 } 592 lappend ret [list $i $a $b] 593 } 594 return [linsert $subret 0 $ret] 595 } 596 proc locktblrows {db tbl body} { 597 set oids [db eval "SELECT oid FROM $tbl"] 598 lockrow $db $tbl $oids $body 599 } 600 601 set scans [locktblrows db t2 { 602 execsql { 603 DELETE FROM t1; 604 } db2 605 }] 606 set error 0 607 608 # Test that each SELECT query returned the expected contents of t2. 609 foreach s $scans { 610 if {[lsort -integer -index 0 $s]!=$::contents} { 611 set error 1 612 } 613 } 614 set error 615} {0} 616 617catch {db close} 618catch {db2 close} 619unset -nocomplain contents 620 621#-------------------------------------------------------------------------- 622# The following tests try to trick the shared-cache code into assuming 623# the wrong encoding for a database. 624# 625file delete -force test.db test.db-journal 626ifcapable utf16 { 627 do_test shared-$av.8.1.1 { 628 sqlite3 db test.db 629 execsql { 630 PRAGMA encoding = 'UTF-16'; 631 SELECT * FROM sqlite_master; 632 } 633 } {} 634 do_test shared-$av.8.1.2 { 635 string range [execsql {PRAGMA encoding;}] 0 end-2 636 } {UTF-16} 637 do_test shared-$av.8.1.3 { 638 sqlite3 db2 test.db 639 execsql { 640 PRAGMA encoding = 'UTF-8'; 641 CREATE TABLE abc(a, b, c); 642 } db2 643 } {} 644 do_test shared-$av.8.1.4 { 645 execsql { 646 SELECT * FROM sqlite_master; 647 } 648 } "table abc abc [expr $AUTOVACUUM?3:2] {CREATE TABLE abc(a, b, c)}" 649 do_test shared-$av.8.1.5 { 650 db2 close 651 execsql { 652 PRAGMA encoding; 653 } 654 } {UTF-8} 655 file delete -force test2.db test2.db-journal 656 do_test shared-$av.8.2.1 { 657 execsql { 658 ATTACH 'test2.db' AS aux; 659 SELECT * FROM aux.sqlite_master; 660 } 661 } {} 662 do_test shared-$av.8.2.2 { 663 sqlite3 db2 test2.db 664 execsql { 665 PRAGMA encoding = 'UTF-16'; 666 CREATE TABLE def(d, e, f); 667 } db2 668 string range [execsql {PRAGMA encoding;} db2] 0 end-2 669 } {UTF-16} 670 do_test shared-$av.8.2.3 { 671 catchsql { 672 SELECT * FROM aux.sqlite_master; 673 } 674 } {1 {attached databases must use the same text encoding as main database}} 675} 676 677catch {db close} 678catch {db2 close} 679file delete -force test.db test2.db 680 681#--------------------------------------------------------------------------- 682# The following tests - shared-9.* - test interactions between TEMP triggers 683# and shared-schemas. 684# 685ifcapable trigger&&tempdb { 686 687do_test shared-$av.9.1 { 688 sqlite3 db test.db 689 sqlite3 db2 test.db 690 execsql { 691 CREATE TABLE abc(a, b, c); 692 CREATE TABLE abc_mirror(a, b, c); 693 CREATE TEMP TRIGGER BEFORE INSERT ON abc BEGIN 694 INSERT INTO abc_mirror(a, b, c) VALUES(new.a, new.b, new.c); 695 END; 696 INSERT INTO abc VALUES(1, 2, 3); 697 SELECT * FROM abc_mirror; 698 } 699} {1 2 3} 700do_test shared-$av.9.2 { 701 execsql { 702 INSERT INTO abc VALUES(4, 5, 6); 703 SELECT * FROM abc_mirror; 704 } db2 705} {1 2 3} 706do_test shared-$av.9.3 { 707 db close 708 db2 close 709} {} 710 711} ; # End shared-9.* 712 713#--------------------------------------------------------------------------- 714# The following tests - shared-10.* - test that the library behaves 715# correctly when a connection to a shared-cache is closed. 716# 717do_test shared-$av.10.1 { 718 # Create a small sample database with two connections to it (db and db2). 719 file delete -force test.db 720 sqlite3 db test.db 721 sqlite3 db2 test.db 722 execsql { 723 CREATE TABLE ab(a PRIMARY KEY, b); 724 CREATE TABLE de(d PRIMARY KEY, e); 725 INSERT INTO ab VALUES('Chiang Mai', 100000); 726 INSERT INTO ab VALUES('Bangkok', 8000000); 727 INSERT INTO de VALUES('Ubon', 120000); 728 INSERT INTO de VALUES('Khon Kaen', 200000); 729 } 730} {} 731do_test shared-$av.10.2 { 732 # Open a read-transaction with the first connection, a write-transaction 733 # with the second. 734 execsql { 735 BEGIN; 736 SELECT * FROM ab; 737 } 738 execsql { 739 BEGIN; 740 INSERT INTO de VALUES('Pataya', 30000); 741 } db2 742} {} 743do_test shared-$av.10.3 { 744 # An external connection should be able to read the database, but not 745 # prepare a write operation. 746 if {$::tcl_platform(platform)=="unix"} { 747 sqlite3 db3 ./test.db 748 } else { 749 sqlite3 db3 TEST.DB 750 } 751 execsql { 752 SELECT * FROM ab; 753 } db3 754 catchsql { 755 BEGIN; 756 INSERT INTO de VALUES('Pataya', 30000); 757 } db3 758} {1 {database is locked}} 759do_test shared-$av.10.4 { 760 # Close the connection with the write-transaction open 761 db2 close 762} {} 763do_test shared-$av.10.5 { 764 # Test that the db2 transaction has been automatically rolled back. 765 # If it has not the ('Pataya', 30000) entry will still be in the table. 766 execsql { 767 SELECT * FROM de; 768 } 769} {Ubon 120000 {Khon Kaen} 200000} 770do_test shared-$av.10.5 { 771 # Closing db2 should have dropped the shared-cache back to a read-lock. 772 # So db3 should be able to prepare a write... 773 catchsql {INSERT INTO de VALUES('Pataya', 30000);} db3 774} {0 {}} 775do_test shared-$av.10.6 { 776 # ... but not commit it. 777 catchsql {COMMIT} db3 778} {1 {database is locked}} 779do_test shared-$av.10.7 { 780 # Commit the (read-only) db transaction. Check via db3 to make sure the 781 # contents of table "de" are still as they should be. 782 execsql { 783 COMMIT; 784 } 785 execsql { 786 SELECT * FROM de; 787 } db3 788} {Ubon 120000 {Khon Kaen} 200000 Pataya 30000} 789do_test shared-$av.10.9 { 790 # Commit the external transaction. 791 catchsql {COMMIT} db3 792} {0 {}} 793integrity_check shared-$av.10.10 794do_test shared-$av.10.11 { 795 db close 796 db3 close 797} {} 798 799do_test shared-$av.11.1 { 800 file delete -force test.db 801 sqlite3 db test.db 802 sqlite3 db2 test.db 803 execsql { 804 CREATE TABLE abc(a, b, c); 805 CREATE TABLE abc2(a, b, c); 806 BEGIN; 807 INSERT INTO abc VALUES(1, 2, 3); 808 } 809} {} 810do_test shared-$av.11.2 { 811 catchsql {BEGIN;} db2 812 catchsql {SELECT * FROM abc;} db2 813} {1 {database table is locked: abc}} 814do_test shared-$av.11.3 { 815 catchsql {BEGIN} db2 816} {1 {cannot start a transaction within a transaction}} 817do_test shared-$av.11.4 { 818 catchsql {SELECT * FROM abc2;} db2 819} {0 {}} 820do_test shared-$av.11.5 { 821 catchsql {INSERT INTO abc2 VALUES(1, 2, 3);} db2 822} {1 {database is locked}} 823do_test shared-$av.11.6 { 824 catchsql {SELECT * FROM abc2} 825} {0 {}} 826do_test shared-$av.11.6 { 827 execsql { 828 ROLLBACK; 829 PRAGMA read_uncommitted = 1; 830 } db2 831} {} 832do_test shared-$av.11.7 { 833 execsql { 834 INSERT INTO abc2 VALUES(4, 5, 6); 835 INSERT INTO abc2 VALUES(7, 8, 9); 836 } 837} {} 838do_test shared-$av.11.8 { 839 set res [list] 840 breakpoint 841 db2 eval { 842 SELECT abc.a as I, abc2.a as II FROM abc, abc2; 843 } { 844 execsql { 845 DELETE FROM abc WHERE 1; 846 } 847 lappend res $I $II 848 } 849 set res 850} {1 4 {} 7} 851 852do_test shared-$av.11.11 { 853 db close 854 db2 close 855} {} 856 857} 858 859sqlite3_enable_shared_cache $::enable_shared_cache 860finish_test 861