/* ** Close an existing SQLite database */ void sqlite_close(sqlite *db){ HashElem *i; int j; db->want_to_close = 1; if( sqliteSafetyCheck(db) || sqliteSafetyOn(db) ){ /* printf("DID NOT CLOSE\n"); fflush(stdout); */ return; } db->magic = SQLITE_MAGIC_CLOSED; for(j=0; j<db->nDb; j++){ struct Db *pDb = &db->aDb[j]; if( pDb->pBt ){ sqliteBtreeClose(pDb->pBt); pDb->pBt = 0; } } sqliteResetInternalSchema(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); } } sqliteHashClear(&db->aFunc); sqliteFree(db); }
/* * Close the supplied Rbtree. Delete everything associated with it. */ static int memRbtreeClose(Rbtree* tree) { HashElem *p; memRbtreeCommit(tree); while( (p=sqliteHashFirst(&tree->tblHash))!=0 ){ tree->eTransState = TRANS_ROLLBACK; memRbtreeDropTable(tree, sqliteHashKeysize(p)); } sqliteHashClear(&tree->tblHash); sqliteFree(tree); return SQLITE_OK; }
/* ** Reset an Agg structure. Delete all its contents. ** ** For installable aggregate functions, if the step function has been ** called, make sure the finalizer function has also been called. The ** finalizer might need to free memory that was allocated as part of its ** private context. If the finalizer has not been called yet, call it ** now. */ void sqliteVdbeAggReset(Agg *pAgg){ int i; HashElem *p; for(p = sqliteHashFirst(&pAgg->hash); p; p = sqliteHashNext(p)){ AggElem *pElem = sqliteHashData(p); assert( pAgg->apFunc!=0 ); for(i=0; i<pAgg->nMem; i++){ Mem *pMem = &pElem->aMem[i]; if( pAgg->apFunc[i] && (pMem->flags & MEM_AggCtx)!=0 ){ sqlite_func ctx; ctx.pFunc = pAgg->apFunc[i]; ctx.s.flags = MEM_Null; ctx.pAgg = pMem->z; ctx.cnt = pMem->i; ctx.isStep = 0; ctx.isError = 0; (*pAgg->apFunc[i]->xFinalize)(&ctx); if( pMem->z!=0 && pMem->z!=pMem->zShort ){ sqliteFree(pMem->z); } if( ctx.s.flags & MEM_Dyn ){ sqliteFree(ctx.s.z); } }else if( pMem->flags & MEM_Dyn ){ sqliteFree(pMem->z); } } sqliteFree(pElem); } sqliteHashClear(&pAgg->hash); sqliteFree(pAgg->apFunc); pAgg->apFunc = 0; pAgg->pCurrent = 0; pAgg->pSearch = 0; pAgg->nMem = 0; }
/* ** Clean up the VM after execution. ** ** This routine will automatically close any cursors, lists, and/or ** sorters that were left open. It also deletes the values of ** variables in the azVariable[] array. */ static void Cleanup(Vdbe *p){ int i; if( p->aStack ){ Mem *pTos = p->pTos; while( pTos>=p->aStack ){ if( pTos->flags & MEM_Dyn ){ sqliteFree(pTos->z); } pTos--; } p->pTos = pTos; } closeAllCursors(p); if( p->aMem ){ for(i=0; i<p->nMem; i++){ if( p->aMem[i].flags & MEM_Dyn ){ sqliteFree(p->aMem[i].z); } } } sqliteFree(p->aMem); p->aMem = 0; p->nMem = 0; if( p->pList ){ sqliteVdbeKeylistFree(p->pList); p->pList = 0; } sqliteVdbeSorterReset(p); if( p->pFile ){ if( p->pFile!=stdin ) fclose(p->pFile); p->pFile = 0; } if( p->azField ){ sqliteFree(p->azField); p->azField = 0; } p->nField = 0; if( p->zLine ){ sqliteFree(p->zLine); p->zLine = 0; } p->nLineAlloc = 0; sqliteVdbeAggReset(&p->agg); if( p->aSet ){ for(i=0; i<p->nSet; i++){ sqliteHashClear(&p->aSet[i].hash); } } sqliteFree(p->aSet); p->aSet = 0; p->nSet = 0; if( p->keylistStack ){ int ii; for(ii = 0; ii < p->keylistStackDepth; ii++){ sqliteVdbeKeylistFree(p->keylistStack[ii]); } sqliteFree(p->keylistStack); p->keylistStackDepth = 0; p->keylistStack = 0; } sqliteFree(p->contextStack); p->contextStack = 0; sqliteFree(p->zErrMsg); p->zErrMsg = 0; }