コード例 #1
0
ファイル: callback.c プロジェクト: cznic/cc
/*
** Free all resources held by the schema structure. The void* argument points
** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the 
** pointer itself, it just cleans up subsidiary resources (i.e. the contents
** of the schema hash tables).
**
** The Schema.cache_size variable is not cleared.
*/
void sqlite3SchemaClear(void *p){
  Hash temp1;
  Hash temp2;
  HashElem *pElem;
  Schema *pSchema = (Schema *)p;

  temp1 = pSchema->tblHash;
  temp2 = pSchema->trigHash;
  sqlite3HashInit(&pSchema->trigHash);
  sqlite3HashClear(&pSchema->idxHash);
  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
    sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem));
  }
  sqlite3HashClear(&temp2);
  sqlite3HashInit(&pSchema->tblHash);
  for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTab = sqliteHashData(pElem);
    sqlite3DeleteTable(0, pTab);
  }
  sqlite3HashClear(&temp1);
  sqlite3HashClear(&pSchema->fkeyHash);
  pSchema->pSeqTab = 0;
  if( pSchema->schemaFlags & DB_SchemaLoaded ){
    pSchema->iGeneration++;
  }
  pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted);
}
コード例 #2
0
ファイル: callback.c プロジェクト: Adoni/WiEngine
/*
** Free all resources held by the schema structure. The void* argument points
** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the 
** pointer itself, it just cleans up subsiduary resources (i.e. the contents
** of the schema hash tables).
**
** The Schema.cache_size variable is not cleared.
*/
void sqlite3SchemaFree(void *p){
  Hash temp1;
  Hash temp2;
  HashElem *pElem;
  Schema *pSchema = (Schema *)p;

  temp1 = pSchema->tblHash;
  temp2 = pSchema->trigHash;
  sqlite3HashInit(&pSchema->trigHash);
  sqlite3HashClear(&pSchema->idxHash);
  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
    sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem));
  }
  sqlite3HashClear(&temp2);
  sqlite3HashInit(&pSchema->tblHash);
  for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTab = sqliteHashData(pElem);
    assert( pTab->dbMem==0 );
    sqlite3DeleteTable(pTab);
  }
  sqlite3HashClear(&temp1);
  sqlite3HashClear(&pSchema->fkeyHash);
  pSchema->pSeqTab = 0;
  pSchema->flags &= ~DB_SchemaLoaded;
}
コード例 #3
0
ファイル: hash.c プロジェクト: 0x7678/owasp-igoat
/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
*/
static void removeElementGivenHash(
  Hash *pH,         /* The pH containing "elem" */
  HashElem* elem,   /* The element to be removed from the pH */
  unsigned int h    /* Hash value for the element */
){
  struct _ht *pEntry;
  if( elem->prev ){
    elem->prev->next = elem->next; 
  }else{
    pH->first = elem->next;
  }
  if( elem->next ){
    elem->next->prev = elem->prev;
  }
  if( pH->ht ){
    pEntry = &pH->ht[h];
    if( pEntry->chain==elem ){
      pEntry->chain = elem->next;
    }
    pEntry->count--;
    assert( pEntry->count>=0 );
  }
  sqlite3_free( elem );
  pH->count--;
  if( pH->count<=0 ){
    assert( pH->first==0 );
    assert( pH->count==0 );
    sqlite3HashClear(pH);
  }
}
コード例 #4
0
SWITCH_DECLARE(switch_status_t) switch_core_hash_destroy(switch_hash_t **hash)
{
	switch_assert(hash != NULL && *hash != NULL);
	sqlite3HashClear(&(*hash)->table);

	if (!(*hash)->pool) {
		free(*hash);
	}

	*hash = NULL;

	return SWITCH_STATUS_SUCCESS;
}
コード例 #5
0
ファイル: callback.c プロジェクト: DrEastex/Platinum
/*
** Free all resources held by the schema structure. The void* argument points
** at a Schema struct. This function does not call sqliteFree() on the 
** pointer itself, it just cleans up subsiduary resources (i.e. the contents
** of the schema hash tables).
*/
void sqlite3SchemaFree(void *p){
  Hash temp1;
  Hash temp2;
  HashElem *pElem;
  Schema *pSchema = (Schema *)p;

  temp1 = pSchema->tblHash;
  temp2 = pSchema->trigHash;
  sqlite3HashInit(&pSchema->trigHash, SQLITE_HASH_STRING, 0);
  sqlite3HashClear(&pSchema->aFKey);
  sqlite3HashClear(&pSchema->idxHash);
  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
    sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem));
  }
  sqlite3HashClear(&temp2);
  sqlite3HashInit(&pSchema->tblHash, SQLITE_HASH_STRING, 0);
  for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTab = sqliteHashData(pElem);
    sqlite3DeleteTable(0, pTab);
  }
  sqlite3HashClear(&temp1);
  pSchema->pSeqTab = 0;
  pSchema->flags &= ~DB_SchemaLoaded;
}
コード例 #6
0
ファイル: test_async.c プロジェクト: Bracket-/psp-ports
/*
** Call this routine to enable or disable the
** asynchronous IO features implemented in this file. 
**
** This routine is not even remotely threadsafe.  Do not call
** this routine while any SQLite database connections are open.
*/
static void asyncEnable(int enable){
  if( enable && xOrigOpenReadWrite==0 ){
    assert(sqlite3Os.xOpenReadWrite);
    sqlite3HashInit(&async.aLock, SQLITE_HASH_BINARY, 1);
    xOrigOpenReadWrite = sqlite3Os.xOpenReadWrite;
    xOrigOpenReadOnly = sqlite3Os.xOpenReadOnly;
    xOrigOpenExclusive = sqlite3Os.xOpenExclusive;
    xOrigDelete = sqlite3Os.xDelete;
    xOrigFileExists = sqlite3Os.xFileExists;
    xOrigSyncDirectory = sqlite3Os.xSyncDirectory;

    sqlite3Os.xOpenReadWrite = asyncOpenReadWrite;
    sqlite3Os.xOpenReadOnly = asyncOpenReadOnly;
    sqlite3Os.xOpenExclusive = asyncOpenExclusive;
    sqlite3Os.xDelete = asyncDelete;
    sqlite3Os.xFileExists = asyncFileExists;
    sqlite3Os.xSyncDirectory = asyncSyncDirectory;
    assert(sqlite3Os.xOpenReadWrite);
  }
  if( !enable && xOrigOpenReadWrite!=0 ){
    assert(sqlite3Os.xOpenReadWrite);
    sqlite3HashClear(&async.aLock);
    sqlite3Os.xOpenReadWrite = xOrigOpenReadWrite;
    sqlite3Os.xOpenReadOnly = xOrigOpenReadOnly;
    sqlite3Os.xOpenExclusive = xOrigOpenExclusive;
    sqlite3Os.xDelete = xOrigDelete;
    sqlite3Os.xFileExists = xOrigFileExists;
    sqlite3Os.xSyncDirectory = xOrigSyncDirectory;

    xOrigOpenReadWrite = 0;
    xOrigOpenReadOnly = 0;
    xOrigOpenExclusive = 0;
    xOrigDelete = 0;
    xOrigFileExists = 0;
    xOrigSyncDirectory = 0;
    assert(sqlite3Os.xOpenReadWrite);
  }
}
コード例 #7
0
int unload_module(void)
{
	int res = 0;
	do_reload = 1;

	ast_config_engine_deregister(&sqlite_engine);
	if (has_cdr) {
		ast_cdr_unregister(cdr_name);
		ast_verbose(VERBOSE_PREFIX_2 "SQLite CDR Disabled\n");
	}

	if (has_cli) {
		ast_verbose(VERBOSE_PREFIX_2 "SQLite CLI Disabled\n");
		ast_cli_unregister(&cli_sqlite1);  
		ast_cli_unregister(&cli_sqlite2);
		ast_cli_unregister(&cli_sqlite3);  
		ast_cli_unregister(&cli_sqlite4);  
		ast_cli_unregister(&cli_sqlite5);  
		ast_cli_unregister(&cli_sqlite6);  
		ast_cli_unregister(&cli_sqlite7);  
		ast_cli_unregister(&cli_sqlite8);  
		ast_cli_unregister(&cli_sqlite9);  
	}
		
	ast_unregister_application(app);




	if (has_switch) {
		ast_verbose(VERBOSE_PREFIX_2 "SQLite Switch Disabled\n");
		ast_unregister_switch(&sqlite_switch);
		sqlite3HashClear(&extens);
	}
	
	return res;
}
コード例 #8
0
static int sqlite_cli(int fd, int argc, char *argv[]) {
	char *errmsg = NULL;
	char sqlbuf[1024];
	int x = 0;
	int start = 0;
	switch_config config;
	extension_cache *cache;
	memset(&config,0,sizeof(switch_config));
	sqlite3 *db=NULL;
	HashElem *elem;
	char path[ARRAY_SIZE];
	char *sql = NULL;

	if (has_switch) {
		if (argv[1] && !strcmp(argv[1],"switchtable")) {
			if (argv[2]) {
				ast_mutex_lock(&switch_lock);
				strncpy(switch_table,argv[2],ARRAY_SIZE);
				ast_mutex_unlock(&switch_lock);
			}
			ast_cli(fd,"\nswitch table is %s\n\n",switch_table);
			return 0;
		}
		else if (argv[1] && !strcmp(argv[1],"switchdb")) {
			if (argv[2]) {
				ast_mutex_lock(&switch_lock);
				pick_path(argv[2],switch_dbfile,ARRAY_SIZE);
				ast_mutex_unlock(&switch_lock);
			}
			ast_cli(fd,"\nswitch db is %s\n\n",switch_dbfile);
			return 0;
		}
	}


	if (has_cdr) {
		if (argv[1] && !strcmp(argv[1],"cdrtable")) {
			if (argv[2]) {
				ast_mutex_lock(&cdr_lock);
				strncpy(cdr_table,argv[2],ARRAY_SIZE);
				ast_mutex_unlock(&cdr_lock);
			}
			ast_cli(fd,"\ncdr table is %s\n\n",cdr_table);
			return 0;
		}
		else if (argv[1] && !strcmp(argv[1],"cdrdb")) {
			if (argv[2]) {
				ast_mutex_lock(&cdr_lock);
				pick_path(argv[2],cdr_dbfile,ARRAY_SIZE);
				ast_mutex_unlock(&cdr_lock);
			}
			ast_cli(fd,"\ncdr db is %s\n\n",cdr_dbfile);
			return 0;
		}
	}


	if (!strcmp(argv[0],"sql")) {
		start = 1;
		if (argv[1] && !strcmp(argv[1],"cacheall")) {


			config.timeout = argv[3] ? atoi(argv[3]) : default_timeout;
			if (!config.timeout)
				config.timeout = default_timeout;
			if (!config.timeout)
				config.timeout = 300;
			db = open_db(clidb);

			if((sql = sqlite3_mprintf("select *,context from %q order by context,exten,pri",argv[2] ? argv[2] : switch_table))) {
				sqlite3_exec(
							 db,
							 sql,
							 exist_callback,
							 &config,
							 &errmsg
							 );
				if (errmsg) {
					ast_log(LOG_WARNING,"SQL ERR [%s]\n",errmsg);
					sqlite3_free(errmsg);
					errmsg = NULL;
				}
			
				sqlite3_free(sql);
				sql = NULL;

			} else {
				ast_cli(fd,"\nmalloc failed, good luck\n");
			}
			sqlite3_close(db);
			return 0;
		}
		else if (argv[1] && (!strcmp(argv[1],"use") || !strcmp(argv[1],"db"))) {
			if (argv[2]) {
				ast_mutex_lock(&switch_lock);
				pick_path(argv[2],path,ARRAY_SIZE);
				strncpy(clidb,path,ARRAY_SIZE);
				ast_mutex_unlock(&switch_lock);
			}
			ast_cli(fd,"\nnow using %s\n\n",clidb);
			return 0;
		}
		else if (argv[1] && !strcmp(argv[1],"cachetimeout")) {
			if (argv[2]) {
				ast_mutex_lock(&switch_lock);
				default_timeout = atoi(argv[2]);
				if (!default_timeout)
					default_timeout = 300;
				ast_mutex_unlock(&switch_lock);
			}
			ast_cli(fd,"\ncachetimeout is %d\n\n",default_timeout);
			return 0;
		}
		else if (argv[1] && !strcmp(argv[1],"vh")) {
			if (argv[2]) {
				ast_mutex_lock(&switch_lock);
				vh = argv[2][0] == 'v' ? 'v' : 'h';
				ast_mutex_unlock(&switch_lock);
			}
			ast_cli(fd,"\nvh is %c\n\n",vh);
			return 0;
		}
		else if (argv[1] && !strcmp(argv[1],"clearcache")) {
			ast_mutex_lock(&switch_lock);
			elem = extens.first;
			while ( elem ){
				HashElem *next_elem = elem->next;
				cache = elem->data;
				ast_cli(fd,"OK Erasing %s@%s\n",cache->exten,cache->context);
				free(cache);
				cache = NULL;
				elem = next_elem;
			}
			sqlite3HashClear(&extens);
			sqlite3HashInit(&extens,SQLITE_HASH_STRING,COPY_KEYS);
			ast_mutex_unlock(&switch_lock);
			ast_cli(fd,"\nOK. Cache Clear!\n\n");
			return 0;
		}

	}

	if (argc > start) {
		memset(sqlbuf,0,1024);
		for(x=start;x<argc;x++) {
			strncat(sqlbuf,argv[x],1024);
			strncat(sqlbuf," ",1024);
		}
		config.fd = fd;
		config.seeheads = 0;
		ast_cli(fd,"\n\n");
		ast_mutex_lock(&switch_lock);
		if ((db = open_db(clidb))) {
			sqlite3_exec(
						 db,
						 sqlbuf,
						 cli_callback,
						 &config,
						 &errmsg
						 );
			ast_mutex_unlock(&switch_lock);
			if (errmsg) {
				ast_cli(fd,"ERROR: '%s'\n[%s]\n",errmsg,sqlbuf);
				sqlite3_free(errmsg);
				errmsg = NULL;
			}
			sqlite3_close(db);
		} else {
			ast_cli(fd,"ERROR OPEINING DB.\n");
			return -1;
		}

	} else {
		ast_cli(fd,"ERROR! NO SQL?\n");
		return -1;
	}
	ast_cli(fd,"\n\n");

	return 0;
}
コード例 #9
0
/*
** Close an existing SQLite database
*/
int sqlite3_close(sqlite3 *db){
  HashElem *i;
  int j;

  if( !db ){
    return SQLITE_OK;
  }
  if( sqlite3SafetyCheck(db) ){
    return SQLITE_MISUSE;
  }

#ifdef SQLITE_SSE
  sqlite3_finalize(db->pFetch);
#endif

  /* If there are any outstanding VMs, return SQLITE_BUSY. */
  if( db->pVdbe ){
    sqlite3Error(db, SQLITE_BUSY,
        "Unable to close due to unfinalised statements");
    return SQLITE_BUSY;
  }
  assert( !sqlite3SafetyCheck(db) );

  /* FIX ME: db->magic may be set to SQLITE_MAGIC_CLOSED if the database
  ** cannot be opened for some reason. So this routine needs to run in
  ** that case. But maybe there should be an extra magic value for the
  ** "failed to open" state.
  */
  if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){
    /* printf("DID NOT CLOSE\n"); fflush(stdout); */
    return SQLITE_ERROR;
  }

  for(j=0; j<db->nDb; j++){
    struct Db *pDb = &db->aDb[j];
    if( pDb->pBt ){
      sqlite3BtreeClose(pDb->pBt);
      pDb->pBt = 0;
    }
  }
  sqlite3ResetInternalSchema(db, 0);
  assert( db->nDb<=2 );
  assert( db->aDb==db->aDbStatic );
  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
    FuncDef *pFunc, *pNext;
    for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
      pNext = pFunc->pNext;
      sqliteFree(pFunc);
    }
  }

  for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){
    CollSeq *pColl = (CollSeq *)sqliteHashData(i);
    sqliteFree(pColl);
  }
  sqlite3HashClear(&db->aCollSeq);

  sqlite3HashClear(&db->aFunc);
  sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
  if( db->pValue ){
    sqlite3ValueFree(db->pValue);
  }
  if( db->pErr ){
    sqlite3ValueFree(db->pErr);
  }

#ifndef SQLITE_OMIT_GLOBALRECOVER
  {
    sqlite3 *pPrev;
    sqlite3OsEnterMutex();
    pPrev = pDbList;
    while( pPrev && pPrev->pNext!=db ){
      pPrev = pPrev->pNext;
    }
    if( pPrev ){
      pPrev->pNext = db->pNext;
    }else{
      assert( pDbList==db );
      pDbList = db->pNext;
    }
    sqlite3OsLeaveMutex();
  }
#endif

  db->magic = SQLITE_MAGIC_ERROR;
  sqliteFree(db);
  return SQLITE_OK;
}
コード例 #10
0
ファイル: main.c プロジェクト: BackupTheBerlios/sqlitepp-svn
/*
** Close an existing SQLite database
*/
int sqlite3_close(sqlite3 *db){
  HashElem *i;
  int j;

  if( !db ){
    return SQLITE_OK;
  }
  if( sqlite3SafetyCheck(db) ){
    return SQLITE_MISUSE;
  }

#ifdef SQLITE_SSE
  sqlite3_finalize(db->pFetch);
#endif 

  /* If there are any outstanding VMs, return SQLITE_BUSY. */
  if( db->pVdbe ){
    sqlite3Error(db, SQLITE_BUSY, 
        "Unable to close due to unfinalised statements");
    return SQLITE_BUSY;
  }
  assert( !sqlite3SafetyCheck(db) );

  /* FIX ME: db->magic may be set to SQLITE_MAGIC_CLOSED if the database
  ** cannot be opened for some reason. So this routine needs to run in
  ** that case. But maybe there should be an extra magic value for the
  ** "failed to open" state.
  */
  if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){
    /* printf("DID NOT CLOSE\n"); fflush(stdout); */
    return SQLITE_ERROR;
  }

  for(j=0; j<db->nDb; j++){
    struct Db *pDb = &db->aDb[j];
    if( pDb->pBt ){
      sqlite3BtreeClose(pDb->pBt);
      pDb->pBt = 0;
      if( j!=1 ){
        pDb->pSchema = 0;
      }
    }
  }
  sqlite3ResetInternalSchema(db, 0);
  assert( db->nDb<=2 );
  assert( db->aDb==db->aDbStatic );
  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
    FuncDef *pFunc, *pNext;
    for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
      pNext = pFunc->pNext;
      sqliteFree(pFunc);
    }
  }

  for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){
    CollSeq *pColl = (CollSeq *)sqliteHashData(i);
    sqliteFree(pColl);
  }
  sqlite3HashClear(&db->aCollSeq);

  sqlite3HashClear(&db->aFunc);
  sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
  if( db->pErr ){
    sqlite3ValueFree(db->pErr);
  }

  db->magic = SQLITE_MAGIC_ERROR;

  /* The temp-database schema is allocated differently from the other schema
  ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
  ** So it needs to be freed here. Todo: Why not roll the temp schema into
  ** the same sqliteMalloc() as the one that allocates the database 
  ** structure?
  */
  sqliteFree(db->aDb[1].pSchema);
  sqliteFree(db);
  sqlite3ReleaseThreadData();
  return SQLITE_OK;
}
コード例 #11
0
/*
** Close an existing SQLite database
*/
EXPORT_C int sqlite3_close(sqlite3 *db){
  HashElem *i;
  int j;

  if( !db ){
    return SQLITE_OK;
  }
  if( sqlite3SafetyCheck(db) ){
    return SQLITE_MISUSE;
  }
  sqlite3_mutex_enter(db->mutex);

#ifdef SQLITE_SSE
  {
    extern void sqlite3SseCleanup(sqlite3*);
    sqlite3SseCleanup(db);
  }
#endif 

  sqlite3ResetInternalSchema(db, 0);

  /* If a transaction is open, the ResetInternalSchema() call above
  ** will not have called the xDisconnect() method on any virtual
  ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback()
  ** call will do so. We need to do this before the check for active
  ** SQL statements below, as the v-table implementation may be storing
  ** some prepared statements internally.
  */
  sqlite3VtabRollback(db);

  /* If there are any outstanding VMs, return SQLITE_BUSY. */
  if( db->pVdbe ){
    sqlite3Error(db, SQLITE_BUSY, 
        "Unable to close due to unfinalised statements");
    sqlite3_mutex_leave(db->mutex);
    return SQLITE_BUSY;
  }
  assert( !sqlite3SafetyCheck(db) );

  /* FIX ME: db->magic may be set to SQLITE_MAGIC_CLOSED if the database
  ** cannot be opened for some reason. So this routine needs to run in
  ** that case. But maybe there should be an extra magic value for the
  ** "failed to open" state.
  **
  ** TODO: Coverage tests do not test the case where this condition is
  ** true. It's hard to see how to cause it without messing with threads.
  */
  if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){
    /* printf("DID NOT CLOSE\n"); fflush(stdout); */
    sqlite3_mutex_leave(db->mutex);
    return SQLITE_ERROR;
  }

  for(j=0; j<db->nDb; j++){
    struct Db *pDb = &db->aDb[j];
    if( pDb->pBt ){
      sqlite3BtreeClose(pDb->pBt);
      pDb->pBt = 0;
      if( j!=1 ){
        pDb->pSchema = 0;
      }
    }
  }
  sqlite3ResetInternalSchema(db, 0);
  assert( db->nDb<=2 );
  assert( db->aDb==db->aDbStatic );
  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
    FuncDef *pFunc, *pNext;
    for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
      pNext = pFunc->pNext;
      sqlite3_free(pFunc);
    }
  }

  for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){
    CollSeq *pColl = (CollSeq *)sqliteHashData(i);
    /* Invoke any destructors registered for collation sequence user data. */
    for(j=0; j<3; j++){
      if( pColl[j].xDel ){
        pColl[j].xDel(pColl[j].pUser);
      }
    }
    sqlite3_free(pColl);
  }
  sqlite3HashClear(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){
    Module *pMod = (Module *)sqliteHashData(i);
    if( pMod->xDestroy ){
      pMod->xDestroy(pMod->pAux);
    }
    sqlite3_free(pMod);
  }
  sqlite3HashClear(&db->aModule);
#endif

  sqlite3HashClear(&db->aFunc);
  sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
  if( db->pErr ){
    sqlite3ValueFree(db->pErr);
  }
  sqlite3CloseExtensions(db);

  db->magic = SQLITE_MAGIC_ERROR;

  /* The temp-database schema is allocated differently from the other schema
  ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
  ** So it needs to be freed here. Todo: Why not roll the temp schema into
  ** the same sqliteMalloc() as the one that allocates the database 
  ** structure?
  */
  sqlite3_free(db->aDb[1].pSchema);
  sqlite3_mutex_leave(db->mutex);
  sqlite3_mutex_free(db->mutex);
  sqlite3_free(db);
  return SQLITE_OK;
}