xref: /sqlite-3.40.0/test/shared.test (revision 7f42dcd9)
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