000001  # 2011 May 06
000002  #
000003  # The author disclaims copyright to this source code.  In place of
000004  # a legal notice, here is a blessing:
000005  #
000006  #    May you do good and not evil.
000007  #    May you find forgiveness for yourself and forgive others.
000008  #    May you share freely, never taking more than you give.
000009  #
000010  #***********************************************************************
000011  #
000012  
000013  set testdir [file dirname $argv0]
000014  source $testdir/tester.tcl
000015  set testprefix e_wal
000016  
000017  db close
000018  forcedelete test.db-shm 
000019  testvfs oldvfs -iversion 1
000020  
000021  
000022  # EVIDENCE-OF: R-58297-14483 WAL databases can be created, read, and
000023  # written even if shared memory is unavailable as long as the
000024  # locking_mode is set to EXCLUSIVE before the first attempted access.
000025  #
000026  # EVIDENCE-OF: R-00449-33772 This feature allows WAL databases to be
000027  # created, read, and written by legacy VFSes that lack the "version 2"
000028  # shared-memory methods xShmMap, xShmLock, xShmBarrier, and xShmUnmap on
000029  # the sqlite3_io_methods object.
000030  #
000031  # 1.1: "create" tests.
000032  # 1.2: "read" tests.
000033  # 1.3: "write" tests.
000034  #
000035  # All three done with VFS "oldvfs", which has iVersion==1 and so does
000036  # not support shared memory.
000037  # 
000038  sqlite3 db test.db -vfs oldvfs
000039  do_execsql_test 1.1.1 {
000040    PRAGMA journal_mode = WAL;
000041  } {delete}
000042  do_execsql_test 1.1.2 {
000043    PRAGMA locking_mode = EXCLUSIVE;
000044    PRAGMA journal_mode = WAL;
000045  } {exclusive wal}
000046  do_execsql_test 1.1.3 {
000047    CREATE TABLE t1(x, y);
000048    INSERT INTO t1 VALUES(1, 2);
000049  } {}
000050  do_test 1.1.4 {
000051    list [file exists test.db-shm] [file exists test.db-wal]
000052  } {0 1}
000053  
000054  do_test 1.2.1 {
000055    db close
000056    sqlite3 db test.db -vfs oldvfs
000057    catchsql { SELECT * FROM t1 }
000058  } {1 {unable to open database file}}
000059  do_test 1.2.2 {
000060    execsql { PRAGMA locking_mode = EXCLUSIVE }
000061    execsql { SELECT * FROM t1 }
000062  } {1 2}
000063  do_test 1.2.3 {
000064    list [file exists test.db-shm] [file exists test.db-wal]
000065  } {0 1}
000066  
000067  do_test 1.3.1 {
000068    db close
000069    sqlite3 db test.db -vfs oldvfs
000070    catchsql { INSERT INTO t1 VALUES(3, 4) }
000071  } {1 {unable to open database file}}
000072  do_test 1.3.2 {
000073    execsql { PRAGMA locking_mode = EXCLUSIVE }
000074    execsql { INSERT INTO t1 VALUES(3, 4) }
000075    execsql { SELECT * FROM t1 }
000076  } {1 2 3 4}
000077  do_test 1.3.3 {
000078    list [file exists test.db-shm] [file exists test.db-wal]
000079  } {0 1}
000080  
000081  # EVIDENCE-OF: R-31969-57825 If EXCLUSIVE locking mode is set prior to
000082  # the first WAL-mode database access, then SQLite never attempts to call
000083  # any of the shared-memory methods and hence no shared-memory wal-index
000084  # is ever created.
000085  #
000086  db close
000087  sqlite3 db test.db
000088  do_execsql_test 2.1.1 {
000089    PRAGMA locking_mode = EXCLUSIVE;
000090    SELECT * FROM t1;
000091  } {exclusive 1 2 3 4}
000092  do_test 2.1.2 {
000093    list [file exists test.db-shm] [file exists test.db-wal]
000094  } {0 1}
000095  
000096  # EVIDENCE-OF: R-36328-16367 In that case, the database connection
000097  # remains in EXCLUSIVE mode as long as the journal mode is WAL; attempts
000098  # to change the locking mode using "PRAGMA locking_mode=NORMAL;" are
000099  # no-ops.
000100  #
000101  do_execsql_test 2.2.1 {
000102    PRAGMA locking_mode = NORMAL;
000103    SELECT * FROM t1;
000104  } {exclusive 1 2 3 4}
000105  do_test 2.2.2 {
000106    sqlite3 db2 test.db
000107    catchsql {SELECT * FROM t1} db2
000108  } {1 {database is locked}}
000109  db2 close
000110  
000111  # EVIDENCE-OF: R-63522-46088 The only way to change out of EXCLUSIVE
000112  # locking mode is to first change out of WAL journal mode.
000113  #
000114  do_execsql_test 2.3.1 {
000115    PRAGMA journal_mode = DELETE;
000116    SELECT * FROM t1;
000117  } {delete 1 2 3 4}
000118  do_test 2.3.2 {
000119    sqlite3 db2 test.db
000120    catchsql {SELECT * FROM t1} db2
000121  } {1 {database is locked}}
000122  do_execsql_test 2.3.3 {
000123    PRAGMA locking_mode = NORMAL;
000124    SELECT * FROM t1;
000125  } {normal 1 2 3 4}
000126  do_test 2.3.4 {
000127    sqlite3 db2 test.db
000128    catchsql {SELECT * FROM t1} db2
000129  } {0 {1 2 3 4}}
000130  db2 close
000131  db close
000132  
000133  
000134  # EVIDENCE-OF: R-57239-11845 If NORMAL locking mode is in effect for the
000135  # first WAL-mode database access, then the shared-memory wal-index is
000136  # created.
000137  #
000138  do_test 3.0 {
000139    sqlite3 db test.db
000140    execsql { PRAGMA journal_mode = WAL }
000141    db close
000142  } {}
000143  do_test 3.1 {
000144    sqlite3 db test.db
000145    execsql { SELECT * FROM t1 }
000146    list [file exists test.db-shm] [file exists test.db-wal]
000147  } {1 1}
000148  
000149  # EVIDENCE-OF: R-13779-07711 As long as exactly one connection is using
000150  # a shared-memory wal-index, the locking mode can be changed freely
000151  # between NORMAL and EXCLUSIVE.
000152  #
000153  do_execsql_test 3.2.1 {
000154    PRAGMA locking_mode = EXCLUSIVE;
000155    PRAGMA locking_mode = NORMAL;
000156    PRAGMA locking_mode = EXCLUSIVE;
000157    INSERT INTO t1 VALUES(5, 6);
000158  } {exclusive normal exclusive}
000159  do_test 3.2.2 {
000160    sqlite3 db2 test.db
000161    catchsql { SELECT * FROM t1 } db2
000162  } {1 {database is locked}}
000163  
000164  # EVIDENCE-OF: R-10993-11647 It is only when the shared-memory wal-index
000165  # is omitted, when the locking mode is EXCLUSIVE prior to the first
000166  # WAL-mode database access, that the locking mode is stuck in EXCLUSIVE.
000167  #
000168  do_execsql_test 3.2.3 {
000169    PRAGMA locking_mode = NORMAL;
000170    SELECT * FROM t1;
000171  } {normal 1 2 3 4 5 6}
000172  do_test 3.2.4 {
000173    catchsql { SELECT * FROM t1 } db2
000174  } {0 {1 2 3 4 5 6}}
000175  
000176  do_catchsql_test 3.2.5 {
000177    PRAGMA locking_mode = EXCLUSIVE;
000178    INSERT INTO t1 VALUES(7, 8);
000179  } {1 {database is locked}}
000180  
000181  db2 close
000182  
000183  # EVIDENCE-OF: R-46197-42811 This means that the underlying VFS must
000184  # support the "version 2" shared-memory.
000185  #
000186  # EVIDENCE-OF: R-55316-21772 If the VFS does not support shared-memory
000187  # methods, then the attempt to open a database that is already in WAL
000188  # mode, or the attempt convert a database into WAL mode, will fail.
000189  #
000190  db close
000191  do_test 3.4.1 {
000192    sqlite3 db test.db -vfs oldvfs
000193    catchsql { SELECT * FROM t1 }
000194  } {1 {unable to open database file}}
000195  db close
000196  do_test 3.4.2 {
000197    forcedelete test.db2
000198    sqlite3 db test.db2 -vfs oldvfs
000199    catchsql { PRAGMA journal_mode = WAL }
000200  } {0 delete}
000201  db close
000202  
000203  
000204  # EVIDENCE-OF: R-45540-25505 To prevent older versions of SQLite (prior
000205  # to version 3.7.0, 2010-07-22) from trying to recover a WAL-mode
000206  # database (and making matters worse) the database file format version
000207  # numbers (bytes 18 and 19 in the database header) are increased from 1
000208  # to 2 in WAL mode.
000209  #
000210  reset_db
000211  do_execsql_test 4.1.1 { CREATE TABLE t1(x, y) }
000212  do_test 4.1.2 { hexio_read test.db 18 2 } {0101}
000213  do_execsql_test 4.1.3 { PRAGMA journal_mode = wAL } {wal}
000214  do_test 4.1.4 { hexio_read test.db 18 2 } {0202}
000215  
000216  
000217  # EVIDENCE-OF: R-02535-05811 One can explicitly change out of WAL mode
000218  # using a pragma such as this: PRAGMA journal_mode=DELETE;
000219  #
000220  do_execsql_test 4.2.1 { INSERT INTO t1 VALUES(1, 1); } {}
000221  do_test 4.2.2 { file exists test.db-wal } {1}
000222  do_execsql_test 4.2.3 { PRAGMA journal_mode = delete } {delete}
000223  do_test 4.2.4 { file exists test.db-wal } {0}
000224  
000225  # EVIDENCE-OF: R-60175-02388 Deliberately changing out of WAL mode
000226  # changes the database file format version numbers back to 1 so that
000227  # older versions of SQLite can once again access the database file.
000228  #
000229  do_test 4.3 { hexio_read test.db 18 2 } {0101}
000230  
000231  finish_test