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