]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add test cases and documentation for the nolock and immutable query
authordrh <drh@noemail.net>
Wed, 7 May 2014 15:09:24 +0000 (15:09 +0000)
committerdrh <drh@noemail.net>
Wed, 7 May 2014 15:09:24 +0000 (15:09 +0000)
parameters.

FossilOrigin-Name: 19d56cbaca222b32e2e354063149cccd89441d73

manifest
manifest.uuid
src/sqlite.h.in
src/test_vfs.c
test/nolock.test [new file with mode: 0644]

index 6ac75f7987e70477e3623e09347dd03a388f8448..f945a392c464fac39df1459f6c9640b611bc3cb6 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Take\sout\sthe\sspecial\shandling\sof\snolock=true\sin\sos_win.c\sand\sadd\sit\sto\npager.c,\sso\sthat\sit\sworks\sfor\sall\sVFSes.\s\sAdd\sthe\spPager->noLock\sboolean\nfor\sclarity.
-D 2014-05-01T01:49:22.279
+C Add\stest\scases\sand\sdocumentation\sfor\sthe\snolock\sand\simmutable\squery\nparameters.
+D 2014-05-07T15:09:24.618
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -220,7 +220,7 @@ F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66
 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
 F src/select.c ed459f7f478a1e533d19c4b953693b3ffa2efd15
 F src/shell.c 2afe7a7154e97be0c74c5feacf09626bda8493be
-F src/sqlite.h.in ad2bbeb6a41c228f6a9dbf24df62e4d3eff79ee5
+F src/sqlite.h.in 564fc23db33870b5096b20d72df7491ce0b8b74f
 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
 F src/sqliteInt.h b2947801eccefd7ba3e5f14e1353289351a83cf3
@@ -270,7 +270,7 @@ F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
 F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
 F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
 F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb
-F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9
+F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c
 F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7
@@ -713,6 +713,7 @@ F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
 F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
 F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a
+F test/nolock.test 77b278317fa765b1ada5f88d59219cdeb8364f8f
 F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
 F test/notify2.test ce23eb522c9e1fff6443f96376fe67872202061c
 F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
@@ -1166,7 +1167,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 1829c38c3233c8cb194fae6d560d35a8916b1348
-R 9585bcff14fbe775451a3a647d896079
+P 725c1c14be331bce9bf074960dbfa7b6d4c1ba87
+R 89db3fd7a34cc009fbfa4be31d82927f
 U drh
-Z 3dae204f6c4a7be4483961b87ae0c17a
+Z 2af631f996ea658459fe7078e363eaf4
index d015fa2fa66ffc0d9768a6258be7a37830bf86ee..164fe707921daeb53203539c9ea2d6a9b9ebc641 100644 (file)
@@ -1 +1 @@
-725c1c14be331bce9bf074960dbfa7b6d4c1ba87
\ No newline at end of file
+19d56cbaca222b32e2e354063149cccd89441d73
\ No newline at end of file
index 81220a88221d6d8c8370c928a330c24f516d29a3..9be07fc1e687f9207086fb592b60ea2538132a5f 100644 (file)
@@ -2778,6 +2778,30 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
 **     a URI filename, its value overrides any behavior requested by setting
 **     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
+**
+**  <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
+**     "1") or "false" (or "off" or "no" or "0") to indicate that the
+**     [powersafe overwrite] property does or does not apply to the
+**     storage media on which the database file resides.  ^The psow query
+**     parameter only works for the built-in unix and Windows VFSes.
+**
+**  <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
+**     which if set disables file locking in rollback journal modes.  This
+**     is useful for accessing a database on a filesystem that does not
+**     support locking.  Caution:  Database corruption might result if two
+**     or more processes write to the same database and any one of those
+**     processes uses nolock=1.
+**
+**  <li> <b>immutable</b>: ^The immutable parameter is a boolean query
+**     parameter that indicates that the database file is stored on
+**     read-only media.  ^When immutable is set, SQLite assumes that the
+**     database file cannot be changed, even by a process with higher
+**     privilege, and so the database is opened read-only and all locking
+**     and change detection is disabled.  Caution: Setting the immutable
+**     property on a database file that does in fact change can result
+**     in incorrect query results and/or [SQLITE_CORRUPT] errors.
+**     See also: [SQLITE_IOCAP_IMMUTABLE].
+**       
 ** </ul>
 **
 ** ^Specifying an unknown parameter in the query component of a URI is not an
@@ -2807,8 +2831,9 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **          Open file "data.db" in the current directory for read-only access.
 **          Regardless of whether or not shared-cache mode is enabled by
 **          default, use a private cache.
-** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
-**          Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
+** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
+**          Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
+**          that uses dot-files in place of posix advisory locking.
 ** <tr><td> file:data.db?mode=readonly <td> 
 **          An error. "readonly" is not a valid option for the "mode" parameter.
 ** </table>
index 613b0fce77482b74116d23e9f59d0899ae56e078..7ee2a93453f56913b7911e706c325f56e17026fc 100644 (file)
@@ -127,8 +127,10 @@ struct Testvfs {
 #define TESTVFS_FULLPATHNAME_MASK 0x00008000
 #define TESTVFS_READ_MASK         0x00010000
 #define TESTVFS_UNLOCK_MASK       0x00020000
+#define TESTVFS_LOCK_MASK         0x00040000
+#define TESTVFS_CKLOCK_MASK       0x00080000
 
-#define TESTVFS_ALL_MASK          0x0003FFFF
+#define TESTVFS_ALL_MASK          0x000FFFFF
 
 
 #define TESTVFS_MAX_PAGES 1024
@@ -466,8 +468,15 @@ static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
 ** Lock an tvfs-file.
 */
 static int tvfsLock(sqlite3_file *pFile, int eLock){
-  TestvfsFd *p = tvfsGetFd(pFile);
-  return sqlite3OsLock(p->pReal, eLock);
+  TestvfsFd *pFd = tvfsGetFd(pFile);
+  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
+  if( p->pScript && p->mask&TESTVFS_LOCK_MASK ){
+    char zLock[30];
+    sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
+    tvfsExecTcl(p, "xLock", Tcl_NewStringObj(pFd->zFilename, -1), 
+                   Tcl_NewStringObj(zLock, -1), 0, 0);
+  }
+  return sqlite3OsLock(pFd->pReal, eLock);
 }
 
 /*
@@ -476,6 +485,12 @@ static int tvfsLock(sqlite3_file *pFile, int eLock){
 static int tvfsUnlock(sqlite3_file *pFile, int eLock){
   TestvfsFd *pFd = tvfsGetFd(pFile);
   Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
+  if( p->pScript && p->mask&TESTVFS_UNLOCK_MASK ){
+    char zLock[30];
+    sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
+    tvfsExecTcl(p, "xUnlock", Tcl_NewStringObj(pFd->zFilename, -1), 
+                   Tcl_NewStringObj(zLock, -1), 0, 0);
+  }
   if( p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
     return SQLITE_IOERR_UNLOCK;
   }
@@ -486,8 +501,13 @@ static int tvfsUnlock(sqlite3_file *pFile, int eLock){
 ** Check if another file-handle holds a RESERVED lock on an tvfs-file.
 */
 static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
-  TestvfsFd *p = tvfsGetFd(pFile);
-  return sqlite3OsCheckReservedLock(p->pReal, pResOut);
+  TestvfsFd *pFd = tvfsGetFd(pFile);
+  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
+  if( p->pScript && p->mask&TESTVFS_CKLOCK_MASK ){
+    tvfsExecTcl(p, "xCheckReservedLock", Tcl_NewStringObj(pFd->zFilename, -1),
+                   0, 0, 0);
+  }
+  return sqlite3OsCheckReservedLock(pFd->pReal, pResOut);
 }
 
 /*
@@ -1111,26 +1131,32 @@ static int testvfs_obj_cmd(
       break;
     }
 
+    /*  TESTVFS filter METHOD-LIST
+    **
+    **     Activate special processing for those methods contained in the list
+    */
     case CMD_FILTER: {
       static struct VfsMethod {
         char *zName;
         int mask;
       } vfsmethod [] = {
-        { "xShmOpen",      TESTVFS_SHMOPEN_MASK },
-        { "xShmLock",      TESTVFS_SHMLOCK_MASK },
-        { "xShmBarrier",   TESTVFS_SHMBARRIER_MASK },
-        { "xShmUnmap",     TESTVFS_SHMCLOSE_MASK },
-        { "xShmMap",       TESTVFS_SHMMAP_MASK },
-        { "xSync",         TESTVFS_SYNC_MASK },
-        { "xDelete",       TESTVFS_DELETE_MASK },
-        { "xWrite",        TESTVFS_WRITE_MASK },
-        { "xRead",         TESTVFS_READ_MASK },
-        { "xTruncate",     TESTVFS_TRUNCATE_MASK },
-        { "xOpen",         TESTVFS_OPEN_MASK },
-        { "xClose",        TESTVFS_CLOSE_MASK },
-        { "xAccess",       TESTVFS_ACCESS_MASK },
-        { "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
-        { "xUnlock",       TESTVFS_UNLOCK_MASK },
+        { "xShmOpen",           TESTVFS_SHMOPEN_MASK },
+        { "xShmLock",           TESTVFS_SHMLOCK_MASK },
+        { "xShmBarrier",        TESTVFS_SHMBARRIER_MASK },
+        { "xShmUnmap",          TESTVFS_SHMCLOSE_MASK },
+        { "xShmMap",            TESTVFS_SHMMAP_MASK },
+        { "xSync",              TESTVFS_SYNC_MASK },
+        { "xDelete",            TESTVFS_DELETE_MASK },
+        { "xWrite",             TESTVFS_WRITE_MASK },
+        { "xRead",              TESTVFS_READ_MASK },
+        { "xTruncate",          TESTVFS_TRUNCATE_MASK },
+        { "xOpen",              TESTVFS_OPEN_MASK },
+        { "xClose",             TESTVFS_CLOSE_MASK },
+        { "xAccess",            TESTVFS_ACCESS_MASK },
+        { "xFullPathname",      TESTVFS_FULLPATHNAME_MASK },
+        { "xUnlock",            TESTVFS_UNLOCK_MASK },
+        { "xLock",              TESTVFS_LOCK_MASK },
+        { "xCheckReservedLock", TESTVFS_CKLOCK_MASK },
       };
       Tcl_Obj **apElem = 0;
       int nElem = 0;
@@ -1162,6 +1188,12 @@ static int testvfs_obj_cmd(
       break;
     }
 
+    /*
+    **  TESTVFS script ?SCRIPT?
+    **
+    **  Query or set the script to be run when filtered VFS events
+    **  occur.
+    */
     case CMD_SCRIPT: {
       if( objc==3 ){
         int nByte;
@@ -1248,6 +1280,7 @@ static int testvfs_obj_cmd(
         { "safe_append",           SQLITE_IOCAP_SAFE_APPEND           },
         { "undeletable_when_open", SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN },
         { "powersafe_overwrite",   SQLITE_IOCAP_POWERSAFE_OVERWRITE   },
+        { "immutable",             SQLITE_IOCAP_IMMUTABLE             },
         { 0, 0 }
       };
       Tcl_Obj *pRet;
diff --git a/test/nolock.test b/test/nolock.test
new file mode 100644 (file)
index 0000000..98ed762
--- /dev/null
@@ -0,0 +1,143 @@
+# 2014-05-07
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file implements regression tests for SQLite library.  The
+# focus of this file is testing the nolock=1 and immutable=1 query
+# parameters and the SQLITE_IOCAP_IMMUTABLE device characteristic.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+unset -nocomplain tvfs_calls
+proc tvfs_reset {} {
+  global tvfs_calls
+  array set tvfs_calls {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
+}
+proc tvfs_callback {op args} {
+  global tvfs_calls
+  incr tvfs_calls($op)
+  return SQLITE_OK
+}
+tvfs_reset
+
+testvfs tvfs
+tvfs script tvfs_callback
+tvfs filter {xLock xUnlock xCheckReservedLock xAccess}
+
+############################################################################
+# Verify that the nolock=1 query parameter for URI filenames disables all
+# calls to xLock and xUnlock for rollback databases.
+#
+do_test nolock-1.0 {
+  db close
+  forcedelete test.db
+  tvfs_reset
+  sqlite db test.db -vfs tvfs
+  db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
+  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
+       xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
+} {xLock 7 xUnlock 5 xCheckReservedLock 0}
+
+do_test nolock-1.1 {
+  db close
+  forcedelete test.db
+  tvfs_reset
+  sqlite db file:test.db?nolock=0 -vfs tvfs -uri 1
+  db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
+  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
+       xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
+} {xLock 7 xUnlock 5 xCheckReservedLock 0}
+
+do_test nolock-1.2 {
+  db close
+  forcedelete test.db
+  tvfs_reset
+  sqlite db file:test.db?nolock=1 -vfs tvfs -uri 1
+  db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
+  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
+       xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
+} {xLock 0 xUnlock 0 xCheckReservedLock 0}
+
+#############################################################################
+# Verify that immutable=1 disables both locking and xAccess calls to the
+# journal files.
+#
+do_test nolock-2.0 {
+  db close
+  forcedelete test.db
+  # begin by creating a test database
+  sqlite3 db test.db
+  db eval {
+     CREATE TABLE t1(a,b);
+     INSERT INTO t1 VALUES('hello','world');
+     CREATE TABLE t2(x,y);
+     INSERT INTO t2 VALUES(12345,67890);
+     SELECT * FROM t1, t2;
+  }
+} {hello world 12345 67890}
+do_test nolock-2.1 {
+  tvfs_reset
+  sqlite3 db2 test.db -vfs tvfs
+  db2 eval {SELECT * FROM t1, t2}
+} {hello world 12345 67890}
+do_test nolock-2.2 {
+  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
+       xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
+       xAccess $::tvfs_calls(xAccess)
+} {xLock 2 xUnlock 2 xCheckReservedLock 0 xAccess 4}
+
+
+do_test nolock-2.11 {
+  db2 close
+  tvfs_reset
+  sqlite3 db2 file:test.db?immutable=0 -vfs tvfs -uri 1
+  db2 eval {SELECT * FROM t1, t2}
+} {hello world 12345 67890}
+do_test nolock-2.12 {
+  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
+       xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
+       xAccess $::tvfs_calls(xAccess)
+} {xLock 2 xUnlock 2 xCheckReservedLock 0 xAccess 4}
+
+
+do_test nolock-2.21 {
+  db2 close
+  tvfs_reset
+  sqlite3 db2 file:test.db?immutable=1 -vfs tvfs -uri 1
+  db2 eval {SELECT * FROM t1, t2}
+} {hello world 12345 67890}
+do_test nolock-2.22 {
+  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
+       xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
+       xAccess $::tvfs_calls(xAccess)
+} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
+
+############################################################################
+# Verify that the SQLITE_IOCAP_IMMUTABLE flag works
+#
+do_test nolock-3.1 {
+  db2 close
+  tvfs devchar immutable
+  tvfs_reset
+  sqlite3 db2 test.db -vfs tvfs
+  db2 eval {SELECT * FROM t1, t2}
+} {hello world 12345 67890}
+do_test nolock-3.2 {
+  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
+       xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
+       xAccess $::tvfs_calls(xAccess)
+} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
+
+db2 close
+db close
+tvfs delete
+finish_test