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