/ Check-in [2af51f85]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Test that it is now possible to use different VFSs for two databases attached to a single handle.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | uri
Files: files | file ages | folders
SHA1: 2af51f856c6203f836d8bb62b6b79b19554886e7
User & Date: dan 2011-04-23 19:06:26
Context
2011-05-02
17:41
Merge the latest trunk changes into uri branch. check-in: 7fdd0786 user: dan tags: uri
2011-04-23
19:06
Test that it is now possible to use different VFSs for two databases attached to a single handle. check-in: 2af51f85 user: dan tags: uri
15:54
Have the ATTACH command do URI interpretation in the same way as sqlite3_open() and sqlite3_open_v2() do. check-in: 68240e75 user: dan tags: uri
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/main.c.

  1787   1787       }
  1788   1788       db->aLimit[limitId] = newLimit;
  1789   1789     }
  1790   1790     return oldLimit;                     /* IMP: R-53341-35419 */
  1791   1791   }
  1792   1792   
  1793   1793   /*
  1794         -** This function is used to parse filenames passed by the user to API
  1795         -** functions sqlite3_open() or sqlite3_open_v2(), and for database filenames
  1796         -** specified as part of ATTACH statements.
         1794  +** This function is used to parse URIs passed by the user to API functions 
         1795  +** sqlite3_open() or sqlite3_open_v2(), and for database URIs specified as 
         1796  +** part of ATTACH statements.
  1797   1797   */
  1798   1798   int sqlite3ParseUri(
  1799   1799     const char *zDefaultVfs,        /* VFS to use if no "vfs=xxx" query option */
  1800   1800     const char *zUri,               /* Nul-terminated URI to parse */
  1801   1801     int *pFlags,                    /* IN/OUT: SQLITE_OPEN_XXX flags */
  1802   1802     sqlite3_vfs **ppVfs,            /* OUT: VFS to use */ 
  1803   1803     char **pzFile,                  /* OUT: Filename component of URI */

Changes to src/test_vfs.c.

   110    110   ** The Testvfs.mask variable is set to a combination of the following.
   111    111   ** If a bit is clear in Testvfs.mask, then calls made by SQLite to the 
   112    112   ** corresponding VFS method is ignored for purposes of:
   113    113   **
   114    114   **   + Simulating IO errors, and
   115    115   **   + Invoking the Tcl callback script.
   116    116   */
   117         -#define TESTVFS_SHMOPEN_MASK    0x00000001
   118         -#define TESTVFS_SHMLOCK_MASK    0x00000010
   119         -#define TESTVFS_SHMMAP_MASK     0x00000020
   120         -#define TESTVFS_SHMBARRIER_MASK 0x00000040
   121         -#define TESTVFS_SHMCLOSE_MASK   0x00000080
          117  +#define TESTVFS_SHMOPEN_MASK      0x00000001
          118  +#define TESTVFS_SHMLOCK_MASK      0x00000010
          119  +#define TESTVFS_SHMMAP_MASK       0x00000020
          120  +#define TESTVFS_SHMBARRIER_MASK   0x00000040
          121  +#define TESTVFS_SHMCLOSE_MASK     0x00000080
   122    122   
   123         -#define TESTVFS_OPEN_MASK       0x00000100
   124         -#define TESTVFS_SYNC_MASK       0x00000200
   125         -#define TESTVFS_DELETE_MASK     0x00000400
   126         -#define TESTVFS_CLOSE_MASK      0x00000800
   127         -#define TESTVFS_WRITE_MASK      0x00001000
   128         -#define TESTVFS_TRUNCATE_MASK   0x00002000
   129         -#define TESTVFS_ACCESS_MASK     0x00004000
   130         -#define TESTVFS_ALL_MASK        0x00007FFF
          123  +#define TESTVFS_OPEN_MASK         0x00000100
          124  +#define TESTVFS_SYNC_MASK         0x00000200
          125  +#define TESTVFS_DELETE_MASK       0x00000400
          126  +#define TESTVFS_CLOSE_MASK        0x00000800
          127  +#define TESTVFS_WRITE_MASK        0x00001000
          128  +#define TESTVFS_TRUNCATE_MASK     0x00002000
          129  +#define TESTVFS_ACCESS_MASK       0x00004000
          130  +#define TESTVFS_FULLPATHNAME_MASK 0x00008000
          131  +#define TESTVFS_ALL_MASK          0x0001FFFF
   131    132   
   132    133   
   133    134   #define TESTVFS_MAX_PAGES 1024
   134    135   
   135    136   /*
   136    137   ** A shared-memory buffer. There is one of these objects for each shared
   137    138   ** memory region opened by clients. If two clients open the same file,
................................................................................
   671    672   */
   672    673   static int tvfsFullPathname(
   673    674     sqlite3_vfs *pVfs, 
   674    675     const char *zPath, 
   675    676     int nOut, 
   676    677     char *zOut
   677    678   ){
          679  +  Testvfs *p = (Testvfs *)pVfs->pAppData;
          680  +  if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){
          681  +    int rc;
          682  +    tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0);
          683  +    if( tvfsResultCode(p, &rc) ){
          684  +      if( rc!=SQLITE_OK ) return rc;
          685  +    }
          686  +  }
   678    687     return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut);
   679    688   }
   680    689   
   681    690   #ifndef SQLITE_OMIT_LOAD_EXTENSION
   682    691   /*
   683    692   ** Open the dynamic library located at zPath and return a handle.
   684    693   */
................................................................................
  1036   1045       }
  1037   1046   
  1038   1047       case CMD_FILTER: {
  1039   1048         static struct VfsMethod {
  1040   1049           char *zName;
  1041   1050           int mask;
  1042   1051         } vfsmethod [] = {
  1043         -        { "xShmOpen",    TESTVFS_SHMOPEN_MASK },
  1044         -        { "xShmLock",    TESTVFS_SHMLOCK_MASK },
  1045         -        { "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
  1046         -        { "xShmUnmap",   TESTVFS_SHMCLOSE_MASK },
  1047         -        { "xShmMap",     TESTVFS_SHMMAP_MASK },
  1048         -        { "xSync",       TESTVFS_SYNC_MASK },
  1049         -        { "xDelete",     TESTVFS_DELETE_MASK },
  1050         -        { "xWrite",      TESTVFS_WRITE_MASK },
  1051         -        { "xTruncate",   TESTVFS_TRUNCATE_MASK },
  1052         -        { "xOpen",       TESTVFS_OPEN_MASK },
  1053         -        { "xClose",      TESTVFS_CLOSE_MASK },
  1054         -        { "xAccess",     TESTVFS_ACCESS_MASK },
         1052  +        { "xShmOpen",      TESTVFS_SHMOPEN_MASK },
         1053  +        { "xShmLock",      TESTVFS_SHMLOCK_MASK },
         1054  +        { "xShmBarrier",   TESTVFS_SHMBARRIER_MASK },
         1055  +        { "xShmUnmap",     TESTVFS_SHMCLOSE_MASK },
         1056  +        { "xShmMap",       TESTVFS_SHMMAP_MASK },
         1057  +        { "xSync",         TESTVFS_SYNC_MASK },
         1058  +        { "xDelete",       TESTVFS_DELETE_MASK },
         1059  +        { "xWrite",        TESTVFS_WRITE_MASK },
         1060  +        { "xTruncate",     TESTVFS_TRUNCATE_MASK },
         1061  +        { "xOpen",         TESTVFS_OPEN_MASK },
         1062  +        { "xClose",        TESTVFS_CLOSE_MASK },
         1063  +        { "xAccess",       TESTVFS_ACCESS_MASK },
         1064  +        { "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
  1055   1065         };
  1056   1066         Tcl_Obj **apElem = 0;
  1057   1067         int nElem = 0;
  1058   1068         int i;
  1059   1069         int mask = 0;
  1060   1070         if( objc!=3 ){
  1061   1071           Tcl_WrongNumArgs(interp, 2, objv, "LIST");

Changes to test/uri.test.

     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   #
    12     12   
    13     13   set testdir [file dirname $argv0]
    14     14   source $testdir/tester.tcl
           15  +
           16  +# Test organization:
           17  +#
           18  +#   1.*: That file names are correctly extracted from URIs.
           19  +#   2.*: That URI options (query parameters) are correctly extracted from URIs.
           20  +#   3.*: That specifying an unknown VFS causes an error.
           21  +#   4.*: Tests for specifying other options (other than "vfs").
           22  +#   5.*: Test using a different VFS with an attached database.
           23  +#
    15     24   
    16     25   set testprefix uri
    17     26   db close
    18     27   sqlite3_shutdown
    19     28   sqlite3_config_uri 1
    20     29   
    21     30   #-------------------------------------------------------------------------
................................................................................
   100    109   # Test that specifying a non-existent VFS raises an error.
   101    110   #
   102    111   do_test 3.1 {
   103    112     list [catch { sqlite3 db "file:test.db?vfs=nosuchvfs" } msg] $msg
   104    113   } {1 {no such vfs: nosuchvfs}}
   105    114   
   106    115   #-------------------------------------------------------------------------
   107         -# Test the "readonly" URI option.
          116  +# Test some of the other options (other than "vfs").
          117  +#
          118  +# TODO: Fix this after the list of options is decided.
   108    119   #
   109    120   do_test 4.0 {
   110    121     sqlite3 db test.db
   111    122     db eval {CREATE TABLE t1(a, b)}
   112    123     db close
   113    124   } {}
   114    125   foreach {tn uri ro} {
................................................................................
   121    132   
   122    133     do_test 4.$tn {
   123    134       sqlite3 db $uri
   124    135       catchsql { INSERT INTO t1 VALUES(1, 2) }
   125    136     } $RES($ro)
   126    137     db close
   127    138   }
          139  +
          140  +#-------------------------------------------------------------------------
          141  +# Test that things work if an ATTACHed database uses a different VFS than
          142  +# the main database. The important point is that for all operations 
          143  +# involving the ATTACHed database, the correct versions of the following
          144  +# VFS are used for all operations involving the attached database.
          145  +#
          146  +#     xOpen
          147  +#     xDelete
          148  +#     xAccess
          149  +#     xFullPathname
          150  +#
          151  +
          152  +# This block of code creates two VFS - "tvfs1" and "tvfs2". Each time one
          153  +# of the above methods is called using "tvfs1", global variable ::T1(X) is
          154  +# set, where X is the file-name the method is called on. Calls to the above
          155  +# methods using "tvfs2" set entries in the global T2 array.
          156  +#
          157  +testvfs tvfs1 
          158  +tvfs1 filter {xOpen xDelete xAccess xFullPathname}
          159  +tvfs1 script tvfs1_callback
          160  +proc tvfs1_callback {method filename args} { 
          161  +  set ::T1([file tail $filename]) 1 
          162  +}
          163  +testvfs tvfs2 
          164  +tvfs2 filter {xOpen xDelete xAccess xFullPathname}
          165  +tvfs2 script tvfs2_callback
          166  +proc tvfs2_callback {method filename args} { 
          167  +  set ::T2([file tail $filename]) 1 
          168  +}
          169  +
          170  +eval forcedelete [glob test.db*]
          171  +do_test 5.1.1 {
          172  +  sqlite3 db file:test.db1?vfs=tvfs1
          173  +  execsql {
          174  +    ATTACH 'file:test.db2?vfs=tvfs2' AS aux;
          175  +    PRAGMA main.journal_mode = PERSIST;
          176  +    PRAGMA aux.journal_mode = PERSIST;
          177  +    CREATE TABLE t1(a, b);
          178  +    CREATE TABLE aux.t2(a, b);
          179  +    PRAGMA main.journal_mode = WAL;
          180  +    PRAGMA aux.journal_mode = PERSIST;
          181  +    INSERT INTO t1 VALUES('x', 'y');
          182  +    INSERT INTO t2 VALUES('x', 'y');
          183  +  }
          184  +  lsort [array names ::T1]
          185  +} {test.db1 test.db1-journal test.db1-wal}
          186  +
          187  +do_test 5.1.2 {
          188  +  lsort [array names ::T2]
          189  +} {test.db2 test.db2-journal test.db2-wal}
          190  +
          191  +db close
          192  +tvfs1 delete
          193  +tvfs2 delete
   128    194   
   129    195   finish_test
   130    196