diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/shell.c.in | 22 | ||||
-rw-r--r-- | src/sqlite.h.in | 19 | ||||
-rw-r--r-- | src/test1.c | 27 | ||||
-rw-r--r-- | src/vtab.c | 22 |
4 files changed, 85 insertions, 5 deletions
diff --git a/src/shell.c.in b/src/shell.c.in index e2c49dd3e..0ee136389 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -3651,6 +3651,7 @@ static const char *(azHelp[]) = { #endif /* SQLITE_OMIT_TRACE */ #ifdef SQLITE_DEBUG ".unmodule NAME ... Unregister virtual table modules", + " --allexcept Unregister everything except those named", #endif ".vfsinfo ?AUX? Information about the top-level VFS", ".vfslist List all available VFSes", @@ -6892,7 +6893,7 @@ static int do_meta_command(char *zLine, ShellState *p){ int nArg = 0; int n, c; int rc = 0; - char *azArg[50]; + char *azArg[52]; #ifndef SQLITE_OMIT_VIRTUALTABLE if( p->expert.pExpert ){ @@ -6902,7 +6903,7 @@ static int do_meta_command(char *zLine, ShellState *p){ /* Parse the input line into tokens. */ - while( zLine[h] && nArg<ArraySize(azArg) ){ + while( zLine[h] && nArg<ArraySize(azArg)-1 ){ while( IsSpace(zLine[h]) ){ h++; } if( zLine[h]==0 ) break; if( zLine[h]=='\'' || zLine[h]=='"' ){ @@ -6923,6 +6924,7 @@ static int do_meta_command(char *zLine, ShellState *p){ resolve_backslashes(azArg[nArg-1]); } } + azArg[nArg] = 0; /* Process the input line. */ @@ -9407,14 +9409,24 @@ static int do_meta_command(char *zLine, ShellState *p){ #ifdef SQLITE_DEBUG if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){ int ii; + int lenOpt; + char *zOpt; if( nArg<2 ){ - raw_printf(stderr, "Usage: .unmodule NAME ...\n"); + raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n"); rc = 1; goto meta_command_exit; } open_db(p, 0); - for(ii=1; ii<nArg; ii++){ - sqlite3_create_module(p->db, azArg[ii], 0, 0); + zOpt = azArg[1]; + if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++; + lenOpt = (int)strlen(zOpt); + if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){ + assert( azArg[nArg]==0 ); + sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0); + }else{ + for(ii=1; ii<nArg; ii++){ + sqlite3_create_module(p->db, azArg[ii], 0, 0); + } } }else #endif diff --git a/src/sqlite.h.in b/src/sqlite.h.in index ed5e2922c..521ddffdb 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6639,6 +6639,8 @@ struct sqlite3_index_info { ** ^If the third parameter (the pointer to the sqlite3_module object) is ** NULL then no new module is create and any existing modules with the ** same name are dropped. +** +** See also: [sqlite3_drop_modules()] */ int sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ @@ -6655,6 +6657,23 @@ int sqlite3_create_module_v2( ); /* +** CAPI3REF: Remove Unnecessary Virtual Table Implementations +** METHOD: sqlite3 +** +** ^The sqlite3_drop_modules(D,L) interface removes all virtual +** table modules from database connection D except those named on list L. +** The L parameter must be either NULL or a pointer to an array of pointers +** to strings where the array is terminated by a single NULL pointer. +** ^If the L parameter is NULL, then all virtual table modules are removed. +** +** See also: [sqlite3_create_module()] +*/ +int sqlite3_drop_modules( + sqlite3 *db, /* Remove modules from this connection */ + const char **azKeep /* Except, do not remove the ones named here */ +); + +/* ** CAPI3REF: Virtual Table Instance Object ** KEYWORDS: sqlite3_vtab ** diff --git a/src/test1.c b/src/test1.c index 6bc64e762..e238d31e8 100644 --- a/src/test1.c +++ b/src/test1.c @@ -1111,6 +1111,32 @@ static int SQLITE_TCLAPI test_create_function( } /* +** Usage: sqlite3_drop_modules DB ?NAME ...? +** +** Invoke the sqlite3_drop_modules(D,L) interface on database +** connection DB, in order to drop all modules except those named in +** the argument. +*/ +static int SQLITE_TCLAPI test_drop_modules( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + int rc; + sqlite3 *db; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB\"", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + sqlite3_drop_modules(db, argc>2 ? (const char**)(argv+2) : 0); + return TCL_OK; +} + +/* ** Routines to implement the x_count() aggregate function. ** ** x_count() counts the number of non-null arguments. But there are @@ -7860,6 +7886,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_close_v2", (Tcl_CmdProc*)sqlite_test_close_v2 }, { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function }, { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, + { "sqlite3_drop_modules", (Tcl_CmdProc*)test_drop_modules }, { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, { "sqlite_bind", (Tcl_CmdProc*)test_bind }, diff --git a/src/vtab.c b/src/vtab.c index 8f6db9f47..dd8a755be 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -134,6 +134,28 @@ int sqlite3_create_module_v2( } /* +** External API to drop all virtual-table modules, except those named +** on the azNames list. +*/ +int sqlite3_drop_modules(sqlite3 *db, const char** azNames){ + HashElem *pThis, *pNext; +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; +#endif + for(pThis=sqliteHashFirst(&db->aModule); pThis; pThis=pNext){ + Module *pMod = (Module*)sqliteHashData(pThis); + pNext = sqliteHashNext(pThis); + if( azNames ){ + int ii; + for(ii=0; azNames[ii]!=0 && strcmp(azNames[ii],pMod->zName)!=0; ii++){} + if( azNames[ii]!=0 ) continue; + } + createModule(db, pMod->zName, 0, 0, 0); + } + return SQLITE_OK; +} + +/* ** Decrement the reference count on a Module object. Destroy the ** module when the reference count reaches zero. */ |