diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/os_unix.c | 6 | ||||
-rw-r--r-- | src/os_win.c | 4 | ||||
-rw-r--r-- | src/shell.c | 13 | ||||
-rw-r--r-- | src/sqlite.h.in | 12 | ||||
-rw-r--r-- | src/test1.c | 34 | ||||
-rw-r--r-- | src/test_multiplex.c | 36 | ||||
-rw-r--r-- | src/test_osinst.c | 6 | ||||
-rw-r--r-- | src/test_quota.c | 6 | ||||
-rw-r--r-- | src/test_vfstrace.c | 8 |
10 files changed, 114 insertions, 15 deletions
diff --git a/src/main.c b/src/main.c index f4519c5b3..690b73c2e 100644 --- a/src/main.c +++ b/src/main.c @@ -239,8 +239,8 @@ int sqlite3_initialize(void){ */ #ifdef SQLITE_EXTRA_INIT if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){ - int SQLITE_EXTRA_INIT(void); - rc = SQLITE_EXTRA_INIT(); + int SQLITE_EXTRA_INIT(const char*); + rc = SQLITE_EXTRA_INIT(0); } #endif diff --git a/src/os_unix.c b/src/os_unix.c index 51778c861..ee5971f10 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -206,6 +206,7 @@ struct UnixUnusedFd { typedef struct unixFile unixFile; struct unixFile { sqlite3_io_methods const *pMethod; /* Always the first entry */ + sqlite3_vfs *pVfs; /* The VFS that created this unixFile */ unixInodeInfo *pInode; /* Info about locks on this inode */ int h; /* The file descriptor */ unsigned char eFileLock; /* The type of lock held on this fd */ @@ -3533,6 +3534,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ } return SQLITE_OK; } + case SQLITE_FCNTL_VFSNAME: { + *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); + return SQLITE_OK; + } #ifndef NDEBUG /* The pager calls this method to signal that it has done ** a rollback and that the database is therefore unchanged and @@ -4560,6 +4565,7 @@ static int fillInUnixFile( OSTRACE(("OPEN %-3d %s\n", h, zFilename)); pNew->h = h; + pNew->pVfs = pVfs; pNew->zPath = zFilename; if( memcmp(pVfs->zName,"unix-excl",10)==0 ){ pNew->ctrlFlags = UNIXFILE_EXCL; diff --git a/src/os_win.c b/src/os_win.c index bfde4b6f9..ab70eebbf 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -2168,6 +2168,10 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){ } return SQLITE_OK; } + case SQLITE_FCNTL_VFSNAME: { + *(char**)pArg = sqlite3_mprintf("win32"); + return SQLITE_OK; + } case SQLITE_FCNTL_SYNC_OMITTED: { return SQLITE_OK; } diff --git a/src/shell.c b/src/shell.c index 911f6fad9..31d3dd8fc 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1405,6 +1405,7 @@ static char zHelp[] = " If TABLE specified, only list tables matching\n" " LIKE pattern TABLE.\n" ".timeout MS Try opening locked tables for MS milliseconds\n" + ".vfsname ?AUX? Print the name of the VFS stack\n" ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" ; @@ -2348,6 +2349,18 @@ static int do_meta_command(char *zLine, struct callback_data *p){ sqlite3_libversion(), sqlite3_sourceid()); }else + if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){ + const char *zDbName = nArg==2 ? azArg[1] : "main"; + char *zVfsName = 0; + if( p->db ){ + sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName); + if( zVfsName ){ + printf("%s\n", zVfsName); + sqlite3_free(zVfsName); + } + } + }else + if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){ int j; assert( nArg<=ArraySize(azArg) ); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 8c9e220e0..0e0e3af6b 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -771,6 +771,17 @@ struct sqlite3_io_methods { ** a write transaction to indicate that, unless it is rolled back for some ** reason, the entire database file will be overwritten by the current ** transaction. This is used by VACUUM operations. +** +** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of +** all [VFSes] in the VFS stack. The names are of all VFS shims and the +** final bottom-level VFS are written into memory obtained from +** [sqlite3_malloc()] and the result is stored in the char* variable +** that the fourth parameter of [sqlite3_file_control()] points to. +** The caller is responsible for freeing the memory when done. As with +** all file-control actions, there is no guarantee that this will actually +** do anything. Callers should initialize the char* variable to a NULL +** pointer in case this file-control is not implemented. This file-control +** is intended for diagnostic use only. */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_GET_LOCKPROXYFILE 2 @@ -783,6 +794,7 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_WIN32_AV_RETRY 9 #define SQLITE_FCNTL_PERSIST_WAL 10 #define SQLITE_FCNTL_OVERWRITE 11 +#define SQLITE_FCNTL_VFSNAME 12 /* ** CAPI3REF: Mutex Handle diff --git a/src/test1.c b/src/test1.c index cf388d244..798366a8c 100644 --- a/src/test1.c +++ b/src/test1.c @@ -5237,6 +5237,39 @@ static int file_control_persist_wal( /* +** tclcmd: file_control_vfsname DB ?AUXDB? +** +** Return a string that describes the stack of VFSes. +*/ +static int file_control_vfsname( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3 *db; + const char *zDbName = "main"; + char *zVfsName = 0; + + if( objc!=2 && objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ + return TCL_ERROR; + } + if( objc==3 ){ + zDbName = Tcl_GetString(objv[2]); + } + sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName); + Tcl_AppendResult(interp, zVfsName, (char*)0); + sqlite3_free(zVfsName); + return TCL_OK; +} + + +/* ** tclcmd: sqlite3_vfs_list ** ** Return a tcl list containing the names of all registered vfs's. @@ -6060,6 +6093,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "file_control_sizehint_test", file_control_sizehint_test, 0 }, { "file_control_win32_av_retry", file_control_win32_av_retry, 0 }, { "file_control_persist_wal", file_control_persist_wal, 0 }, + { "file_control_vfsname", file_control_vfsname, 0 }, { "sqlite3_vfs_list", vfs_list, 0 }, { "sqlite3_create_function_v2", test_create_function_v2, 0 }, diff --git a/src/test_multiplex.c b/src/test_multiplex.c index ce55bad08..f6540d82d 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -81,6 +81,9 @@ #define sqlite3_mutex_notheld(X) ((void)(X),1) #endif /* SQLITE_THREADSAFE==0 */ +/* First chunk for rollback journal files */ +#define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400 + /************************ Shim Definitions ******************************/ @@ -97,7 +100,7 @@ #endif /* This used to be the default limit on number of chunks, but -** it is no longer enforced. There is currently no limit to the +** it is no longer enforced. There is currently no limit to the ** number of chunks. ** ** May be changed by calling the xFileControl() interface. @@ -241,10 +244,10 @@ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){ if( i>=n-4 ) n = i+1; if( pGroup->flags & (SQLITE_OPEN_MAIN_JOURNAL|SQLITE_OPEN_TEMP_JOURNAL) ){ /* The extensions on overflow files for main databases are 001, 002, - ** 003 and so forth. To avoid name collisions, add 100 to the - ** extensions of journal files so that they are 101, 102, 103, .... + ** 003 and so forth. To avoid name collisions, add 400 to the + ** extensions of journal files so that they are 401, 402, 403, .... */ - iChunk += 100; + iChunk += SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET; } #endif sqlite3_snprintf(4,&z[n],"%03d",iChunk); @@ -264,6 +267,18 @@ static sqlite3_file *multiplexSubOpen( ){ sqlite3_file *pSubOpen = 0; sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ + +#ifdef SQLITE_ENABLE_8_3_NAMES + /* If JOURNAL_8_3_OFFSET is set to (say) 400, then any overflow files are + ** part of a database journal are named db.401, db.402, and so on. A + ** database may therefore not grow to larger than 400 chunks. Attempting + ** to open chunk 401 indicates the database is full. */ + if( iChunk>=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){ + *rc = SQLITE_FULL; + return 0; + } +#endif + *rc = multiplexSubFilename(pGroup, iChunk); if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){ pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile ); @@ -455,7 +470,7 @@ static int multiplexOpen( sqlite3_int64 sz; rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz); - if( rc2==SQLITE_OK ){ + if( rc2==SQLITE_OK && zName ){ /* If the first overflow file exists and if the size of the main file ** is different from the chunk size, that means the chunk size is set ** set incorrectly. So fix it. @@ -633,7 +648,7 @@ static int multiplexWrite( rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst); } }else{ - while( iAmt > 0 ){ + while( rc==SQLITE_OK && iAmt>0 ){ int i = (int)(iOfst / pGroup->szChunk); sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL); if( pSubOpen ){ @@ -643,13 +658,9 @@ static int multiplexWrite( iAmt -= extra; rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst % pGroup->szChunk); - if( rc!=SQLITE_OK ) break; pBuf = (char *)pBuf + iAmt; iOfst += iAmt; iAmt = extra; - }else{ - rc = SQLITE_IOERR_WRITE; - break; } } } @@ -845,6 +856,9 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){ pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL); if( pSubOpen ){ rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg); + if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){ + *(char**)pArg = sqlite3_mprintf("multiplex/%z", *(char**)pArg); + } } break; } @@ -857,7 +871,7 @@ static int multiplexSectorSize(sqlite3_file *pConn){ multiplexConn *p = (multiplexConn*)pConn; int rc; sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL); - if( pSubOpen ){ + if( pSubOpen && pSubOpen->pMethods->xSectorSize ){ return pSubOpen->pMethods->xSectorSize(pSubOpen); } return DEFAULT_SECTOR_SIZE; diff --git a/src/test_osinst.c b/src/test_osinst.c index 50d6250e6..b7f350577 100644 --- a/src/test_osinst.c +++ b/src/test_osinst.c @@ -389,7 +389,11 @@ static int vfslogCheckReservedLock(sqlite3_file *pFile, int *pResOut){ */ static int vfslogFileControl(sqlite3_file *pFile, int op, void *pArg){ VfslogFile *p = (VfslogFile *)pFile; - return p->pReal->pMethods->xFileControl(p->pReal, op, pArg); + int rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg); + if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){ + *(char**)pArg = sqlite3_mprintf("vfslog/%z", *(char**)pArg); + } + return rc; } /* diff --git a/src/test_quota.c b/src/test_quota.c index 74d1a6d3b..9aad4967b 100644 --- a/src/test_quota.c +++ b/src/test_quota.c @@ -589,7 +589,11 @@ static int quotaCheckReservedLock(sqlite3_file *pConn, int *pResOut){ */ static int quotaFileControl(sqlite3_file *pConn, int op, void *pArg){ sqlite3_file *pSubOpen = quotaSubOpen(pConn); - return pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg); + int rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg); + if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){ + *(char**)pArg = sqlite3_mprintf("quota/%z", *(char**)pArg); + } + return rc; } /* Pass xSectorSize requests through to the original VFS unchanged. diff --git a/src/test_vfstrace.c b/src/test_vfstrace.c index 5e94f5cf0..62577207b 100644 --- a/src/test_vfstrace.c +++ b/src/test_vfstrace.c @@ -471,6 +471,10 @@ static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){ } case SQLITE_FCNTL_FILE_POINTER: zOp = "FILE_POINTER"; break; case SQLITE_FCNTL_SYNC_OMITTED: zOp = "SYNC_OMITTED"; break; + case SQLITE_FCNTL_WIN32_AV_RETRY: zOp = "WIN32_AV_RETRY"; break; + case SQLITE_FCNTL_PERSIST_WAL: zOp = "PERSIST_WAL"; break; + case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break; + case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break; case 0xca093fa0: zOp = "DB_UNCHANGED"; break; default: { sqlite3_snprintf(sizeof zBuf, zBuf, "%d", op); @@ -482,6 +486,10 @@ static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){ pInfo->zVfsName, p->zFName, zOp); rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg); vfstrace_print_errcode(pInfo, " -> %s\n", rc); + if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){ + *(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z", + pInfo->zVfsName, *(char**)pArg); + } return rc; } |