1aef0bf64Sdanielk1977# 2005 December 30 2aef0bf64Sdanielk1977# 3aef0bf64Sdanielk1977# The author disclaims copyright to this source code. In place of 4aef0bf64Sdanielk1977# a legal notice, here is a blessing: 5aef0bf64Sdanielk1977# 6aef0bf64Sdanielk1977# May you do good and not evil. 7aef0bf64Sdanielk1977# May you find forgiveness for yourself and forgive others. 8aef0bf64Sdanielk1977# May you share freely, never taking more than you give. 9aef0bf64Sdanielk1977# 10aef0bf64Sdanielk1977#*********************************************************************** 11aef0bf64Sdanielk1977# 12404ca075Sdanielk1977# $Id: shared.test,v 1.36 2009/03/16 13:19:36 danielk1977 Exp $ 13aef0bf64Sdanielk1977 14aef0bf64Sdanielk1977set testdir [file dirname $argv0] 15aef0bf64Sdanielk1977source $testdir/tester.tcl 16aef0bf64Sdanielk1977db close 17aef0bf64Sdanielk1977 185a8f9374Sdanielk1977# These tests cannot be run without the ATTACH command. 195a8f9374Sdanielk1977# 205a8f9374Sdanielk1977ifcapable !shared_cache||!attach { 21aef0bf64Sdanielk1977 finish_test 22aef0bf64Sdanielk1977 return 23aef0bf64Sdanielk1977} 24a96a7103Sdanielk1977 25da184236Sdanielk1977set ::enable_shared_cache [sqlite3_enable_shared_cache 1] 26aef0bf64Sdanielk1977 27a96a7103Sdanielk1977foreach av [list 0 1] { 28a96a7103Sdanielk1977 29a96a7103Sdanielk1977# Open the database connection and execute the auto-vacuum pragma 30fda06befSmistachkinforcedelete test.db 31a96a7103Sdanielk1977sqlite3 db test.db 32bab45c64Sdanielk1977 33bab45c64Sdanielk1977ifcapable autovacuum { 34bab45c64Sdanielk1977 do_test shared-[expr $av+1].1.0 { 35a96a7103Sdanielk1977 execsql "pragma auto_vacuum=$::av" 36a96a7103Sdanielk1977 execsql {pragma auto_vacuum} 37a96a7103Sdanielk1977 } "$av" 38bab45c64Sdanielk1977} else { 39bab45c64Sdanielk1977 if {$av} { 40bab45c64Sdanielk1977 db close 41bab45c64Sdanielk1977 break 42bab45c64Sdanielk1977 } 43bab45c64Sdanielk1977} 44bab45c64Sdanielk1977 45aebf413dSaswift# if we're using proxy locks, we use 2 filedescriptors for a db 46aebf413dSaswift# that is open but NOT yet locked, after a lock is taken we'll have 3, 47aebf413dSaswift# normally sqlite uses 1 (proxy locking adds the conch and the local lock) 48aebf413dSaswiftset using_proxy 0 49aebf413dSaswiftforeach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] { 50aebf413dSaswift set using_proxy $value 51aebf413dSaswift} 52aebf413dSaswiftset extrafds_prelock 0 53aebf413dSaswiftset extrafds_postlock 0 54aebf413dSaswiftif {$using_proxy>0} { 55aebf413dSaswift set extrafds_prelock 1 56aebf413dSaswift set extrafds_postlock 2 57aebf413dSaswift} 58aebf413dSaswift 59191c3e7dSdanielk1977# $av is currently 0 if this loop iteration is to test with auto-vacuum turned 60191c3e7dSdanielk1977# off, and 1 if it is turned on. Increment it so that (1 -> no auto-vacuum) 61191c3e7dSdanielk1977# and (2 -> auto-vacuum). The sole reason for this is so that it looks nicer 62191c3e7dSdanielk1977# when we use this variable as part of test-case names. 63191c3e7dSdanielk1977# 64a96a7103Sdanielk1977incr av 65a96a7103Sdanielk1977 66aef0bf64Sdanielk1977# Test organization: 67aef0bf64Sdanielk1977# 68aef0bf64Sdanielk1977# shared-1.*: Simple test to verify basic sanity of table level locking when 69aef0bf64Sdanielk1977# two connections share a pager cache. 70aef0bf64Sdanielk1977# shared-2.*: Test that a read transaction can co-exist with a 71aef0bf64Sdanielk1977# write-transaction, including a simple test to ensure the 72aef0bf64Sdanielk1977# external locking protocol is still working. 73da184236Sdanielk1977# shared-3.*: Simple test of read-uncommitted mode. 74de0fe3e4Sdanielk1977# shared-4.*: Check that the schema is locked and unlocked correctly. 75aaf22685Sdanielk1977# shared-5.*: Test that creating/dropping schema items works when databases 76aaf22685Sdanielk1977# are attached in different orders to different handles. 77c00da105Sdanielk1977# shared-6.*: Locking, UNION ALL queries and sub-queries. 7814db2665Sdanielk1977# shared-7.*: Autovacuum and shared-cache. 79ed429311Sdanielk1977# shared-8.*: Tests related to the text encoding of shared-cache databases. 80ed429311Sdanielk1977# shared-9.*: TEMP triggers and shared-cache databases. 81ed429311Sdanielk1977# shared-10.*: Tests of sqlite3_close(). 824b202ae2Sdanielk1977# shared-11.*: Test transaction locking. 83de0fe3e4Sdanielk1977# 84aef0bf64Sdanielk1977 85a96a7103Sdanielk1977do_test shared-$av.1.1 { 86aef0bf64Sdanielk1977 # Open a second database on the file test.db. It should use the same pager 87aef0bf64Sdanielk1977 # cache and schema as the original connection. Verify that only 1 file is 88aef0bf64Sdanielk1977 # opened. 89aef0bf64Sdanielk1977 sqlite3 db2 test.db 90aef0bf64Sdanielk1977 set ::sqlite_open_file_count 91aebf413dSaswift expr $sqlite_open_file_count-$extrafds_postlock 92aef0bf64Sdanielk1977} {1} 93a96a7103Sdanielk1977do_test shared-$av.1.2 { 94aef0bf64Sdanielk1977 # Add a table and a single row of data via the first connection. 95aef0bf64Sdanielk1977 # Ensure that the second connection can see them. 96aef0bf64Sdanielk1977 execsql { 97aef0bf64Sdanielk1977 CREATE TABLE abc(a, b, c); 98aef0bf64Sdanielk1977 INSERT INTO abc VALUES(1, 2, 3); 99aef0bf64Sdanielk1977 } db 100aef0bf64Sdanielk1977 execsql { 101aef0bf64Sdanielk1977 SELECT * FROM abc; 102aef0bf64Sdanielk1977 } db2 103aef0bf64Sdanielk1977} {1 2 3} 104a96a7103Sdanielk1977do_test shared-$av.1.3 { 105aef0bf64Sdanielk1977 # Have the first connection begin a transaction and obtain a read-lock 106aef0bf64Sdanielk1977 # on table abc. This should not prevent the second connection from 107aef0bf64Sdanielk1977 # querying abc. 108aef0bf64Sdanielk1977 execsql { 109aef0bf64Sdanielk1977 BEGIN; 110aef0bf64Sdanielk1977 SELECT * FROM abc; 111aef0bf64Sdanielk1977 } 112aef0bf64Sdanielk1977 execsql { 113aef0bf64Sdanielk1977 SELECT * FROM abc; 114aef0bf64Sdanielk1977 } db2 115aef0bf64Sdanielk1977} {1 2 3} 116a96a7103Sdanielk1977do_test shared-$av.1.4 { 117aef0bf64Sdanielk1977 # Try to insert a row into abc via connection 2. This should fail because 118aef0bf64Sdanielk1977 # of the read-lock connection 1 is holding on table abc (obtained in the 119aef0bf64Sdanielk1977 # previous test case). 120aef0bf64Sdanielk1977 catchsql { 121aef0bf64Sdanielk1977 INSERT INTO abc VALUES(4, 5, 6); 122aef0bf64Sdanielk1977 } db2 123c00da105Sdanielk1977} {1 {database table is locked: abc}} 124a96a7103Sdanielk1977do_test shared-$av.1.5 { 125da184236Sdanielk1977 # Using connection 2 (the one without the open transaction), try to create 126da184236Sdanielk1977 # a new table. This should fail because of the open read transaction 127da184236Sdanielk1977 # held by connection 1. 128da184236Sdanielk1977 catchsql { 129da184236Sdanielk1977 CREATE TABLE def(d, e, f); 130da184236Sdanielk1977 } db2 131c00da105Sdanielk1977} {1 {database table is locked: sqlite_master}} 132a96a7103Sdanielk1977do_test shared-$av.1.6 { 133da184236Sdanielk1977 # Upgrade connection 1's transaction to a write transaction. Create 134da184236Sdanielk1977 # a new table - def - and insert a row into it. Because the connection 1 135da184236Sdanielk1977 # transaction modifies the schema, it should not be possible for 136da184236Sdanielk1977 # connection 2 to access the database at all until the connection 1 137da184236Sdanielk1977 # has finished the transaction. 138aef0bf64Sdanielk1977 execsql { 139aef0bf64Sdanielk1977 CREATE TABLE def(d, e, f); 140aef0bf64Sdanielk1977 INSERT INTO def VALUES('IV', 'V', 'VI'); 141aef0bf64Sdanielk1977 } 142aef0bf64Sdanielk1977} {} 143a96a7103Sdanielk1977do_test shared-$av.1.7 { 144aef0bf64Sdanielk1977 # Read from the sqlite_master table with connection 1 (inside the 145da184236Sdanielk1977 # transaction). Then test that we can not do this with connection 2. This 146da184236Sdanielk1977 # is because of the schema-modified lock established by connection 1 147da184236Sdanielk1977 # in the previous test case. 148aef0bf64Sdanielk1977 execsql { 149aef0bf64Sdanielk1977 SELECT * FROM sqlite_master; 150aef0bf64Sdanielk1977 } 151aef0bf64Sdanielk1977 catchsql { 152aef0bf64Sdanielk1977 SELECT * FROM sqlite_master; 153aef0bf64Sdanielk1977 } db2 154c87d34d0Sdanielk1977} {1 {database schema is locked: main}} 155a96a7103Sdanielk1977do_test shared-$av.1.8 { 156aef0bf64Sdanielk1977 # Commit the connection 1 transaction. 157aef0bf64Sdanielk1977 execsql { 158aef0bf64Sdanielk1977 COMMIT; 159aef0bf64Sdanielk1977 } 160aef0bf64Sdanielk1977} {} 161aef0bf64Sdanielk1977 162a96a7103Sdanielk1977do_test shared-$av.2.1 { 163*7f42dcd9Sdrh # Open connection db3 to the database. 164c693e9e6Sdrh if {$::tcl_platform(platform)=="unix"} { 165*7f42dcd9Sdrh sqlite3 db3 "file:test.db?cache=private" -uri 1 166c693e9e6Sdrh } else { 167c693e9e6Sdrh sqlite3 db3 TEST.DB 168c693e9e6Sdrh } 169aef0bf64Sdanielk1977 set ::sqlite_open_file_count 170aebf413dSaswift expr $sqlite_open_file_count-($extrafds_prelock+$extrafds_postlock) 171aef0bf64Sdanielk1977} {2} 172a96a7103Sdanielk1977do_test shared-$av.2.2 { 173aef0bf64Sdanielk1977 # Start read transactions on db and db2 (the shared pager cache). Ensure 174aef0bf64Sdanielk1977 # db3 cannot write to the database. 175aef0bf64Sdanielk1977 execsql { 176aef0bf64Sdanielk1977 BEGIN; 177aef0bf64Sdanielk1977 SELECT * FROM abc; 178aef0bf64Sdanielk1977 } 179aef0bf64Sdanielk1977 execsql { 180aef0bf64Sdanielk1977 BEGIN; 181aef0bf64Sdanielk1977 SELECT * FROM abc; 182aef0bf64Sdanielk1977 } db2 183aef0bf64Sdanielk1977 catchsql { 184aef0bf64Sdanielk1977 INSERT INTO abc VALUES(1, 2, 3); 185aef0bf64Sdanielk1977 } db2 186c00da105Sdanielk1977} {1 {database table is locked: abc}} 187a96a7103Sdanielk1977do_test shared-$av.2.3 { 188aef0bf64Sdanielk1977 # Turn db's transaction into a write-transaction. db3 should still be 189aef0bf64Sdanielk1977 # able to read from table def (but will not see the new row). Connection 190aef0bf64Sdanielk1977 # db2 should not be able to read def (because of the write-lock). 191aef0bf64Sdanielk1977 192aef0bf64Sdanielk1977# Todo: The failed "INSERT INTO abc ..." statement in the above test 193aef0bf64Sdanielk1977# has started a write-transaction on db2 (should this be so?). This 194aef0bf64Sdanielk1977# would prevent connection db from starting a write-transaction. So roll the 195aef0bf64Sdanielk1977# db2 transaction back and replace it with a new read transaction. 196aef0bf64Sdanielk1977 execsql { 197aef0bf64Sdanielk1977 ROLLBACK; 198aef0bf64Sdanielk1977 BEGIN; 199aef0bf64Sdanielk1977 SELECT * FROM abc; 200aef0bf64Sdanielk1977 } db2 201aef0bf64Sdanielk1977 202aef0bf64Sdanielk1977 execsql { 203aef0bf64Sdanielk1977 INSERT INTO def VALUES('VII', 'VIII', 'IX'); 204aef0bf64Sdanielk1977 } 205aef0bf64Sdanielk1977 concat [ 206aef0bf64Sdanielk1977 catchsql { SELECT * FROM def; } db3 207aef0bf64Sdanielk1977 ] [ 208aef0bf64Sdanielk1977 catchsql { SELECT * FROM def; } db2 209aef0bf64Sdanielk1977 ] 210c00da105Sdanielk1977} {0 {IV V VI} 1 {database table is locked: def}} 211a96a7103Sdanielk1977do_test shared-$av.2.4 { 212aef0bf64Sdanielk1977 # Commit the open transaction on db. db2 still holds a read-transaction. 213aef0bf64Sdanielk1977 # This should prevent db3 from writing to the database, but not from 214aef0bf64Sdanielk1977 # reading. 215aef0bf64Sdanielk1977 execsql { 216aef0bf64Sdanielk1977 COMMIT; 217aef0bf64Sdanielk1977 } 218aef0bf64Sdanielk1977 concat [ 219aef0bf64Sdanielk1977 catchsql { SELECT * FROM def; } db3 220aef0bf64Sdanielk1977 ] [ 221aef0bf64Sdanielk1977 catchsql { INSERT INTO def VALUES('X', 'XI', 'XII'); } db3 222aef0bf64Sdanielk1977 ] 223da184236Sdanielk1977} {0 {IV V VI VII VIII IX} 1 {database is locked}} 224aef0bf64Sdanielk1977 225da184236Sdanielk1977catchsql COMMIT db2 226da184236Sdanielk1977 227a96a7103Sdanielk1977do_test shared-$av.3.1.1 { 228da184236Sdanielk1977 # This test case starts a linear scan of table 'seq' using a 229da184236Sdanielk1977 # read-uncommitted connection. In the middle of the scan, rows are added 230da184236Sdanielk1977 # to the end of the seq table (ahead of the current cursor position). 231da184236Sdanielk1977 # The uncommitted rows should be included in the results of the scan. 232da184236Sdanielk1977 execsql " 233191c3e7dSdanielk1977 CREATE TABLE seq(i PRIMARY KEY, x); 234da184236Sdanielk1977 INSERT INTO seq VALUES(1, '[string repeat X 500]'); 235da184236Sdanielk1977 INSERT INTO seq VALUES(2, '[string repeat X 500]'); 236da184236Sdanielk1977 " 237da184236Sdanielk1977 execsql {SELECT * FROM sqlite_master} db2 238da184236Sdanielk1977 execsql {PRAGMA read_uncommitted = 1} db2 239da184236Sdanielk1977 240da184236Sdanielk1977 set ret [list] 241191c3e7dSdanielk1977 db2 eval {SELECT i FROM seq ORDER BY i} { 242da184236Sdanielk1977 if {$i < 4} { 2431576cd92Sdanielk1977 set max [execsql {SELECT max(i) FROM seq}] 2441576cd92Sdanielk1977 db eval { 2453bdca9c9Sdanielk1977 INSERT INTO seq SELECT i + :max, x FROM seq; 246da184236Sdanielk1977 } 247da184236Sdanielk1977 } 248da184236Sdanielk1977 lappend ret $i 249da184236Sdanielk1977 } 250da184236Sdanielk1977 set ret 251da184236Sdanielk1977} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16} 252a96a7103Sdanielk1977do_test shared-$av.3.1.2 { 253da184236Sdanielk1977 # Another linear scan through table seq using a read-uncommitted connection. 254da184236Sdanielk1977 # This time, delete each row as it is read. Should not affect the results of 255da184236Sdanielk1977 # the scan, but the table should be empty after the scan is concluded 256da184236Sdanielk1977 # (test 3.1.3 verifies this). 257da184236Sdanielk1977 set ret [list] 258da184236Sdanielk1977 db2 eval {SELECT i FROM seq} { 2593bdca9c9Sdanielk1977 db eval {DELETE FROM seq WHERE i = :i} 260da184236Sdanielk1977 lappend ret $i 261da184236Sdanielk1977 } 262da184236Sdanielk1977 set ret 263da184236Sdanielk1977} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16} 264a96a7103Sdanielk1977do_test shared-$av.3.1.3 { 265da184236Sdanielk1977 execsql { 266da184236Sdanielk1977 SELECT * FROM seq; 267da184236Sdanielk1977 } 268da184236Sdanielk1977} {} 269aef0bf64Sdanielk1977 270aef0bf64Sdanielk1977catch {db close} 271aef0bf64Sdanielk1977catch {db2 close} 272aef0bf64Sdanielk1977catch {db3 close} 273aef0bf64Sdanielk1977 274de0fe3e4Sdanielk1977#-------------------------------------------------------------------------- 275de0fe3e4Sdanielk1977# Tests shared-4.* test that the schema locking rules are applied 276de0fe3e4Sdanielk1977# correctly. i.e.: 277de0fe3e4Sdanielk1977# 278de0fe3e4Sdanielk1977# 1. All transactions require a read-lock on the schemas of databases they 279de0fe3e4Sdanielk1977# access. 280de0fe3e4Sdanielk1977# 2. Transactions that modify a database schema require a write-lock on that 281de0fe3e4Sdanielk1977# schema. 282de0fe3e4Sdanielk1977# 3. It is not possible to compile a statement while another handle has a 283de0fe3e4Sdanielk1977# write-lock on the schema. 284de0fe3e4Sdanielk1977# 285de0fe3e4Sdanielk1977 286de0fe3e4Sdanielk1977# Open two database handles db and db2. Each has a single attach database 287de0fe3e4Sdanielk1977# (as well as main): 288de0fe3e4Sdanielk1977# 289de0fe3e4Sdanielk1977# db.main -> ./test.db 290de0fe3e4Sdanielk1977# db.test2 -> ./test2.db 291de0fe3e4Sdanielk1977# db2.main -> ./test2.db 292de0fe3e4Sdanielk1977# db2.test -> ./test.db 293de0fe3e4Sdanielk1977# 294fda06befSmistachkinforcedelete test.db 295fda06befSmistachkinforcedelete test2.db 296fda06befSmistachkinforcedelete test2.db-journal 297de0fe3e4Sdanielk1977sqlite3 db test.db 298de0fe3e4Sdanielk1977sqlite3 db2 test2.db 299a96a7103Sdanielk1977do_test shared-$av.4.1.1 { 300de0fe3e4Sdanielk1977 set sqlite_open_file_count 301aebf413dSaswift expr $sqlite_open_file_count-($extrafds_prelock*2) 302de0fe3e4Sdanielk1977} {2} 303a96a7103Sdanielk1977do_test shared-$av.4.1.2 { 304de0fe3e4Sdanielk1977 execsql {ATTACH 'test2.db' AS test2} 305de0fe3e4Sdanielk1977 set sqlite_open_file_count 306aebf413dSaswift expr $sqlite_open_file_count-($extrafds_postlock*2) 307de0fe3e4Sdanielk1977} {2} 308a96a7103Sdanielk1977do_test shared-$av.4.1.3 { 309de0fe3e4Sdanielk1977 execsql {ATTACH 'test.db' AS test} db2 310de0fe3e4Sdanielk1977 set sqlite_open_file_count 311aebf413dSaswift expr $sqlite_open_file_count-($extrafds_postlock*2) 312de0fe3e4Sdanielk1977} {2} 313de0fe3e4Sdanielk1977 314c87d34d0Sdanielk1977# Sanity check: Create a table in ./test.db via handle db, and test that handle 315c87d34d0Sdanielk1977# db2 can "see" the new table immediately. A handle using a seperate pager 316c87d34d0Sdanielk1977# cache would have to reload the database schema before this were possible. 317c87d34d0Sdanielk1977# 318a96a7103Sdanielk1977do_test shared-$av.4.2.1 { 319de0fe3e4Sdanielk1977 execsql { 320de0fe3e4Sdanielk1977 CREATE TABLE abc(a, b, c); 321c87d34d0Sdanielk1977 CREATE TABLE def(d, e, f); 322de0fe3e4Sdanielk1977 INSERT INTO abc VALUES('i', 'ii', 'iii'); 323c87d34d0Sdanielk1977 INSERT INTO def VALUES('I', 'II', 'III'); 324de0fe3e4Sdanielk1977 } 325de0fe3e4Sdanielk1977} {} 326a96a7103Sdanielk1977do_test shared-$av.4.2.2 { 327de0fe3e4Sdanielk1977 execsql { 328de0fe3e4Sdanielk1977 SELECT * FROM test.abc; 329de0fe3e4Sdanielk1977 } db2 330de0fe3e4Sdanielk1977} {i ii iii} 331de0fe3e4Sdanielk1977 332c87d34d0Sdanielk1977# Open a read-transaction and read from table abc via handle 2. Check that 333c87d34d0Sdanielk1977# handle 1 can read table abc. Check that handle 1 cannot modify table abc 334c87d34d0Sdanielk1977# or the database schema. Then check that handle 1 can modify table def. 335c87d34d0Sdanielk1977# 336a96a7103Sdanielk1977do_test shared-$av.4.3.1 { 337c87d34d0Sdanielk1977 execsql { 338c87d34d0Sdanielk1977 BEGIN; 339c87d34d0Sdanielk1977 SELECT * FROM test.abc; 340c87d34d0Sdanielk1977 } db2 341c87d34d0Sdanielk1977} {i ii iii} 342a96a7103Sdanielk1977do_test shared-$av.4.3.2 { 343c87d34d0Sdanielk1977 catchsql { 344c87d34d0Sdanielk1977 INSERT INTO abc VALUES('iv', 'v', 'vi'); 345c87d34d0Sdanielk1977 } 346c00da105Sdanielk1977} {1 {database table is locked: abc}} 347a96a7103Sdanielk1977do_test shared-$av.4.3.3 { 348c87d34d0Sdanielk1977 catchsql { 349c87d34d0Sdanielk1977 CREATE TABLE ghi(g, h, i); 350c87d34d0Sdanielk1977 } 351c00da105Sdanielk1977} {1 {database table is locked: sqlite_master}} 352a96a7103Sdanielk1977do_test shared-$av.4.3.3 { 353c87d34d0Sdanielk1977 catchsql { 354c87d34d0Sdanielk1977 INSERT INTO def VALUES('IV', 'V', 'VI'); 355c87d34d0Sdanielk1977 } 356c87d34d0Sdanielk1977} {0 {}} 357a96a7103Sdanielk1977do_test shared-$av.4.3.4 { 358c87d34d0Sdanielk1977 # Cleanup: commit the transaction opened by db2. 359c87d34d0Sdanielk1977 execsql { 360c87d34d0Sdanielk1977 COMMIT 361c87d34d0Sdanielk1977 } db2 362c87d34d0Sdanielk1977} {} 363c87d34d0Sdanielk1977 364c87d34d0Sdanielk1977# Open a write-transaction using handle 1 and modify the database schema. 365c87d34d0Sdanielk1977# Then try to execute a compiled statement to read from the same 366c87d34d0Sdanielk1977# database via handle 2 (fails to get the lock on sqlite_master). Also 367c87d34d0Sdanielk1977# try to compile a read of the same database using handle 2 (also fails). 368c87d34d0Sdanielk1977# Finally, compile a read of the other database using handle 2. This 369c87d34d0Sdanielk1977# should also fail. 370c87d34d0Sdanielk1977# 371ff890793Sdanielk1977ifcapable compound { 372a96a7103Sdanielk1977 do_test shared-$av.4.4.1.2 { 373c87d34d0Sdanielk1977 # Sanity check 1: Check that the schema is what we think it is when viewed 374c87d34d0Sdanielk1977 # via handle 1. 375c87d34d0Sdanielk1977 execsql { 376c87d34d0Sdanielk1977 CREATE TABLE test2.ghi(g, h, i); 377c87d34d0Sdanielk1977 SELECT 'test.db:'||name FROM sqlite_master 378c87d34d0Sdanielk1977 UNION ALL 379c87d34d0Sdanielk1977 SELECT 'test2.db:'||name FROM test2.sqlite_master; 380c87d34d0Sdanielk1977 } 381c87d34d0Sdanielk1977 } {test.db:abc test.db:def test2.db:ghi} 382a96a7103Sdanielk1977 do_test shared-$av.4.4.1.2 { 383c87d34d0Sdanielk1977 # Sanity check 2: Check that the schema is what we think it is when viewed 384c87d34d0Sdanielk1977 # via handle 2. 385c87d34d0Sdanielk1977 execsql { 386c87d34d0Sdanielk1977 SELECT 'test2.db:'||name FROM sqlite_master 387c87d34d0Sdanielk1977 UNION ALL 388c87d34d0Sdanielk1977 SELECT 'test.db:'||name FROM test.sqlite_master; 389c87d34d0Sdanielk1977 } db2 390c87d34d0Sdanielk1977 } {test2.db:ghi test.db:abc test.db:def} 391ff890793Sdanielk1977} 392c87d34d0Sdanielk1977 393a96a7103Sdanielk1977do_test shared-$av.4.4.2 { 394c87d34d0Sdanielk1977 set ::DB2 [sqlite3_connection_pointer db2] 395c87d34d0Sdanielk1977 set sql {SELECT * FROM abc} 396c87d34d0Sdanielk1977 set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY] 397c87d34d0Sdanielk1977 execsql { 398c87d34d0Sdanielk1977 BEGIN; 399c87d34d0Sdanielk1977 CREATE TABLE jkl(j, k, l); 400c87d34d0Sdanielk1977 } 401c87d34d0Sdanielk1977 sqlite3_step $::STMT1 402c87d34d0Sdanielk1977} {SQLITE_ERROR} 403a96a7103Sdanielk1977do_test shared-$av.4.4.3 { 404c87d34d0Sdanielk1977 sqlite3_finalize $::STMT1 405c87d34d0Sdanielk1977} {SQLITE_LOCKED} 406a96a7103Sdanielk1977do_test shared-$av.4.4.4 { 407c87d34d0Sdanielk1977 set rc [catch { 408c87d34d0Sdanielk1977 set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY] 409c87d34d0Sdanielk1977 } msg] 410c87d34d0Sdanielk1977 list $rc $msg 411c87d34d0Sdanielk1977} {1 {(6) database schema is locked: test}} 412a96a7103Sdanielk1977do_test shared-$av.4.4.5 { 413c87d34d0Sdanielk1977 set rc [catch { 414c87d34d0Sdanielk1977 set ::STMT1 [sqlite3_prepare $::DB2 "SELECT * FROM ghi" -1 DUMMY] 415c87d34d0Sdanielk1977 } msg] 416c87d34d0Sdanielk1977 list $rc $msg 417c87d34d0Sdanielk1977} {1 {(6) database schema is locked: test}} 418c87d34d0Sdanielk1977 419aaf22685Sdanielk1977 420de0fe3e4Sdanielk1977catch {db2 close} 421de0fe3e4Sdanielk1977catch {db close} 422de0fe3e4Sdanielk1977 423aaf22685Sdanielk1977#-------------------------------------------------------------------------- 424aaf22685Sdanielk1977# Tests shared-5.* 425aaf22685Sdanielk1977# 426aaf22685Sdanielk1977foreach db [list test.db test1.db test2.db test3.db] { 427fda06befSmistachkin forcedelete $db ${db}-journal 428aaf22685Sdanielk1977} 429a96a7103Sdanielk1977do_test shared-$av.5.1.1 { 430aaf22685Sdanielk1977 sqlite3 db1 test.db 431aaf22685Sdanielk1977 sqlite3 db2 test.db 432aaf22685Sdanielk1977 execsql { 433aaf22685Sdanielk1977 ATTACH 'test1.db' AS test1; 434aaf22685Sdanielk1977 ATTACH 'test2.db' AS test2; 435aaf22685Sdanielk1977 ATTACH 'test3.db' AS test3; 436aaf22685Sdanielk1977 } db1 437aaf22685Sdanielk1977 execsql { 438aaf22685Sdanielk1977 ATTACH 'test3.db' AS test3; 439aaf22685Sdanielk1977 ATTACH 'test2.db' AS test2; 440aaf22685Sdanielk1977 ATTACH 'test1.db' AS test1; 441aaf22685Sdanielk1977 } db2 442aaf22685Sdanielk1977} {} 443a96a7103Sdanielk1977do_test shared-$av.5.1.2 { 444aaf22685Sdanielk1977 execsql { 445aaf22685Sdanielk1977 CREATE TABLE test1.t1(a, b); 446aaf22685Sdanielk1977 CREATE INDEX test1.i1 ON t1(a, b); 4473bdca9c9Sdanielk1977 } db1 4483bdca9c9Sdanielk1977} {} 4493bdca9c9Sdanielk1977ifcapable view { 4503bdca9c9Sdanielk1977 do_test shared-$av.5.1.3 { 4513bdca9c9Sdanielk1977 execsql { 452aaf22685Sdanielk1977 CREATE VIEW test1.v1 AS SELECT * FROM t1; 4533bdca9c9Sdanielk1977 } db1 4543bdca9c9Sdanielk1977 } {} 4553bdca9c9Sdanielk1977} 4563bdca9c9Sdanielk1977ifcapable trigger { 4573bdca9c9Sdanielk1977 do_test shared-$av.5.1.4 { 4583bdca9c9Sdanielk1977 execsql { 459aaf22685Sdanielk1977 CREATE TRIGGER test1.trig1 AFTER INSERT ON t1 BEGIN 460aaf22685Sdanielk1977 INSERT INTO t1 VALUES(new.a, new.b); 461aaf22685Sdanielk1977 END; 462aaf22685Sdanielk1977 } db1 4633bdca9c9Sdanielk1977 } {} 4643bdca9c9Sdanielk1977} 4653bdca9c9Sdanielk1977do_test shared-$av.5.1.5 { 466aaf22685Sdanielk1977 execsql { 467aaf22685Sdanielk1977 DROP INDEX i1; 4683bdca9c9Sdanielk1977 } db2 4693bdca9c9Sdanielk1977} {} 4703bdca9c9Sdanielk1977ifcapable view { 4713bdca9c9Sdanielk1977 do_test shared-$av.5.1.6 { 4723bdca9c9Sdanielk1977 execsql { 473aaf22685Sdanielk1977 DROP VIEW v1; 4743bdca9c9Sdanielk1977 } db2 4753bdca9c9Sdanielk1977 } {} 4763bdca9c9Sdanielk1977} 4773bdca9c9Sdanielk1977ifcapable trigger { 4783bdca9c9Sdanielk1977 do_test shared-$av.5.1.7 { 4793bdca9c9Sdanielk1977 execsql { 480aaf22685Sdanielk1977 DROP TRIGGER trig1; 4813bdca9c9Sdanielk1977 } db2 4823bdca9c9Sdanielk1977 } {} 4833bdca9c9Sdanielk1977} 4843bdca9c9Sdanielk1977do_test shared-$av.5.1.8 { 4853bdca9c9Sdanielk1977 execsql { 486aaf22685Sdanielk1977 DROP TABLE t1; 487aaf22685Sdanielk1977 } db2 488aaf22685Sdanielk1977} {} 489ff890793Sdanielk1977ifcapable compound { 4903bdca9c9Sdanielk1977 do_test shared-$av.5.1.9 { 491aaf22685Sdanielk1977 execsql { 492aaf22685Sdanielk1977 SELECT * FROM sqlite_master UNION ALL SELECT * FROM test1.sqlite_master 493aaf22685Sdanielk1977 } db1 494aaf22685Sdanielk1977 } {} 495ff890793Sdanielk1977} 496aaf22685Sdanielk1977 497c00da105Sdanielk1977#-------------------------------------------------------------------------- 498c00da105Sdanielk1977# Tests shared-6.* test that a query obtains all the read-locks it needs 499c00da105Sdanielk1977# before starting execution of the query. This means that there is no chance 500c00da105Sdanielk1977# some rows of data will be returned before a lock fails and SQLITE_LOCK 501c00da105Sdanielk1977# is returned. 502c00da105Sdanielk1977# 503a96a7103Sdanielk1977do_test shared-$av.6.1.1 { 504c00da105Sdanielk1977 execsql { 505c00da105Sdanielk1977 CREATE TABLE t1(a, b); 506c00da105Sdanielk1977 CREATE TABLE t2(a, b); 507c00da105Sdanielk1977 INSERT INTO t1 VALUES(1, 2); 508c00da105Sdanielk1977 INSERT INTO t2 VALUES(3, 4); 509c00da105Sdanielk1977 } db1 510ff890793Sdanielk1977} {} 511ff890793Sdanielk1977ifcapable compound { 512ff890793Sdanielk1977 do_test shared-$av.6.1.2 { 513c00da105Sdanielk1977 execsql { 514c00da105Sdanielk1977 SELECT * FROM t1 UNION ALL SELECT * FROM t2; 515c00da105Sdanielk1977 } db2 516c00da105Sdanielk1977 } {1 2 3 4} 517ff890793Sdanielk1977} 518ff890793Sdanielk1977do_test shared-$av.6.1.3 { 519c00da105Sdanielk1977 # Establish a write lock on table t2 via connection db2. Then make a 520c00da105Sdanielk1977 # UNION all query using connection db1 that first accesses t1, followed 521c00da105Sdanielk1977 # by t2. If the locks are grabbed at the start of the statement (as 522c00da105Sdanielk1977 # they should be), no rows are returned. If (as was previously the case) 523c00da105Sdanielk1977 # they are grabbed as the tables are accessed, the t1 rows will be 524c00da105Sdanielk1977 # returned before the query fails. 525c00da105Sdanielk1977 # 526c00da105Sdanielk1977 execsql { 527c00da105Sdanielk1977 BEGIN; 528c00da105Sdanielk1977 INSERT INTO t2 VALUES(5, 6); 529c00da105Sdanielk1977 } db2 530c00da105Sdanielk1977 set ret [list] 531c00da105Sdanielk1977 catch { 532c00da105Sdanielk1977 db1 eval {SELECT * FROM t1 UNION ALL SELECT * FROM t2} { 533c00da105Sdanielk1977 lappend ret $a $b 534c00da105Sdanielk1977 } 535c00da105Sdanielk1977 } 536c00da105Sdanielk1977 set ret 537c00da105Sdanielk1977} {} 538ff890793Sdanielk1977do_test shared-$av.6.1.4 { 539c00da105Sdanielk1977 execsql { 540c00da105Sdanielk1977 COMMIT; 541c00da105Sdanielk1977 BEGIN; 542c00da105Sdanielk1977 INSERT INTO t1 VALUES(7, 8); 543c00da105Sdanielk1977 } db2 544c00da105Sdanielk1977 set ret [list] 545c00da105Sdanielk1977 catch { 546c00da105Sdanielk1977 db1 eval { 547c00da105Sdanielk1977 SELECT (CASE WHEN a>4 THEN (SELECT a FROM t1) ELSE 0 END) AS d FROM t2; 548c00da105Sdanielk1977 } { 549c00da105Sdanielk1977 lappend ret $d 550c00da105Sdanielk1977 } 551c00da105Sdanielk1977 } 552c00da105Sdanielk1977 set ret 553c00da105Sdanielk1977} {} 554c00da105Sdanielk1977 555aaf22685Sdanielk1977catch {db1 close} 556aaf22685Sdanielk1977catch {db2 close} 557e501b89aSdanielk1977foreach f [list test.db test2.db] { 558fda06befSmistachkin forcedelete $f ${f}-journal 559e501b89aSdanielk1977} 560e501b89aSdanielk1977 561e501b89aSdanielk1977#-------------------------------------------------------------------------- 562e501b89aSdanielk1977# Tests shared-7.* test auto-vacuum does not invalidate cursors from 563e501b89aSdanielk1977# other shared-cache users when it reorganizes the database on 564e501b89aSdanielk1977# COMMIT. 565e501b89aSdanielk1977# 566a96a7103Sdanielk1977do_test shared-$av.7.1 { 56714db2665Sdanielk1977 # This test case sets up a test database in auto-vacuum mode consisting 56814db2665Sdanielk1977 # of two tables, t1 and t2. Both have a single index. Table t1 is 56914db2665Sdanielk1977 # populated first (so consists of pages toward the start of the db file), 57014db2665Sdanielk1977 # t2 second (pages toward the end of the file). 571e501b89aSdanielk1977 sqlite3 db test.db 572e501b89aSdanielk1977 sqlite3 db2 test.db 573e501b89aSdanielk1977 execsql { 574e501b89aSdanielk1977 BEGIN; 575e501b89aSdanielk1977 CREATE TABLE t1(a PRIMARY KEY, b); 576e501b89aSdanielk1977 CREATE TABLE t2(a PRIMARY KEY, b); 577e501b89aSdanielk1977 } 5787a91dd86Sdrh set ::contents {} 579e501b89aSdanielk1977 for {set i 0} {$i < 100} {incr i} { 580e501b89aSdanielk1977 set a [string repeat "$i " 20] 581e501b89aSdanielk1977 set b [string repeat "$i " 20] 582e501b89aSdanielk1977 db eval { 5833bdca9c9Sdanielk1977 INSERT INTO t1 VALUES(:a, :b); 584e501b89aSdanielk1977 } 585e501b89aSdanielk1977 lappend ::contents [list [expr $i+1] $a $b] 586e501b89aSdanielk1977 } 587e501b89aSdanielk1977 execsql { 588e501b89aSdanielk1977 INSERT INTO t2 SELECT * FROM t1; 589e501b89aSdanielk1977 COMMIT; 590e501b89aSdanielk1977 } 591bab45c64Sdanielk1977} {} 592a96a7103Sdanielk1977do_test shared-$av.7.2 { 59314db2665Sdanielk1977 # This test case deletes the contents of table t1 (the one at the start of 59485b623f2Sdrh # the file) while many cursors are open on table t2 and its index. All of 59514db2665Sdanielk1977 # the non-root pages will be moved from the end to the start of the file 59614db2665Sdanielk1977 # when the DELETE is committed - this test verifies that moving the pages 59714db2665Sdanielk1977 # does not disturb the open cursors. 59814db2665Sdanielk1977 # 59914db2665Sdanielk1977 600e501b89aSdanielk1977 proc lockrow {db tbl oids body} { 601e501b89aSdanielk1977 set ret [list] 602e501b89aSdanielk1977 db eval "SELECT oid AS i, a, b FROM $tbl ORDER BY a" { 603e501b89aSdanielk1977 if {$i==[lindex $oids 0]} { 604e501b89aSdanielk1977 set noids [lrange $oids 1 end] 605e501b89aSdanielk1977 if {[llength $noids]==0} { 606e501b89aSdanielk1977 set subret [eval $body] 607e501b89aSdanielk1977 } else { 608e501b89aSdanielk1977 set subret [lockrow $db $tbl $noids $body] 609e501b89aSdanielk1977 } 610e501b89aSdanielk1977 } 611e501b89aSdanielk1977 lappend ret [list $i $a $b] 612e501b89aSdanielk1977 } 613e501b89aSdanielk1977 return [linsert $subret 0 $ret] 614e501b89aSdanielk1977 } 615e501b89aSdanielk1977 proc locktblrows {db tbl body} { 616e501b89aSdanielk1977 set oids [db eval "SELECT oid FROM $tbl"] 617e501b89aSdanielk1977 lockrow $db $tbl $oids $body 618e501b89aSdanielk1977 } 619e501b89aSdanielk1977 620e501b89aSdanielk1977 set scans [locktblrows db t2 { 621e501b89aSdanielk1977 execsql { 622e501b89aSdanielk1977 DELETE FROM t1; 623e501b89aSdanielk1977 } db2 624e501b89aSdanielk1977 }] 625e501b89aSdanielk1977 set error 0 62614db2665Sdanielk1977 62714db2665Sdanielk1977 # Test that each SELECT query returned the expected contents of t2. 628e501b89aSdanielk1977 foreach s $scans { 629e501b89aSdanielk1977 if {[lsort -integer -index 0 $s]!=$::contents} { 630e501b89aSdanielk1977 set error 1 631e501b89aSdanielk1977 } 632e501b89aSdanielk1977 } 633e501b89aSdanielk1977 set error 634e501b89aSdanielk1977} {0} 635e501b89aSdanielk1977 636e501b89aSdanielk1977catch {db close} 637e501b89aSdanielk1977catch {db2 close} 6387a91dd86Sdrhunset -nocomplain contents 639aaf22685Sdanielk1977 64014db2665Sdanielk1977#-------------------------------------------------------------------------- 64114db2665Sdanielk1977# The following tests try to trick the shared-cache code into assuming 64214db2665Sdanielk1977# the wrong encoding for a database. 64314db2665Sdanielk1977# 644fda06befSmistachkinforcedelete test.db test.db-journal 6453bdca9c9Sdanielk1977ifcapable utf16 { 646a96a7103Sdanielk1977 do_test shared-$av.8.1.1 { 64714db2665Sdanielk1977 sqlite3 db test.db 64814db2665Sdanielk1977 execsql { 64914db2665Sdanielk1977 PRAGMA encoding = 'UTF-16'; 65014db2665Sdanielk1977 SELECT * FROM sqlite_master; 65114db2665Sdanielk1977 } 65214db2665Sdanielk1977 } {} 653a96a7103Sdanielk1977 do_test shared-$av.8.1.2 { 65414db2665Sdanielk1977 string range [execsql {PRAGMA encoding;}] 0 end-2 65514db2665Sdanielk1977 } {UTF-16} 656f51bf48bSdanielk1977 657a96a7103Sdanielk1977 do_test shared-$av.8.1.3 { 65814db2665Sdanielk1977 sqlite3 db2 test.db 65914db2665Sdanielk1977 execsql { 66014db2665Sdanielk1977 PRAGMA encoding = 'UTF-8'; 66114db2665Sdanielk1977 CREATE TABLE abc(a, b, c); 66214db2665Sdanielk1977 } db2 66314db2665Sdanielk1977 } {} 664a96a7103Sdanielk1977 do_test shared-$av.8.1.4 { 66514db2665Sdanielk1977 execsql { 66614db2665Sdanielk1977 SELECT * FROM sqlite_master; 66714db2665Sdanielk1977 } 66814db2665Sdanielk1977 } "table abc abc [expr $AUTOVACUUM?3:2] {CREATE TABLE abc(a, b, c)}" 669a96a7103Sdanielk1977 do_test shared-$av.8.1.5 { 67014db2665Sdanielk1977 db2 close 67114db2665Sdanielk1977 execsql { 67214db2665Sdanielk1977 PRAGMA encoding; 67314db2665Sdanielk1977 } 67414db2665Sdanielk1977 } {UTF-8} 675f51bf48bSdanielk1977 676fda06befSmistachkin forcedelete test2.db test2.db-journal 677a96a7103Sdanielk1977 do_test shared-$av.8.2.1 { 67814db2665Sdanielk1977 execsql { 67914db2665Sdanielk1977 ATTACH 'test2.db' AS aux; 68014db2665Sdanielk1977 SELECT * FROM aux.sqlite_master; 68114db2665Sdanielk1977 } 68214db2665Sdanielk1977 } {} 683a96a7103Sdanielk1977 do_test shared-$av.8.2.2 { 68414db2665Sdanielk1977 sqlite3 db2 test2.db 68514db2665Sdanielk1977 execsql { 68614db2665Sdanielk1977 PRAGMA encoding = 'UTF-16'; 68714db2665Sdanielk1977 CREATE TABLE def(d, e, f); 68814db2665Sdanielk1977 } db2 68914db2665Sdanielk1977 string range [execsql {PRAGMA encoding;} db2] 0 end-2 69014db2665Sdanielk1977 } {UTF-16} 691d42f8fdcSdanielk1977 692f51bf48bSdanielk1977 catch {db close} 693f51bf48bSdanielk1977 catch {db2 close} 694fda06befSmistachkin forcedelete test.db test2.db 695f51bf48bSdanielk1977 696f51bf48bSdanielk1977 do_test shared-$av.8.3.2 { 697f51bf48bSdanielk1977 sqlite3 db test.db 698f51bf48bSdanielk1977 execsql { CREATE TABLE def(d, e, f) } 699f51bf48bSdanielk1977 execsql { PRAGMA encoding } 700f51bf48bSdanielk1977 } {UTF-8} 701f51bf48bSdanielk1977 do_test shared-$av.8.3.3 { 702f51bf48bSdanielk1977 set zDb16 "[encoding convertto unicode test.db]\x00\x00" 703f51bf48bSdanielk1977 set db16 [sqlite3_open16 $zDb16 {}] 704f51bf48bSdanielk1977 705f51bf48bSdanielk1977 set stmt [sqlite3_prepare $db16 "SELECT sql FROM sqlite_master" -1 DUMMY] 706f51bf48bSdanielk1977 sqlite3_step $stmt 707f51bf48bSdanielk1977 set sql [sqlite3_column_text $stmt 0] 708f51bf48bSdanielk1977 sqlite3_finalize $stmt 709f51bf48bSdanielk1977 set sql 710f51bf48bSdanielk1977 } {CREATE TABLE def(d, e, f)} 711f51bf48bSdanielk1977 do_test shared-$av.8.3.4 { 712f51bf48bSdanielk1977 set stmt [sqlite3_prepare $db16 "PRAGMA encoding" -1 DUMMY] 713f51bf48bSdanielk1977 sqlite3_step $stmt 714f51bf48bSdanielk1977 set enc [sqlite3_column_text $stmt 0] 715f51bf48bSdanielk1977 sqlite3_finalize $stmt 716f51bf48bSdanielk1977 set enc 717f51bf48bSdanielk1977 } {UTF-8} 718f51bf48bSdanielk1977 719f51bf48bSdanielk1977 sqlite3_close $db16 720f51bf48bSdanielk1977 721d42f8fdcSdanielk1977# Bug #2547 is causing this to fail. 722d42f8fdcSdanielk1977if 0 { 723a96a7103Sdanielk1977 do_test shared-$av.8.2.3 { 72414db2665Sdanielk1977 catchsql { 72514db2665Sdanielk1977 SELECT * FROM aux.sqlite_master; 72614db2665Sdanielk1977 } 72714db2665Sdanielk1977 } {1 {attached databases must use the same text encoding as main database}} 7283bdca9c9Sdanielk1977} 729d42f8fdcSdanielk1977} 73014db2665Sdanielk1977 73114db2665Sdanielk1977catch {db close} 73214db2665Sdanielk1977catch {db2 close} 733fda06befSmistachkinforcedelete test.db test2.db 734eecfb3eeSdanielk1977 735eecfb3eeSdanielk1977#--------------------------------------------------------------------------- 736eecfb3eeSdanielk1977# The following tests - shared-9.* - test interactions between TEMP triggers 737eecfb3eeSdanielk1977# and shared-schemas. 738eecfb3eeSdanielk1977# 739eecfb3eeSdanielk1977ifcapable trigger&&tempdb { 740eecfb3eeSdanielk1977 741a96a7103Sdanielk1977do_test shared-$av.9.1 { 742eecfb3eeSdanielk1977 sqlite3 db test.db 743eecfb3eeSdanielk1977 sqlite3 db2 test.db 744eecfb3eeSdanielk1977 execsql { 745eecfb3eeSdanielk1977 CREATE TABLE abc(a, b, c); 746eecfb3eeSdanielk1977 CREATE TABLE abc_mirror(a, b, c); 747eecfb3eeSdanielk1977 CREATE TEMP TRIGGER BEFORE INSERT ON abc BEGIN 748eecfb3eeSdanielk1977 INSERT INTO abc_mirror(a, b, c) VALUES(new.a, new.b, new.c); 749eecfb3eeSdanielk1977 END; 750eecfb3eeSdanielk1977 INSERT INTO abc VALUES(1, 2, 3); 751eecfb3eeSdanielk1977 SELECT * FROM abc_mirror; 752eecfb3eeSdanielk1977 } 753eecfb3eeSdanielk1977} {1 2 3} 754a96a7103Sdanielk1977do_test shared-$av.9.2 { 755eecfb3eeSdanielk1977 execsql { 756eecfb3eeSdanielk1977 INSERT INTO abc VALUES(4, 5, 6); 757eecfb3eeSdanielk1977 SELECT * FROM abc_mirror; 758eecfb3eeSdanielk1977 } db2 759eecfb3eeSdanielk1977} {1 2 3} 760a96a7103Sdanielk1977do_test shared-$av.9.3 { 761eecfb3eeSdanielk1977 db close 762eecfb3eeSdanielk1977 db2 close 763eecfb3eeSdanielk1977} {} 764eecfb3eeSdanielk1977 765eecfb3eeSdanielk1977} ; # End shared-9.* 76614db2665Sdanielk1977 767b597f74aSdanielk1977#--------------------------------------------------------------------------- 768b597f74aSdanielk1977# The following tests - shared-10.* - test that the library behaves 769b597f74aSdanielk1977# correctly when a connection to a shared-cache is closed. 770b597f74aSdanielk1977# 771a96a7103Sdanielk1977do_test shared-$av.10.1 { 772b597f74aSdanielk1977 # Create a small sample database with two connections to it (db and db2). 773fda06befSmistachkin forcedelete test.db 774b597f74aSdanielk1977 sqlite3 db test.db 775b597f74aSdanielk1977 sqlite3 db2 test.db 776b597f74aSdanielk1977 execsql { 777b597f74aSdanielk1977 CREATE TABLE ab(a PRIMARY KEY, b); 778b597f74aSdanielk1977 CREATE TABLE de(d PRIMARY KEY, e); 779b597f74aSdanielk1977 INSERT INTO ab VALUES('Chiang Mai', 100000); 780b597f74aSdanielk1977 INSERT INTO ab VALUES('Bangkok', 8000000); 781b597f74aSdanielk1977 INSERT INTO de VALUES('Ubon', 120000); 782b597f74aSdanielk1977 INSERT INTO de VALUES('Khon Kaen', 200000); 783b597f74aSdanielk1977 } 784b597f74aSdanielk1977} {} 785a96a7103Sdanielk1977do_test shared-$av.10.2 { 786b597f74aSdanielk1977 # Open a read-transaction with the first connection, a write-transaction 787b597f74aSdanielk1977 # with the second. 788b597f74aSdanielk1977 execsql { 789b597f74aSdanielk1977 BEGIN; 790b597f74aSdanielk1977 SELECT * FROM ab; 791b597f74aSdanielk1977 } 792b597f74aSdanielk1977 execsql { 793b597f74aSdanielk1977 BEGIN; 794b597f74aSdanielk1977 INSERT INTO de VALUES('Pataya', 30000); 795b597f74aSdanielk1977 } db2 796b597f74aSdanielk1977} {} 797a96a7103Sdanielk1977do_test shared-$av.10.3 { 798b597f74aSdanielk1977 # An external connection should be able to read the database, but not 799b597f74aSdanielk1977 # prepare a write operation. 800c693e9e6Sdrh if {$::tcl_platform(platform)=="unix"} { 801*7f42dcd9Sdrh sqlite3 db3 "file:test.db?cache=private" -uri 1 802c693e9e6Sdrh } else { 803c693e9e6Sdrh sqlite3 db3 TEST.DB 804c693e9e6Sdrh } 805b597f74aSdanielk1977 execsql { 806b597f74aSdanielk1977 SELECT * FROM ab; 807b597f74aSdanielk1977 } db3 808b597f74aSdanielk1977 catchsql { 809b597f74aSdanielk1977 BEGIN; 810b597f74aSdanielk1977 INSERT INTO de VALUES('Pataya', 30000); 811b597f74aSdanielk1977 } db3 812b597f74aSdanielk1977} {1 {database is locked}} 813a96a7103Sdanielk1977do_test shared-$av.10.4 { 814b597f74aSdanielk1977 # Close the connection with the write-transaction open 815b597f74aSdanielk1977 db2 close 816b597f74aSdanielk1977} {} 817a96a7103Sdanielk1977do_test shared-$av.10.5 { 818b597f74aSdanielk1977 # Test that the db2 transaction has been automatically rolled back. 819b597f74aSdanielk1977 # If it has not the ('Pataya', 30000) entry will still be in the table. 820b597f74aSdanielk1977 execsql { 821b597f74aSdanielk1977 SELECT * FROM de; 822b597f74aSdanielk1977 } 823b597f74aSdanielk1977} {Ubon 120000 {Khon Kaen} 200000} 824a96a7103Sdanielk1977do_test shared-$av.10.5 { 825b597f74aSdanielk1977 # Closing db2 should have dropped the shared-cache back to a read-lock. 826b597f74aSdanielk1977 # So db3 should be able to prepare a write... 827b597f74aSdanielk1977 catchsql {INSERT INTO de VALUES('Pataya', 30000);} db3 828b597f74aSdanielk1977} {0 {}} 829a96a7103Sdanielk1977do_test shared-$av.10.6 { 830b597f74aSdanielk1977 # ... but not commit it. 831b597f74aSdanielk1977 catchsql {COMMIT} db3 832b597f74aSdanielk1977} {1 {database is locked}} 833a96a7103Sdanielk1977do_test shared-$av.10.7 { 834b597f74aSdanielk1977 # Commit the (read-only) db transaction. Check via db3 to make sure the 835b597f74aSdanielk1977 # contents of table "de" are still as they should be. 836b597f74aSdanielk1977 execsql { 837b597f74aSdanielk1977 COMMIT; 838b597f74aSdanielk1977 } 839b597f74aSdanielk1977 execsql { 840b597f74aSdanielk1977 SELECT * FROM de; 841b597f74aSdanielk1977 } db3 842b597f74aSdanielk1977} {Ubon 120000 {Khon Kaen} 200000 Pataya 30000} 843a96a7103Sdanielk1977do_test shared-$av.10.9 { 844b597f74aSdanielk1977 # Commit the external transaction. 845b597f74aSdanielk1977 catchsql {COMMIT} db3 846b597f74aSdanielk1977} {0 {}} 847a96a7103Sdanielk1977integrity_check shared-$av.10.10 848a96a7103Sdanielk1977do_test shared-$av.10.11 { 849b597f74aSdanielk1977 db close 850b597f74aSdanielk1977 db3 close 851b597f74aSdanielk1977} {} 852b597f74aSdanielk1977 8534b202ae2Sdanielk1977do_test shared-$av.11.1 { 854fda06befSmistachkin forcedelete test.db 8554b202ae2Sdanielk1977 sqlite3 db test.db 8564b202ae2Sdanielk1977 sqlite3 db2 test.db 8574b202ae2Sdanielk1977 execsql { 8584b202ae2Sdanielk1977 CREATE TABLE abc(a, b, c); 8594b202ae2Sdanielk1977 CREATE TABLE abc2(a, b, c); 8604b202ae2Sdanielk1977 BEGIN; 8614b202ae2Sdanielk1977 INSERT INTO abc VALUES(1, 2, 3); 8624b202ae2Sdanielk1977 } 8634b202ae2Sdanielk1977} {} 8644b202ae2Sdanielk1977do_test shared-$av.11.2 { 8654b202ae2Sdanielk1977 catchsql {BEGIN;} db2 8664b202ae2Sdanielk1977 catchsql {SELECT * FROM abc;} db2 8674b202ae2Sdanielk1977} {1 {database table is locked: abc}} 8684b202ae2Sdanielk1977do_test shared-$av.11.3 { 8694b202ae2Sdanielk1977 catchsql {BEGIN} db2 8704b202ae2Sdanielk1977} {1 {cannot start a transaction within a transaction}} 8714b202ae2Sdanielk1977do_test shared-$av.11.4 { 8724b202ae2Sdanielk1977 catchsql {SELECT * FROM abc2;} db2 8734b202ae2Sdanielk1977} {0 {}} 8744b202ae2Sdanielk1977do_test shared-$av.11.5 { 8754b202ae2Sdanielk1977 catchsql {INSERT INTO abc2 VALUES(1, 2, 3);} db2 876404ca075Sdanielk1977} {1 {database table is locked}} 8774b202ae2Sdanielk1977do_test shared-$av.11.6 { 8784b202ae2Sdanielk1977 catchsql {SELECT * FROM abc2} 8794b202ae2Sdanielk1977} {0 {}} 8804b202ae2Sdanielk1977do_test shared-$av.11.6 { 8814b202ae2Sdanielk1977 execsql { 8824b202ae2Sdanielk1977 ROLLBACK; 8834b202ae2Sdanielk1977 PRAGMA read_uncommitted = 1; 8844b202ae2Sdanielk1977 } db2 8854b202ae2Sdanielk1977} {} 8864b202ae2Sdanielk1977do_test shared-$av.11.7 { 8874b202ae2Sdanielk1977 execsql { 8884b202ae2Sdanielk1977 INSERT INTO abc2 VALUES(4, 5, 6); 8894b202ae2Sdanielk1977 INSERT INTO abc2 VALUES(7, 8, 9); 8904b202ae2Sdanielk1977 } 8914b202ae2Sdanielk1977} {} 8924b202ae2Sdanielk1977do_test shared-$av.11.8 { 8934b202ae2Sdanielk1977 set res [list] 8944b202ae2Sdanielk1977 db2 eval { 8954b202ae2Sdanielk1977 SELECT abc.a as I, abc2.a as II FROM abc, abc2; 8964b202ae2Sdanielk1977 } { 8974b202ae2Sdanielk1977 execsql { 8984b202ae2Sdanielk1977 DELETE FROM abc WHERE 1; 8994b202ae2Sdanielk1977 } 9004b202ae2Sdanielk1977 lappend res $I $II 9014b202ae2Sdanielk1977 } 9024b202ae2Sdanielk1977 set res 9034b202ae2Sdanielk1977} {1 4 {} 7} 90416a9b836Sdrhif {[llength [info command sqlite3_shared_cache_report]]==1} { 9054a41f345Smistachkin ifcapable curdir { 9065f9c1a2cSdrh do_test shared-$av.11.9 { 907044d305cSdanielk1977 string tolower [sqlite3_shared_cache_report] 908cf77a45aSshane } [string tolower [list [file nativename [file normalize test.db]] 2]] 9097c4ac0c5Sdrh } 9104a41f345Smistachkin} 9114b202ae2Sdanielk1977 9124b202ae2Sdanielk1977do_test shared-$av.11.11 { 9134b202ae2Sdanielk1977 db close 9144b202ae2Sdanielk1977 db2 close 9154b202ae2Sdanielk1977} {} 9164b202ae2Sdanielk1977 917843e65f2Sdanielk1977# This tests that if it is impossible to free any pages, SQLite will 918843e65f2Sdanielk1977# exceed the limit set by PRAGMA cache_size. 919fda06befSmistachkinforcedelete test.db test.db-journal 920843e65f2Sdanielk1977sqlite3 db test.db 9214152e677Sdanielk1977ifcapable pager_pragmas { 9224152e677Sdanielk1977 do_test shared-$av.12.1 { 923843e65f2Sdanielk1977 execsql { 924843e65f2Sdanielk1977 PRAGMA cache_size = 10; 925843e65f2Sdanielk1977 PRAGMA cache_size; 926843e65f2Sdanielk1977 } 927843e65f2Sdanielk1977 } {10} 9284152e677Sdanielk1977} 929843e65f2Sdanielk1977do_test shared-$av.12.2 { 930843e65f2Sdanielk1977 set ::db_handles [list] 931843e65f2Sdanielk1977 for {set i 1} {$i < 15} {incr i} { 932843e65f2Sdanielk1977 lappend ::db_handles db$i 933843e65f2Sdanielk1977 sqlite3 db$i test.db 934843e65f2Sdanielk1977 execsql "CREATE TABLE db${i}(a, b, c)" db$i 935843e65f2Sdanielk1977 execsql "INSERT INTO db${i} VALUES(1, 2, 3)" 936843e65f2Sdanielk1977 } 937843e65f2Sdanielk1977} {} 938843e65f2Sdanielk1977proc nested_select {handles} { 939843e65f2Sdanielk1977 [lindex $handles 0] eval "SELECT * FROM [lindex $handles 0]" { 940843e65f2Sdanielk1977 lappend ::res $a $b $c 941843e65f2Sdanielk1977 if {[llength $handles]>1} { 942843e65f2Sdanielk1977 nested_select [lrange $handles 1 end] 943843e65f2Sdanielk1977 } 944843e65f2Sdanielk1977 } 945843e65f2Sdanielk1977} 946843e65f2Sdanielk1977do_test shared-$av.12.3 { 947843e65f2Sdanielk1977 set ::res [list] 948843e65f2Sdanielk1977 nested_select $::db_handles 949843e65f2Sdanielk1977 set ::res 950843e65f2Sdanielk1977} [string range [string repeat "1 2 3 " [llength $::db_handles]] 0 end-1] 951843e65f2Sdanielk1977 952843e65f2Sdanielk1977do_test shared-$av.12.X { 953843e65f2Sdanielk1977 db close 954843e65f2Sdanielk1977 foreach h $::db_handles { 955843e65f2Sdanielk1977 $h close 956843e65f2Sdanielk1977 } 957843e65f2Sdanielk1977} {} 958843e65f2Sdanielk1977 959983e2309Sdanielk1977# Internally, locks are acquired on shared B-Tree structures in the order 960983e2309Sdanielk1977# that the structures appear in the virtual memory address space. This 961983e2309Sdanielk1977# test case attempts to cause the order of the structures in memory 962983e2309Sdanielk1977# to be different from the order in which they are attached to a given 963983e2309Sdanielk1977# database handle. This covers an extra line or two. 964983e2309Sdanielk1977# 965983e2309Sdanielk1977do_test shared-$av.13.1 { 966fda06befSmistachkin forcedelete test2.db test3.db test4.db test5.db 967983e2309Sdanielk1977 sqlite3 db :memory: 968983e2309Sdanielk1977 execsql { 969983e2309Sdanielk1977 ATTACH 'test2.db' AS aux2; 970983e2309Sdanielk1977 ATTACH 'test3.db' AS aux3; 971983e2309Sdanielk1977 ATTACH 'test4.db' AS aux4; 972983e2309Sdanielk1977 ATTACH 'test5.db' AS aux5; 973983e2309Sdanielk1977 DETACH aux2; 974983e2309Sdanielk1977 DETACH aux3; 975983e2309Sdanielk1977 DETACH aux4; 976983e2309Sdanielk1977 ATTACH 'test2.db' AS aux2; 977983e2309Sdanielk1977 ATTACH 'test3.db' AS aux3; 978983e2309Sdanielk1977 ATTACH 'test4.db' AS aux4; 979983e2309Sdanielk1977 } 980983e2309Sdanielk1977} {} 981983e2309Sdanielk1977do_test shared-$av.13.2 { 982983e2309Sdanielk1977 execsql { 983983e2309Sdanielk1977 CREATE TABLE t1(a, b, c); 984983e2309Sdanielk1977 CREATE TABLE aux2.t2(a, b, c); 985983e2309Sdanielk1977 CREATE TABLE aux3.t3(a, b, c); 986983e2309Sdanielk1977 CREATE TABLE aux4.t4(a, b, c); 987983e2309Sdanielk1977 CREATE TABLE aux5.t5(a, b, c); 988983e2309Sdanielk1977 SELECT count(*) FROM 989983e2309Sdanielk1977 aux2.sqlite_master, 990983e2309Sdanielk1977 aux3.sqlite_master, 991983e2309Sdanielk1977 aux4.sqlite_master, 992983e2309Sdanielk1977 aux5.sqlite_master 993983e2309Sdanielk1977 } 994983e2309Sdanielk1977} {1} 995983e2309Sdanielk1977do_test shared-$av.13.3 { 996983e2309Sdanielk1977 db close 997983e2309Sdanielk1977} {} 998983e2309Sdanielk1977 999983e2309Sdanielk1977# Test that nothing horrible happens if a connection to a shared B-Tree 1000983e2309Sdanielk1977# structure is closed while some other connection has an open cursor. 1001983e2309Sdanielk1977# 1002983e2309Sdanielk1977do_test shared-$av.14.1 { 1003983e2309Sdanielk1977 sqlite3 db test.db 1004983e2309Sdanielk1977 sqlite3 db2 test.db 1005983e2309Sdanielk1977 execsql {SELECT name FROM sqlite_master} 1006983e2309Sdanielk1977} {db1 db2 db3 db4 db5 db6 db7 db8 db9 db10 db11 db12 db13 db14} 1007983e2309Sdanielk1977do_test shared-$av.14.2 { 1008983e2309Sdanielk1977 set res [list] 1009983e2309Sdanielk1977 db eval {SELECT name FROM sqlite_master} { 1010983e2309Sdanielk1977 if {$name eq "db7"} { 1011983e2309Sdanielk1977 db2 close 1012983e2309Sdanielk1977 } 1013983e2309Sdanielk1977 lappend res $name 1014983e2309Sdanielk1977 } 1015983e2309Sdanielk1977 set res 1016983e2309Sdanielk1977} {db1 db2 db3 db4 db5 db6 db7 db8 db9 db10 db11 db12 db13 db14} 1017983e2309Sdanielk1977do_test shared-$av.14.3 { 1018983e2309Sdanielk1977 db close 1019983e2309Sdanielk1977} {} 1020983e2309Sdanielk1977 10212949e4e8Sdan# Populate a database schema using connection [db]. Then drop it using 10222949e4e8Sdan# [db2]. This is to try to find any points where shared-schema elements 10232949e4e8Sdan# are allocated using the lookaside buffer of [db]. 10242949e4e8Sdan# 10252949e4e8Sdan# Mutexes are enabled for this test as that activates a couple of useful 10262949e4e8Sdan# assert() statements in the C code. 10272949e4e8Sdan# 10282949e4e8Sdando_test shared-$av-15.1 { 1029fda06befSmistachkin forcedelete test.db 10302949e4e8Sdan sqlite3 db test.db -fullmutex 1 10312949e4e8Sdan sqlite3 db2 test.db -fullmutex 1 10322949e4e8Sdan execsql { 10332949e4e8Sdan CREATE TABLE t1(a, b, c); 10342949e4e8Sdan CREATE INDEX i1 ON t1(a, b); 10352949e4e8Sdan CREATE VIEW v1 AS SELECT * FROM t1; 10362949e4e8Sdan CREATE VIEW v2 AS SELECT * FROM t1, v1 10372949e4e8Sdan WHERE t1.c=v1.c GROUP BY t1.a ORDER BY v1.b; 10382949e4e8Sdan CREATE TRIGGER tr1 AFTER INSERT ON t1 10392949e4e8Sdan WHEN new.a!=1 10402949e4e8Sdan BEGIN 10412949e4e8Sdan DELETE FROM t1 WHERE a=5; 10422949e4e8Sdan INSERT INTO t1 VALUES(1, 2, 3); 10432949e4e8Sdan UPDATE t1 SET c=c+1; 10442949e4e8Sdan END; 10452949e4e8Sdan 10462949e4e8Sdan INSERT INTO t1 VALUES(5, 6, 7); 10472949e4e8Sdan INSERT INTO t1 VALUES(8, 9, 10); 10482949e4e8Sdan INSERT INTO t1 VALUES(11, 12, 13); 10492949e4e8Sdan ANALYZE; 10502949e4e8Sdan SELECT * FROM t1; 10512949e4e8Sdan } 10522949e4e8Sdan} {1 2 6 8 9 12 1 2 5 11 12 14 1 2 4} 10532949e4e8Sdando_test shared-$av-15.2 { 10542949e4e8Sdan execsql { DROP TABLE t1 } db2 10552949e4e8Sdan} {} 10562949e4e8Sdandb close 10572949e4e8Sdandb2 close 10582949e4e8Sdan 10594ab9d254Sdrh# Shared cache on a :memory: database. This only works for URI filenames. 1060afc8b7f0Sdrh# 1061afc8b7f0Sdrhdo_test shared-$av-16.1 { 10624ab9d254Sdrh sqlite3 db1 file::memory: -uri 1 10634ab9d254Sdrh sqlite3 db2 file::memory: -uri 1 1064afc8b7f0Sdrh db1 eval { 1065afc8b7f0Sdrh CREATE TABLE t1(x); INSERT INTO t1 VALUES(1),(2),(3); 1066a96a7103Sdanielk1977 } 1067afc8b7f0Sdrh db2 eval { 1068afc8b7f0Sdrh SELECT x FROM t1 ORDER BY x; 1069afc8b7f0Sdrh } 1070afc8b7f0Sdrh} {1 2 3} 1071afc8b7f0Sdrhdo_test shared-$av-16.2 { 1072afc8b7f0Sdrh db2 eval { 1073afc8b7f0Sdrh INSERT INTO t1 VALUES(99); 1074afc8b7f0Sdrh DELETE FROM t1 WHERE x=2; 1075afc8b7f0Sdrh } 1076afc8b7f0Sdrh db1 eval { 1077afc8b7f0Sdrh SELECT x FROM t1 ORDER BY x; 1078afc8b7f0Sdrh } 1079afc8b7f0Sdrh} {1 3 99} 1080afc8b7f0Sdrh 10814ab9d254Sdrh# Verify that there is no cache sharing ordinary (non-URI) filenames are 10824ab9d254Sdrh# used. 10834ab9d254Sdrh# 10844ab9d254Sdrhdo_test shared-$av-16.3 { 10854ab9d254Sdrh db1 close 10864ab9d254Sdrh db2 close 10874ab9d254Sdrh sqlite3 db1 :memory: 10884ab9d254Sdrh sqlite3 db2 :memory: 10894ab9d254Sdrh db1 eval { 10904ab9d254Sdrh CREATE TABLE t1(x); INSERT INTO t1 VALUES(4),(5),(6); 10914ab9d254Sdrh } 10924ab9d254Sdrh catchsql { 10934ab9d254Sdrh SELECT * FROM t1; 10944ab9d254Sdrh } db2 10954ab9d254Sdrh} {1 {no such table: t1}} 10969c67b2aaSdrh 10979c67b2aaSdrh# Shared cache on named memory databases. 10989c67b2aaSdrh# 10999c67b2aaSdrhdo_test shared-$av-16.4 { 11009c67b2aaSdrh db1 close 11019c67b2aaSdrh db2 close 11029c67b2aaSdrh forcedelete test.db test.db-wal test.db-journal 11039c67b2aaSdrh sqlite3 db1 file:test.db?mode=memory -uri 1 11049c67b2aaSdrh sqlite3 db2 file:test.db?mode=memory -uri 1 11059c67b2aaSdrh db1 eval { 11069c67b2aaSdrh CREATE TABLE t1(x); INSERT INTO t1 VALUES(1),(2),(3); 11079c67b2aaSdrh } 11089c67b2aaSdrh db2 eval { 11099c67b2aaSdrh SELECT x FROM t1 ORDER BY x; 11109c67b2aaSdrh } 11119c67b2aaSdrh} {1 2 3} 11129c67b2aaSdrhdo_test shared-$av-16.5 { 11139c67b2aaSdrh db2 eval { 11149c67b2aaSdrh INSERT INTO t1 VALUES(99); 11159c67b2aaSdrh DELETE FROM t1 WHERE x=2; 11169c67b2aaSdrh } 11179c67b2aaSdrh db1 eval { 11189c67b2aaSdrh SELECT x FROM t1 ORDER BY x; 11199c67b2aaSdrh } 11209c67b2aaSdrh} {1 3 99} 11219c67b2aaSdrhdo_test shared-$av-16.6 { 11229c67b2aaSdrh file exists test.db 11239c67b2aaSdrh} {0} ;# Verify that the database is in-memory 11249c67b2aaSdrh 11259c67b2aaSdrh# Shared cache on named memory databases with different names. 11269c67b2aaSdrh# 11279c67b2aaSdrhdo_test shared-$av-16.7 { 11289c67b2aaSdrh db1 close 11299c67b2aaSdrh db2 close 11309c67b2aaSdrh forcedelete test1.db test2.db 11319c67b2aaSdrh sqlite3 db1 file:test1.db?mode=memory -uri 1 11329c67b2aaSdrh sqlite3 db2 file:test2.db?mode=memory -uri 1 11339c67b2aaSdrh db1 eval { 11349c67b2aaSdrh CREATE TABLE t1(x); INSERT INTO t1 VALUES(1),(2),(3); 11359c67b2aaSdrh } 11369c67b2aaSdrh catchsql { 11379c67b2aaSdrh SELECT x FROM t1 ORDER BY x; 11389c67b2aaSdrh } db2 11399c67b2aaSdrh} {1 {no such table: t1}} 11409c67b2aaSdrhdo_test shared-$av-16.8 { 11419c67b2aaSdrh file exists test1.db 11429c67b2aaSdrh} {0} ;# Verify that the database is in-memory 11439c67b2aaSdrh 11440b8dcfa2Sdan# Shared cache on named memory databases attached to readonly connections. 11450b8dcfa2Sdan# 1146bafad061Sdrhif {![sqlite3 -has-codec]} { 11470b8dcfa2Sdan do_test shared-$av-16.8.1 { 11480b8dcfa2Sdan db1 close 11490b8dcfa2Sdan db2 close 11500b8dcfa2Sdan 11510b8dcfa2Sdan sqlite3 db test1.db 11520b8dcfa2Sdan db eval { 11530b8dcfa2Sdan CREATE TABLE yy(a, b); 11540b8dcfa2Sdan INSERT INTO yy VALUES(77, 88); 11550b8dcfa2Sdan } 11560b8dcfa2Sdan db close 11570b8dcfa2Sdan 11580b8dcfa2Sdan sqlite3 db1 test1.db -uri 1 -readonly 1 11590b8dcfa2Sdan sqlite3 db2 test2.db -uri 1 11600b8dcfa2Sdan 11610b8dcfa2Sdan db1 eval { 11620b8dcfa2Sdan ATTACH 'file:mem?mode=memory&cache=shared' AS shared; 11630b8dcfa2Sdan CREATE TABLE shared.xx(a, b); 11640b8dcfa2Sdan INSERT INTO xx VALUES(55, 66); 11650b8dcfa2Sdan } 11660b8dcfa2Sdan db2 eval { 11670b8dcfa2Sdan ATTACH 'file:mem?mode=memory&cache=shared' AS shared; 11680b8dcfa2Sdan SELECT * FROM xx; 11690b8dcfa2Sdan } 11700b8dcfa2Sdan } {55 66} 11710b8dcfa2Sdan 11720b8dcfa2Sdan do_test shared-$av-16.8.2 { db1 eval { SELECT * FROM yy } } {77 88} 11730b8dcfa2Sdan do_test shared-$av-16.8.3 { 11740b8dcfa2Sdan list [catch {db1 eval { INSERT INTO yy VALUES(1, 2) }} msg] $msg 11750b8dcfa2Sdan } {1 {attempt to write a readonly database}} 11769c67b2aaSdrh 11774ab9d254Sdrh db1 close 11784ab9d254Sdrh db2 close 1179bafad061Sdrh} 11804ab9d254Sdrh 1181afc8b7f0Sdrh} ;# end of autovacuum on/off loop 1182a96a7103Sdanielk1977 1183aef0bf64Sdanielk1977sqlite3_enable_shared_cache $::enable_shared_cache 1184a96a7103Sdanielk1977finish_test 1185