/* ** 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); }
/* ** 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; }
/* 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); } }
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; }
/* ** 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; }
/* ** 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); } }
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; }
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; }
/* ** 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; }
/* ** 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; }
/* ** 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; }