Add the SQLITE_IOCAP_IMMUTABLE bit as a possible return value from
the xDeviceCharacteristics method in the VFS. Add the "nolock" and "immutable" query parameters to URI filenames. FossilOrigin-Name: 1a0d7d3d9dd54b783e3a805961287dd01f94770c
This commit is contained in:
commit
731dc0cb0e
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
||||
C Update\sthe\stemplate\sVSIX\spackage\sfile\sas\swell.
|
||||
D 2014-05-06T21:37:10.782
|
||||
C Add\sthe\sSQLITE_IOCAP_IMMUTABLE\sbit\sas\sa\spossible\sreturn\svalue\sfrom\nthe\sxDeviceCharacteristics\smethod\sin\sthe\sVFS.\s\sAdd\sthe\s"nolock"\sand\n"immutable"\squery\sparameters\sto\sURI\sfilenames.
|
||||
D 2014-05-07T15:46:04.082
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in dd2b1aba364ff9b05de41086f74407f285c57670
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -208,7 +208,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c ae4b5240af4619d711301d7992396e182585269f
|
||||
F src/os_win.c 485d06a93965f306c7281fca0937829292367234
|
||||
F src/os_win.h 057344a6720b4c8405d9bd98f58cb37a6ee46c25
|
||||
F src/pager.c ab62a24218d87dda1be641f6c5ad291bff78fd94
|
||||
F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8
|
||||
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
|
||||
F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
|
||||
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
|
||||
@ -222,7 +222,7 @@ F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66
|
||||
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
|
||||
F src/select.c 089c4d46f067a5cccae93524c6377f981ba99bd9
|
||||
F src/shell.c 2afe7a7154e97be0c74c5feacf09626bda8493be
|
||||
F src/sqlite.h.in bde98816e1ba0c9ffef50afe7b32f4e5a8f54fe0
|
||||
F src/sqlite.h.in 564fc23db33870b5096b20d72df7491ce0b8b74f
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h b2947801eccefd7ba3e5f14e1353289351a83cf3
|
||||
@ -272,7 +272,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
|
||||
@ -715,6 +715,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 0540dd96f39b8876e3ffdd8814fad0ea425efeee
|
||||
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
|
||||
F test/notify2.test ce23eb522c9e1fff6443f96376fe67872202061c
|
||||
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
|
||||
@ -1168,7 +1169,8 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||
F tool/win/sqlite.vsix a94fb9b1b1ef06efc2898975cdfcfa9643731f5e
|
||||
P c1fb04f61eb74d80d1b7607ae6904fe2e1717988
|
||||
R e86d9d0c4e9d221c23e483062a69a0ee
|
||||
U mistachkin
|
||||
Z 61035ffe1ca5b1a658207d61a8a19a18
|
||||
P 99d96765cc378fde7b285f4577ea2b5d130d9a61 e193aced2942e7405d0f45f90d4954b5663b4ba5
|
||||
R 397fc32d1bd36ead839d4c78d231487f
|
||||
T +closed e193aced2942e7405d0f45f90d4954b5663b4ba5
|
||||
U drh
|
||||
Z 57c6364c482e6b92f356dd08394fdb62
|
||||
|
@ -1 +1 @@
|
||||
99d96765cc378fde7b285f4577ea2b5d130d9a61
|
||||
1a0d7d3d9dd54b783e3a805961287dd01f94770c
|
68
src/pager.c
68
src/pager.c
@ -626,7 +626,8 @@ struct Pager {
|
||||
u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
|
||||
u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */
|
||||
u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
|
||||
u8 tempFile; /* zFilename is a temporary file */
|
||||
u8 tempFile; /* zFilename is a temporary or immutable file */
|
||||
u8 noLock; /* Do not lock (except in WAL mode) */
|
||||
u8 readOnly; /* True for a read-only database */
|
||||
u8 memDb; /* True to inhibit all file I/O */
|
||||
|
||||
@ -1091,7 +1092,7 @@ static int pagerUnlockDb(Pager *pPager, int eLock){
|
||||
assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
|
||||
if( isOpen(pPager->fd) ){
|
||||
assert( pPager->eLock>=eLock );
|
||||
rc = sqlite3OsUnlock(pPager->fd, eLock);
|
||||
rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock);
|
||||
if( pPager->eLock!=UNKNOWN_LOCK ){
|
||||
pPager->eLock = (u8)eLock;
|
||||
}
|
||||
@ -1115,7 +1116,7 @@ static int pagerLockDb(Pager *pPager, int eLock){
|
||||
|
||||
assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
|
||||
if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
|
||||
rc = sqlite3OsLock(pPager->fd, eLock);
|
||||
rc = pPager->noLock ? SQLITE_OK : sqlite3OsLock(pPager->fd, eLock);
|
||||
if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
|
||||
pPager->eLock = (u8)eLock;
|
||||
IOTRACE(("LOCK %p %d\n", pPager, eLock))
|
||||
@ -4674,30 +4675,38 @@ int sqlite3PagerOpen(
|
||||
** + The value returned by sqlite3OsSectorSize()
|
||||
** + The largest page size that can be written atomically.
|
||||
*/
|
||||
if( rc==SQLITE_OK && !readOnly ){
|
||||
setSectorSize(pPager);
|
||||
assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
|
||||
if( szPageDflt<pPager->sectorSize ){
|
||||
if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
|
||||
szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
|
||||
}else{
|
||||
szPageDflt = (u32)pPager->sectorSize;
|
||||
}
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
{
|
||||
int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
|
||||
int ii;
|
||||
assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
|
||||
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
|
||||
assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
|
||||
for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
|
||||
if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
|
||||
szPageDflt = ii;
|
||||
if( rc==SQLITE_OK ){
|
||||
int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
|
||||
if( !readOnly ){
|
||||
setSectorSize(pPager);
|
||||
assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
|
||||
if( szPageDflt<pPager->sectorSize ){
|
||||
if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
|
||||
szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
|
||||
}else{
|
||||
szPageDflt = (u32)pPager->sectorSize;
|
||||
}
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
{
|
||||
int ii;
|
||||
assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
|
||||
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
|
||||
assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
|
||||
for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
|
||||
if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
|
||||
szPageDflt = ii;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0);
|
||||
if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0
|
||||
|| sqlite3_uri_boolean(zFilename, "immutable", 0) ){
|
||||
vfsFlags |= SQLITE_OPEN_READONLY;
|
||||
goto act_like_temp_file;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* If a temporary file is requested, it is not opened immediately.
|
||||
@ -4707,10 +4716,14 @@ int sqlite3PagerOpen(
|
||||
** This branch is also run for an in-memory database. An in-memory
|
||||
** database is the same as a temp-file that is never written out to
|
||||
** disk and uses an in-memory rollback journal.
|
||||
**
|
||||
** This branch also runs for files marked as immutable.
|
||||
*/
|
||||
act_like_temp_file:
|
||||
tempFile = 1;
|
||||
pPager->eState = PAGER_READER;
|
||||
pPager->eLock = EXCLUSIVE_LOCK;
|
||||
pPager->eState = PAGER_READER; /* Pretend we already have a lock */
|
||||
pPager->eLock = EXCLUSIVE_LOCK; /* Pretend we are in EXCLUSIVE locking mode */
|
||||
pPager->noLock = 1; /* Do no locking */
|
||||
readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
|
||||
}
|
||||
|
||||
@ -4751,9 +4764,6 @@ int sqlite3PagerOpen(
|
||||
/* pPager->nPage = 0; */
|
||||
pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
|
||||
/* pPager->state = PAGER_UNLOCK; */
|
||||
#if 0
|
||||
assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
|
||||
#endif
|
||||
/* pPager->errMask = 0; */
|
||||
pPager->tempFile = (u8)tempFile;
|
||||
assert( tempFile==PAGER_LOCKINGMODE_NORMAL
|
||||
|
@ -555,7 +555,10 @@ int sqlite3_exec(
|
||||
** file that were written at the application level might have changed
|
||||
** and that adjacent bytes, even bytes within the same sector are
|
||||
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
|
||||
** flag indicate that a file cannot be deleted when open.
|
||||
** flag indicate that a file cannot be deleted when open. The
|
||||
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
|
||||
** read-only media and cannot be changed even by processes with
|
||||
** elevated privileges.
|
||||
*/
|
||||
#define SQLITE_IOCAP_ATOMIC 0x00000001
|
||||
#define SQLITE_IOCAP_ATOMIC512 0x00000002
|
||||
@ -570,6 +573,7 @@ int sqlite3_exec(
|
||||
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
|
||||
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
|
||||
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
|
||||
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
|
||||
|
||||
/*
|
||||
** CAPI3REF: File Locking Levels
|
||||
@ -2774,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
|
||||
@ -2803,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>
|
||||
|
@ -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;
|
||||
|
185
test/nolock.test
Normal file
185
test/nolock.test
Normal file
@ -0,0 +1,185 @@
|
||||
# 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}
|
||||
|
||||
do_test nolock-1.3 {
|
||||
db close
|
||||
tvfs_reset
|
||||
sqlite db file:test.db?nolock=0 -vfs tvfs -uri 1 -readonly 1
|
||||
db eval {SELECT * FROM t1}
|
||||
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
|
||||
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
|
||||
} {xLock 2 xUnlock 2 xCheckReservedLock 0}
|
||||
|
||||
do_test nolock-1.4 {
|
||||
db close
|
||||
tvfs_reset
|
||||
sqlite db file:test.db?nolock=1 -vfs tvfs -uri 1 -readonly 1
|
||||
db eval {SELECT * FROM t1}
|
||||
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}
|
||||
|
||||
do_test nolock-2.31 {
|
||||
db2 close
|
||||
tvfs_reset
|
||||
sqlite3 db2 file:test.db?immutable=1 -vfs tvfs -uri 1 -readonly 1
|
||||
db2 eval {SELECT * FROM t1, t2}
|
||||
} {hello world 12345 67890}
|
||||
do_test nolock-2.32 {
|
||||
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}
|
||||
|
||||
do_test nolock-3.11 {
|
||||
db2 close
|
||||
tvfs_reset
|
||||
sqlite3 db2 test.db -vfs tvfs -readonly 1
|
||||
db2 eval {SELECT * FROM t1, t2}
|
||||
} {hello world 12345 67890}
|
||||
do_test nolock-3.12 {
|
||||
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
|
Loading…
x
Reference in New Issue
Block a user