SQLite

Changes On Branch sqlite3_drop_modules_except
Login

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

Changes In Branch sqlite3_drop_modules_except Excluding Merge-Ins

This is equivalent to a diff from 5d6f4dfe to e5ba47c2

2019-08-19
20:44
Add the sqlite3_drop_modules() interface. (check-in: e2c6fed8 user: drh tags: trunk)
20:35
Omit the "_except" term from the name of the new interface. (Closed-Leaf check-in: e5ba47c2 user: drh tags: sqlite3_drop_modules_except)
2019-08-17
19:55
Fix to the query planner for the LSM1 extension. (check-in: 7496e872 user: drh tags: trunk)
19:45
The experimental sqlite3_drop_modules_except() interface. (check-in: 0851db4d user: drh tags: sqlite3_drop_modules_except)
19:31
Fix the new ability to unregister virtual table modules so that it works for the automatic PRAGMA virtual tables. (check-in: 5d6f4dfe user: drh tags: trunk)
19:13
When populating an ephemeral b-tree for the RHS of an IN(...) clause, avoid applying an affinity to a value that may be used later on for some other purpose. Fix for [c7a117190]. (check-in: 43e8b143 user: dan tags: trunk)

Changes to src/shell.c.in.

3647
3648
3649
3650
3651
3652
3653

3654
3655
3656
3657
3658
3659
3660
  "    --stmt                  Trace statement execution (SQLITE_TRACE_STMT)",
  "    --profile               Profile statements (SQLITE_TRACE_PROFILE)",
  "    --row                   Trace each row (SQLITE_TRACE_ROW)",
  "    --close                 Trace connection close (SQLITE_TRACE_CLOSE)",
#endif /* SQLITE_OMIT_TRACE */
#ifdef SQLITE_DEBUG
  ".unmodule NAME ...       Unregister virtual table modules",

#endif
  ".vfsinfo ?AUX?           Information about the top-level VFS",
  ".vfslist                 List all available VFSes",
  ".vfsname ?AUX?           Print the name of the VFS stack",
  ".width NUM1 NUM2 ...     Set column widths for \"column\" mode",
  "     Negative values right-justify",
};







>







3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
  "    --stmt                  Trace statement execution (SQLITE_TRACE_STMT)",
  "    --profile               Profile statements (SQLITE_TRACE_PROFILE)",
  "    --row                   Trace each row (SQLITE_TRACE_ROW)",
  "    --close                 Trace connection close (SQLITE_TRACE_CLOSE)",
#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",
  ".vfsname ?AUX?           Print the name of the VFS stack",
  ".width NUM1 NUM2 ...     Set column widths for \"column\" mode",
  "     Negative values right-justify",
};
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925

6926
6927
6928
6929
6930
6931
6932
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
static int do_meta_command(char *zLine, ShellState *p){
  int h = 1;
  int nArg = 0;
  int n, c;
  int rc = 0;
  char *azArg[50];

#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( p->expert.pExpert ){
    expertFinish(p, 1, 0);
  }
#endif

  /* Parse the input line into tokens.
  */
  while( zLine[h] && nArg<ArraySize(azArg) ){
    while( IsSpace(zLine[h]) ){ h++; }
    if( zLine[h]==0 ) break;
    if( zLine[h]=='\'' || zLine[h]=='"' ){
      int delim = zLine[h++];
      azArg[nArg++] = &zLine[h];
      while( zLine[h] && zLine[h]!=delim ){
        if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
        h++;
      }
      if( zLine[h]==delim ){
        zLine[h++] = 0;
      }
      if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
    }else{
      azArg[nArg++] = &zLine[h];
      while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
      if( zLine[h] ) zLine[h++] = 0;
      resolve_backslashes(azArg[nArg-1]);
    }
  }


  /* Process the input line.
  */
  if( nArg==0 ) return 0; /* no tokens, no error */
  n = strlen30(azArg[0]);
  c = azArg[0][0];
  clearTempFile(p);







|









|




















>







6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
static int do_meta_command(char *zLine, ShellState *p){
  int h = 1;
  int nArg = 0;
  int n, c;
  int rc = 0;
  char *azArg[52];

#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( p->expert.pExpert ){
    expertFinish(p, 1, 0);
  }
#endif

  /* Parse the input line into tokens.
  */
  while( zLine[h] && nArg<ArraySize(azArg)-1 ){
    while( IsSpace(zLine[h]) ){ h++; }
    if( zLine[h]==0 ) break;
    if( zLine[h]=='\'' || zLine[h]=='"' ){
      int delim = zLine[h++];
      azArg[nArg++] = &zLine[h];
      while( zLine[h] && zLine[h]!=delim ){
        if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
        h++;
      }
      if( zLine[h]==delim ){
        zLine[h++] = 0;
      }
      if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
    }else{
      azArg[nArg++] = &zLine[h];
      while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
      if( zLine[h] ) zLine[h++] = 0;
      resolve_backslashes(azArg[nArg-1]);
    }
  }
  azArg[nArg] = 0;

  /* Process the input line.
  */
  if( nArg==0 ) return 0; /* no tokens, no error */
  n = strlen30(azArg[0]);
  c = azArg[0][0];
  clearTempFile(p);
9403
9404
9405
9406
9407
9408
9409


9410
9411
9412
9413
9414
9415







9416
9417

9418
9419
9420
9421
9422
9423
9424
    }
  }else
#endif /* !defined(SQLITE_OMIT_TRACE) */

#ifdef SQLITE_DEBUG
  if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
    int ii;


    if( nArg<2 ){
      raw_printf(stderr, "Usage: .unmodule 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);

    }
  }else
#endif

#if SQLITE_USER_AUTHENTICATION
  if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
    if( nArg<2 ){







>
>

|




>
>
>
>
>
>
>
|
|
>







9405
9406
9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419
9420
9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434
9435
9436
    }
  }else
#endif /* !defined(SQLITE_OMIT_TRACE) */

#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 [--allexcept] NAME ...\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 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

#if SQLITE_USER_AUTHENTICATION
  if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
    if( nArg<2 ){

Changes to src/sqlite.h.in.

6635
6636
6637
6638
6639
6640
6641


6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655

















6656
6657
6658
6659
6660
6661
6662
** ^The sqlite3_create_module()
** interface is equivalent to sqlite3_create_module_v2() with a NULL
** destructor.
**
** ^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.


*/
int sqlite3_create_module(
  sqlite3 *db,               /* SQLite connection to register module with */
  const char *zName,         /* Name of the module */
  const sqlite3_module *p,   /* Methods for the module */
  void *pClientData          /* Client data for xCreate/xConnect */
);
int sqlite3_create_module_v2(
  sqlite3 *db,               /* SQLite connection to register module with */
  const char *zName,         /* Name of the module */
  const sqlite3_module *p,   /* Methods for the module */
  void *pClientData,         /* Client data for xCreate/xConnect */
  void(*xDestroy)(void*)     /* Module destructor function */
);


















/*
** CAPI3REF: Virtual Table Instance Object
** KEYWORDS: sqlite3_vtab
**
** Every [virtual table module] implementation uses a subclass
** of this object to describe a particular instance







>
>














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
** ^The sqlite3_create_module()
** interface is equivalent to sqlite3_create_module_v2() with a NULL
** destructor.
**
** ^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 */
  const char *zName,         /* Name of the module */
  const sqlite3_module *p,   /* Methods for the module */
  void *pClientData          /* Client data for xCreate/xConnect */
);
int sqlite3_create_module_v2(
  sqlite3 *db,               /* SQLite connection to register module with */
  const char *zName,         /* Name of the module */
  const sqlite3_module *p,   /* Methods for the module */
  void *pClientData,         /* Client data for xCreate/xConnect */
  void(*xDestroy)(void*)     /* Module destructor function */
);

/*
** 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
**
** Every [virtual table module] implementation uses a subclass
** of this object to describe a particular instance

Changes to src/test1.c.

1105
1106
1107
1108
1109
1110
1111


























1112
1113
1114
1115
1116
1117
1118
  }
#endif

  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  return TCL_OK;
}



























/*
** Routines to implement the x_count() aggregate function.
**
** x_count() counts the number of non-null arguments.  But there are
** some twists for testing purposes.
**







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
  }
#endif

  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  return TCL_OK;
}

/*
** 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
** some twists for testing purposes.
**
7856
7857
7858
7859
7860
7861
7862

7863
7864
7865
7866
7867
7868
7869
#ifndef SQLITE_OMIT_GET_TABLE
     { "sqlite3_get_table_printf",      (Tcl_CmdProc*)test_get_table_printf },
#endif
     { "sqlite3_close",                 (Tcl_CmdProc*)sqlite_test_close     },
     { "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 },

     { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func    },
     { "sqlite_abort",                  (Tcl_CmdProc*)sqlite_abort          },
     { "sqlite_bind",                   (Tcl_CmdProc*)test_bind             },
     { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       },
     { "sqlite3_key",                   (Tcl_CmdProc*)test_key              },
     { "sqlite3_rekey",                 (Tcl_CmdProc*)test_rekey            },
     { "sqlite_set_magic",              (Tcl_CmdProc*)sqlite_set_magic      },







>







7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
#ifndef SQLITE_OMIT_GET_TABLE
     { "sqlite3_get_table_printf",      (Tcl_CmdProc*)test_get_table_printf },
#endif
     { "sqlite3_close",                 (Tcl_CmdProc*)sqlite_test_close     },
     { "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             },
     { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       },
     { "sqlite3_key",                   (Tcl_CmdProc*)test_key              },
     { "sqlite3_rekey",                 (Tcl_CmdProc*)test_rekey            },
     { "sqlite_set_magic",              (Tcl_CmdProc*)sqlite_set_magic      },

Changes to src/vtab.c.

128
129
130
131
132
133
134






















135
136
137
138
139
140
141
  void (*xDestroy)(void *)        /* Module destructor function */
){
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT;
#endif
  return createModule(db, zName, pModule, pAux, xDestroy);
}























/*
** Decrement the reference count on a Module object.  Destroy the
** module when the reference count reaches zero.
*/
void sqlite3VtabModuleUnref(sqlite3 *db, Module *pMod){
  assert( pMod->nRefModule>0 );







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
  void (*xDestroy)(void *)        /* Module destructor function */
){
#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT;
#endif
  return createModule(db, zName, pModule, pAux, xDestroy);
}

/*
** 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.
*/
void sqlite3VtabModuleUnref(sqlite3 *db, Module *pMod){
  assert( pMod->nRefModule>0 );