-C Have\sthe\sxFullpath\smethod\sin\sos_win.c\sdiscard\sthe\sinitial\s"/"\sif\sa\sfilename\sbegins\swith\s"/X:",\swhere\sX\sis\sany\salphabetic\scharacter.\sAlso\sfix\ssome\stest\sissues\sin\suri.test.
-D 2011-05-05T18:53:48.721
+C Update\scomments\sand\sdocumentation\sassociated\swith\snew\sURI\sparsing\scode.\sAdd\stest\sfile\se_uri.test,\scontaining\stests\smapped\sto\sdocumentation\sregarding\sURI\sfilenames.
+D 2011-05-06T18:34:54.463
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
F src/loadext.c 3ae0d52da013a6326310655be6473fd472347b85
-F src/main.c 872493d84fed9b9c910e1b7b2427a3e28dbe995a
+F src/main.c 145f04d5d8a6a391093b8e6a3b37511ac79e05c3
F src/malloc.c 74c740e8ba22b806cfb980c8c0ddea1cbd54a20e
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c d9d440809025a58547e39f4f268c2a296bfb56ff
F src/shell.c 72e7e176bf46d5c6518d15ac4ad6847c4bb5df79
-F src/sqlite.h.in f865bde9a0af4cd77b85265df71a9d760e5def18
+F src/sqlite.h.in 6acf3863a9ac8cd613029ff4d477519406632d78
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
F src/sqliteInt.h 5a7bf51f767fb67b484f09d73cccff683731af22
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 501c9a200fd998a268be475be5858febc90b725b
-F src/test1.c e0e4af306b678da05334c2ccaf0377ae8f06e911
+F src/test1.c f506164085bc4cbbb4b5c14b9c6de153f1aeafc5
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
F src/test3.c 124ff9735fb6bb7d41de180d6bac90e7b1509432
F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7
F test/e_select.test bf385ae3aa0f014c4933ae66fd3e1302138493eb
F test/e_select2.test 5c3d3da19c7b3e90ae444579db2b70098599ab92
F test/e_update.test 963d6876064e65f318d1c93aaed36a02b9b389bf
+F test/e_uri.test 26c3ba638e38b9a92272174564df41e7c48e25a1
F test/e_vacuum.test 6c09c2af7f2f140518f371c5342100118f779dcf
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 6d91a5286f59add0cfcbb2d0da913b76f2242398
F test/unixexcl.test 9d80a54d86d2261f660758928959368ffc36151e
F test/unordered.test e81169ce2a8f31b2c6b66af691887e1376ab3ced
F test/update.test 8bc86fd7ef1a00014f76dc6a6a7c974df4aef172
-F test/uri.test f21a5cd025ccedf0c6d4c5e365bb47e163098c04
+F test/uri.test e8579b07985b8f4f658eb4e077962a9b2b7b6491
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F test/vacuum.test 29b60e8cc9e573b39676df6c4a75fe9e02d04a09
F test/vacuum2.test 91a84c9b08adfc4472097d2e8deb0150214e0e76
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P ea562d6d67c2f2ef8baca02a77634c21b945196f
-R ab4f619c8bbf9faf6cdcf553d75032d8
+P fe57a8f621944fd2af5a4e9349c8fd77c4aba237
+R 3f5b227194b2ccadbce712d322c27966
U dan
-Z d81fc059a3e07abc471a058222e61ec9
+Z 5f09c493780289f14c0820ca02b5d7dc
-fe57a8f621944fd2af5a4e9349c8fd77c4aba237
\ No newline at end of file
+92751788eae082e3104838cb6dd8b9793cb325d1
\ No newline at end of file
}
/*
-** This function is used to parse URIs passed by the user to API functions
-** sqlite3_open() or sqlite3_open_v2(), and for database URIs specified as
-** part of ATTACH statements.
+** This function is used to parse both URIs and non-URI filenames passed by the
+** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database
+** URIs specified as part of ATTACH statements.
+**
+** The first argument to this function is the name of the VFS to use (or
+** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx"
+** query parameter. The second argument contains the URI (or non-URI filename)
+** itself. When this function is called the *pFlags variable should contain
+** the default flags to open the database handle with. The value stored in
+** *pFlags may be updated before returning if the URI filename contains
+** "cache=xxx" or "mode=xxx" query parameters.
+**
+** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
+** the VFS that should be used to open the database file. *pzFile is set to
+** point to a buffer containing the name of the file to open. It is the
+** responsibility of the caller to eventually call sqlite3_free() to release
+** this buffer.
+**
+** If an error occurs, then an SQLite error code is returned and *pzErrMsg
+** may be set to point to a buffer containing an English language error
+** message. It is the responsibility of the caller to eventually release
+** this buffer by calling sqlite3_free().
*/
int sqlite3ParseUri(
const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */
int iIn; /* Input character index */
int iOut = 0; /* Output character index */
int nByte = nUri+2; /* Bytes of space to allocate */
- for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
+ /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
+ ** method that there may be extra parameters following the file-name. */
+ flags |= SQLITE_OPEN_URI;
+
+ for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
zFile = sqlite3_malloc(nByte);
if( !zFile ) return SQLITE_NOMEM;
char *zVal = &zOpt[nOpt+1];
int nVal = sqlite3Strlen30(zVal);
- if( nOpt==3 && sqlite3_strnicmp("vfs", zOpt, 3)==0 ){
+ if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
zVfs = zVal;
}else{
struct OpenMode {
int mask;
int limit;
- if( nOpt==5 && sqlite3_strnicmp("cache", zOpt, 5)==0 ){
+ if( nOpt==5 && memcmp("cache", zOpt, 5)==0 ){
static struct OpenMode aCacheMode[] = {
{ "shared", SQLITE_OPEN_SHAREDCACHE },
{ "private", SQLITE_OPEN_PRIVATECACHE },
limit = mask;
zModeType = "cache";
}
- if( nOpt==4 && sqlite3_strnicmp("mode", zOpt, 4)==0 ){
+ if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){
static struct OpenMode aOpenMode[] = {
{ "ro", SQLITE_OPEN_READONLY },
{ "rw", SQLITE_OPEN_READWRITE },
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) ){
+ if( nVal==strlen(z) && 0==memcmp(zVal, z, nVal) ){
mode = aMode[i].mode;
break;
}
** ^SQLite uses the 'path' component of the URI as the path to the database file
** to open. ^If the path begins with a '/' character, then it is interpreted as
** an absolute path. ^If it does not begin with a '/', it is interpreted as a
-** relative path. ^On windows, if the first component of an absolute path is
-** of the form "X:", where "X" is any alphabetic character, it is interpreted
-** as a drive specification. ^Otherwise, the absolute path is interpreted as
-** the full pathname of a file on the current drive.
+** relative path. ^On windows, the first component of an absolute path
+** is a drive specification (e.g. "C:").
**
** The query component of a URI may contain parameters that are interpreted
** either by SQLite itself, or by a [sqlite3_vfs | custom VFS implementation].
** a VFS object that provides the operating system interface that should
** be used to access the database file on disk. ^If this option is set to
** an empty string the default VFS object is used. ^Specifying an unknown
-** VFS is an error.
-**
-** <li> <b>mode</b>: ^(This option may be set to either "ro", "rw" or "rwc".
-** Attempting to set it to any other value is an error)^. ^If "ro" is
-** specified, then the database is opened for read-only access, just as if
-** the [SQLITE_OPEN_READONLY] flag had been set in the third argument to
-** sqlite3_prepare_v2(). ^If the mode option is set to "rw", then the
-** database is opened for read-write (but not create) access, as if
-** SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had been set.
-** ^Value "rwc" is equivalent to setting both SQLITE_OPEN_READWRITE and
-** SQLITE_OPEN_CREATE.
-** ^If sqlite3_open_v2() is used, it is an error to specify a value for
-** the mode parameter that is less restrictive than that specified by the
-** flags passed as the third parameter.
+** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
+** present, then the VFS specified by the option takes precedence over
+** the value passed as the fourth parameter to sqlite3_open_v2().
+**
+** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
+** "rwc". Attempting to set it to any other value is an error)^.
+** ^If "ro" is specified, then the database is opened for read-only
+** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
+** third argument to sqlite3_prepare_v2(). ^If the mode option is set to
+** "rw", then the database is opened for read-write (but not create)
+** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
+** been set. ^Value "rwc" is equivalent to setting both
+** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is
+** used, it is an error to specify a value for the mode parameter that is
+** less restrictive than that specified by the flags passed as the third
+** parameter.
**
** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
** "private". ^Setting it to "shared" is equivalent to setting the
** <tr><td style="white-space:nowrap">
** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
** <td> Windows only: Open the file "data.db" on fred's desktop on drive
-** C:. If the "C:/" component were omitted from this URI, then the
-** file "\Documents and Settings\fred\Desktop\data.db" would be opened
-** on the current drive. Note that the %20 escaping in this example
-** is not strictly necessary - space characters can be used literally
+** C:. Note that the %20 escaping in this example is not strictly
+** necessary - space characters can be used literally
** in URI filenames.
** <tr><td> file:data.db?mode=ro&cache=private <td>
** Open file "data.db" in the current directory for read-only access.
return TCL_OK;
}
+/*
+** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
+*/
+static int test_open_v2(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ const char *zFilename;
+ const char *zVfs;
+ int flags = 0;
+ sqlite3 *db;
+ int rc;
+ char zBuf[100];
+
+ int nFlag;
+ Tcl_Obj **apFlag;
+ int i;
+
+ if( objc!=4 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
+ return TCL_ERROR;
+ }
+ zFilename = Tcl_GetString(objv[1]);
+ zVfs = Tcl_GetString(objv[3]);
+ if( zVfs[0]==0x00 ) zVfs = 0;
+
+ rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
+ if( rc!=TCL_OK ) return rc;
+ for(i=0; i<nFlag; i++){
+ int iFlag;
+ struct OpenFlag {
+ const char *zFlag;
+ int flag;
+ } aFlag[] = {
+ { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
+ { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
+ { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
+ { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
+ { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
+ { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
+ { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
+ { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
+ { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
+ { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
+ { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
+ { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
+ { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
+ { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
+ { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
+ { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
+ { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
+ { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
+ { "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
+ { 0, 0 }
+ };
+ rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]),
+ "flag", 0, &iFlag
+ );
+ if( rc!=TCL_OK ) return rc;
+ flags |= aFlag[iFlag].flag;
+ }
+
+ rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
+ if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
+ Tcl_AppendResult(interp, zBuf, 0);
+ return TCL_OK;
+}
+
/*
** Usage: sqlite3_open16 filename options
*/
{ "sqlite3_errmsg16", test_errmsg16 ,0 },
{ "sqlite3_open", test_open ,0 },
{ "sqlite3_open16", test_open16 ,0 },
+ { "sqlite3_open_v2", test_open_v2 ,0 },
{ "sqlite3_complete16", test_complete16 ,0 },
{ "sqlite3_prepare", test_prepare ,0 },
--- /dev/null
+# 2011 May 06
+#
+# 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.
+#
+#***********************************************************************
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix e_uri
+
+db close
+
+proc parse_uri {uri} {
+ testvfs tvfs2
+ testvfs tvfs
+ tvfs filter xOpen
+ tvfs script parse_uri_open_cb
+
+ set ::uri_open [list]
+ set DB [sqlite3_open_v2 $uri {
+ SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL
+ } tvfs]
+ sqlite3_close $DB
+ tvfs delete
+ tvfs2 delete
+
+ set ::uri_open
+}
+proc parse_uri_open_cb {method file arglist} {
+ set ::uri_open [list $file $arglist]
+}
+
+proc open_uri_error {uri} {
+ set flags {SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL}
+ set DB [sqlite3_open_v2 $uri $flags ""]
+ set e [sqlite3_errmsg $DB]
+ sqlite3_close $DB
+ set e
+}
+
+# EVIDENCE-OF: R-35840-33204 If URI filename interpretation is enabled,
+# and the filename argument begins with "file:", then the filename is
+# interpreted as a URI.
+#
+# EVIDENCE-OF: R-00067-59538 URI filename interpretation is enabled if
+# the SQLITE_OPEN_URI flag is is set in the fourth argument to
+# sqlite3_open_v2(), or if it has been enabled globally using the
+# SQLITE_CONFIG_URI option with the sqlite3_config() method.
+#
+if {$tcl_platform(platform) == "unix"} {
+ set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE]
+
+ # Tests with SQLITE_CONFIG_URI configured to false. URI intepretation is
+ # only enabled if the SQLITE_OPEN_URI flag is specified.
+ sqlite3_shutdown
+ sqlite3_config_uri 0
+ do_test 1.1 {
+ forcedelete file:test.db test.db
+ set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]
+ list [file exists file:test.db] [file exists test.db]
+ } {0 1}
+ sqlite3_close $DB
+ do_test 1.2 {
+ forcedelete file:test.db test.db
+ set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]
+ list [file exists file:test.db] [file exists test.db]
+ } {1 0}
+ sqlite3_close $DB
+
+ # Tests with SQLITE_CONFIG_URI configured to true. URI intepretation is
+ # enabled with or without SQLITE_OPEN_URI.
+ sqlite3_shutdown
+ sqlite3_config_uri 1
+ do_test 1.3 {
+ forcedelete file:test.db test.db
+ set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]
+ list [file exists file:test.db] [file exists test.db]
+ } {0 1}
+ sqlite3_close $DB
+ do_test 1.4 {
+ forcedelete file:test.db test.db
+ set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]
+ list [file exists file:test.db] [file exists test.db]
+ } {0 1}
+ sqlite3_close $DB
+}
+
+# EVIDENCE-OF: R-17482-00398 If the authority is not an empty string or
+# "localhost", an error is returned to the caller.
+#
+if {$tcl_platform(platform) == "unix"} {
+ set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
+ foreach {tn uri error} "
+ 1 {file://localhost[pwd]/test.db} {not an error}
+ 2 {file://[pwd]/test.db} {not an error}
+ 3 {file://x[pwd]/test.db} {invalid uri authority: x}
+ 4 {file://invalid[pwd]/test.db} {invalid uri authority: invalid}
+ " {
+ do_test 2.$tn {
+ set DB [sqlite3_open_v2 $uri $flags ""]
+ set e [sqlite3_errmsg $DB]
+ sqlite3_close $DB
+ set e
+ } $error
+ }
+}
+
+# EVIDENCE-OF: R-43804-65312 The 'fragment' component of a URI, if
+# present, is always ignored.
+#
+# It is difficult to test that something is ignore correctly. So these tests
+# just show that adding a fragment does not interfere with the pathname or
+# parameters passed through to the VFS xOpen() methods.
+#
+if {$tcl_platform(platform) == "unix"} {
+ foreach {tn uri parse} "
+ 1 {file:test.db#abc} {[pwd]/test.db {}}
+ 2 {file:test.db?a=b#abc} {[pwd]/test.db {a b}}
+ 3 {file:test.db?a=b#?c=d} {[pwd]/test.db {a b}}
+ " {
+ do_test 3.$tn { parse_uri $uri } $parse
+ }
+}
+
+# EVIDENCE-OF: R-00273-20588 SQLite uses the 'path' component of the URI
+# as the path to the database file to open.
+#
+# EVIDENCE-OF: R-28659-11035 If the path begins with a '/' character,
+# then it is interpreted as an absolute path.
+#
+# EVIDENCE-OF: R-39349-47203 If it does not begin with a '/', it is
+# interpreted as a relative path.
+#
+if {$tcl_platform(platform) == "unix"} {
+ foreach {tn uri parse} "
+ 1 {file:test.db} {[pwd]/test.db {}}
+ 2 {file:/test.db} {/test.db {}}
+ 3 {file:///test.db} {/test.db {}}
+ 4 {file://localhost/test.db} {/test.db {}}
+ 5 {file:/a/b/c/test.db} {/a/b/c/test.db {}}
+ " {
+ do_test 4.$tn { parse_uri $uri } $parse
+ }
+}
+
+# EVIDENCE-OF: R-01612-30877 The "vfs" parameter may be used to specify
+# the name of a VFS object that provides the operating system interface
+# that should be used to access the database file on disk.
+#
+# The above is tested by cases 1.* below.
+#
+# EVIDENCE-OF: R-52293-58497 If this option is set to an empty string
+# the default VFS object is used.
+#
+# The above is tested by cases 2.* below.
+#
+# EVIDENCE-OF: R-31855-18665 If sqlite3_open_v2() is used and the vfs
+# option is present, then the VFS specified by the option takes
+# precedence over the value passed as the fourth parameter to
+# sqlite3_open_v2().
+#
+# The above is tested by cases 3.* below.
+#
+proc vfs_open_cb {name args} {
+ set ::vfs $name
+}
+foreach {name default} {vfs1 0 vfs2 0 vfs3 1} {
+ testvfs $name -default $default
+ $name filter xOpen
+ $name script [list vfs_open_cb $name]
+}
+foreach {tn uri defvfs vfs} {
+ 1.1 "file:test.db?vfs=vfs1" "" vfs1
+ 1.2 "file:test.db?vfs=vfs2" "" vfs2
+
+ 2.1 "file:test.db" vfs1 vfs1
+ 2.2 "file:test.db?vfs=" vfs1 vfs3
+
+ 3.1 "file:test.db?vfs=vfs1" vfs2 vfs1
+ 3.2 "file:test.db?vfs=vfs2" vfs1 vfs2
+ 3.3 "file:test.db?xvfs=vfs1" vfs2 vfs2
+ 3.4 "file:test.db?xvfs=vfs2" vfs1 vfs1
+} {
+ do_test 5.$tn {
+ set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
+ sqlite3_close [
+ sqlite3_open_v2 $uri $flags $defvfs
+ ]
+ set ::vfs
+ } $vfs
+}
+vfs1 delete
+vfs2 delete
+vfs3 delete
+
+# EVIDENCE-OF: R-48365-36308 Specifying an unknown VFS is an error.
+#
+set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
+do_test 6.1 {
+ set DB [sqlite3_open_v2 file:test.db?vfs=nosuchvfs $flags ""]
+ set errmsg [sqlite3_errmsg $DB]
+ sqlite3_close $DB
+ set errmsg
+} {no such vfs: nosuchvfs}
+
+
+# EVIDENCE-OF: R-60479-64270 The mode parameter may be set to either
+# "ro", "rw" or "rwc". Attempting to set it to any other value is an
+# error
+#
+sqlite3 db test.db
+db close
+foreach {tn uri error} "
+ 1 {file:test.db?mode=ro} {not an error}
+ 2 {file:test.db?mode=rw} {not an error}
+ 3 {file:test.db?mode=rwc} {not an error}
+ 4 {file:test.db?mode=Ro} {no such access mode: Ro}
+ 5 {file:test.db?mode=Rw} {no such access mode: Rw}
+ 6 {file:test.db?mode=Rwc} {no such access mode: Rwc}
+" {
+ do_test 7.$tn { open_uri_error $uri } $error
+}
+
+
+# EVIDENCE-OF: R-09651-31805 If "ro" is specified, then the database is
+# opened for read-only access, just as if the SQLITE_OPEN_READONLY flag
+# had been set in the third argument to sqlite3_prepare_v2().
+#
+# EVIDENCE-OF: R-40137-26050 If the mode option is set to "rw", then the
+# database is opened for read-write (but not create) access, as if
+# SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had been set.
+#
+# EVIDENCE-OF: R-26845-32976 Value "rwc" is equivalent to setting both
+# SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE.
+#
+sqlite3_shutdown
+sqlite3_config_uri 1
+foreach {tn uri read write create} {
+ 1 {file:test.db?mode=ro} 1 0 0
+ 2 {file:test.db?mode=rw} 1 1 0
+ 3 {file:test.db?mode=rwc} 1 1 1
+} {
+ set RES(c,0) {1 {unable to open database file}}
+ set RES(c,1) {0 {}}
+ set RES(w,0) {1 {attempt to write a readonly database}}
+ set RES(w,1) {0 {}}
+ set RES(r,0) {1 {this never happens}}
+ set RES(r,1) {0 {a b}}
+
+ # Test CREATE access:
+ forcedelete test.db
+ do_test 8.$tn.c { list [catch { sqlite3 db $uri } msg] $msg } $RES(c,$create)
+ catch { db close }
+
+ sqlite3 db test.db
+ db eval { CREATE TABLE t1(a, b) ; INSERT INTO t1 VALUES('a', 'b') ;}
+ db close
+
+ # Test READ access:
+ do_test 8.$tn.r {
+ sqlite3 db $uri
+ catchsql { SELECT * FROM t1 }
+ } $RES(r,$read)
+
+ # Test WRITE access:
+ do_test 8.$tn.w {
+ sqlite3 db $uri
+ catchsql { INSERT INTO t1 VALUES(1, 2) }
+ } $RES(w,$write)
+
+ catch {db close}
+}
+
+# EVIDENCE-OF: R-56032-32287 If sqlite3_open_v2() is used, it is an
+# error to specify a value for the mode parameter that is less
+# restrictive than that specified by the flags passed as the third
+# parameter.
+#
+forcedelete test.db
+sqlite3 db test.db
+db close
+foreach {tn uri flags error} {
+ 1 {file:test.db?mode=ro} ro {not an error}
+ 2 {file:test.db?mode=ro} rw {not an error}
+ 3 {file:test.db?mode=ro} rwc {not an error}
+
+ 4 {file:test.db?mode=rw} ro {access permission denied}
+ 5 {file:test.db?mode=rw} rw {not an error}
+ 6 {file:test.db?mode=rw} rwc {not an error}
+
+ 7 {file:test.db?mode=rwc} ro {access permission denied}
+ 8 {file:test.db?mode=rwc} rw {access permission denied}
+ 9 {file:test.db?mode=rwc} rwc {not an error}
+} {
+ set f(ro) [list SQLITE_OPEN_READONLY SQLITE_OPEN_URI]
+ set f(rw) [list SQLITE_OPEN_READWRITE SQLITE_OPEN_URI]
+ set f(rwc) [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
+
+ set DB [sqlite3_open_v2 $uri $f($flags) ""]
+ set e [sqlite3_errmsg $DB]
+ sqlite3_close $DB
+
+ do_test 9.$tn { set e } $error
+}
+
+# EVIDENCE-OF: R-23182-54295 The cache parameter may be set to either
+# "shared" or "private".
+sqlite3 db test.db
+db close
+foreach {tn uri error} "
+ 1 {file:test.db?cache=private} {not an error}
+ 2 {file:test.db?cache=shared} {not an error}
+ 3 {file:test.db?cache=yes} {no such cache mode: yes}
+ 4 {file:test.db?cache=} {no such cache mode: }
+" {
+ do_test 10.$tn { open_uri_error $uri } $error
+}
+
+# EVIDENCE-OF: R-23027-03515 Setting it to "shared" is equivalent to
+# setting the SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed
+# to sqlite3_open_v2().
+#
+# EVIDENCE-OF: R-49793-28525 Setting the cache parameter to "private" is
+# equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
+#
+# EVIDENCE-OF: R-19510-48080 If sqlite3_open_v2() is used and the
+# "cache" parameter is present in a URI filename, its value overrides
+# any behaviour requested by setting SQLITE_OPEN_PRIVATECACHE or
+# SQLITE_OPEN_SHAREDCACHE flag.
+#
+set orig [sqlite3_enable_shared_cache]
+foreach {tn uri flags shared_default isshared} {
+ 1.1 "file:test.db" "" 0 0
+ 1.2 "file:test.db" "" 1 1
+ 1.3 "file:test.db" private 0 0
+ 1.4 "file:test.db" private 1 0
+ 1.5 "file:test.db" shared 0 1
+ 1.6 "file:test.db" shared 1 1
+
+ 2.1 "file:test.db?cache=private" "" 0 0
+ 2.2 "file:test.db?cache=private" "" 1 0
+ 2.3 "file:test.db?cache=private" private 0 0
+ 2.4 "file:test.db?cache=private" private 1 0
+ 2.5 "file:test.db?cache=private" shared 0 0
+ 2.6 "file:test.db?cache=private" shared 1 0
+
+ 3.1 "file:test.db?cache=shared" "" 0 1
+ 3.2 "file:test.db?cache=shared" "" 1 1
+ 3.3 "file:test.db?cache=shared" private 0 1
+ 3.4 "file:test.db?cache=shared" private 1 1
+ 3.5 "file:test.db?cache=shared" shared 0 1
+ 3.6 "file:test.db?cache=shared" shared 1 1
+} {
+ forcedelete test.db
+ sqlite3_enable_shared_cache 1
+ sqlite3 db test.db
+ sqlite3_enable_shared_cache 0
+
+ db eval {
+ CREATE TABLE t1(x);
+ INSERT INTO t1 VALUES('ok');
+ }
+
+ unset -nocomplain f
+ set f() {SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI}
+ set f(shared) [concat $f() SQLITE_OPEN_SHAREDCACHE]
+ set f(private) [concat $f() SQLITE_OPEN_PRIVATECACHE]
+
+ sqlite3_enable_shared_cache $shared_default
+ set DB [sqlite3_open_v2 $uri $f($flags) ""]
+
+ set STMT [sqlite3_prepare $DB "SELECT * FROM t1" -1 dummy]
+
+ db eval {
+ BEGIN;
+ INSERT INTO t1 VALUES('ko');
+ }
+
+ sqlite3_step $STMT
+ sqlite3_finalize $STMT
+
+ set RES(0) {not an error}
+ set RES(1) {database table is locked: t1}
+
+ do_test 11.$tn { sqlite3_errmsg $DB } $RES($isshared)
+
+ sqlite3_close $DB
+ db close
+}
+sqlite3_enable_shared_cache $orig
+
+# EVIDENCE-OF: R-63472-46769 Specifying an unknown parameter in the
+# query component of a URI is not an error.
+#
+do_test 12.1 {
+ parse_uri file://localhost/test.db?an=unknown¶meter=is&ok=
+} {/test.db {an unknown parameter is ok {}}}
+do_test 12.2 {
+ parse_uri file://localhost/test.db?an&unknown¶meter&is&ok
+} {/test.db {an {} unknown {} parameter {} is {} ok {}}}
+
+# EVIDENCE-OF: R-27458-04043 URI hexadecimal escape sequences (%HH) are
+# supported within the path and query components of a URI.
+#
+# EVIDENCE-OF: R-52765-50368 Before the path or query components of a
+# URI filename are interpreted, they are encoded using UTF-8 and all
+# hexadecimal escape sequences replaced by a single byte containing the
+# corresponding octet.
+#
+# The second of the two statements above is tested by creating a
+# multi-byte utf-8 character using a sequence of %HH escapes.
+#
+foreach {tn uri parse} "
+ 1 {file:/test.%64%62} {/test.db {}}
+ 2 {file:/test.db?%68%65%6c%6c%6f=%77%6f%72%6c%64} {/test.db {hello world}}
+ 3 {file:/%C3%BF.db} {/\xFF.db {}}
+" {
+ do_test 13.$tn { parse_uri $uri } $parse
+}
+
+finish_test
# 3.*: That specifying an unknown VFS causes an error.
# 4.*: Tests for specifying other options (other than "vfs").
# 5.*: Test using a different VFS with an attached database.
+# 6.*: Test that authorities other than "" and localhost cause errors.
#
set testprefix uri
#-------------------------------------------------------------------------
# Test some of the other options (other than "vfs").
#
-# TODO: Fix this after the list of options is decided.
-#
foreach {tn mode create_ok write_ok readonly_ok} {
1 ro 0 0 1
2 rw 0 1 0