]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Update comments and documentation associated with new URI parsing code. Add test...
authordan <dan@noemail.net>
Fri, 6 May 2011 18:34:54 +0000 (18:34 +0000)
committerdan <dan@noemail.net>
Fri, 6 May 2011 18:34:54 +0000 (18:34 +0000)
FossilOrigin-Name: 92751788eae082e3104838cb6dd8b9793cb325d1

manifest
manifest.uuid
src/main.c
src/sqlite.h.in
src/test1.c
test/e_uri.test [new file with mode: 0644]
test/uri.test

index b62b84089c9574046404e293b24cacdc92219835..e5d13928ae56af9de0270056f19cabbe5c6ec7e8 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-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
@@ -144,7 +144,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 872493d84fed9b9c910e1b7b2427a3e28dbe995a
+F src/main.c 145f04d5d8a6a391093b8e6a3b37511ac79e05c3
 F src/malloc.c 74c740e8ba22b806cfb980c8c0ddea1cbd54a20e
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206
@@ -179,14 +179,14 @@ F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
 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
@@ -379,6 +379,7 @@ F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
 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
@@ -840,7 +841,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 f21a5cd025ccedf0c6d4c5e365bb47e163098c04
+F test/uri.test e8579b07985b8f4f658eb4e077962a9b2b7b6491
 F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
 F test/vacuum.test 29b60e8cc9e573b39676df6c4a75fe9e02d04a09
 F test/vacuum2.test 91a84c9b08adfc4472097d2e8deb0150214e0e76
@@ -934,7 +935,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 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
index 1014b9c4177ee4d8660f2c797e68a5345d2f8096..4ea86418d5da18b5110fb6e563e98eccd9e5f2eb 100644 (file)
@@ -1 +1 @@
-fe57a8f621944fd2af5a4e9349c8fd77c4aba237
\ No newline at end of file
+92751788eae082e3104838cb6dd8b9793cb325d1
\ No newline at end of file
index 9021b8514b1ac32b24a9867330c58df39bf942ed..bcfd2deb04883ff0893d71d538b5be2cfd624608 100644 (file)
@@ -1791,9 +1791,28 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
 }
 
 /*
-** 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 */
@@ -1819,8 +1838,12 @@ int sqlite3ParseUri(
     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;
 
@@ -1907,7 +1930,7 @@ int sqlite3ParseUri(
       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 {
@@ -1918,7 +1941,7 @@ int sqlite3ParseUri(
         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 },
@@ -1930,7 +1953,7 @@ int sqlite3ParseUri(
           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 }, 
@@ -1949,7 +1972,7 @@ int sqlite3ParseUri(
           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;
             }
index d394d6c819339960ebbbf9f8acc8fb924ead6cc5..d8180bca5097dbc80ec82e7cd4596a34a46a137b 100644 (file)
@@ -2430,10 +2430,8 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 ** ^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].
@@ -2444,20 +2442,22 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     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
@@ -2487,10 +2487,8 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 ** <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.
index b79bbd08269f2f43cbd03c2bf158970be3e2f1fb..8e3012343341b6521eb54aa47e487d44602a364e 100644 (file)
@@ -3845,6 +3845,76 @@ static int test_open(
   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
 */
@@ -5593,6 +5663,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "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 },
diff --git a/test/e_uri.test b/test/e_uri.test
new file mode 100644 (file)
index 0000000..22bb49d
--- /dev/null
@@ -0,0 +1,427 @@
+# 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&parameter=is&ok=
+} {/test.db {an unknown parameter is ok {}}}
+do_test 12.2 {
+  parse_uri file://localhost/test.db?an&unknown&parameter&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
index b8b83e8fd44580900690673bcf870f1d8aa81abb..22e0fc9bdedd08ca6f7005ff5bec05feb23b2f17 100644 (file)
@@ -20,6 +20,7 @@ source $testdir/tester.tcl
 #   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
@@ -128,8 +129,6 @@ do_test 3.1 {
 #-------------------------------------------------------------------------
 # 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