mirror of https://github.com/sqlite/sqlite
Change the supported URI options to "mode" and "cache".
FossilOrigin-Name: 0a694a0b27e3ce251ce313cb5d19a7637c2fa309
This commit is contained in:
parent
fb261ceceb
commit
78e9dd2b54
14
manifest
14
manifest
|
@ -1,5 +1,5 @@
|
|||
C Merge\sthe\slatest\strunk\schanges\sinto\suri\sbranch.
|
||||
D 2011-05-02T17:41:01.076
|
||||
C Change\sthe\ssupported\sURI\soptions\sto\s"mode"\sand\s"cache".
|
||||
D 2011-05-03T10:22:32.361
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
|
@ -143,7 +143,7 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
|
|||
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
|
||||
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
|
||||
F src/loadext.c 3ae0d52da013a6326310655be6473fd472347b85
|
||||
F src/main.c 933d0bcf586ba7acbe2ce3f37d35c474a8306109
|
||||
F src/main.c 8e13c02ec1992f94dcc06b4b2bc0001a79b3e68f
|
||||
F src/malloc.c 74c740e8ba22b806cfb980c8c0ddea1cbd54a20e
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206
|
||||
|
@ -837,7 +837,7 @@ F test/unique.test 083c7fff74695bcc27a71d75699deba3595bc9c2
|
|||
F test/unixexcl.test 9d80a54d86d2261f660758928959368ffc36151e
|
||||
F test/unordered.test e81169ce2a8f31b2c6b66af691887e1376ab3ced
|
||||
F test/update.test 8bc86fd7ef1a00014f76dc6a6a7c974df4aef172
|
||||
F test/uri.test 062ba42524a5042985e7994dc2289259424b60bf
|
||||
F test/uri.test 2e2dea3054bc6b3e5e1bf43fbab09a847ed9eb5f
|
||||
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
|
||||
F test/vacuum.test 29b60e8cc9e573b39676df6c4a75fe9e02d04a09
|
||||
F test/vacuum2.test 91a84c9b08adfc4472097d2e8deb0150214e0e76
|
||||
|
@ -931,7 +931,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
|||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P 2af51f856c6203f836d8bb62b6b79b19554886e7 f55156c5194e85c47728b8a97fde3e5f0a5c9b56
|
||||
R 5b3361d8c251d725e8fb18c102b1e7f2
|
||||
P 7fdd0786c7e0d66baf3aba4485128e16a4e5ea46
|
||||
R 9466d8a507f14eedc64f1b5ce9c925cf
|
||||
U dan
|
||||
Z ce77508d586b51f29df902539114b8b5
|
||||
Z bebe00795592ddf7acadaf3bca1d1f57
|
||||
|
|
|
@ -1 +1 @@
|
|||
7fdd0786c7e0d66baf3aba4485128e16a4e5ea46
|
||||
0a694a0b27e3ce251ce313cb5d19a7637c2fa309
|
141
src/main.c
141
src/main.c
|
@ -1803,18 +1803,7 @@ int sqlite3ParseUri(
|
|||
char **pzFile, /* OUT: Filename component of URI */
|
||||
char **pzErrMsg /* OUT: Error message (if rc!=SQLITE_OK) */
|
||||
){
|
||||
struct UriOption {
|
||||
const char *zOption;
|
||||
int mask;
|
||||
} aOpt [] = {
|
||||
{ "vfs", 0 },
|
||||
{ "readonly", SQLITE_OPEN_READONLY },
|
||||
{ "readwrite", SQLITE_OPEN_READWRITE },
|
||||
{ "create", SQLITE_OPEN_CREATE },
|
||||
{ "sharedcache", SQLITE_OPEN_SHAREDCACHE },
|
||||
{ "privatecache", SQLITE_OPEN_PRIVATECACHE }
|
||||
};
|
||||
|
||||
int rc = SQLITE_OK;
|
||||
int flags = *pFlags;
|
||||
const char *zVfs = zDefaultVfs;
|
||||
char *zFile;
|
||||
|
@ -1864,7 +1853,12 @@ int sqlite3ParseUri(
|
|||
codepoint += sqlite3HexToInt(zUri[iIn++]);
|
||||
|
||||
assert( codepoint>=0 && codepoint<256 );
|
||||
if( codepoint==0 ){
|
||||
if( codepoint>=128 ){
|
||||
*pzErrMsg = sqlite3_mprintf("invalid uri escape: %.3s", &zUri[-3]);
|
||||
rc = SQLITE_ERROR;
|
||||
goto parse_uri_out;
|
||||
}
|
||||
else if( codepoint==0 ){
|
||||
/* This branch is taken when "%00" appears within the URI. In this
|
||||
** case we ignore all text in the remainder of the path, name or
|
||||
** value currently being parsed. So ignore the current character
|
||||
|
@ -1904,27 +1898,70 @@ int sqlite3ParseUri(
|
|||
/* Check if there were any options specified that should be interpreted
|
||||
** here. Options that are interpreted here include "vfs" and those that
|
||||
** correspond to flags that may be passed to the sqlite3_open_v2()
|
||||
** method. */
|
||||
** method. */
|
||||
zOpt = &zFile[sqlite3Strlen30(zFile)+1];
|
||||
while( zOpt[0] ){
|
||||
int nOpt = sqlite3Strlen30(zOpt);
|
||||
char *zVal = &zOpt[nOpt+1];
|
||||
int nVal = sqlite3Strlen30(zVal);
|
||||
int i;
|
||||
|
||||
for(i=0; i<ArraySize(aOpt); i++){
|
||||
const char *z = aOpt[i].zOption;
|
||||
if( nOpt==sqlite3Strlen30(z) && 0==memcmp(zOpt, z, nOpt) ){
|
||||
int mask = aOpt[i].mask;
|
||||
if( mask==0 ){
|
||||
zVfs = zVal;
|
||||
}else{
|
||||
if( zVal[0]=='\0' || sqlite3GetBoolean(zVal) ){
|
||||
flags |= mask;
|
||||
}else{
|
||||
flags &= ~mask;
|
||||
if( nOpt==3 && sqlite3_strnicmp("vfs", zOpt, 3)==0 ){
|
||||
zVfs = zVal;
|
||||
}else{
|
||||
struct OpenMode {
|
||||
const char *z;
|
||||
int mode;
|
||||
} *aMode = 0;
|
||||
char *zModeType;
|
||||
int mask;
|
||||
int limit;
|
||||
|
||||
if( nOpt==5 && sqlite3_strnicmp("cache", zOpt, 5)==0 ){
|
||||
static struct OpenMode aCacheMode[] = {
|
||||
{ "shared", SQLITE_OPEN_SHAREDCACHE },
|
||||
{ "private", SQLITE_OPEN_PRIVATECACHE },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
mask = SQLITE_OPEN_SHAREDCACHE|SQLITE_OPEN_PRIVATECACHE;
|
||||
aMode = aCacheMode;
|
||||
limit = mask;
|
||||
zModeType = "cache";
|
||||
}
|
||||
if( nOpt==4 && sqlite3_strnicmp("mode", zOpt, 4)==0 ){
|
||||
static struct OpenMode aOpenMode[] = {
|
||||
{ "ro", SQLITE_OPEN_READONLY },
|
||||
{ "rw", SQLITE_OPEN_READWRITE },
|
||||
{ "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
mask = SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
|
||||
aMode = aOpenMode;
|
||||
limit = mask & flags;
|
||||
zModeType = "access";
|
||||
}
|
||||
|
||||
if( aMode ){
|
||||
int i;
|
||||
int mode = 0;
|
||||
for(i=0; aMode[i].z; i++){
|
||||
const char *z = aMode[i].z;
|
||||
if( nVal==strlen(z) && 0==sqlite3_strnicmp(zVal, z, nVal) ){
|
||||
mode = aMode[i].mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( mode==0 ){
|
||||
*pzErrMsg = sqlite3_mprintf("no such %s mode: %s", zModeType, zVal);
|
||||
rc = SQLITE_ERROR;
|
||||
goto parse_uri_out;
|
||||
}
|
||||
if( mode>limit ){
|
||||
rc = SQLITE_PERM;
|
||||
goto parse_uri_out;
|
||||
}
|
||||
flags = (flags & ~mask) | mode;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1942,12 +1979,16 @@ int sqlite3ParseUri(
|
|||
*ppVfs = sqlite3_vfs_find(zVfs);
|
||||
if( *ppVfs==0 ){
|
||||
*pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
parse_uri_out:
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(zFile);
|
||||
return SQLITE_ERROR;
|
||||
zFile = 0;
|
||||
}
|
||||
*pFlags = flags;
|
||||
*pzFile = zFile;
|
||||
return SQLITE_OK;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1974,6 +2015,27 @@ static int openDatabase(
|
|||
if( rc ) return rc;
|
||||
#endif
|
||||
|
||||
/* Only allow sensible combinations of bits in the flags argument.
|
||||
** Throw an error if any non-sense combination is used. If we
|
||||
** do not block illegal combinations here, it could trigger
|
||||
** assert() statements in deeper layers. Sensible combinations
|
||||
** are:
|
||||
**
|
||||
** 1: SQLITE_OPEN_READONLY
|
||||
** 2: SQLITE_OPEN_READWRITE
|
||||
** 6: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
|
||||
*/
|
||||
assert( SQLITE_OPEN_READONLY == 0x01 );
|
||||
assert( SQLITE_OPEN_READWRITE == 0x02 );
|
||||
assert( SQLITE_OPEN_CREATE == 0x04 );
|
||||
testcase( (1<<(flags&7))==0x02 ); /* READONLY */
|
||||
testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
|
||||
testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
|
||||
if( ((1<<(flags&7)) & 0x46)==0 ){
|
||||
rc = SQLITE_MISUSE;
|
||||
goto opendb_out;
|
||||
}
|
||||
|
||||
if( sqlite3GlobalConfig.bCoreMutex==0 ){
|
||||
isThreadsafe = 0;
|
||||
}else if( flags & SQLITE_OPEN_NOMUTEX ){
|
||||
|
@ -2078,32 +2140,11 @@ static int openDatabase(
|
|||
/* Parse the filename/URI argument. */
|
||||
rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3Error(db, rc, "%s", zErrMsg);
|
||||
sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
|
||||
sqlite3_free(zErrMsg);
|
||||
goto opendb_out;
|
||||
}
|
||||
|
||||
/* Only allow sensible combinations of bits in the flags argument.
|
||||
** Throw an error if any non-sense combination is used. If we
|
||||
** do not block illegal combinations here, it could trigger
|
||||
** assert() statements in deeper layers. Sensible combinations
|
||||
** are:
|
||||
**
|
||||
** 1: SQLITE_OPEN_READONLY
|
||||
** 2: SQLITE_OPEN_READWRITE
|
||||
** 6: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
|
||||
*/
|
||||
assert( SQLITE_OPEN_READONLY == 0x01 );
|
||||
assert( SQLITE_OPEN_READWRITE == 0x02 );
|
||||
assert( SQLITE_OPEN_CREATE == 0x04 );
|
||||
testcase( (1<<(flags&7))==0x02 ); /* READONLY */
|
||||
testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
|
||||
testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
|
||||
if( ((1<<(flags&7)) & 0x46)==0 ){
|
||||
rc = SQLITE_MISUSE;
|
||||
goto opendb_out;
|
||||
}
|
||||
|
||||
/* Open the backend database driver */
|
||||
db->openFlags = flags;
|
||||
rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
|
||||
|
|
|
@ -117,26 +117,77 @@ do_test 3.1 {
|
|||
#
|
||||
# TODO: Fix this after the list of options is decided.
|
||||
#
|
||||
do_test 4.0 {
|
||||
sqlite3 db test.db
|
||||
db eval {CREATE TABLE t1(a, b)}
|
||||
db close
|
||||
} {}
|
||||
foreach {tn uri ro} {
|
||||
1 "file:test.db" 0
|
||||
2 "file:test.db?readonly=0" 0
|
||||
3 "file:test.db?readonly=1&readwrite=0&create=0" 1
|
||||
foreach {tn mode create_ok write_ok readonly_ok} {
|
||||
1 ro 0 0 1
|
||||
2 rw 0 1 0
|
||||
3 rwc 1 1 0
|
||||
} {
|
||||
set RES(0) {0 {}}
|
||||
set RES(1) {1 {attempt to write a readonly database}}
|
||||
catch { db close }
|
||||
forcedelete test.db
|
||||
|
||||
do_test 4.$tn {
|
||||
sqlite3 db $uri
|
||||
catchsql { INSERT INTO t1 VALUES(1, 2) }
|
||||
} $RES($ro)
|
||||
set A(1) {0 {}}
|
||||
set A(0) {1 {unable to open database file}}
|
||||
do_test 4.1.$tn.1 {
|
||||
list [catch {sqlite3 db "file:test.db?mode=$mode"} msg] $msg
|
||||
} $A($create_ok)
|
||||
|
||||
catch { db close }
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval { CREATE TABLE t1(a, b) }
|
||||
db close
|
||||
|
||||
set A(1) {0 {}}
|
||||
set A(0) {1 {attempt to write a readonly database}}
|
||||
do_test 4.1.$tn.2 {
|
||||
sqlite3 db "file:test.db?mode=$mode"
|
||||
catchsql { INSERT INTO t1 VALUES(1, 2) }
|
||||
} $A($write_ok)
|
||||
|
||||
set A(1) {0 {}}
|
||||
set A(0) {1 {access permission denied}}
|
||||
do_test 4.1.$tn.3 {
|
||||
list [catch {sqlite3 db "file:test.db?mode=$mode" -readonly 1} msg] $msg
|
||||
} $A($readonly_ok)
|
||||
}
|
||||
|
||||
set orig [sqlite3_enable_shared_cache]
|
||||
foreach {tn options sc_default is_shared} {
|
||||
1 "" 1 1
|
||||
2 "cache=private" 1 0
|
||||
3 "cache=shared" 1 1
|
||||
4 "" 0 0
|
||||
5 "cache=private" 0 0
|
||||
6 "cache=shared" 0 1
|
||||
} {
|
||||
catch { db close }
|
||||
forcedelete test.db
|
||||
|
||||
sqlite3_enable_shared_cache 1
|
||||
sqlite3 db2 test.db
|
||||
db2 eval {CREATE TABLE t1(a, b)}
|
||||
|
||||
sqlite3_enable_shared_cache $sc_default
|
||||
sqlite3 db "file:test.db?$options"
|
||||
db eval {SELECT * FROM t1}
|
||||
|
||||
set A(1) {1 {database table is locked: t1}}
|
||||
set A(0) {0 {}}
|
||||
do_test 4.2.$tn {
|
||||
db2 eval {BEGIN; INSERT INTO t1 VALUES(1, 2);}
|
||||
catchsql { SELECT * FROM t1 }
|
||||
} $A($is_shared)
|
||||
|
||||
db2 close
|
||||
}
|
||||
|
||||
do_test 4.3.1 {
|
||||
list [catch {sqlite3 db "file:test.db?mode=rc"} msg] $msg
|
||||
} {1 {no such access mode: rc}}
|
||||
do_test 4.3.2 {
|
||||
list [catch {sqlite3 db "file:test.db?cache=public"} msg] $msg
|
||||
} {1 {no such cache mode: public}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that things work if an ATTACHed database uses a different VFS than
|
||||
# the main database. The important point is that for all operations
|
||||
|
@ -177,7 +228,7 @@ do_test 5.1.1 {
|
|||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE aux.t2(a, b);
|
||||
PRAGMA main.journal_mode = WAL;
|
||||
PRAGMA aux.journal_mode = PERSIST;
|
||||
PRAGMA aux.journal_mode = WAL;
|
||||
INSERT INTO t1 VALUES('x', 'y');
|
||||
INSERT INTO t2 VALUES('x', 'y');
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue