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 |
Timelines: | family | ancestors | descendants | both | uri |
Files: | files | file ages | folders |
SHA1: |
2af51f856c6203f836d8bb62b6b79b19 |
User & Date: | dan 2011-04-23 19:06:26.760 |
Context
2011-05-02
| ||
17:41 | Merge the latest trunk changes into uri branch. (check-in: 7fdd0786c7 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: 2af51f856c 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: 68240e75e8 user: dan tags: uri) | |
Changes
Changes to src/main.c.
︙ | ︙ | |||
1787 1788 1789 1790 1791 1792 1793 | } db->aLimit[limitId] = newLimit; } return oldLimit; /* IMP: R-53341-35419 */ } /* | | | | | 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 | } db->aLimit[limitId] = newLimit; } return oldLimit; /* IMP: R-53341-35419 */ } /* ** 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. */ int sqlite3ParseUri( const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */ const char *zUri, /* Nul-terminated URI to parse */ int *pFlags, /* IN/OUT: SQLITE_OPEN_XXX flags */ sqlite3_vfs **ppVfs, /* OUT: VFS to use */ char **pzFile, /* OUT: Filename component of URI */ |
︙ | ︙ |
Changes to src/test_vfs.c.
︙ | ︙ | |||
110 111 112 113 114 115 116 | ** The Testvfs.mask variable is set to a combination of the following. ** If a bit is clear in Testvfs.mask, then calls made by SQLite to the ** corresponding VFS method is ignored for purposes of: ** ** + Simulating IO errors, and ** + Invoking the Tcl callback script. */ | | | | | | | | | | | | | > | | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | ** The Testvfs.mask variable is set to a combination of the following. ** If a bit is clear in Testvfs.mask, then calls made by SQLite to the ** corresponding VFS method is ignored for purposes of: ** ** + Simulating IO errors, and ** + Invoking the Tcl callback script. */ #define TESTVFS_SHMOPEN_MASK 0x00000001 #define TESTVFS_SHMLOCK_MASK 0x00000010 #define TESTVFS_SHMMAP_MASK 0x00000020 #define TESTVFS_SHMBARRIER_MASK 0x00000040 #define TESTVFS_SHMCLOSE_MASK 0x00000080 #define TESTVFS_OPEN_MASK 0x00000100 #define TESTVFS_SYNC_MASK 0x00000200 #define TESTVFS_DELETE_MASK 0x00000400 #define TESTVFS_CLOSE_MASK 0x00000800 #define TESTVFS_WRITE_MASK 0x00001000 #define TESTVFS_TRUNCATE_MASK 0x00002000 #define TESTVFS_ACCESS_MASK 0x00004000 #define TESTVFS_FULLPATHNAME_MASK 0x00008000 #define TESTVFS_ALL_MASK 0x0001FFFF #define TESTVFS_MAX_PAGES 1024 /* ** A shared-memory buffer. There is one of these objects for each shared ** memory region opened by clients. If two clients open the same file, |
︙ | ︙ | |||
671 672 673 674 675 676 677 678 679 680 681 682 683 684 | */ static int tvfsFullPathname( sqlite3_vfs *pVfs, const char *zPath, int nOut, char *zOut ){ return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut); } #ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** Open the dynamic library located at zPath and return a handle. */ | > > > > > > > > | 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 | */ static int tvfsFullPathname( sqlite3_vfs *pVfs, const char *zPath, int nOut, char *zOut ){ Testvfs *p = (Testvfs *)pVfs->pAppData; if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){ int rc; tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0); if( tvfsResultCode(p, &rc) ){ if( rc!=SQLITE_OK ) return rc; } } return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut); } #ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** Open the dynamic library located at zPath and return a handle. */ |
︙ | ︙ | |||
1036 1037 1038 1039 1040 1041 1042 | } case CMD_FILTER: { static struct VfsMethod { char *zName; int mask; } vfsmethod [] = { | | | | | | | | | | | | | > | 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 | } case CMD_FILTER: { static struct VfsMethod { char *zName; int mask; } vfsmethod [] = { { "xShmOpen", TESTVFS_SHMOPEN_MASK }, { "xShmLock", TESTVFS_SHMLOCK_MASK }, { "xShmBarrier", TESTVFS_SHMBARRIER_MASK }, { "xShmUnmap", TESTVFS_SHMCLOSE_MASK }, { "xShmMap", TESTVFS_SHMMAP_MASK }, { "xSync", TESTVFS_SYNC_MASK }, { "xDelete", TESTVFS_DELETE_MASK }, { "xWrite", TESTVFS_WRITE_MASK }, { "xTruncate", TESTVFS_TRUNCATE_MASK }, { "xOpen", TESTVFS_OPEN_MASK }, { "xClose", TESTVFS_CLOSE_MASK }, { "xAccess", TESTVFS_ACCESS_MASK }, { "xFullPathname", TESTVFS_FULLPATHNAME_MASK }, }; Tcl_Obj **apElem = 0; int nElem = 0; int i; int mask = 0; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "LIST"); |
︙ | ︙ |
Changes to test/uri.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # May you share freely, never taking more than you give. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix uri db close sqlite3_shutdown sqlite3_config_uri 1 #------------------------------------------------------------------------- | > > > > > > > > > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # May you share freely, never taking more than you give. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl # Test organization: # # 1.*: That file names are correctly extracted from URIs. # 2.*: That URI options (query parameters) are correctly extracted from URIs. # 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. # set testprefix uri db close sqlite3_shutdown sqlite3_config_uri 1 #------------------------------------------------------------------------- |
︙ | ︙ | |||
100 101 102 103 104 105 106 | # Test that specifying a non-existent VFS raises an error. # do_test 3.1 { list [catch { sqlite3 db "file:test.db?vfs=nosuchvfs" } msg] $msg } {1 {no such vfs: nosuchvfs}} #------------------------------------------------------------------------- | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | # Test that specifying a non-existent VFS raises an error. # do_test 3.1 { list [catch { sqlite3 db "file:test.db?vfs=nosuchvfs" } msg] $msg } {1 {no such vfs: nosuchvfs}} #------------------------------------------------------------------------- # Test some of the other options (other than "vfs"). # # 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 } { set RES(0) {0 {}} set RES(1) {1 {attempt to write a readonly database}} do_test 4.$tn { sqlite3 db $uri catchsql { INSERT INTO t1 VALUES(1, 2) } } $RES($ro) db close } #------------------------------------------------------------------------- # Test that things work if an ATTACHed database uses a different VFS than # the main database. The important point is that for all operations # involving the ATTACHed database, the correct versions of the following # VFS are used for all operations involving the attached database. # # xOpen # xDelete # xAccess # xFullPathname # # This block of code creates two VFS - "tvfs1" and "tvfs2". Each time one # of the above methods is called using "tvfs1", global variable ::T1(X) is # set, where X is the file-name the method is called on. Calls to the above # methods using "tvfs2" set entries in the global T2 array. # testvfs tvfs1 tvfs1 filter {xOpen xDelete xAccess xFullPathname} tvfs1 script tvfs1_callback proc tvfs1_callback {method filename args} { set ::T1([file tail $filename]) 1 } testvfs tvfs2 tvfs2 filter {xOpen xDelete xAccess xFullPathname} tvfs2 script tvfs2_callback proc tvfs2_callback {method filename args} { set ::T2([file tail $filename]) 1 } eval forcedelete [glob test.db*] do_test 5.1.1 { sqlite3 db file:test.db1?vfs=tvfs1 execsql { ATTACH 'file:test.db2?vfs=tvfs2' AS aux; PRAGMA main.journal_mode = PERSIST; PRAGMA aux.journal_mode = PERSIST; CREATE TABLE t1(a, b); CREATE TABLE aux.t2(a, b); PRAGMA main.journal_mode = WAL; PRAGMA aux.journal_mode = PERSIST; INSERT INTO t1 VALUES('x', 'y'); INSERT INTO t2 VALUES('x', 'y'); } lsort [array names ::T1] } {test.db1 test.db1-journal test.db1-wal} do_test 5.1.2 { lsort [array names ::T2] } {test.db2 test.db2-journal test.db2-wal} db close tvfs1 delete tvfs2 delete finish_test |