Add void* argument to sqlite3_create_module to replace sqlite3_module.pAux. (CVS 3251)

FossilOrigin-Name: 470a3a0b20775be1226fb4d477c798d8da2d5708
diff --git a/src/delete.c b/src/delete.c
index 37b8577..f1cdcdb 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** in order to generate code for DELETE FROM statements.
 **
-** $Id: delete.c,v 1.124 2006/06/14 19:00:21 drh Exp $
+** $Id: delete.c,v 1.125 2006/06/15 04:28:13 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -45,7 +45,7 @@
   if( (pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
         && pParse->nested==0) 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-      || (pTab->pModule && pTab->pModule->xUpdate==0)
+      || (pTab->pMod && pTab->pMod->pModule->xUpdate==0)
 #endif
   ){
     sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
diff --git a/src/main.c b/src/main.c
index 526eaed..463ba99 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.343 2006/06/14 15:35:37 drh Exp $
+** $Id: main.c,v 1.344 2006/06/15 04:28:13 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -160,6 +160,10 @@
   }
   sqlite3HashClear(&db->aCollSeq);
 #ifndef SQLITE_OMIT_VIRTUALTABLE
+  for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){
+    Module *pMod = (Module *)sqliteHashData(i);
+    sqliteFree(pMod);
+  }
   sqlite3HashClear(&db->aModule);
 #endif
 
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 2f8f144..68f3a56 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -12,7 +12,7 @@
 ** This header file defines the interface that the SQLite library
 ** presents to client programs.
 **
-** @(#) $Id: sqlite.h.in,v 1.176 2006/06/14 13:03:23 danielk1977 Exp $
+** @(#) $Id: sqlite.h.in,v 1.177 2006/06/15 04:28:13 danielk1977 Exp $
 */
 #ifndef _SQLITE3_H_
 #define _SQLITE3_H_
@@ -1536,7 +1536,6 @@
 struct sqlite3_module {
   int iVersion;
   const char *zName;
-  void *pAux;
   int (*xCreate)(sqlite3*, void *pAux,
                int argc, char **argv,
                sqlite3_vtab **ppVTab);
@@ -1649,7 +1648,8 @@
 int sqlite3_create_module(
   sqlite3 *db,               /* SQLite connection to register module with */
   const char *zName,         /* Name of the module */
-  const sqlite3_module *     /* Methods for the module */
+  const sqlite3_module *,    /* Methods for the module */
+  void *                     /* Client data for xCreate/xConnect */
 );
 
 /*
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index fcc147a..f51ead3 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.505 2006/06/14 19:00:21 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.506 2006/06/15 04:28:13 danielk1977 Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -343,6 +343,7 @@
 typedef struct Index Index;
 typedef struct KeyClass KeyClass;
 typedef struct KeyInfo KeyInfo;
+typedef struct Module Module;
 typedef struct NameContext NameContext;
 typedef struct Parse Parse;
 typedef struct Select Select;
@@ -567,6 +568,17 @@
 };
 
 /*
+** Each SQLite module (virtual table definition) is defined by an
+** instance of the following structure, stored in the sqlite3.aModule
+** hash table.
+*/
+struct Module {
+  const sqlite3_module *pModule;       /* Callback pointers */
+  const char *zName;                   /* Name passed to create_module() */
+  void *pAux;                          /* pAux passed to create_module() */
+};
+
+/*
 ** Possible values for FuncDef.flags
 */
 #define SQLITE_FUNC_LIKE   0x01  /* Candidate for the LIKE optimization */
@@ -705,7 +717,7 @@
   int addColOffset;  /* Offset in CREATE TABLE statement to add a new column */
 #endif
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  sqlite3_module *pModule;  /* Pointer to the implementation of the module */
+  Module *pMod;             /* Pointer to the implementation of the module */
   sqlite3_vtab *pVtab;      /* Pointer to the module instance */
   u8 isVirtual;             /* True if this is a virtual table */
   int nModuleArg;           /* Number of arguments to the module */
diff --git a/src/test8.c b/src/test8.c
index 7742216..ead6644 100644
--- a/src/test8.c
+++ b/src/test8.c
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test8.c,v 1.19 2006/06/14 23:43:31 drh Exp $
+** $Id: test8.c,v 1.20 2006/06/15 04:28:13 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -622,7 +622,6 @@
 static sqlite3_module echoModule = {
   0,                         /* iVersion */
   "echo",                    /* zName */
-  0,                         /* pAux */
   echoCreate,
   echoConnect,
   echoBestIndex,
@@ -661,9 +660,8 @@
     return TCL_ERROR;
   }
   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-  echoModule.pAux = interp;
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  sqlite3_create_module(db, "echo", &echoModule);
+  sqlite3_create_module(db, "echo", &echoModule, (void *)interp);
 #endif
   return TCL_OK;
 }
diff --git a/src/test_tclvar.c b/src/test_tclvar.c
index fc474bb..daa86e7 100644
--- a/src/test_tclvar.c
+++ b/src/test_tclvar.c
@@ -16,7 +16,7 @@
 ** The emphasis of this file is a virtual table that provides
 ** access to TCL variables.
 **
-** $Id: test_tclvar.c,v 1.2 2006/06/14 06:58:16 danielk1977 Exp $
+** $Id: test_tclvar.c,v 1.3 2006/06/15 04:28:13 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -65,6 +65,7 @@
 ** methods are identical. */
 static int tclvarDisconnect(sqlite3_vtab *pVtab){
   free(pVtab);
+  return SQLITE_OK;
 }
 /* The xDisconnect and xDestroy methods are also the same */
 
@@ -126,7 +127,6 @@
 static sqlite3_module tclvarModule = {
   0,                         /* iVersion */
   "tclvar",                  /* zName */
-  0,                         /* pAux */
   tclvarConnect,
   tclvarConnect,
   tclvarBestIndex,
@@ -164,9 +164,8 @@
     return TCL_ERROR;
   }
   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-  tclvarModule.pAux = interp;
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  sqlite3_create_module(db, "tclvar", &tclvarModule);
+  sqlite3_create_module(db, "tclvar", &tclvarModule, (void *)interp);
 #endif
   return TCL_OK;
 }
diff --git a/src/vtab.c b/src/vtab.c
index a7fd6a8..727ee51 100644
--- a/src/vtab.c
+++ b/src/vtab.c
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to help implement virtual tables.
 **
-** $Id: vtab.c,v 1.11 2006/06/14 13:03:24 danielk1977 Exp $
+** $Id: vtab.c,v 1.12 2006/06/15 04:28:13 danielk1977 Exp $
 */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
 #include "sqliteInt.h"
@@ -22,11 +22,22 @@
 int sqlite3_create_module(
   sqlite3 *db,                    /* Database in which module is registered */
   const char *zName,              /* Name assigned to this module */
-  const sqlite3_module *pModule   /* The definition of the module */
+  const sqlite3_module *pModule,  /* The definition of the module */
+  void *pAux                      /* Context pointer for xCreate/xConnect */
 ){
-  sqlite3HashInsert(&db->aModule, zName, strlen(zName), (void*)pModule);
-  sqlite3ResetInternalSchema(db, 0);
-  return SQLITE_OK;
+  int nName = strlen(zName);
+  Module *pMod = (Module *)sqliteMallocRaw(sizeof(Module) + nName + 1);
+  if( pMod ){
+    char *zCopy = (char *)(&pMod[1]);
+    strcpy(zCopy, zName);
+    pMod->zName = zCopy;
+    pMod->pModule = pModule;
+    pMod->pAux = pAux;
+    pMod = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);
+    sqliteFree(pMod);
+    sqlite3ResetInternalSchema(db, 0);
+  }
+  return sqlite3ApiExit(db, SQLITE_OK);
 }
 
 /*
@@ -36,8 +47,8 @@
 */
 void sqlite3VtabClear(Table *p){
   if( p->pVtab ){
-    assert( p->pModule!=0 );
-    p->pModule->xDisconnect(p->pVtab);
+    assert( p->pMod && p->pMod->pModule );
+    p->pMod->pModule->xDisconnect(p->pVtab);
   }
   if( p->azModuleArg ){
     int i;
@@ -116,6 +127,7 @@
   Table *pTab;        /* The table being constructed */
   sqlite3 *db;        /* The database connection */
   char *zModule;      /* The module name of the table: USING modulename */
+  Module *pMod = 0;
 
   addArgumentToVtab(pParse);
   sqliteFree(pParse->zArg);
@@ -128,8 +140,8 @@
   db = pParse->db;
   if( pTab->nModuleArg<1 ) return;
   zModule = pTab->azModuleArg[0];
-  pTab->pModule = (sqlite3_module*)sqlite3HashFind(&db->aModule, 
-                     zModule, strlen(zModule));
+  pMod = (Module *)sqlite3HashFind(&db->aModule, zModule, strlen(zModule));
+  pTab->pMod = pMod;
   
   /* If the CREATE VIRTUAL TABLE statement is being entered for the
   ** first time (in other words if the virtual table is actually being
@@ -142,7 +154,7 @@
     char *zWhere;
     int iDb;
     Vdbe *v;
-    if( pTab->pModule==0 ){
+    if( !pMod ){
       sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
     }
 
@@ -241,7 +253,7 @@
 static int vtabCallConstructor(
   sqlite3 *db, 
   Table *pTab,
-  sqlite3_module *pModule,
+  Module *pMod,
   int (*xConstruct)(sqlite3*, void *, int, char **, sqlite3_vtab **),
   char **pzErr
 ){
@@ -256,10 +268,10 @@
   db->pVTab = pTab;
   rc = sqlite3SafetyOff(db);
   assert( rc==SQLITE_OK );
-  rc = xConstruct(db, pModule->pAux, nArg, azArg, &pTab->pVtab);
+  rc = xConstruct(db, pMod->pAux, nArg, azArg, &pTab->pVtab);
   rc2 = sqlite3SafetyOn(db);
   if( pTab->pVtab ){
-    pTab->pVtab->pModule = pModule;
+    pTab->pVtab->pModule = pMod->pModule;
   }
 
   if( SQLITE_OK!=rc ){
@@ -284,7 +296,7 @@
 ** This call is a no-op if table pTab is not a virtual table.
 */
 int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
-  sqlite3_module *pModule;
+  Module *pMod;
   const char *zModule;
   int rc = SQLITE_OK;
 
@@ -292,15 +304,16 @@
     return SQLITE_OK;
   }
 
-  pModule = pTab->pModule;
+  pMod = pTab->pMod;
   zModule = pTab->azModuleArg[0];
-  if( !pModule ){
+  if( !pMod ){
     const char *zModule = pTab->azModuleArg[0];
     sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
     rc = SQLITE_ERROR;
   } else {
     char *zErr = 0;
-    rc = vtabCallConstructor(pParse->db,pTab,pModule,pModule->xConnect,&zErr);
+    sqlite3 *db = pParse->db;
+    rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
     if( rc!=SQLITE_OK ){
       sqlite3ErrorMsg(pParse, "%s", zErr);
     }
@@ -321,23 +334,23 @@
 int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
   int rc = SQLITE_OK;
   Table *pTab;
-  sqlite3_module *pModule;
+  Module *pMod;
   const char *zModule;
 
   pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
   assert(pTab && pTab->isVirtual && !pTab->pVtab);
-  pModule = pTab->pModule;
+  pMod = pTab->pMod;
   zModule = pTab->azModuleArg[0];
 
   /* If the module has been registered and includes a Create method, 
   ** invoke it now. If the module has not been registered, return an 
   ** error. Otherwise, do nothing.
   */
-  if( !pModule ){
+  if( !pMod ){
     *pzErr = sqlite3MPrintf("no such module: %s", zModule);
     rc = SQLITE_ERROR;
   }else{
-    rc = vtabCallConstructor(db, pTab, pModule, pModule->xCreate, pzErr);
+    rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr);
   }
 
   return rc;
@@ -401,15 +414,16 @@
 {
   int rc = SQLITE_OK;
   Table *pTab;
-  sqlite3_module *pModule;
 
   pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
-  pModule = pTab->pModule;
   assert(pTab);
   if( pTab->pVtab ){
+    int (*xDestroy)(sqlite3_vtab *pVTab) = pTab->pMod->pModule->xDestroy;
     rc = sqlite3SafetyOff(db);
     assert( rc==SQLITE_OK );
-    rc = pModule->xDestroy(pTab->pVtab);
+    if( xDestroy ){
+      rc = xDestroy(pTab->pVtab);
+    }
     sqlite3SafetyOn(db);
     if( rc==SQLITE_OK ){
       pTab->pVtab = 0;