diff --git a/manifest b/manifest index 5dc2612251..af1b667873 100644 --- a/manifest +++ b/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 diff --git a/manifest.uuid b/manifest.uuid index 8258359950..1c54c8762d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7fdd0786c7e0d66baf3aba4485128e16a4e5ea46 \ No newline at end of file +0a694a0b27e3ce251ce313cb5d19a7637c2fa309 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 313222f54b..eaf0f74159 100644 --- a/src/main.c +++ b/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; ilimit ){ + 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, diff --git a/test/uri.test b/test/uri.test index 6248381f81..38b0740ec1 100644 --- a/test/uri.test +++ b/test/uri.test @@ -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'); }