/ Check-in [19d56cba]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add test cases and documentation for the nolock and immutable query parameters.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | win32-none
Files: files | file ages | folders
SHA1: 19d56cbaca222b32e2e354063149cccd89441d73
User & Date: drh 2014-05-07 15:09:24
Context
2014-05-07
15:32
Fix nolock and immutable so that they work even if READONLY is requested. Closed-Leaf check-in: e193aced user: drh tags: win32-none
15:09
Add test cases and documentation for the nolock and immutable query parameters. check-in: 19d56cba user: drh tags: win32-none
2014-05-01
01:49
Take out the special handling of nolock=true in os_win.c and add it to pager.c, so that it works for all VFSes. Add the pPager->noLock boolean for clarity. check-in: 725c1c14 user: drh tags: win32-none
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/sqlite.h.in.

  2774   2774   **     "private". ^Setting it to "shared" is equivalent to setting the
  2775   2775   **     SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
  2776   2776   **     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
  2777   2777   **     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
  2778   2778   **     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
  2779   2779   **     a URI filename, its value overrides any behavior requested by setting
  2780   2780   **     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
         2781  +**
         2782  +**  <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
         2783  +**     "1") or "false" (or "off" or "no" or "0") to indicate that the
         2784  +**     [powersafe overwrite] property does or does not apply to the
         2785  +**     storage media on which the database file resides.  ^The psow query
         2786  +**     parameter only works for the built-in unix and Windows VFSes.
         2787  +**
         2788  +**  <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
         2789  +**     which if set disables file locking in rollback journal modes.  This
         2790  +**     is useful for accessing a database on a filesystem that does not
         2791  +**     support locking.  Caution:  Database corruption might result if two
         2792  +**     or more processes write to the same database and any one of those
         2793  +**     processes uses nolock=1.
         2794  +**
         2795  +**  <li> <b>immutable</b>: ^The immutable parameter is a boolean query
         2796  +**     parameter that indicates that the database file is stored on
         2797  +**     read-only media.  ^When immutable is set, SQLite assumes that the
         2798  +**     database file cannot be changed, even by a process with higher
         2799  +**     privilege, and so the database is opened read-only and all locking
         2800  +**     and change detection is disabled.  Caution: Setting the immutable
         2801  +**     property on a database file that does in fact change can result
         2802  +**     in incorrect query results and/or [SQLITE_CORRUPT] errors.
         2803  +**     See also: [SQLITE_IOCAP_IMMUTABLE].
         2804  +**       
  2781   2805   ** </ul>
  2782   2806   **
  2783   2807   ** ^Specifying an unknown parameter in the query component of a URI is not an
  2784   2808   ** error.  Future versions of SQLite might understand additional query
  2785   2809   ** parameters.  See "[query parameters with special meaning to SQLite]" for
  2786   2810   ** additional information.
  2787   2811   **
................................................................................
  2803   2827   **          C:. Note that the %20 escaping in this example is not strictly 
  2804   2828   **          necessary - space characters can be used literally
  2805   2829   **          in URI filenames.
  2806   2830   ** <tr><td> file:data.db?mode=ro&cache=private <td> 
  2807   2831   **          Open file "data.db" in the current directory for read-only access.
  2808   2832   **          Regardless of whether or not shared-cache mode is enabled by
  2809   2833   **          default, use a private cache.
  2810         -** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
  2811         -**          Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
         2834  +** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
         2835  +**          Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
         2836  +**          that uses dot-files in place of posix advisory locking.
  2812   2837   ** <tr><td> file:data.db?mode=readonly <td> 
  2813   2838   **          An error. "readonly" is not a valid option for the "mode" parameter.
  2814   2839   ** </table>
  2815   2840   **
  2816   2841   ** ^URI hexadecimal escape sequences (%HH) are supported within the path and
  2817   2842   ** query components of a URI. A hexadecimal escape sequence consists of a
  2818   2843   ** percent sign - "%" - followed by exactly two hexadecimal digits 

Changes to src/test_vfs.c.

   123    123   #define TESTVFS_CLOSE_MASK        0x00000800
   124    124   #define TESTVFS_WRITE_MASK        0x00001000
   125    125   #define TESTVFS_TRUNCATE_MASK     0x00002000
   126    126   #define TESTVFS_ACCESS_MASK       0x00004000
   127    127   #define TESTVFS_FULLPATHNAME_MASK 0x00008000
   128    128   #define TESTVFS_READ_MASK         0x00010000
   129    129   #define TESTVFS_UNLOCK_MASK       0x00020000
          130  +#define TESTVFS_LOCK_MASK         0x00040000
          131  +#define TESTVFS_CKLOCK_MASK       0x00080000
   130    132   
   131         -#define TESTVFS_ALL_MASK          0x0003FFFF
          133  +#define TESTVFS_ALL_MASK          0x000FFFFF
   132    134   
   133    135   
   134    136   #define TESTVFS_MAX_PAGES 1024
   135    137   
   136    138   /*
   137    139   ** A shared-memory buffer. There is one of these objects for each shared
   138    140   ** memory region opened by clients. If two clients open the same file,
................................................................................
   462    464     return sqlite3OsFileSize(p->pReal, pSize);
   463    465   }
   464    466   
   465    467   /*
   466    468   ** Lock an tvfs-file.
   467    469   */
   468    470   static int tvfsLock(sqlite3_file *pFile, int eLock){
   469         -  TestvfsFd *p = tvfsGetFd(pFile);
   470         -  return sqlite3OsLock(p->pReal, eLock);
          471  +  TestvfsFd *pFd = tvfsGetFd(pFile);
          472  +  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
          473  +  if( p->pScript && p->mask&TESTVFS_LOCK_MASK ){
          474  +    char zLock[30];
          475  +    sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
          476  +    tvfsExecTcl(p, "xLock", Tcl_NewStringObj(pFd->zFilename, -1), 
          477  +                   Tcl_NewStringObj(zLock, -1), 0, 0);
          478  +  }
          479  +  return sqlite3OsLock(pFd->pReal, eLock);
   471    480   }
   472    481   
   473    482   /*
   474    483   ** Unlock an tvfs-file.
   475    484   */
   476    485   static int tvfsUnlock(sqlite3_file *pFile, int eLock){
   477    486     TestvfsFd *pFd = tvfsGetFd(pFile);
   478    487     Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
          488  +  if( p->pScript && p->mask&TESTVFS_UNLOCK_MASK ){
          489  +    char zLock[30];
          490  +    sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
          491  +    tvfsExecTcl(p, "xUnlock", Tcl_NewStringObj(pFd->zFilename, -1), 
          492  +                   Tcl_NewStringObj(zLock, -1), 0, 0);
          493  +  }
   479    494     if( p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
   480    495       return SQLITE_IOERR_UNLOCK;
   481    496     }
   482    497     return sqlite3OsUnlock(pFd->pReal, eLock);
   483    498   }
   484    499   
   485    500   /*
   486    501   ** Check if another file-handle holds a RESERVED lock on an tvfs-file.
   487    502   */
   488    503   static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
   489         -  TestvfsFd *p = tvfsGetFd(pFile);
   490         -  return sqlite3OsCheckReservedLock(p->pReal, pResOut);
          504  +  TestvfsFd *pFd = tvfsGetFd(pFile);
          505  +  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
          506  +  if( p->pScript && p->mask&TESTVFS_CKLOCK_MASK ){
          507  +    tvfsExecTcl(p, "xCheckReservedLock", Tcl_NewStringObj(pFd->zFilename, -1),
          508  +                   0, 0, 0);
          509  +  }
          510  +  return sqlite3OsCheckReservedLock(pFd->pReal, pResOut);
   491    511   }
   492    512   
   493    513   /*
   494    514   ** File control method. For custom operations on an tvfs-file.
   495    515   */
   496    516   static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){
   497    517     TestvfsFd *p = tvfsGetFd(pFile);
................................................................................
  1107   1127           if( pgsz==0 ) pgsz = 65536;
  1108   1128           Tcl_AppendObjToObj(pObj, Tcl_NewByteArrayObj(pBuffer->aPage[i], pgsz));
  1109   1129         }
  1110   1130         Tcl_SetObjResult(interp, pObj);
  1111   1131         break;
  1112   1132       }
  1113   1133   
         1134  +    /*  TESTVFS filter METHOD-LIST
         1135  +    **
         1136  +    **     Activate special processing for those methods contained in the list
         1137  +    */
  1114   1138       case CMD_FILTER: {
  1115   1139         static struct VfsMethod {
  1116   1140           char *zName;
  1117   1141           int mask;
  1118   1142         } vfsmethod [] = {
  1119         -        { "xShmOpen",      TESTVFS_SHMOPEN_MASK },
  1120         -        { "xShmLock",      TESTVFS_SHMLOCK_MASK },
  1121         -        { "xShmBarrier",   TESTVFS_SHMBARRIER_MASK },
  1122         -        { "xShmUnmap",     TESTVFS_SHMCLOSE_MASK },
  1123         -        { "xShmMap",       TESTVFS_SHMMAP_MASK },
  1124         -        { "xSync",         TESTVFS_SYNC_MASK },
  1125         -        { "xDelete",       TESTVFS_DELETE_MASK },
  1126         -        { "xWrite",        TESTVFS_WRITE_MASK },
  1127         -        { "xRead",         TESTVFS_READ_MASK },
  1128         -        { "xTruncate",     TESTVFS_TRUNCATE_MASK },
  1129         -        { "xOpen",         TESTVFS_OPEN_MASK },
  1130         -        { "xClose",        TESTVFS_CLOSE_MASK },
  1131         -        { "xAccess",       TESTVFS_ACCESS_MASK },
  1132         -        { "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
  1133         -        { "xUnlock",       TESTVFS_UNLOCK_MASK },
         1143  +        { "xShmOpen",           TESTVFS_SHMOPEN_MASK },
         1144  +        { "xShmLock",           TESTVFS_SHMLOCK_MASK },
         1145  +        { "xShmBarrier",        TESTVFS_SHMBARRIER_MASK },
         1146  +        { "xShmUnmap",          TESTVFS_SHMCLOSE_MASK },
         1147  +        { "xShmMap",            TESTVFS_SHMMAP_MASK },
         1148  +        { "xSync",              TESTVFS_SYNC_MASK },
         1149  +        { "xDelete",            TESTVFS_DELETE_MASK },
         1150  +        { "xWrite",             TESTVFS_WRITE_MASK },
         1151  +        { "xRead",              TESTVFS_READ_MASK },
         1152  +        { "xTruncate",          TESTVFS_TRUNCATE_MASK },
         1153  +        { "xOpen",              TESTVFS_OPEN_MASK },
         1154  +        { "xClose",             TESTVFS_CLOSE_MASK },
         1155  +        { "xAccess",            TESTVFS_ACCESS_MASK },
         1156  +        { "xFullPathname",      TESTVFS_FULLPATHNAME_MASK },
         1157  +        { "xUnlock",            TESTVFS_UNLOCK_MASK },
         1158  +        { "xLock",              TESTVFS_LOCK_MASK },
         1159  +        { "xCheckReservedLock", TESTVFS_CKLOCK_MASK },
  1134   1160         };
  1135   1161         Tcl_Obj **apElem = 0;
  1136   1162         int nElem = 0;
  1137   1163         int i;
  1138   1164         int mask = 0;
  1139   1165         if( objc!=3 ){
  1140   1166           Tcl_WrongNumArgs(interp, 2, objv, "LIST");
................................................................................
  1158   1184             return TCL_ERROR;
  1159   1185           }
  1160   1186         }
  1161   1187         p->mask = mask;
  1162   1188         break;
  1163   1189       }
  1164   1190   
         1191  +    /*
         1192  +    **  TESTVFS script ?SCRIPT?
         1193  +    **
         1194  +    **  Query or set the script to be run when filtered VFS events
         1195  +    **  occur.
         1196  +    */
  1165   1197       case CMD_SCRIPT: {
  1166   1198         if( objc==3 ){
  1167   1199           int nByte;
  1168   1200           if( p->pScript ){
  1169   1201             Tcl_DecrRefCount(p->pScript);
  1170   1202             p->pScript = 0;
  1171   1203           }
................................................................................
  1244   1276           { "atomic16k",             SQLITE_IOCAP_ATOMIC16K             },
  1245   1277           { "atomic32k",             SQLITE_IOCAP_ATOMIC32K             },
  1246   1278           { "atomic64k",             SQLITE_IOCAP_ATOMIC64K             },
  1247   1279           { "sequential",            SQLITE_IOCAP_SEQUENTIAL            },
  1248   1280           { "safe_append",           SQLITE_IOCAP_SAFE_APPEND           },
  1249   1281           { "undeletable_when_open", SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN },
  1250   1282           { "powersafe_overwrite",   SQLITE_IOCAP_POWERSAFE_OVERWRITE   },
         1283  +        { "immutable",             SQLITE_IOCAP_IMMUTABLE             },
  1251   1284           { 0, 0 }
  1252   1285         };
  1253   1286         Tcl_Obj *pRet;
  1254   1287         int iFlag;
  1255   1288   
  1256   1289         if( objc>3 ){
  1257   1290           Tcl_WrongNumArgs(interp, 2, objv, "?ATTR-LIST?");

Added test/nolock.test.

            1  +# 2014-05-07
            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  +# This file implements regression tests for SQLite library.  The
           13  +# focus of this file is testing the nolock=1 and immutable=1 query
           14  +# parameters and the SQLITE_IOCAP_IMMUTABLE device characteristic.
           15  +#
           16  +
           17  +set testdir [file dirname $argv0]
           18  +source $testdir/tester.tcl
           19  +
           20  +unset -nocomplain tvfs_calls
           21  +proc tvfs_reset {} {
           22  +  global tvfs_calls
           23  +  array set tvfs_calls {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
           24  +}
           25  +proc tvfs_callback {op args} {
           26  +  global tvfs_calls
           27  +  incr tvfs_calls($op)
           28  +  return SQLITE_OK
           29  +}
           30  +tvfs_reset
           31  +
           32  +testvfs tvfs
           33  +tvfs script tvfs_callback
           34  +tvfs filter {xLock xUnlock xCheckReservedLock xAccess}
           35  +
           36  +############################################################################
           37  +# Verify that the nolock=1 query parameter for URI filenames disables all
           38  +# calls to xLock and xUnlock for rollback databases.
           39  +#
           40  +do_test nolock-1.0 {
           41  +  db close
           42  +  forcedelete test.db
           43  +  tvfs_reset
           44  +  sqlite db test.db -vfs tvfs
           45  +  db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
           46  +  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
           47  +       xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
           48  +} {xLock 7 xUnlock 5 xCheckReservedLock 0}
           49  +
           50  +do_test nolock-1.1 {
           51  +  db close
           52  +  forcedelete test.db
           53  +  tvfs_reset
           54  +  sqlite db file:test.db?nolock=0 -vfs tvfs -uri 1
           55  +  db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
           56  +  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
           57  +       xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
           58  +} {xLock 7 xUnlock 5 xCheckReservedLock 0}
           59  +
           60  +do_test nolock-1.2 {
           61  +  db close
           62  +  forcedelete test.db
           63  +  tvfs_reset
           64  +  sqlite db file:test.db?nolock=1 -vfs tvfs -uri 1
           65  +  db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
           66  +  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
           67  +       xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
           68  +} {xLock 0 xUnlock 0 xCheckReservedLock 0}
           69  +
           70  +#############################################################################
           71  +# Verify that immutable=1 disables both locking and xAccess calls to the
           72  +# journal files.
           73  +#
           74  +do_test nolock-2.0 {
           75  +  db close
           76  +  forcedelete test.db
           77  +  # begin by creating a test database
           78  +  sqlite3 db test.db
           79  +  db eval {
           80  +     CREATE TABLE t1(a,b);
           81  +     INSERT INTO t1 VALUES('hello','world');
           82  +     CREATE TABLE t2(x,y);
           83  +     INSERT INTO t2 VALUES(12345,67890);
           84  +     SELECT * FROM t1, t2;
           85  +  }
           86  +} {hello world 12345 67890}
           87  +do_test nolock-2.1 {
           88  +  tvfs_reset
           89  +  sqlite3 db2 test.db -vfs tvfs
           90  +  db2 eval {SELECT * FROM t1, t2}
           91  +} {hello world 12345 67890}
           92  +do_test nolock-2.2 {
           93  +  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
           94  +       xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
           95  +       xAccess $::tvfs_calls(xAccess)
           96  +} {xLock 2 xUnlock 2 xCheckReservedLock 0 xAccess 4}
           97  +
           98  +
           99  +do_test nolock-2.11 {
          100  +  db2 close
          101  +  tvfs_reset
          102  +  sqlite3 db2 file:test.db?immutable=0 -vfs tvfs -uri 1
          103  +  db2 eval {SELECT * FROM t1, t2}
          104  +} {hello world 12345 67890}
          105  +do_test nolock-2.12 {
          106  +  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
          107  +       xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
          108  +       xAccess $::tvfs_calls(xAccess)
          109  +} {xLock 2 xUnlock 2 xCheckReservedLock 0 xAccess 4}
          110  +
          111  +
          112  +do_test nolock-2.21 {
          113  +  db2 close
          114  +  tvfs_reset
          115  +  sqlite3 db2 file:test.db?immutable=1 -vfs tvfs -uri 1
          116  +  db2 eval {SELECT * FROM t1, t2}
          117  +} {hello world 12345 67890}
          118  +do_test nolock-2.22 {
          119  +  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
          120  +       xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
          121  +       xAccess $::tvfs_calls(xAccess)
          122  +} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
          123  +
          124  +############################################################################
          125  +# Verify that the SQLITE_IOCAP_IMMUTABLE flag works
          126  +#
          127  +do_test nolock-3.1 {
          128  +  db2 close
          129  +  tvfs devchar immutable
          130  +  tvfs_reset
          131  +  sqlite3 db2 test.db -vfs tvfs
          132  +  db2 eval {SELECT * FROM t1, t2}
          133  +} {hello world 12345 67890}
          134  +do_test nolock-3.2 {
          135  +  list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
          136  +       xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
          137  +       xAccess $::tvfs_calls(xAccess)
          138  +} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
          139  +
          140  +db2 close
          141  +db close
          142  +tvfs delete
          143  +finish_test