Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Rearchitect the way in which filenames are stored in the Pager object so that the sqlite3_uri_parameter() interface will work from journal and WAL filenames too. This check-in implements the central idea, and compile and runs somewhat, but crashes on an extended test. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | enhanced-uri |
Files: | files | file ages | folders |
SHA3-256: |
2ae77bd2335708343bce4541b4d2cf16 |
User & Date: | drh 2020-01-10 18:05:55.320 |
Context
2020-01-11
| ||
16:08 | Redesign for better legacy compatibility. Add the sqlite3_uri_key() interface. (check-in: bcb43d11c4 user: drh tags: enhanced-uri) | |
2020-01-10
| ||
18:05 | Rearchitect the way in which filenames are stored in the Pager object so that the sqlite3_uri_parameter() interface will work from journal and WAL filenames too. This check-in implements the central idea, and compile and runs somewhat, but crashes on an extended test. (check-in: 2ae77bd233 user: drh tags: enhanced-uri) | |
01:05 | Fix to the register validity tracking logic in debug builds. No impact on release builds. (check-in: 0a500da6aa user: drh tags: trunk) | |
Changes
Changes to src/main.c.
︙ | ︙ | |||
4268 4269 4270 4271 4272 4273 4274 4275 | ** The zFilename argument is the filename pointer passed into the xOpen() ** method of a VFS implementation. The zParam argument is the name of the ** query parameter we seek. This routine returns the value of the zParam ** parameter if it exists. If the parameter does not exist, this routine ** returns a NULL pointer. */ const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){ if( zFilename==0 || zParam==0 ) return 0; | > > | > > | | | | | | 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 | ** The zFilename argument is the filename pointer passed into the xOpen() ** method of a VFS implementation. The zParam argument is the name of the ** query parameter we seek. This routine returns the value of the zParam ** parameter if it exists. If the parameter does not exist, this routine ** returns a NULL pointer. */ const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){ const Pager *pPager; const char *z; if( zFilename==0 || zParam==0 ) return 0; pPager = sqlite3PagerFromFilename(zFilename); assert( pPager!=0 ); z = sqlite3PagerQueryParameters(pPager); while( z[0] ){ int x = strcmp(z, zParam); z += sqlite3Strlen30(z) + 1; if( x==0 ) return z; z += sqlite3Strlen30(z) + 1; } return 0; } /* ** Return a boolean value for a query parameter. */ |
︙ | ︙ | |||
4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 | const char *z = sqlite3_uri_parameter(zFilename, zParam); sqlite3_int64 v; if( z && sqlite3DecOrHexToI64(z, &v)==0 ){ bDflt = v; } return bDflt; } /* ** Return the Btree pointer identified by zDbName. Return NULL if not found. */ Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ int iDb = zDbName ? sqlite3FindDbName(db, zDbName) : 0; return iDb<0 ? 0 : db->aDb[iDb].pBt; | > > > > > > > > > > > > > > > > > > > > > > > > > > | 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 | const char *z = sqlite3_uri_parameter(zFilename, zParam); sqlite3_int64 v; if( z && sqlite3DecOrHexToI64(z, &v)==0 ){ bDflt = v; } return bDflt; } /* ** Translate a filename that was handed to a VFS routine into the corresponding ** database, journal, or WAL file. ** ** It is an error to pass this routine a filename string that was not ** passed into the VFS from the SQLite core. Doing so is similar to ** passing free() a pointer that was not obtained from malloc() - it is ** an error that we cannot easily detect but that will likely cause memory ** corruption. */ const char *sqlite3_filename_database(const char *zFilename){ const Pager *pPager = sqlite3PagerFromFilename(zFilename); assert( pPager!=0 ); return sqlite3PagerFilename(pPager, 0); } const char *sqlite3_filename_journal(const char *zFilename){ const Pager *pPager = sqlite3PagerFromFilename(zFilename); assert( pPager!=0 ); return sqlite3PagerJournalFilename(pPager); } const char *sqlite3_filename_wal(const char *zFilename){ const Pager *pPager = sqlite3PagerFromFilename(zFilename); assert( pPager!=0 ); return sqlite3PagerWalFilename(pPager); } /* ** Return the Btree pointer identified by zDbName. Return NULL if not found. */ Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ int iDb = zDbName ? sqlite3FindDbName(db, zDbName) : 0; return iDb<0 ? 0 : db->aDb[iDb].pBt; |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
692 693 694 695 696 697 698 699 700 701 702 703 704 705 | i16 nReserve; /* Number of unused bytes at end of each page */ u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ u32 sectorSize; /* Assumed sector size during rollback */ int pageSize; /* Number of bytes in a page */ Pgno mxPgno; /* Maximum allowed size of the database */ i64 journalSizeLimit; /* Size limit for persistent journal files */ char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ int (*xBusyHandler)(void*); /* Function to call when busy */ void *pBusyHandlerArg; /* Context argument for xBusyHandler */ int aStat[4]; /* Total cache hits, misses, writes, spills */ #ifdef SQLITE_TEST int nRead; /* Database pages read */ #endif | > | 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 | i16 nReserve; /* Number of unused bytes at end of each page */ u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ u32 sectorSize; /* Assumed sector size during rollback */ int pageSize; /* Number of bytes in a page */ Pgno mxPgno; /* Maximum allowed size of the database */ i64 journalSizeLimit; /* Size limit for persistent journal files */ char *zFilename; /* Name of the database file */ char *zQueryParam; /* URI query parameters on the filename */ char *zJournal; /* Name of the journal file */ int (*xBusyHandler)(void*); /* Function to call when busy */ void *pBusyHandlerArg; /* Context argument for xBusyHandler */ int aStat[4]; /* Total cache hits, misses, writes, spills */ #ifdef SQLITE_TEST int nRead; /* Database pages read */ #endif |
︙ | ︙ | |||
4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 | ** file name. The layout in memory is as follows: ** ** Pager object (sizeof(Pager) bytes) ** PCache object (sqlite3PcacheSize() bytes) ** Database file handle (pVfs->szOsFile bytes) ** Sub-journal file handle (journalFileSize bytes) ** Main journal file handle (journalFileSize bytes) ** Database file name (nPathname+1 bytes) ** Journal file name (nPathname+8+1 bytes) */ pPtr = (u8 *)sqlite3MallocZero( | > > > > > > > | | | | > | > | > | > < | | > | | < | > > | | | > | > > | | < < > > > | | | < < | > > > | | > | > | 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 | ** file name. The layout in memory is as follows: ** ** Pager object (sizeof(Pager) bytes) ** PCache object (sqlite3PcacheSize() bytes) ** Database file handle (pVfs->szOsFile bytes) ** Sub-journal file handle (journalFileSize bytes) ** Main journal file handle (journalFileSize bytes) ** Pointer back to self (sizeof(*Pager) bytes) ** Database file name (nPathname+1 bytes) ** URI query parameters (nUriByte bytes) ** padding for 8-byte alignment ** Pointer back to self (sizeof(*Pager) bytes) ** WAL filename (nPathname+4+1 bytes) ** padding for 8-byte alignment ** Pointer back to self (sizeof(*Pager) bytes) ** Journal file name (nPathname+8+1 bytes) */ pPtr = (u8 *)sqlite3MallocZero( ROUND8(sizeof(*pPager)) + /* Pager structure */ ROUND8(pcacheSize) + /* PCache object */ ROUND8(pVfs->szOsFile) + /* The main db file */ journalFileSize * 2 + /* The two journal files */ sizeof(Pager*) + /* Self-pointer for database */ ROUND8(nPathname + 1 + nUriByte) + /* database filename + query params */ sizeof(Pager*) + /* Self-pointer for journal */ ROUND8(nPathname + 8 + 2) + /* zJournal */ #ifndef SQLITE_OMIT_WAL sizeof(Pager*) + /* Self-pointer for zWal */ ROUND8(nPathname + 4 + 2) + /* zWal */ #endif 0 ); assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) ); if( !pPtr ){ sqlite3DbFree(0, zPathname); return SQLITE_NOMEM_BKPT; } pPager = (Pager*)pPtr; pPtr += ROUND8(sizeof(*pPager)); pPager->pPCache = (PCache*)pPtr; pPtr += ROUND8(pcacheSize); pPager->fd = (sqlite3_file*)pPtr; pPtr += ROUND8(pVfs->szOsFile); pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize; pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize; assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) ); /* Fill in the Pager.zFilename and pPager.zQueryParam fields */ assert( EIGHT_BYTE_ALIGNMENT(pPtr) ); memcpy(pPtr, &pPager, sizeof(pPager)); pPtr += sizeof(pPager); pPager->zFilename = (char*)pPtr; if( nPathname==0 ) zPathname = ""; memcpy(pPtr, zPathname, nPathname); pPager->zQueryParam = pPager->zFilename + nPathname + 1; if( zUri ) memcpy(pPager->zQueryParam, zUri, nUriByte); assert( nUriByte>=1 ); assert( nUriByte >= nUri*3 + 1 ); pPtr += ROUND8(nPathname + 1 + nUriByte); #ifndef SQLITE_OMIT_WAL /* Fill in Pager.zWal */ assert( EIGHT_BYTE_ALIGNMENT(pPtr) ); memcpy(pPtr, &pPager, sizeof(pPager)); pPtr += sizeof(pPager); pPager->zWal = (char*)pPtr; memcpy(pPtr, zPathname, nPathname); memcpy(pPtr+nPathname, "-wal", 4); pPtr += ROUND8(nPathname + 4 + 2); #endif /* Fill in Pager.zJournal */ assert( EIGHT_BYTE_ALIGNMENT(pPtr) ); memcpy(pPtr, &pPager, sizeof(pPager)); pPtr += sizeof(pPager); pPager->zJournal = (char*)pPtr; memcpy(pPtr, zPathname, nPathname); memcpy(pPtr+nPathname, "-journal",8); /*pPtr += ROUND8(nPathname + 8 + 2);*/ if( nPathname ) sqlite3DbFree(0, zPathname); pPager->pVfs = pVfs; pPager->vfsFlags = vfsFlags; /* Open the pager file. */ if( zFilename && zFilename[0] ){ int fout = 0; /* VFS flags returned by xOpen() */ |
︙ | ︙ | |||
4929 4930 4931 4932 4933 4934 4935 | if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){ szPageDflt = ii; } } } #endif } | | | | 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 | if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){ szPageDflt = ii; } } } #endif } pPager->noLock = sqlite3_uri_boolean(pPager->zFilename, "nolock", 0); if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0 || sqlite3_uri_boolean(pPager->zFilename, "immutable", 0) ){ vfsFlags |= SQLITE_OPEN_READONLY; goto act_like_temp_file; } } }else{ /* If a temporary file is requested, it is not opened immediately. ** In this case we accept the default page size and delay actually |
︙ | ︙ | |||
6995 6996 6997 6998 6999 7000 7001 | ** Except, if the pager is in-memory only, then return an empty string if ** nullIfMemDb is true. This routine is called with nullIfMemDb==1 when ** used to report the filename to the user, for compatibility with legacy ** behavior. But when the Btree needs to know the filename for matching to ** shared cache, it uses nullIfMemDb==0 so that in-memory databases can ** participate in shared-cache. */ | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 | ** Except, if the pager is in-memory only, then return an empty string if ** nullIfMemDb is true. This routine is called with nullIfMemDb==1 when ** used to report the filename to the user, for compatibility with legacy ** behavior. But when the Btree needs to know the filename for matching to ** shared cache, it uses nullIfMemDb==0 so that in-memory databases can ** participate in shared-cache. */ const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){ return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename; } /* ** Return the name of the Journal file or WAL file of the given pager. */ const char *sqlite3PagerJournalFilename(const Pager *pPager){ assert( pPager!=0 ); return pPager->zJournal; } #ifndef SQLITE_OMIT_WAL const char *sqlite3PagerWalFilename(const Pager *pPager){ assert( pPager!=0 ); return pPager->zWal; } #endif /* SQLITE_OMIT_WAL */ /* Return a pointer to the URI query parameters associated with the ** pager. ** ** The query parameters are a sequence of strings pairs. The first ** string of each pair is the key and the second string is the value. ** All strings are terminated by a single 0x00 byte. The list is ** terminated by the first empty-string key. */ const char *sqlite3PagerQueryParameters(const Pager *pPager){ assert( pPager!=0 ); return pPager->zQueryParam; } /* If zFilename is a filename passed to the xOpen method of the VFS - ** either the main database file, the WAL file, or the journal file - ** then this routine returns a pointer to the Pager object associated ** with that file. */ const Pager *sqlite3PagerFromFilename(const char *zFilename){ const Pager **pp = (const Pager**)zFilename; pp--; assert( (*pp)->zFilename==zFilename || (*pp)->zJournal==zFilename || (*pp)->zWal==zFilename ); return *pp; } /* ** Return the VFS structure for the pager. */ sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){ return pPager->pVfs; } |
︙ | ︙ | |||
7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 | pPager->pWal = 0; pagerFixMaplimit(pPager); if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); } } return rc; } #ifdef SQLITE_ENABLE_SNAPSHOT /* ** If this is a WAL database, obtain a snapshot handle for the snapshot ** currently open. Otherwise, return an error. */ int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot){ | > > | 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 | pPager->pWal = 0; pagerFixMaplimit(pPager); if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); } } return rc; } #ifdef SQLITE_ENABLE_SNAPSHOT /* ** If this is a WAL database, obtain a snapshot handle for the snapshot ** currently open. Otherwise, return an error. */ int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot){ |
︙ | ︙ |
Changes to src/pager.h.
︙ | ︙ | |||
199 200 201 202 203 204 205 | /* Functions used to query pager state and configuration. */ u8 sqlite3PagerIsreadonly(Pager*); u32 sqlite3PagerDataVersion(Pager*); #ifdef SQLITE_DEBUG int sqlite3PagerRefcount(Pager*); #endif int sqlite3PagerMemUsed(Pager*); | | > > > > | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | /* Functions used to query pager state and configuration. */ u8 sqlite3PagerIsreadonly(Pager*); u32 sqlite3PagerDataVersion(Pager*); #ifdef SQLITE_DEBUG int sqlite3PagerRefcount(Pager*); #endif int sqlite3PagerMemUsed(Pager*); const char *sqlite3PagerFilename(const Pager*, int); const char *sqlite3PagerWalFilename(const Pager*); const char *sqlite3PagerJournalFilename(const Pager*); const char *sqlite3PagerQueryParameters(const Pager*); const Pager *sqlite3PagerFromFilename(const char*); sqlite3_vfs *sqlite3PagerVfs(Pager*); sqlite3_file *sqlite3PagerFile(Pager*); sqlite3_file *sqlite3PagerJrnlFile(Pager*); const char *sqlite3PagerJournalname(Pager*); void *sqlite3PagerTempSpace(Pager*); int sqlite3PagerIsMemdb(Pager*); void sqlite3PagerCacheStat(Pager *, int, int, int *); |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 | ** ** See the [URI filename] documentation for additional information. */ const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); /* ** CAPI3REF: Error Codes And Messages ** METHOD: sqlite3 ** ** ^If the most recent sqlite3_* API call associated with ** [database connection] D failed, then the sqlite3_errcode(D) interface | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 | ** ** See the [URI filename] documentation for additional information. */ const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); /* ** CAPI3REF: Translate filenames ** ** These routines are available to VFS implementations for translating ** filenames between the main database file, the journal file, and the ** WAL file. ** ** If F is the name of an sqlite database file, journal file, or WAL file ** then sqlite3_filename_database(F) returns the name of the corresponding ** database file. ** ** If F is the name of an sqlite database file, journal file, or WAL file ** then sqlite3_filename_journal(F) returns the name of the corresponding ** rollback journal file. ** ** If F is the name of an sqlite database file, journal file, or WAL file ** then sqlite3_filename_wal(F) returns the name of the corresponding ** WAL file. ** ** In all of the above, if F is not the name of a database, journal or WAL ** filename passed into the VFS from the SQLite core, then the result is ** undefined and is likely a memory access violation. */ const char *sqlite3_filename_database(const char*); const char *sqlite3_filename_journal(const char*); const char *sqlite3_filename_wal(const char*); /* ** CAPI3REF: Error Codes And Messages ** METHOD: sqlite3 ** ** ^If the most recent sqlite3_* API call associated with ** [database connection] D failed, then the sqlite3_errcode(D) interface |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
4104 4105 4106 4107 4108 4109 4110 | void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); void sqlite3AddCheckConstraint(Parse*, Expr*); void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*); void sqlite3AddCollateType(Parse*, Token*); void sqlite3AddGenerated(Parse*,Expr*,Token*); void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); | < < < | 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 | void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); void sqlite3AddCheckConstraint(Parse*, Expr*); void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*); void sqlite3AddCollateType(Parse*, Token*); void sqlite3AddGenerated(Parse*,Expr*,Token*); void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); int sqlite3ParseUri(const char*,const char*,unsigned int*, sqlite3_vfs**,char**,char **); #ifdef SQLITE_HAS_CODEC int sqlite3CodecQueryParameters(sqlite3*,const char*,const char*); #else # define sqlite3CodecQueryParameters(A,B,C) 0 #endif |
︙ | ︙ |