int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, int eTextRep, void *pUserData, void (*xFunc)(sqlite3_context*,int,sqlite3_value**), void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ){ int rc; char const *zFunc8; sqlite3_value *pTmp; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } pTmp = sqlite3GetTransientValue(db); sqlite3ValueSetStr(pTmp, -1, zFunctionName, SQLITE_UTF16NATIVE,SQLITE_STATIC); zFunc8 = sqlite3ValueText(pTmp, SQLITE_UTF8); if( !zFunc8 ){ return SQLITE_NOMEM; } rc = sqlite3_create_function(db, zFunc8, nArg, eTextRep, pUserData, xFunc, xStep, xFinal); return rc; }
/* ** Return UTF-16 encoded English language explanation of the most recent ** error. */ const void *sqlite3_errmsg16(sqlite3 *db){ /* Because all the characters in the string are in the unicode ** range 0x00-0xFF, if we pad the big-endian string with a ** zero byte, we can obtain the little-endian string with ** &big_endian[1]. */ static const char outOfMemBe[] = { 0, 'o', 0, 'u', 0, 't', 0, ' ', 0, 'o', 0, 'f', 0, ' ', 0, 'm', 0, 'e', 0, 'm', 0, 'o', 0, 'r', 0, 'y', 0, 0, 0 }; static const char misuseBe [] = { 0, 'l', 0, 'i', 0, 'b', 0, 'r', 0, 'a', 0, 'r', 0, 'y', 0, ' ', 0, 'r', 0, 'o', 0, 'u', 0, 't', 0, 'i', 0, 'n', 0, 'e', 0, ' ', 0, 'c', 0, 'a', 0, 'l', 0, 'l', 0, 'e', 0, 'd', 0, ' ', 0, 'o', 0, 'u', 0, 't', 0, ' ', 0, 'o', 0, 'f', 0, ' ', 0, 's', 0, 'e', 0, 'q', 0, 'u', 0, 'e', 0, 'n', 0, 'c', 0, 'e', 0, 0, 0 }; const void *z; if( sqlite3_malloc_failed ){ return (void *)(&outOfMemBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ return (void *)(&misuseBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); } z = sqlite3_value_text16(db->pErr); if( z==0 ){ sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode), SQLITE_UTF8, SQLITE_STATIC); z = sqlite3_value_text16(db->pErr); } return z; }
/* ** Compile the UTF-16 encoded SQL statement zSql into a statement handle. */ int sqlite3_prepare16( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const void **pzTail /* OUT: End of parsed string */ ){ /* This function currently works by first transforming the UTF-16 ** encoded string to UTF-8, then invoking sqlite3_prepare(). The ** tricky bit is figuring out the pointer to return in *pzTail. */ char *zSql8; const char *zTail8 = 0; int rc = SQLITE_OK; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } zSql8 = sqlite3utf16to8(zSql, nBytes); if( zSql8 ){ rc = sqlite3_prepare(db, zSql8, -1, ppStmt, &zTail8); } if( zTail8 && pzTail ){ /* If sqlite3_prepare returns a tail pointer, we calculate the ** equivalent pointer into the UTF-16 string by counting the unicode ** characters between zSql8 and zTail8, and then returning a pointer ** the same number of characters into the UTF-16 string. */ int chars_parsed = sqlite3utf8CharLen(zSql8, zTail8-zSql8); *pzTail = (u8 *)zSql + sqlite3utf16ByteLen(zSql, chars_parsed); } sqliteFree(zSql8); return sqlite3ApiExit(db, rc); }
/* ** Return the most recent error code generated by an SQLite routine. If NULL is ** passed to this function, we assume a malloc() failed during sqlite3_open(). */ int sqlite3_errcode(sqlite3 *db){ if( !db || sqlite3MallocFailed() ){ return SQLITE_NOMEM; } if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } return db->errCode; }
/* ** Return the most recent error code generated by an SQLite routine. */ int sqlite3_errcode(sqlite3 *db){ if( sqlite3_malloc_failed ){ return SQLITE_NOMEM; } if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } return db->errCode; }
/* ** Return the most recent error code generated by an SQLite routine. If NULL is ** passed to this function, we assume a malloc() failed during sqlite3_open(). */ EXPORT_C int sqlite3_errcode(sqlite3 *db){ if( !db || db->mallocFailed ){ return SQLITE_NOMEM; } if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } return db->errCode & db->errMask; }
/* ** Register a new collation sequence with the database handle db. */ int sqlite3_create_collation( sqlite3* db, const char *zName, int enc, void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*) ){ CollSeq *pColl; int rc = SQLITE_OK; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } /* If SQLITE_UTF16 is specified as the encoding type, transform this ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. */ if( enc==SQLITE_UTF16 ){ enc = SQLITE_UTF16NATIVE; } if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF16LE && enc!=SQLITE_UTF16BE ){ sqlite3Error(db, SQLITE_ERROR, "Param 3 to sqlite3_create_collation() must be one of " "SQLITE_UTF8, SQLITE_UTF16, SQLITE_UTF16LE or SQLITE_UTF16BE" ); return SQLITE_ERROR; } /* Check if this call is removing or replacing an existing collation ** sequence. If so, and there are active VMs, return busy. If there ** are no active VMs, invalidate any pre-compiled statements. */ pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 0); if( pColl && pColl->xCmp ){ if( db->activeVdbeCnt ){ sqlite3Error(db, SQLITE_BUSY, "Unable to delete/modify collation sequence due to active statements"); return SQLITE_BUSY; } sqlite3ExpirePreparedStatements(db); } pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1); if( 0==pColl ){ rc = SQLITE_NOMEM; }else{ pColl->xCmp = xCompare; pColl->pUser = pCtx; pColl->enc = enc; } sqlite3Error(db, rc, 0); return rc; }
/* ** This routine installs a default busy handler that waits for the ** specified number of milliseconds before returning 0. */ EXPORT_C int sqlite3_busy_timeout(sqlite3 *db, int ms){ if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } if( ms>0 ){ db->busyTimeout = ms; sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); }else{ sqlite3_busy_handler(db, NULL, NULL); } return SQLITE_OK; }
/* ** This routine sets the busy callback for an Sqlite database to the ** given callback function with the given argument. */ int sqlite3_busy_handler( sqlite3 *db, int (*xBusy)(void*,int), void *pArg ){ if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } db->busyHandler.xFunc = xBusy; db->busyHandler.pArg = pArg; return SQLITE_OK; }
/* ** Register a collation sequence factory callback with the database handle ** db. Replace any previously installed collation sequence factory. */ int sqlite3_collation_needed16( sqlite3 *db, void *pCollNeededArg, void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*) ){ if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } db->xCollNeeded = 0; db->xCollNeeded16 = xCollNeeded16; db->pCollNeededArg = pCollNeededArg; return SQLITE_OK; }
/* ** Create a new collating function for database "db". The name is zName ** and the encoding is enc. */ static int createCollation( sqlite3* db, const char *zName, int enc, void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*) ){ CollSeq *pColl; int enc2; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } /* If SQLITE_UTF16 is specified as the encoding type, transform this ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. */ enc2 = enc & ~SQLITE_UTF16_ALIGNED; if( enc2==SQLITE_UTF16 ){ enc2 = SQLITE_UTF16NATIVE; } if( (enc2&~3)!=0 ){ sqlite3Error(db, SQLITE_ERROR, "unknown encoding"); return SQLITE_ERROR; } /* Check if this call is removing or replacing an existing collation ** sequence. If so, and there are active VMs, return busy. If there ** are no active VMs, invalidate any pre-compiled statements. */ pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 0); if( pColl && pColl->xCmp ){ if( db->activeVdbeCnt ){ sqlite3Error(db, SQLITE_BUSY, "Unable to delete/modify collation sequence due to active statements"); return SQLITE_BUSY; } sqlite3ExpirePreparedStatements(db); } pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 1); if( pColl ){ pColl->xCmp = xCompare; pColl->pUser = pCtx; pColl->enc = enc2 | (enc & SQLITE_UTF16_ALIGNED); } sqlite3Error(db, SQLITE_OK, 0); return SQLITE_OK; }
/* ** Return UTF-8 encoded English language explanation of the most recent ** error. */ const char *sqlite3_errmsg(sqlite3 *db){ const char *z; if( sqlite3_malloc_failed ){ return sqlite3ErrStr(SQLITE_NOMEM); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ return sqlite3ErrStr(SQLITE_MISUSE); } z = sqlite3_value_text(db->pErr); if( z==0 ){ z = sqlite3ErrStr(db->errCode); } return z; }
/* ** Unlock a virtual table. When the last lock is removed, ** disconnect the virtual table. */ void sqlite3VtabUnlock(sqlite3 *db, sqlite3_vtab *pVtab){ pVtab->nRef--; assert(db); assert(!sqlite3SafetyCheck(db)); if( pVtab->nRef==0 ){ if( db->magic==SQLITE_MAGIC_BUSY ){ sqlite3SafetyOff(db); pVtab->pModule->xDisconnect(pVtab); sqlite3SafetyOn(db); } else { pVtab->pModule->xDisconnect(pVtab); } } }
/* ** Return UTF-8 encoded English language explanation of the most recent ** error. */ const char *sqlite3_errmsg(sqlite3 *db){ const char *z; assert( !sqlite3MallocFailed() ); if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ return sqlite3ErrStr(SQLITE_MISUSE); } z = (char*)sqlite3_value_text(db->pErr); if( z==0 ){ z = sqlite3ErrStr(db->errCode); } return z; }
/* ** Register a collation sequence factory callback with the database handle ** db. Replace any previously installed collation sequence factory. */ extern "C" int sqlite3_collation_needed16( sqlite3 *db, void *pCollNeededArg, void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*) ){ if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } sqlite3_mutex_enter(db->mutex); db->xCollNeeded = 0; db->xCollNeeded16 = xCollNeeded16; db->pCollNeededArg = pCollNeededArg; sqlite3_mutex_leave(db->mutex); return SQLITE_OK; }
/* ** This routine sets the busy callback for an Sqlite database to the ** given callback function with the given argument. */ extern "C" int sqlite3_busy_handler( sqlite3 *db, int (*xBusy)(void*,int), void *pArg ){ if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } sqlite3_mutex_enter(db->mutex); db->busyHandler.xFunc = xBusy; db->busyHandler.pArg = pArg; db->busyHandler.nBusy = 0; sqlite3_mutex_leave(db->mutex); return SQLITE_OK; }
/* ** Return UTF-8 encoded English language explanation of the most recent ** error. */ EXPORT_C const char *sqlite3_errmsg(sqlite3 *db){ const char *z; if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ return sqlite3ErrStr(SQLITE_MISUSE); } sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); z = (char*)sqlite3_value_text(db->pErr); if( z==0 ){ z = sqlite3ErrStr(db->errCode); } sqlite3_mutex_leave(db->mutex); return z; }
/* ** Register a new collation sequence with the database handle db. */ int sqlite3_create_collation16( sqlite3* db, const char *zName, int enc, void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*) ){ char const *zName8; sqlite3_value *pTmp; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } pTmp = sqlite3GetTransientValue(db); sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF16NATIVE, SQLITE_STATIC); zName8 = sqlite3ValueText(pTmp, SQLITE_UTF8); return sqlite3_create_collation(db, zName8, enc, pCtx, xCompare); }
/* ** This routine sets the progress callback for an Sqlite database to the ** given callback function with the given argument. The progress callback will ** be invoked every nOps opcodes. */ void sqlite3_progress_handler( sqlite3 *db, int nOps, int (*xProgress)(void*), void *pArg ){ if( !sqlite3SafetyCheck(db) ){ if( nOps>0 ){ db->xProgress = xProgress; db->nProgressOps = nOps; db->pProgressArg = pArg; }else{ db->xProgress = 0; db->nProgressOps = 0; db->pProgressArg = 0; } } }
/* ** This routine sets the progress callback for an Sqlite database to the ** given callback function with the given argument. The progress callback will ** be invoked every nOps opcodes. */ extern "C" void sqlite3_progress_handler( sqlite3 *db, int nOps, int (*xProgress)(void*), void *pArg ){ if( !sqlite3SafetyCheck(db) ){ sqlite3_mutex_enter(db->mutex); if( nOps>0 ){ db->xProgress = xProgress; db->nProgressOps = nOps; db->pProgressArg = pArg; }else{ db->xProgress = 0; db->nProgressOps = 0; db->pProgressArg = 0; } sqlite3_mutex_leave(db->mutex); } }
/* ** Compile the UTF-16 encoded SQL statement zSql into a statement handle. */ int sqlite3_prepare16( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const void **pzTail /* OUT: End of parsed string */ ){ /* This function currently works by first transforming the UTF-16 ** encoded string to UTF-8, then invoking sqlite3_prepare(). The ** tricky bit is figuring out the pointer to return in *pzTail. */ char const *zSql8 = 0; char const *zTail8 = 0; int rc; sqlite3_value *pTmp; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } pTmp = sqlite3GetTransientValue(db); sqlite3ValueSetStr(pTmp, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); zSql8 = sqlite3ValueText(pTmp, SQLITE_UTF8); if( !zSql8 ){ sqlite3Error(db, SQLITE_NOMEM, 0); return SQLITE_NOMEM; } rc = sqlite3_prepare(db, zSql8, -1, ppStmt, &zTail8); if( zTail8 && pzTail ){ /* If sqlite3_prepare returns a tail pointer, we calculate the ** equivalent pointer into the UTF-16 string by counting the unicode ** characters between zSql8 and zTail8, and then returning a pointer ** the same number of characters into the UTF-16 string. */ int chars_parsed = sqlite3utf8CharLen(zSql8, zTail8-zSql8); *pzTail = (u8 *)zSql + sqlite3utf16ByteLen(zSql, chars_parsed); } return rc; }
/* ** 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; }
/* ** Create new user functions. */ int sqlite3_create_function( sqlite3 *db, const char *zFunctionName, int nArg, int enc, void *pUserData, void (*xFunc)(sqlite3_context*,int,sqlite3_value **), void (*xStep)(sqlite3_context*,int,sqlite3_value **), void (*xFinal)(sqlite3_context*) ){ FuncDef *p; int nName; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } if( zFunctionName==0 || (xFunc && (xFinal || xStep)) || (!xFunc && (xFinal && !xStep)) || (!xFunc && (!xFinal && xStep)) || (nArg<-1 || nArg>127) || (255<(nName = strlen(zFunctionName))) ){ return SQLITE_ERROR; } #ifndef SQLITE_OMIT_UTF16 /* If SQLITE_UTF16 is specified as the encoding type, transform this ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. ** ** If SQLITE_ANY is specified, add three versions of the function ** to the hash table. */ if( enc==SQLITE_UTF16 ){ enc = SQLITE_UTF16NATIVE; }else if( enc==SQLITE_ANY ){ int rc; rc = sqlite3_create_function(db, zFunctionName, nArg, SQLITE_UTF8, pUserData, xFunc, xStep, xFinal); if( rc!=SQLITE_OK ) return rc; rc = sqlite3_create_function(db, zFunctionName, nArg, SQLITE_UTF16LE, pUserData, xFunc, xStep, xFinal); if( rc!=SQLITE_OK ) return rc; enc = SQLITE_UTF16BE; } #else enc = SQLITE_UTF8; #endif /* Check if an existing function is being overridden or deleted. If so, ** and there are active VMs, then return SQLITE_BUSY. If a function ** is being overridden/deleted but there are no active VMs, allow the ** operation to continue but invalidate all precompiled statements. */ p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 0); if( p && p->iPrefEnc==enc && p->nArg==nArg ){ if( db->activeVdbeCnt ){ sqlite3Error(db, SQLITE_BUSY, "Unable to delete/modify user-function due to active statements"); return SQLITE_BUSY; }else{ sqlite3ExpirePreparedStatements(db); } } p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1); if( p==0 ) return SQLITE_NOMEM; p->xFunc = xFunc; p->xStep = xStep; p->xFinalize = xFinal; p->pUserData = pUserData; 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; } } 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; }
/* ** Cause any pending operation to stop at its earliest opportunity. */ void sqlite3_interrupt(sqlite3 *db){ if( !sqlite3SafetyCheck(db) ){ db->flags |= SQLITE_Interrupt; } }
/* ** Create a new collating function for database "db". The name is zName ** and the encoding is enc. */ static int createCollation( sqlite3* db, const char *zName, int enc, void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*), void(*xDel)(void*) ){ CollSeq *pColl; int enc2; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } assert( sqlite3_mutex_held(db->mutex) ); /* If SQLITE_UTF16 is specified as the encoding type, transform this ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. */ enc2 = enc & ~SQLITE_UTF16_ALIGNED; if( enc2==SQLITE_UTF16 ){ enc2 = SQLITE_UTF16NATIVE; } if( (enc2&~3)!=0 ){ sqlite3Error(db, SQLITE_ERROR, "unknown encoding"); return SQLITE_ERROR; } /* Check if this call is removing or replacing an existing collation ** sequence. If so, and there are active VMs, return busy. If there ** are no active VMs, invalidate any pre-compiled statements. */ pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 0); if( pColl && pColl->xCmp ){ if( db->activeVdbeCnt ){ sqlite3Error(db, SQLITE_BUSY, "Unable to delete/modify collation sequence due to active statements"); return SQLITE_BUSY; } sqlite3ExpirePreparedStatements(db); /* If collation sequence pColl was created directly by a call to ** sqlite3_create_collation, and not generated by synthCollSeq(), ** then any copies made by synthCollSeq() need to be invalidated. ** Also, collation destructor - CollSeq.xDel() - function may need ** to be called. */ if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){ CollSeq *aColl = (CollSeq*)sqlite3HashFind(&db->aCollSeq, zName, strlen(zName)); int j; for(j=0; j<3; j++){ CollSeq *p = &aColl[j]; if( p->enc==pColl->enc ){ if( p->xDel ){ p->xDel(p->pUser); } p->xCmp = 0; } } } } pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 1); if( pColl ){ pColl->xCmp = xCompare; pColl->pUser = pCtx; pColl->xDel = xDel; pColl->enc = enc2 | (enc & SQLITE_UTF16_ALIGNED); } sqlite3Error(db, SQLITE_OK, 0); return SQLITE_OK; }