xref: /sqlite-3.40.0/test/exclusive.test (revision d0add948)
141483468Sdanielk1977# 2007 March 24
241483468Sdanielk1977#
341483468Sdanielk1977# The author disclaims copyright to this source code.  In place of
441483468Sdanielk1977# a legal notice, here is a blessing:
541483468Sdanielk1977#
641483468Sdanielk1977#    May you do good and not evil.
741483468Sdanielk1977#    May you find forgiveness for yourself and forgive others.
841483468Sdanielk1977#    May you share freely, never taking more than you give.
941483468Sdanielk1977#
1041483468Sdanielk1977#***********************************************************************
11ded6f4b2Sdanielk1977# This file implements regression tests for SQLite library. The focus
12ded6f4b2Sdanielk1977# of these tests is exclusive access mode (i.e. the thing activated by
13ded6f4b2Sdanielk1977# "PRAGMA locking_mode = EXCLUSIVE").
1441483468Sdanielk1977#
1531559aeeSdanielk1977# $Id: exclusive.test,v 1.15 2009/06/26 12:30:40 danielk1977 Exp $
1641483468Sdanielk1977
1741483468Sdanielk1977set testdir [file dirname $argv0]
1841483468Sdanielk1977source $testdir/tester.tcl
1941483468Sdanielk1977
2041483468Sdanielk1977ifcapable {!pager_pragmas} {
2141483468Sdanielk1977  finish_test
2241483468Sdanielk1977  return
2341483468Sdanielk1977}
2441483468Sdanielk1977
25fda06befSmistachkinforcedelete test2.db-journal
26fda06befSmistachkinforcedelete test2.db
27fda06befSmistachkinforcedelete test3.db-journal
28fda06befSmistachkinforcedelete test3.db
29fda06befSmistachkinforcedelete test4.db-journal
30fda06befSmistachkinforcedelete test4.db
3141483468Sdanielk1977
3241483468Sdanielk1977#----------------------------------------------------------------------
3341483468Sdanielk1977# Test cases exclusive-1.X test the PRAGMA logic.
3441483468Sdanielk1977#
3541483468Sdanielk1977do_test exclusive-1.0 {
3641483468Sdanielk1977  execsql {
3741483468Sdanielk1977    pragma locking_mode;
3841483468Sdanielk1977    pragma main.locking_mode;
39369339dbSdrh    pragma temp.locking_mode;
4041483468Sdanielk1977  }
418a7adb0dSdanielk1977} [list normal normal exclusive]
4241483468Sdanielk1977do_test exclusive-1.1 {
4341483468Sdanielk1977  execsql {
4441483468Sdanielk1977    pragma locking_mode = exclusive;
4541483468Sdanielk1977  }
4641483468Sdanielk1977} {exclusive}
4741483468Sdanielk1977do_test exclusive-1.2 {
4841483468Sdanielk1977  execsql {
4941483468Sdanielk1977    pragma locking_mode;
5041483468Sdanielk1977    pragma main.locking_mode;
51369339dbSdrh    pragma temp.locking_mode;
5241483468Sdanielk1977  }
538a7adb0dSdanielk1977} [list exclusive exclusive exclusive]
5441483468Sdanielk1977do_test exclusive-1.3 {
5541483468Sdanielk1977  execsql {
5641483468Sdanielk1977    pragma locking_mode = normal;
5741483468Sdanielk1977  }
5841483468Sdanielk1977} {normal}
5941483468Sdanielk1977do_test exclusive-1.4 {
6041483468Sdanielk1977  execsql {
6141483468Sdanielk1977    pragma locking_mode;
6241483468Sdanielk1977    pragma main.locking_mode;
63369339dbSdrh    pragma temp.locking_mode;
6441483468Sdanielk1977  }
658a7adb0dSdanielk1977} [list normal normal exclusive]
6641483468Sdanielk1977do_test exclusive-1.5 {
6741483468Sdanielk1977  execsql {
6841483468Sdanielk1977    pragma locking_mode = invalid;
6941483468Sdanielk1977  }
7041483468Sdanielk1977} {normal}
7141483468Sdanielk1977do_test exclusive-1.6 {
7241483468Sdanielk1977  execsql {
7341483468Sdanielk1977    pragma locking_mode;
7441483468Sdanielk1977    pragma main.locking_mode;
75369339dbSdrh    pragma temp.locking_mode;
7641483468Sdanielk1977  }
778a7adb0dSdanielk1977} [list normal normal exclusive]
785a8f9374Sdanielk1977ifcapable attach {
7941483468Sdanielk1977  do_test exclusive-1.7 {
8041483468Sdanielk1977    execsql {
8141483468Sdanielk1977      pragma locking_mode = exclusive;
8241483468Sdanielk1977      ATTACH 'test2.db' as aux;
8341483468Sdanielk1977    }
8441483468Sdanielk1977    execsql {
8541483468Sdanielk1977      pragma main.locking_mode;
8641483468Sdanielk1977      pragma aux.locking_mode;
8741483468Sdanielk1977    }
8841483468Sdanielk1977  } {exclusive exclusive}
8941483468Sdanielk1977  do_test exclusive-1.8 {
9041483468Sdanielk1977    execsql {
9141483468Sdanielk1977      pragma main.locking_mode = normal;
9241483468Sdanielk1977    }
9341483468Sdanielk1977    execsql {
9441483468Sdanielk1977      pragma main.locking_mode;
95369339dbSdrh      pragma temp.locking_mode;
9641483468Sdanielk1977      pragma aux.locking_mode;
9741483468Sdanielk1977    }
988a7adb0dSdanielk1977  } [list normal exclusive exclusive]
9941483468Sdanielk1977  do_test exclusive-1.9 {
10041483468Sdanielk1977    execsql {
10141483468Sdanielk1977      pragma locking_mode;
10241483468Sdanielk1977    }
10341483468Sdanielk1977  } {exclusive}
10441483468Sdanielk1977  do_test exclusive-1.10 {
10541483468Sdanielk1977    execsql {
10641483468Sdanielk1977      ATTACH 'test3.db' as aux2;
10741483468Sdanielk1977    }
10841483468Sdanielk1977    execsql {
10941483468Sdanielk1977      pragma main.locking_mode;
11041483468Sdanielk1977      pragma aux.locking_mode;
11141483468Sdanielk1977      pragma aux2.locking_mode;
11241483468Sdanielk1977    }
11341483468Sdanielk1977  } {normal exclusive exclusive}
11441483468Sdanielk1977  do_test exclusive-1.11 {
11541483468Sdanielk1977    execsql {
11641483468Sdanielk1977      pragma aux.locking_mode = normal;
11741483468Sdanielk1977    }
11841483468Sdanielk1977    execsql {
11941483468Sdanielk1977      pragma main.locking_mode;
12041483468Sdanielk1977      pragma aux.locking_mode;
12141483468Sdanielk1977      pragma aux2.locking_mode;
12241483468Sdanielk1977    }
12341483468Sdanielk1977  } {normal normal exclusive}
12441483468Sdanielk1977  do_test exclusive-1.12 {
12541483468Sdanielk1977    execsql {
12641483468Sdanielk1977      pragma locking_mode = normal;
12741483468Sdanielk1977    }
12841483468Sdanielk1977    execsql {
12941483468Sdanielk1977      pragma main.locking_mode;
130369339dbSdrh      pragma temp.locking_mode;
13141483468Sdanielk1977      pragma aux.locking_mode;
13241483468Sdanielk1977      pragma aux2.locking_mode;
13341483468Sdanielk1977    }
1348a7adb0dSdanielk1977  } [list normal exclusive normal normal]
13541483468Sdanielk1977  do_test exclusive-1.13 {
13641483468Sdanielk1977    execsql {
13741483468Sdanielk1977      ATTACH 'test4.db' as aux3;
13841483468Sdanielk1977    }
13941483468Sdanielk1977    execsql {
14041483468Sdanielk1977      pragma main.locking_mode;
141369339dbSdrh      pragma temp.locking_mode;
14241483468Sdanielk1977      pragma aux.locking_mode;
14341483468Sdanielk1977      pragma aux2.locking_mode;
14441483468Sdanielk1977      pragma aux3.locking_mode;
14541483468Sdanielk1977    }
1468a7adb0dSdanielk1977  } [list normal exclusive normal normal normal]
14741483468Sdanielk1977
14841483468Sdanielk1977  do_test exclusive-1.99 {
14941483468Sdanielk1977    execsql {
15041483468Sdanielk1977      DETACH aux;
15141483468Sdanielk1977      DETACH aux2;
15241483468Sdanielk1977      DETACH aux3;
15341483468Sdanielk1977    }
15441483468Sdanielk1977  } {}
1555a8f9374Sdanielk1977}
15641483468Sdanielk1977
15741483468Sdanielk1977#----------------------------------------------------------------------
15841483468Sdanielk1977# Test cases exclusive-2.X verify that connections in exclusive
15941483468Sdanielk1977# locking_mode do not relinquish locks.
16041483468Sdanielk1977#
16141483468Sdanielk1977do_test exclusive-2.0 {
16241483468Sdanielk1977  execsql {
16341483468Sdanielk1977    CREATE TABLE abc(a, b, c);
16441483468Sdanielk1977    INSERT INTO abc VALUES(1, 2, 3);
16541483468Sdanielk1977    PRAGMA locking_mode = exclusive;
16641483468Sdanielk1977  }
16741483468Sdanielk1977} {exclusive}
16841483468Sdanielk1977do_test exclusive-2.1 {
16941483468Sdanielk1977  sqlite3 db2 test.db
17041483468Sdanielk1977  execsql {
17141483468Sdanielk1977    INSERT INTO abc VALUES(4, 5, 6);
17241483468Sdanielk1977    SELECT * FROM abc;
17341483468Sdanielk1977  } db2
17441483468Sdanielk1977} {1 2 3 4 5 6}
17541483468Sdanielk1977do_test exclusive-2.2 {
17641483468Sdanielk1977  # This causes connection 'db' (in exclusive mode) to establish
17741483468Sdanielk1977  # a shared-lock on the db. The other connection should now be
17841483468Sdanielk1977  # locked out as a writer.
17941483468Sdanielk1977  execsql {
18041483468Sdanielk1977    SELECT * FROM abc;
18141483468Sdanielk1977  } db
18241483468Sdanielk1977} {1 2 3 4 5 6}
18341483468Sdanielk1977do_test exclusive-2.4 {
18441483468Sdanielk1977  execsql {
18541483468Sdanielk1977    SELECT * FROM abc;
18641483468Sdanielk1977  } db2
18741483468Sdanielk1977} {1 2 3 4 5 6}
18841483468Sdanielk1977do_test exclusive-2.5 {
18941483468Sdanielk1977  catchsql {
19041483468Sdanielk1977    INSERT INTO abc VALUES(7, 8, 9);
19141483468Sdanielk1977  } db2
19241483468Sdanielk1977} {1 {database is locked}}
1933aefabafSdrhsqlite3_soft_heap_limit 0
19441483468Sdanielk1977do_test exclusive-2.6 {
19541483468Sdanielk1977  # Because connection 'db' only has a shared-lock, the other connection
19641483468Sdanielk1977  # will be able to get a RESERVED, but will fail to upgrade to EXCLUSIVE.
19741483468Sdanielk1977  execsql {
19841483468Sdanielk1977    BEGIN;
19941483468Sdanielk1977    INSERT INTO abc VALUES(7, 8, 9);
20041483468Sdanielk1977  } db2
20141483468Sdanielk1977  catchsql {
20241483468Sdanielk1977    COMMIT
20341483468Sdanielk1977  } db2
20441483468Sdanielk1977} {1 {database is locked}}
20541483468Sdanielk1977do_test exclusive-2.7 {
20641483468Sdanielk1977  catchsql {
20741483468Sdanielk1977    COMMIT
20841483468Sdanielk1977  } db2
20941483468Sdanielk1977} {1 {database is locked}}
21041483468Sdanielk1977do_test exclusive-2.8 {
21141483468Sdanielk1977  execsql {
21241483468Sdanielk1977    ROLLBACK;
21341483468Sdanielk1977  } db2
21441483468Sdanielk1977} {}
215c1a60c51Sdansqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
21641483468Sdanielk1977
21741483468Sdanielk1977do_test exclusive-2.9 {
21841483468Sdanielk1977  # Write the database to establish the exclusive lock with connection 'db.
21941483468Sdanielk1977  execsql {
22041483468Sdanielk1977    INSERT INTO abc VALUES(7, 8, 9);
22141483468Sdanielk1977  } db
22241483468Sdanielk1977  catchsql {
22341483468Sdanielk1977    SELECT * FROM abc;
22441483468Sdanielk1977  } db2
22541483468Sdanielk1977} {1 {database is locked}}
22641483468Sdanielk1977do_test exclusive-2.10 {
22741483468Sdanielk1977  # Changing the locking-mode does not release any locks.
22841483468Sdanielk1977  execsql {
22941483468Sdanielk1977    PRAGMA locking_mode = normal;
23041483468Sdanielk1977  } db
23141483468Sdanielk1977  catchsql {
23241483468Sdanielk1977    SELECT * FROM abc;
23341483468Sdanielk1977  } db2
23441483468Sdanielk1977} {1 {database is locked}}
23541483468Sdanielk1977do_test exclusive-2.11 {
23641483468Sdanielk1977  # After changing the locking mode, accessing the db releases locks.
23741483468Sdanielk1977  execsql {
23841483468Sdanielk1977    SELECT * FROM abc;
23941483468Sdanielk1977  } db
24041483468Sdanielk1977  execsql {
24141483468Sdanielk1977    SELECT * FROM abc;
24241483468Sdanielk1977  } db2
24341483468Sdanielk1977} {1 2 3 4 5 6 7 8 9}
24441483468Sdanielk1977db2 close
24541483468Sdanielk1977
24641483468Sdanielk1977#----------------------------------------------------------------------
24741483468Sdanielk1977# Tests exclusive-3.X - test that a connection in exclusive mode
24841483468Sdanielk1977# truncates instead of deletes the journal file when committing
24941483468Sdanielk1977# a transaction.
25041483468Sdanielk1977#
251e5dd3896Sdanielk1977# These tests are not run on windows because the windows backend
252e5dd3896Sdanielk1977# opens the journal file for exclusive access, preventing its contents
253e5dd3896Sdanielk1977# from being inspected externally.
254e5dd3896Sdanielk1977#
25569aedc8dSdanif {$tcl_platform(platform) != "windows"
25669aedc8dSdan && [atomic_batch_write test.db]==0
25769aedc8dSdan} {
258d0864087Sdan
259d0864087Sdan  # Return a list of two booleans (either 0 or 1). The first is true
260d0864087Sdan  # if the named file exists. The second is true only if the file
261d0864087Sdan  # exists and the first 28 bytes contain at least one non-zero byte.
262d0864087Sdan  #
26341483468Sdanielk1977  proc filestate {fname} {
26441483468Sdanielk1977    set exists 0
26541483468Sdanielk1977    set content 0
26641483468Sdanielk1977    if {[file exists $fname]} {
26741483468Sdanielk1977      set exists 1
268f3a87624Sdrh      set hdr [hexio_read $fname 0 28]
26931559aeeSdanielk1977      set content [expr {0==[string match $hdr [string repeat 0 56]]}]
27041483468Sdanielk1977    }
27141483468Sdanielk1977    list $exists $content
27241483468Sdanielk1977  }
273d0864087Sdan
27441483468Sdanielk1977  do_test exclusive-3.0 {
27541483468Sdanielk1977    filestate test.db-journal
27641483468Sdanielk1977  } {0 0}
27741483468Sdanielk1977  do_test exclusive-3.1 {
27841483468Sdanielk1977    execsql {
27941483468Sdanielk1977      PRAGMA locking_mode = exclusive;
28041483468Sdanielk1977      BEGIN;
28141483468Sdanielk1977      DELETE FROM abc;
28241483468Sdanielk1977    }
28341483468Sdanielk1977    filestate test.db-journal
28441483468Sdanielk1977  } {1 1}
28541483468Sdanielk1977  do_test exclusive-3.2 {
28641483468Sdanielk1977    execsql {
28741483468Sdanielk1977      COMMIT;
28841483468Sdanielk1977    }
28941483468Sdanielk1977    filestate test.db-journal
29041483468Sdanielk1977  } {1 0}
29141483468Sdanielk1977  do_test exclusive-3.3 {
29241483468Sdanielk1977    execsql {
29341483468Sdanielk1977      INSERT INTO abc VALUES('A', 'B', 'C');
29441483468Sdanielk1977      SELECT * FROM abc;
29541483468Sdanielk1977    }
29641483468Sdanielk1977  } {A B C}
29741483468Sdanielk1977  do_test exclusive-3.4 {
29841483468Sdanielk1977    execsql {
29941483468Sdanielk1977      BEGIN;
30041483468Sdanielk1977      UPDATE abc SET a = 1, b = 2, c = 3;
30141483468Sdanielk1977      ROLLBACK;
30241483468Sdanielk1977      SELECT * FROM abc;
30341483468Sdanielk1977    }
304334cdb63Sdanielk1977  } {A B C}
30541483468Sdanielk1977  do_test exclusive-3.5 {
30641483468Sdanielk1977    filestate test.db-journal
30741483468Sdanielk1977  } {1 0}
30841483468Sdanielk1977  do_test exclusive-3.6 {
30941483468Sdanielk1977    execsql {
31041483468Sdanielk1977      PRAGMA locking_mode = normal;
31141483468Sdanielk1977      SELECT * FROM abc;
31241483468Sdanielk1977    }
31341483468Sdanielk1977    filestate test.db-journal
31441483468Sdanielk1977  } {0 0}
315e5dd3896Sdanielk1977}
31641483468Sdanielk1977
317334cdb63Sdanielk1977#----------------------------------------------------------------------
318334cdb63Sdanielk1977# Tests exclusive-4.X - test that rollback works correctly when
319334cdb63Sdanielk1977# in exclusive-access mode.
320334cdb63Sdanielk1977#
321334cdb63Sdanielk1977
32241483468Sdanielk1977# The following procedure computes a "signature" for table "t3".  If
32341483468Sdanielk1977# T3 changes in any way, the signature should change.
32441483468Sdanielk1977#
32541483468Sdanielk1977# This is used to test ROLLBACK.  We gather a signature for t3, then
32641483468Sdanielk1977# make lots of changes to t3, then rollback and take another signature.
32741483468Sdanielk1977# The two signatures should be the same.
32841483468Sdanielk1977#
32941483468Sdanielk1977proc signature {} {
33041483468Sdanielk1977  return [db eval {SELECT count(*), md5sum(x) FROM t3}]
33141483468Sdanielk1977}
33241483468Sdanielk1977
33341483468Sdanielk1977do_test exclusive-4.0 {
33441483468Sdanielk1977  execsql { PRAGMA locking_mode = exclusive; }
335334cdb63Sdanielk1977  execsql { PRAGMA default_cache_size = 10; }
33641483468Sdanielk1977  execsql {
33741483468Sdanielk1977    BEGIN;
33841483468Sdanielk1977    CREATE TABLE t3(x TEXT);
33941483468Sdanielk1977    INSERT INTO t3 VALUES(randstr(10,400));
34041483468Sdanielk1977    INSERT INTO t3 VALUES(randstr(10,400));
34141483468Sdanielk1977    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
34241483468Sdanielk1977    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
34341483468Sdanielk1977    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
34441483468Sdanielk1977    INSERT INTO t3 SELECT randstr(10,400) FROM t3;
34541483468Sdanielk1977    COMMIT;
34641483468Sdanielk1977  }
347334cdb63Sdanielk1977  execsql {SELECT count(*) FROM t3;}
348334cdb63Sdanielk1977} {32}
349334cdb63Sdanielk1977
350334cdb63Sdanielk1977set ::X [signature]
35141483468Sdanielk1977do_test exclusive-4.1 {
35241483468Sdanielk1977  execsql {
35341483468Sdanielk1977    BEGIN;
35441483468Sdanielk1977    DELETE FROM t3 WHERE random()%10!=0;
35541483468Sdanielk1977    INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
35641483468Sdanielk1977    INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
357334cdb63Sdanielk1977    SELECT count(*) FROM t3;
35841483468Sdanielk1977    ROLLBACK;
35941483468Sdanielk1977  }
36041483468Sdanielk1977  signature
361334cdb63Sdanielk1977} $::X
36241483468Sdanielk1977
363334cdb63Sdanielk1977do_test exclusive-4.2 {
364334cdb63Sdanielk1977  execsql {
365334cdb63Sdanielk1977    BEGIN;
366334cdb63Sdanielk1977    DELETE FROM t3 WHERE random()%10!=0;
367334cdb63Sdanielk1977    INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
368334cdb63Sdanielk1977    DELETE FROM t3 WHERE random()%10!=0;
369334cdb63Sdanielk1977    INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
370334cdb63Sdanielk1977    ROLLBACK;
37141483468Sdanielk1977  }
372334cdb63Sdanielk1977  signature
373334cdb63Sdanielk1977} $::X
374334cdb63Sdanielk1977
375334cdb63Sdanielk1977do_test exclusive-4.3 {
376334cdb63Sdanielk1977  execsql {
377334cdb63Sdanielk1977    INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0;
378334cdb63Sdanielk1977  }
379334cdb63Sdanielk1977} {}
380334cdb63Sdanielk1977
381334cdb63Sdanielk1977do_test exclusive-4.4 {
382334cdb63Sdanielk1977  catch {set ::X [signature]}
383334cdb63Sdanielk1977} {0}
384334cdb63Sdanielk1977do_test exclusive-4.5 {
385334cdb63Sdanielk1977  execsql {
386334cdb63Sdanielk1977    PRAGMA locking_mode = NORMAL;
387334cdb63Sdanielk1977    DROP TABLE t3;
388334cdb63Sdanielk1977    DROP TABLE abc;
389334cdb63Sdanielk1977  }
390334cdb63Sdanielk1977} {normal}
391334cdb63Sdanielk1977
392334cdb63Sdanielk1977#----------------------------------------------------------------------
393334cdb63Sdanielk1977# Tests exclusive-5.X - test that statement journals are truncated
394334cdb63Sdanielk1977# instead of deleted when in exclusive access mode.
395334cdb63Sdanielk1977#
39669aedc8dSdanif {[atomic_batch_write test.db]==0} {
397369339dbSdrh
398369339dbSdrh# Close and reopen the database so that the temp database is no
399369339dbSdrh# longer active.
400369339dbSdrh#
401369339dbSdrhdb close
4024c0f1649Sdrhsqlite3 db test.db
403369339dbSdrh
404aebf413dSaswift# if we're using proxy locks, we use 3 filedescriptors for a db
405aebf413dSaswift# that is open but NOT writing changes, normally
406aebf413dSaswift# sqlite uses 1 (proxy locking adds the conch and the local lock)
407aebf413dSaswiftset using_proxy 0
408aebf413dSaswiftforeach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
409aebf413dSaswift  set using_proxy $value
410aebf413dSaswift}
411aebf413dSaswiftset extrafds 0
412aebf413dSaswiftif {$using_proxy!=0} {
413aebf413dSaswift  set extrafds 2
414aebf413dSaswift}
415369339dbSdrh
416334cdb63Sdanielk1977do_test exclusive-5.0 {
417334cdb63Sdanielk1977  execsql {
418334cdb63Sdanielk1977    CREATE TABLE abc(a UNIQUE, b UNIQUE, c UNIQUE);
419334cdb63Sdanielk1977    BEGIN;
420334cdb63Sdanielk1977    INSERT INTO abc VALUES(1, 2, 3);
421334cdb63Sdanielk1977    INSERT INTO abc SELECT a+1, b+1, c+1 FROM abc;
422334cdb63Sdanielk1977  }
423334cdb63Sdanielk1977} {}
424334cdb63Sdanielk1977do_test exclusive-5.1 {
425334cdb63Sdanielk1977  # Three files are open: The db, journal and statement-journal.
4263ac9a864Sdrh  # (2016-03-04) The statement-journal is now opened lazily
427334cdb63Sdanielk1977  set sqlite_open_file_count
428aebf413dSaswift  expr $sqlite_open_file_count-$extrafds
429b6eb6662Sdan} {2}
430334cdb63Sdanielk1977do_test exclusive-5.2 {
431334cdb63Sdanielk1977  execsql {
432334cdb63Sdanielk1977    COMMIT;
433334cdb63Sdanielk1977  }
434334cdb63Sdanielk1977  # One file open: the db.
435334cdb63Sdanielk1977  set sqlite_open_file_count
436aebf413dSaswift  expr $sqlite_open_file_count-$extrafds
437334cdb63Sdanielk1977} {1}
438334cdb63Sdanielk1977do_test exclusive-5.3 {
439334cdb63Sdanielk1977  execsql {
440334cdb63Sdanielk1977    PRAGMA locking_mode = exclusive;
441334cdb63Sdanielk1977    BEGIN;
442334cdb63Sdanielk1977    INSERT INTO abc VALUES(5, 6, 7);
443334cdb63Sdanielk1977  }
444334cdb63Sdanielk1977  # Two files open: the db and journal.
445334cdb63Sdanielk1977  set sqlite_open_file_count
446aebf413dSaswift  expr $sqlite_open_file_count-$extrafds
447f9d1a214Sdanielk1977} {2}
448334cdb63Sdanielk1977do_test exclusive-5.4 {
449334cdb63Sdanielk1977  execsql {
450334cdb63Sdanielk1977    INSERT INTO abc SELECT a+10, b+10, c+10 FROM abc;
451334cdb63Sdanielk1977  }
452334cdb63Sdanielk1977  # Three files are open: The db, journal and statement-journal.
4533ac9a864Sdrh  # 2016-03-04: The statement-journal open is deferred
454334cdb63Sdanielk1977  set sqlite_open_file_count
455aebf413dSaswift  expr $sqlite_open_file_count-$extrafds
456b6eb6662Sdan} {2}
457334cdb63Sdanielk1977do_test exclusive-5.5 {
458334cdb63Sdanielk1977  execsql {
459334cdb63Sdanielk1977    COMMIT;
460334cdb63Sdanielk1977  }
461334cdb63Sdanielk1977  # Three files are still open: The db, journal and statement-journal.
4623ac9a864Sdrh  # 2016-03-04: The statement-journal open is deferred
463334cdb63Sdanielk1977  set sqlite_open_file_count
464aebf413dSaswift  expr $sqlite_open_file_count-$extrafds
465b6eb6662Sdan} {2}
466334cdb63Sdanielk1977do_test exclusive-5.6 {
467334cdb63Sdanielk1977  execsql {
468334cdb63Sdanielk1977    PRAGMA locking_mode = normal;
469334cdb63Sdanielk1977    SELECT * FROM abc;
470334cdb63Sdanielk1977  }
471334cdb63Sdanielk1977} {normal 1 2 3 2 3 4 5 6 7 11 12 13 12 13 14 15 16 17}
472334cdb63Sdanielk1977do_test exclusive-5.7 {
473334cdb63Sdanielk1977  # Just the db open.
474334cdb63Sdanielk1977  set sqlite_open_file_count
475aebf413dSaswift  expr $sqlite_open_file_count-$extrafds
476334cdb63Sdanielk1977} {1}
47741483468Sdanielk1977
47876de8a75Sdan#-------------------------------------------------------------------------
47976de8a75Sdan
48076de8a75Sdando_execsql_test exclusive-6.1 {
48176de8a75Sdan  CREATE TABLE t4(a, b);
48276de8a75Sdan  INSERT INTO t4 VALUES('Eden', 1955);
48376de8a75Sdan  BEGIN;
48476de8a75Sdan    INSERT INTO t4 VALUES('Macmillan', 1957);
48576de8a75Sdan    INSERT INTO t4 VALUES('Douglas-Home', 1963);
48676de8a75Sdan    INSERT INTO t4 VALUES('Wilson', 1964);
48776de8a75Sdan}
48876de8a75Sdando_test exclusive-6.2 {
48976de8a75Sdan  forcedelete test2.db test2.db-journal
490fda06befSmistachkin  copy_file test.db test2.db
491fda06befSmistachkin  copy_file test.db-journal test2.db-journal
49276de8a75Sdan  sqlite3 db test2.db
49376de8a75Sdan} {}
49476de8a75Sdan
49576de8a75Sdando_execsql_test exclusive-6.3 {
49676de8a75Sdan  PRAGMA locking_mode = EXCLUSIVE;
49776de8a75Sdan  SELECT * FROM t4;
49876de8a75Sdan} {exclusive Eden 1955}
49976de8a75Sdan
50076de8a75Sdando_test exclusive-6.4 {
50176de8a75Sdan  db close
50276de8a75Sdan  forcedelete test.db test.db-journal
50376de8a75Sdan  set fd [open test.db-journal w]
50476de8a75Sdan  puts $fd x
50576de8a75Sdan  close $fd
50676de8a75Sdan  sqlite3 db test.db
50776de8a75Sdan} {}
50876de8a75Sdan
50976de8a75Sdando_execsql_test exclusive-6.5 {
51076de8a75Sdan  PRAGMA locking_mode = EXCLUSIVE;
51176de8a75Sdan  SELECT * FROM sqlite_master;
512bfa7e199Sdan} {exclusive}
51376de8a75Sdan
514fce8165eSdrh# 2019-12-26 ticket fb3b3024ea238d5c
515*d0add948Sdanif {[permutation]!="journaltest"} {
516*d0add948Sdan  # The custom VFS used by the "journaltest" permutation cannot open the
517*d0add948Sdan  # shared-memory file. So, while it is able to switch the db file to
518*d0add948Sdan  # journal_mode=WAL when locking_mode=EXCLUSIVE, it can no longer access
519*d0add948Sdan  # it once the locking_mode is changed back to NORMAL.
520fce8165eSdrh  do_test exclusive-7.1 {
521fce8165eSdrh    db close
522fce8165eSdrh    forcedelete test.db test.db-journal test.db-wal
523fce8165eSdrh    sqlite3 db test.db
524fce8165eSdrh    # The following sequence of pragmas would trigger an assert()
525fce8165eSdrh    # associated with Pager.changeCountDone inside of assert_pager_state(),
526fce8165eSdrh    # prior to the fix.
527fce8165eSdrh    db eval {
528fce8165eSdrh      PRAGMA locking_mode = EXCLUSIVE;
529fce8165eSdrh      PRAGMA journal_mode = WAL;
530fce8165eSdrh      PRAGMA locking_mode = NORMAL;
531fce8165eSdrh      PRAGMA user_version;
532fce8165eSdrh      PRAGMA journal_mode = DELETE;
533fce8165eSdrh    }
534fce8165eSdrh  } {exclusive wal normal 0 delete}
535*d0add948Sdan}
536fce8165eSdrh
537fce8165eSdrh
53869aedc8dSdan} ;# atomic_batch_write==0
53969aedc8dSdan
54041483468Sdanielk1977finish_test
541