/ Changes On Branch win32nolock
Login

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

Changes In Branch win32nolock Excluding Merge-Ins

This is equivalent to a diff from e1d8ef311c to 549abe3f89

2016-07-09
00:06
Add support for the win32-none VFS. (check-in: b5f32a896d user: drh tags: trunk)
2016-07-08
21:14
Initial work on a Win32 VFS with NOP locking. (Closed-Leaf check-in: 549abe3f89 user: mistachkin tags: win32nolock)
19:54
Another attempt to fix error handling in Lemon. This change is a no-op for SQLite's usage. (check-in: e1d8ef311c user: drh tags: trunk)
02:14
In the sqldiff program, make sure the first argument to the db_prepare() utility function is always a valid format string. (check-in: 8bb8d886ff user: drh tags: trunk)

Changes to src/os_win.c.

   286    286     void *pMapRegion;             /* Area memory mapped */
   287    287     sqlite3_int64 mmapSize;       /* Usable size of mapped region */
   288    288     sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
   289    289     sqlite3_int64 mmapSizeMax;    /* Configured FCNTL_MMAP_SIZE value */
   290    290   #endif
   291    291   };
   292    292   
          293  +/*
          294  +** The winVfsAppData structure is used for the pAppData member for all of the
          295  +** Win32 VFS variants.
          296  +*/
          297  +typedef struct winVfsAppData winVfsAppData;
          298  +struct winVfsAppData {
          299  +  const sqlite3_io_methods *pMethod; /* The file I/O methods to use. */
          300  +  void *pAppData;                    /* The extra pAppData, if any. */
          301  +  BOOL bNoLock;                      /* Non-zero if locking is disabled. */
          302  +};
          303  +
   293    304   /*
   294    305   ** Allowed values for winFile.ctrlFlags
   295    306   */
   296    307   #define WINFILE_RDONLY          0x02   /* Connection is read only */
   297    308   #define WINFILE_PERSIST_WAL     0x04   /* Persistent WAL mode */
   298    309   #define WINFILE_PSOW            0x10   /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
   299    310   
................................................................................
  2607   2618   
  2608   2619     do{
  2609   2620       rc = osCloseHandle(pFile->h);
  2610   2621       /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
  2611   2622     }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
  2612   2623   #if SQLITE_OS_WINCE
  2613   2624   #define WINCE_DELETION_ATTEMPTS 3
  2614         -  winceDestroyLock(pFile);
         2625  +  {
         2626  +    winVfsAppData *pAppData = (winVfsAppData*)pFile->pVfs->pAppData;
         2627  +    if( pAppData==NULL || !pAppData->bNoLock ){
         2628  +      winceDestroyLock(pFile);
         2629  +    }
         2630  +  }
  2615   2631     if( pFile->zDeleteOnClose ){
  2616   2632       int cnt = 0;
  2617   2633       while(
  2618   2634              osDeleteFileW(pFile->zDeleteOnClose)==0
  2619   2635           && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
  2620   2636           && cnt++ < WINCE_DELETION_ATTEMPTS
  2621   2637       ){
................................................................................
  3338   3354       winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
  3339   3355     }
  3340   3356     pFile->locktype = (u8)locktype;
  3341   3357     OSTRACE(("UNLOCK file=%p, lock=%d, rc=%s\n",
  3342   3358              pFile->h, pFile->locktype, sqlite3ErrName(rc)));
  3343   3359     return rc;
  3344   3360   }
         3361  +
         3362  +/******************************************************************************
         3363  +****************************** No-op Locking **********************************
         3364  +**
         3365  +** Of the various locking implementations available, this is by far the
         3366  +** simplest:  locking is ignored.  No attempt is made to lock the database
         3367  +** file for reading or writing.
         3368  +**
         3369  +** This locking mode is appropriate for use on read-only databases
         3370  +** (ex: databases that are burned into CD-ROM, for example.)  It can
         3371  +** also be used if the application employs some external mechanism to
         3372  +** prevent simultaneous access of the same database by two or more
         3373  +** database connections.  But there is a serious risk of database
         3374  +** corruption if this locking mode is used in situations where multiple
         3375  +** database connections are accessing the same database file at the same
         3376  +** time and one or more of those connections are writing.
         3377  +*/
         3378  +
         3379  +static int winNolockLock(sqlite3_file *id, int locktype){
         3380  +  UNUSED_PARAMETER(id);
         3381  +  UNUSED_PARAMETER(locktype);
         3382  +  return SQLITE_OK;
         3383  +}
         3384  +
         3385  +static int winNolockCheckReservedLock(sqlite3_file *id, int *pResOut){
         3386  +  UNUSED_PARAMETER(id);
         3387  +  UNUSED_PARAMETER(pResOut);
         3388  +  return SQLITE_OK;
         3389  +}
         3390  +
         3391  +static int winNolockUnlock(sqlite3_file *id, int locktype){
         3392  +  UNUSED_PARAMETER(id);
         3393  +  UNUSED_PARAMETER(locktype);
         3394  +  return SQLITE_OK;
         3395  +}
         3396  +
         3397  +/******************* End of the no-op lock implementation *********************
         3398  +******************************************************************************/
  3345   3399   
  3346   3400   /*
  3347   3401   ** If *pArg is initially negative then this is a query.  Set *pArg to
  3348   3402   ** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
  3349   3403   **
  3350   3404   ** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
  3351   3405   */
................................................................................
  4402   4456     winShmMap,                      /* xShmMap */
  4403   4457     winShmLock,                     /* xShmLock */
  4404   4458     winShmBarrier,                  /* xShmBarrier */
  4405   4459     winShmUnmap,                    /* xShmUnmap */
  4406   4460     winFetch,                       /* xFetch */
  4407   4461     winUnfetch                      /* xUnfetch */
  4408   4462   };
         4463  +
         4464  +/*
         4465  +** This vector defines all the methods that can operate on an
         4466  +** sqlite3_file for win32 without performing any locking.
         4467  +*/
         4468  +static const sqlite3_io_methods winIoNolockMethod = {
         4469  +  3,                              /* iVersion */
         4470  +  winClose,                       /* xClose */
         4471  +  winRead,                        /* xRead */
         4472  +  winWrite,                       /* xWrite */
         4473  +  winTruncate,                    /* xTruncate */
         4474  +  winSync,                        /* xSync */
         4475  +  winFileSize,                    /* xFileSize */
         4476  +  winNolockLock,                  /* xLock */
         4477  +  winNolockUnlock,                /* xUnlock */
         4478  +  winNolockCheckReservedLock,     /* xCheckReservedLock */
         4479  +  winFileControl,                 /* xFileControl */
         4480  +  winSectorSize,                  /* xSectorSize */
         4481  +  winDeviceCharacteristics,       /* xDeviceCharacteristics */
         4482  +  winShmMap,                      /* xShmMap */
         4483  +  winShmLock,                     /* xShmLock */
         4484  +  winShmBarrier,                  /* xShmBarrier */
         4485  +  winShmUnmap,                    /* xShmUnmap */
         4486  +  winFetch,                       /* xFetch */
         4487  +  winUnfetch                      /* xUnfetch */
         4488  +};
         4489  +
         4490  +static winVfsAppData winAppData = {
         4491  +  &winIoMethod,       /* pMethod */
         4492  +  0,                  /* pAppData */
         4493  +  0                   /* bNoLock */
         4494  +};
         4495  +
         4496  +static winVfsAppData winNolockAppData = {
         4497  +  &winIoNolockMethod, /* pMethod */
         4498  +  0,                  /* pAppData */
         4499  +  1                   /* bNoLock */
         4500  +};
  4409   4501   
  4410   4502   /****************************************************************************
  4411   4503   **************************** sqlite3_vfs methods ****************************
  4412   4504   **
  4413   4505   ** This division contains the implementation of methods on the
  4414   4506   ** sqlite3_vfs object.
  4415   4507   */
................................................................................
  4735   4827     return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY);
  4736   4828   }
  4737   4829   
  4738   4830   /*
  4739   4831   ** Open a file.
  4740   4832   */
  4741   4833   static int winOpen(
  4742         -  sqlite3_vfs *pVfs,        /* Used to get maximum path name length */
         4834  +  sqlite3_vfs *pVfs,        /* Used to get maximum path length and AppData */
  4743   4835     const char *zName,        /* Name of the file (UTF-8) */
  4744   4836     sqlite3_file *id,         /* Write the SQLite file handle here */
  4745   4837     int flags,                /* Open mode flags */
  4746   4838     int *pOutFlags            /* Status return flags */
  4747   4839   ){
  4748   4840     HANDLE h;
  4749   4841     DWORD lastErrno = 0;
................................................................................
  4750   4842     DWORD dwDesiredAccess;
  4751   4843     DWORD dwShareMode;
  4752   4844     DWORD dwCreationDisposition;
  4753   4845     DWORD dwFlagsAndAttributes = 0;
  4754   4846   #if SQLITE_OS_WINCE
  4755   4847     int isTemp = 0;
  4756   4848   #endif
         4849  +  winVfsAppData *pAppData;
  4757   4850     winFile *pFile = (winFile*)id;
  4758   4851     void *zConverted;              /* Filename in OS encoding */
  4759   4852     const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
  4760   4853     int cnt = 0;
  4761   4854   
  4762   4855     /* If argument zPath is a NULL pointer, this function is required to open
  4763   4856     ** a temporary file. Use this buffer to store the file name in.
................................................................................
  4971   5064       }
  4972   5065     }
  4973   5066   
  4974   5067     OSTRACE(("OPEN file=%p, name=%s, access=%lx, pOutFlags=%p, *pOutFlags=%d, "
  4975   5068              "rc=%s\n", h, zUtf8Name, dwDesiredAccess, pOutFlags, pOutFlags ?
  4976   5069              *pOutFlags : 0, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
  4977   5070   
         5071  +  pAppData = (winVfsAppData*)pVfs->pAppData;
         5072  +
  4978   5073   #if SQLITE_OS_WINCE
  4979         -  if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
  4980         -       && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
  4981         -  ){
  4982         -    osCloseHandle(h);
  4983         -    sqlite3_free(zConverted);
  4984         -    sqlite3_free(zTmpname);
  4985         -    OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc)));
  4986         -    return rc;
         5074  +  {
         5075  +    if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
         5076  +         && ((pAppData==NULL) || !pAppData->bNoLock)
         5077  +         && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
         5078  +    ){
         5079  +      osCloseHandle(h);
         5080  +      sqlite3_free(zConverted);
         5081  +      sqlite3_free(zTmpname);
         5082  +      OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc)));
         5083  +      return rc;
         5084  +    }
  4987   5085     }
  4988   5086     if( isTemp ){
  4989   5087       pFile->zDeleteOnClose = zConverted;
  4990   5088     }else
  4991   5089   #endif
  4992   5090     {
  4993   5091       sqlite3_free(zConverted);
  4994   5092     }
  4995   5093   
  4996   5094     sqlite3_free(zTmpname);
  4997         -  pFile->pMethod = &winIoMethod;
         5095  +  pFile->pMethod = pAppData ? pAppData->pMethod : &winIoMethod;
  4998   5096     pFile->pVfs = pVfs;
  4999   5097     pFile->h = h;
  5000   5098     if( isReadonly ){
  5001   5099       pFile->ctrlFlags |= WINFILE_RDONLY;
  5002   5100     }
  5003   5101     if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
  5004   5102       pFile->ctrlFlags |= WINFILE_PSOW;
................................................................................
  5713   5811   }
  5714   5812   
  5715   5813   /*
  5716   5814   ** Initialize and deinitialize the operating system interface.
  5717   5815   */
  5718   5816   int sqlite3_os_init(void){
  5719   5817     static sqlite3_vfs winVfs = {
  5720         -    3,                   /* iVersion */
  5721         -    sizeof(winFile),     /* szOsFile */
         5818  +    3,                     /* iVersion */
         5819  +    sizeof(winFile),       /* szOsFile */
  5722   5820       SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */
  5723         -    0,                   /* pNext */
  5724         -    "win32",             /* zName */
  5725         -    0,                   /* pAppData */
  5726         -    winOpen,             /* xOpen */
  5727         -    winDelete,           /* xDelete */
  5728         -    winAccess,           /* xAccess */
  5729         -    winFullPathname,     /* xFullPathname */
  5730         -    winDlOpen,           /* xDlOpen */
  5731         -    winDlError,          /* xDlError */
  5732         -    winDlSym,            /* xDlSym */
  5733         -    winDlClose,          /* xDlClose */
  5734         -    winRandomness,       /* xRandomness */
  5735         -    winSleep,            /* xSleep */
  5736         -    winCurrentTime,      /* xCurrentTime */
  5737         -    winGetLastError,     /* xGetLastError */
  5738         -    winCurrentTimeInt64, /* xCurrentTimeInt64 */
  5739         -    winSetSystemCall,    /* xSetSystemCall */
  5740         -    winGetSystemCall,    /* xGetSystemCall */
  5741         -    winNextSystemCall,   /* xNextSystemCall */
         5821  +    0,                     /* pNext */
         5822  +    "win32",               /* zName */
         5823  +    &winAppData,           /* pAppData */
         5824  +    winOpen,               /* xOpen */
         5825  +    winDelete,             /* xDelete */
         5826  +    winAccess,             /* xAccess */
         5827  +    winFullPathname,       /* xFullPathname */
         5828  +    winDlOpen,             /* xDlOpen */
         5829  +    winDlError,            /* xDlError */
         5830  +    winDlSym,              /* xDlSym */
         5831  +    winDlClose,            /* xDlClose */
         5832  +    winRandomness,         /* xRandomness */
         5833  +    winSleep,              /* xSleep */
         5834  +    winCurrentTime,        /* xCurrentTime */
         5835  +    winGetLastError,       /* xGetLastError */
         5836  +    winCurrentTimeInt64,   /* xCurrentTimeInt64 */
         5837  +    winSetSystemCall,      /* xSetSystemCall */
         5838  +    winGetSystemCall,      /* xGetSystemCall */
         5839  +    winNextSystemCall,     /* xNextSystemCall */
  5742   5840     };
  5743   5841   #if defined(SQLITE_WIN32_HAS_WIDE)
  5744   5842     static sqlite3_vfs winLongPathVfs = {
  5745         -    3,                   /* iVersion */
  5746         -    sizeof(winFile),     /* szOsFile */
         5843  +    3,                     /* iVersion */
         5844  +    sizeof(winFile),       /* szOsFile */
         5845  +    SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */
         5846  +    0,                     /* pNext */
         5847  +    "win32-longpath",      /* zName */
         5848  +    &winAppData,           /* pAppData */
         5849  +    winOpen,               /* xOpen */
         5850  +    winDelete,             /* xDelete */
         5851  +    winAccess,             /* xAccess */
         5852  +    winFullPathname,       /* xFullPathname */
         5853  +    winDlOpen,             /* xDlOpen */
         5854  +    winDlError,            /* xDlError */
         5855  +    winDlSym,              /* xDlSym */
         5856  +    winDlClose,            /* xDlClose */
         5857  +    winRandomness,         /* xRandomness */
         5858  +    winSleep,              /* xSleep */
         5859  +    winCurrentTime,        /* xCurrentTime */
         5860  +    winGetLastError,       /* xGetLastError */
         5861  +    winCurrentTimeInt64,   /* xCurrentTimeInt64 */
         5862  +    winSetSystemCall,      /* xSetSystemCall */
         5863  +    winGetSystemCall,      /* xGetSystemCall */
         5864  +    winNextSystemCall,     /* xNextSystemCall */
         5865  +  };
         5866  +#endif
         5867  +  static sqlite3_vfs winNolockVfs = {
         5868  +    3,                     /* iVersion */
         5869  +    sizeof(winFile),       /* szOsFile */
         5870  +    SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */
         5871  +    0,                     /* pNext */
         5872  +    "win32-none",          /* zName */
         5873  +    &winNolockAppData,     /* pAppData */
         5874  +    winOpen,               /* xOpen */
         5875  +    winDelete,             /* xDelete */
         5876  +    winAccess,             /* xAccess */
         5877  +    winFullPathname,       /* xFullPathname */
         5878  +    winDlOpen,             /* xDlOpen */
         5879  +    winDlError,            /* xDlError */
         5880  +    winDlSym,              /* xDlSym */
         5881  +    winDlClose,            /* xDlClose */
         5882  +    winRandomness,         /* xRandomness */
         5883  +    winSleep,              /* xSleep */
         5884  +    winCurrentTime,        /* xCurrentTime */
         5885  +    winGetLastError,       /* xGetLastError */
         5886  +    winCurrentTimeInt64,   /* xCurrentTimeInt64 */
         5887  +    winSetSystemCall,      /* xSetSystemCall */
         5888  +    winGetSystemCall,      /* xGetSystemCall */
         5889  +    winNextSystemCall,     /* xNextSystemCall */
         5890  +  };
         5891  +#if defined(SQLITE_WIN32_HAS_WIDE)
         5892  +  static sqlite3_vfs winLongPathNolockVfs = {
         5893  +    3,                     /* iVersion */
         5894  +    sizeof(winFile),       /* szOsFile */
  5747   5895       SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */
  5748         -    0,                   /* pNext */
  5749         -    "win32-longpath",    /* zName */
  5750         -    0,                   /* pAppData */
  5751         -    winOpen,             /* xOpen */
  5752         -    winDelete,           /* xDelete */
  5753         -    winAccess,           /* xAccess */
  5754         -    winFullPathname,     /* xFullPathname */
  5755         -    winDlOpen,           /* xDlOpen */
  5756         -    winDlError,          /* xDlError */
  5757         -    winDlSym,            /* xDlSym */
  5758         -    winDlClose,          /* xDlClose */
  5759         -    winRandomness,       /* xRandomness */
  5760         -    winSleep,            /* xSleep */
  5761         -    winCurrentTime,      /* xCurrentTime */
  5762         -    winGetLastError,     /* xGetLastError */
  5763         -    winCurrentTimeInt64, /* xCurrentTimeInt64 */
  5764         -    winSetSystemCall,    /* xSetSystemCall */
  5765         -    winGetSystemCall,    /* xGetSystemCall */
  5766         -    winNextSystemCall,   /* xNextSystemCall */
         5896  +    0,                     /* pNext */
         5897  +    "win32-longpath-none", /* zName */
         5898  +    &winNolockAppData,     /* pAppData */
         5899  +    winOpen,               /* xOpen */
         5900  +    winDelete,             /* xDelete */
         5901  +    winAccess,             /* xAccess */
         5902  +    winFullPathname,       /* xFullPathname */
         5903  +    winDlOpen,             /* xDlOpen */
         5904  +    winDlError,            /* xDlError */
         5905  +    winDlSym,              /* xDlSym */
         5906  +    winDlClose,            /* xDlClose */
         5907  +    winRandomness,         /* xRandomness */
         5908  +    winSleep,              /* xSleep */
         5909  +    winCurrentTime,        /* xCurrentTime */
         5910  +    winGetLastError,       /* xGetLastError */
         5911  +    winCurrentTimeInt64,   /* xCurrentTimeInt64 */
         5912  +    winSetSystemCall,      /* xSetSystemCall */
         5913  +    winGetSystemCall,      /* xGetSystemCall */
         5914  +    winNextSystemCall,     /* xNextSystemCall */
  5767   5915     };
  5768   5916   #endif
  5769   5917   
  5770   5918     /* Double-check that the aSyscall[] array has been constructed
  5771   5919     ** correctly.  See ticket [bb3a86e890c8e96ab] */
  5772   5920     assert( ArraySize(aSyscall)==80 );
  5773   5921   
................................................................................
  5782   5930     assert( winSysInfo.dwPageSize>0 );
  5783   5931   
  5784   5932     sqlite3_vfs_register(&winVfs, 1);
  5785   5933   
  5786   5934   #if defined(SQLITE_WIN32_HAS_WIDE)
  5787   5935     sqlite3_vfs_register(&winLongPathVfs, 0);
  5788   5936   #endif
         5937  +
         5938  +  sqlite3_vfs_register(&winNolockVfs, 0);
         5939  +
         5940  +#if defined(SQLITE_WIN32_HAS_WIDE)
         5941  +  sqlite3_vfs_register(&winLongPathNolockVfs, 0);
         5942  +#endif
  5789   5943   
  5790   5944     return SQLITE_OK;
  5791   5945   }
  5792   5946   
  5793   5947   int sqlite3_os_end(void){
  5794   5948   #if SQLITE_OS_WINRT
  5795   5949     if( sleepObj!=NULL ){

Added test/win32nolock.test.

            1  +# 2016 July 8
            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  +# This file implements regression tests for SQLite library.
           12  +#
           13  +
           14  +if {$tcl_platform(platform)!="windows"} return
           15  +
           16  +set testdir [file dirname $argv0]
           17  +source $testdir/tester.tcl
           18  +set testprefix win32nolock
           19  +
           20  +do_test win32nolock-1.0 {
           21  +  sqlite3 db test.db
           22  +  execsql {
           23  +    CREATE TABLE t1(a, b);
           24  +    BEGIN;
           25  +    INSERT INTO t1 VALUES(1, 2);
           26  +  }
           27  +} {}
           28  +
           29  +do_test win32nolock-1.1 {
           30  +  execsql COMMIT
           31  +  catchsql { SELECT * FROM t1 }
           32  +} {0 {1 2}}
           33  +
           34  +db close
           35  +
           36  +do_test win32nolock-1.2 {
           37  +  sqlite3 db test.db -vfs win32-none
           38  +  sqlite3 db2 test.db -vfs win32-none
           39  +  execsql { PRAGMA mmap_size = 0 } db2
           40  +  execsql {
           41  +    BEGIN;
           42  +    INSERT INTO t1 VALUES(3, 4);
           43  +  }
           44  +} {}
           45  +
           46  +do_test win32nolock-1.3 {
           47  +  execsql { SELECT * FROM t1 }
           48  +} {1 2 3 4}
           49  +
           50  +do_test win32nolock-1.4 {
           51  +  execsql { SELECT * FROM t1; } db2
           52  +} {1 2}
           53  +
           54  +do_test win32nolock-1.5 {
           55  +  execsql {
           56  +    BEGIN;
           57  +    SELECT * FROM t1;
           58  +  } db2
           59  +} {1 2}
           60  +
           61  +do_test win32nolock-1.6 {
           62  +  execsql COMMIT
           63  +  execsql {SELECT * FROM t1} db2
           64  +} {1 2}
           65  +
           66  +ifcapable memorymanage {
           67  +  do_test win32nolock-1.7 {
           68  +    sqlite3_release_memory 1000000
           69  +    execsql {SELECT * FROM t1} db2
           70  +  } {1 2 3 4}
           71  +}
           72  +
           73  +do_test win32nolock-1.8 {
           74  +  db close
           75  +  db2 close
           76  +} {}
           77  +
           78  +do_test win32nolock-1.9.1 {
           79  +  sqlite3 db test.db
           80  +  sqlite3 db2 test.db
           81  +  list [catchsql { BEGIN EXCLUSIVE; } db] \
           82  +      [catchsql { BEGIN EXCLUSIVE; } db2]
           83  +} {{0 {}} {1 {database is locked}}}
           84  +
           85  +do_test win32nolock-1.9.2 {
           86  +  db close
           87  +  db2 close
           88  +} {}
           89  +
           90  +do_test win32nolock-1.10.1 {
           91  +  sqlite3 db test.db -vfs win32-none
           92  +  sqlite3 db2 test.db
           93  +  list [catchsql { BEGIN EXCLUSIVE; } db] \
           94  +      [catchsql { BEGIN EXCLUSIVE; } db2]
           95  +} {{0 {}} {0 {}}}
           96  +
           97  +do_test win32nolock-1.10.2 {
           98  +  db close
           99  +  db2 close
          100  +} {}
          101  +
          102  +do_test win32nolock-1.11.1 {
          103  +  sqlite3 db test.db
          104  +  sqlite3 db2 test.db -vfs win32-none
          105  +  list [catchsql { BEGIN EXCLUSIVE; } db] \
          106  +      [catchsql { BEGIN EXCLUSIVE; } db2]
          107  +} {{0 {}} {0 {}}}
          108  +
          109  +do_test win32nolock-1.11.2 {
          110  +  db close
          111  +  db2 close
          112  +} {}
          113  +
          114  +do_test win32nolock-1.12.1 {
          115  +  sqlite3 db test.db -vfs win32-none
          116  +  sqlite3 db2 test.db -vfs win32-none
          117  +  list [catchsql { BEGIN EXCLUSIVE; } db] \
          118  +      [catchsql { BEGIN EXCLUSIVE; } db2]
          119  +} {{0 {}} {0 {}}}
          120  +
          121  +do_test win32nolock-1.12.2 {
          122  +  db close
          123  +  db2 close
          124  +} {}
          125  +
          126  +finish_test