#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
typedef struct {
sqlite *db;
char **pzErrMsg;
} InitData;
static void corruptSchema(InitData *pData, const char *zExtra){
sqliteSetString(pData->pzErrMsg, "malformed database schema",
zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
}
static
int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){
InitData *pData = (InitData*)pInit;
int nErr = 0;
assert( argc==5 );
if( argv==0 ) return 0;
if( argv[0]==0 ){
corruptSchema(pData, 0);
return 1;
}
switch( argv[0][0] ){
case 'v':
case 'i':
case 't': {
sqlite *db = pData->db;
if( argv[2]==0 || argv[4]==0 ){
corruptSchema(pData, 0);
return 1;
}
if( argv[3] && argv[3][0] ){
char *zErr;
assert( db->init.busy );
db->init.iDb = atoi(argv[4]);
assert( db->init.iDb>=0 && db->init.iDb<db->nDb );
db->init.newTnum = atoi(argv[2]);
if( sqlite_exec(db, argv[3], 0, 0, &zErr) ){
corruptSchema(pData, zErr);
sqlite_freemem(zErr);
}
db->init.iDb = 0;
}else{
int iDb;
Index *pIndex;
iDb = atoi(argv[4]);
assert( iDb>=0 && iDb<db->nDb );
pIndex = sqliteFindIndex(db, argv[1], db->aDb[iDb].zName);
if( pIndex==0 || pIndex->tnum!=0 ){
;
}else{
pIndex->tnum = atoi(argv[2]);
}
}
break;
}
default: {
nErr = 1;
assert( nErr==0 );
}
}
return nErr;
}
static
int upgrade_3_callback(void *pInit, int argc, char **argv, char **NotUsed){
InitData *pData = (InitData*)pInit;
int rc;
Table *pTab;
Trigger *pTrig;
char *zErr = 0;
pTab = sqliteFindTable(pData->db, argv[0], 0);
assert( pTab!=0 );
assert( sqliteStrICmp(pTab->zName, argv[0])==0 );
if( pTab ){
pTrig = pTab->pTrigger;
pTab->pTrigger = 0;
}
rc = sqlite_exec_printf(pData->db,
"CREATE TEMP TABLE sqlite_x AS SELECT * FROM '%q'; "
"DELETE FROM '%q'; "
"INSERT INTO '%q' SELECT * FROM sqlite_x; "
"DROP TABLE sqlite_x;",
0, 0, &zErr, argv[0], argv[0], argv[0]);
if( zErr ){
if( *pData->pzErrMsg ) sqlite_freemem(*pData->pzErrMsg);
*pData->pzErrMsg = zErr;
}
pTab = sqliteFindTable(pData->db, argv[0], 0);
if( pTab ){
assert( sqliteStrICmp(pTab->zName, argv[0])==0 );
pTab->pTrigger = pTrig;
}
return rc!=SQLITE_OK;
}
static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
int rc;
BtCursor *curMain;
int size;
Table *pTab;
char const *azArg[6];
char zDbNum[30];
int meta[SQLITE_N_BTREE_META];
InitData initData;
char const *zMasterSchema;
char const *zMasterName;
char *zSql = 0;
static char master_schema[] =
"CREATE TABLE sqlite_master(\n"
" type text,\n"
" name text,\n"
" tbl_name text,\n"
" rootpage integer,\n"
" sql text\n"
")"
;
static char temp_master_schema[] =
"CREATE TEMP TABLE sqlite_temp_master(\n"
" type text,\n"
" name text,\n"
" tbl_name text,\n"
" rootpage integer,\n"
" sql text\n"
")"
;
assert( iDb>=0 && iDb<db->nDb );
if( iDb==1 ){
zMasterSchema = temp_master_schema;
zMasterName = TEMP_MASTER_NAME;
}else{
zMasterSchema = master_schema;
zMasterName = MASTER_NAME;
}
sqliteSafetyOff(db);
azArg[0] = "table";
azArg[1] = zMasterName;
azArg[2] = "2";
azArg[3] = zMasterSchema;
sprintf(zDbNum, "%d", iDb);
azArg[4] = zDbNum;
azArg[5] = 0;
initData.db = db;
initData.pzErrMsg = pzErrMsg;
sqliteInitCallback(&initData, 5, (char **)azArg, 0);
pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName);
if( pTab ){
pTab->readOnly = 1;
}else{
return SQLITE_NOMEM;
}
sqliteSafetyOn(db);
if( db->aDb[iDb].pBt==0 ) return SQLITE_OK;
rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain);
if( rc ){
sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0);
return rc;
}
rc = sqliteBtreeGetMeta(db->aDb[iDb].pBt, meta);
if( rc ){
sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0);
sqliteBtreeCloseCursor(curMain);
return rc;
}
db->aDb[iDb].schema_cookie = meta[1];
if( iDb==0 ){
db->next_cookie = meta[1];
db->file_format = meta[2];
size = meta[3];
if( size==0 ){ size = MAX_PAGES; }
db->cache_size = size;
db->safety_level = meta[4];
if( meta[6]>0 && meta[6]<=2 && db->temp_store==0 ){
db->temp_store = meta[6];
}
if( db->safety_level==0 ) db->safety_level = 2;
if( db->file_format==0 ){
db->file_format = 4;
}else if( db->file_format>4 ){
sqliteBtreeCloseCursor(curMain);
sqliteSetString(pzErrMsg, "unsupported file format", (char*)0);
return SQLITE_ERROR;
}
}else if( iDb!=1 && (db->file_format!=meta[2] || db->file_format<4) ){
assert( db->file_format>=4 );
if( meta[2]==0 ){
sqliteSetString(pzErrMsg, "cannot attach empty database: ",
db->aDb[iDb].zName, (char*)0);
}else{
sqliteSetString(pzErrMsg, "incompatible file format in auxiliary "
"database: ", db->aDb[iDb].zName, (char*)0);
}
sqliteBtreeClose(db->aDb[iDb].pBt);
db->aDb[iDb].pBt = 0;
return SQLITE_FORMAT;
}
sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size);
sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]);
assert( db->init.busy );
sqliteSafetyOff(db);
if( db->file_format>=2 ){
sqliteSetString(&zSql,
"SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
db->aDb[iDb].zName, "\".", zMasterName, (char*)0);
}else{
sqliteSetString(&zSql,
"SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
db->aDb[iDb].zName, "\".", zMasterName,
" WHERE type IN ('table', 'index')"
" ORDER BY CASE type WHEN 'table' THEN 0 ELSE 1 END", (char*)0);
}
rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
sqliteFree(zSql);
sqliteSafetyOn(db);
sqliteBtreeCloseCursor(curMain);
if( sqlite_malloc_failed ){
sqliteSetString(pzErrMsg, "out of memory", (char*)0);
rc = SQLITE_NOMEM;
sqliteResetInternalSchema(db, 0);
}
if( rc==SQLITE_OK ){
DbSetProperty(db, iDb, DB_SchemaLoaded);
}else{
sqliteResetInternalSchema(db, iDb);
}
return rc;
}
int sqliteInit(sqlite *db, char **pzErrMsg){
int i, rc;
if( db->init.busy ) return SQLITE_OK;
assert( (db->flags & SQLITE_Initialized)==0 );
rc = SQLITE_OK;
db->init.busy = 1;
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
rc = sqliteInitOne(db, i, pzErrMsg);
if( rc ){
sqliteResetInternalSchema(db, i);
}
}
if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
rc = sqliteInitOne(db, 1, pzErrMsg);
if( rc ){
sqliteResetInternalSchema(db, 1);
}
}
db->init.busy = 0;
if( rc==SQLITE_OK ){
db->flags |= SQLITE_Initialized;
sqliteCommitInternalChanges(db);
}
if( rc==SQLITE_OK && db->file_format<3 ){
char *zErr = 0;
InitData initData;
int meta[SQLITE_N_BTREE_META];
db->magic = SQLITE_MAGIC_OPEN;
initData.db = db;
initData.pzErrMsg = &zErr;
db->file_format = 3;
rc = sqlite_exec(db,
"BEGIN; SELECT name FROM sqlite_master WHERE type='table';",
upgrade_3_callback,
&initData,
&zErr);
if( rc==SQLITE_OK ){
sqliteBtreeGetMeta(db->aDb[0].pBt, meta);
meta[2] = 4;
sqliteBtreeUpdateMeta(db->aDb[0].pBt, meta);
sqlite_exec(db, "COMMIT", 0, 0, 0);
}
if( rc!=SQLITE_OK ){
sqliteSetString(pzErrMsg,
"unable to upgrade database to the version 2.6 format",
zErr ? ": " : 0, zErr, (char*)0);
}
sqlite_freemem(zErr);
}
if( rc!=SQLITE_OK ){
db->flags &= ~SQLITE_Initialized;
}
return rc;
}
const char rcsid[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $";
const char sqlite_version[] = SQLITE_VERSION;
#ifdef SQLITE_UTF8
const char sqlite_encoding[] = "UTF-8";
#else
const char sqlite_encoding[] = "iso8859";
#endif
sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
sqlite *db;
int rc, i;
db = sqliteMalloc( sizeof(sqlite) );
if( pzErrMsg ) *pzErrMsg = 0;
if( db==0 ) goto no_mem_on_open;
db->onError = OE_Default;
db->priorNewRowid = 0;
db->magic = SQLITE_MAGIC_BUSY;
db->nDb = 2;
db->aDb = db->aDbStatic;
sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1);
for(i=0; i<db->nDb; i++){
sqliteHashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1);
}
if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){
db->temp_store = 2;
}
rc = sqliteBtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt);
if( rc!=SQLITE_OK ){
switch( rc ){
default: {
sqliteSetString(pzErrMsg, "unable to open database: ",
zFilename, (char*)0);
}
}
sqliteFree(db);
sqliteStrRealloc(pzErrMsg);
return 0;
}
db->aDb[0].zName = "main";
db->aDb[1].zName = "temp";
sqliteRegisterBuiltinFunctions(db);
rc = sqliteInit(db, pzErrMsg);
db->magic = SQLITE_MAGIC_OPEN;
if( sqlite_malloc_failed ){
sqlite_close(db);
goto no_mem_on_open;
}else if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
sqlite_close(db);
sqliteStrRealloc(pzErrMsg);
return 0;
}else if( pzErrMsg ){
sqliteFree(*pzErrMsg);
*pzErrMsg = 0;
}
return db;
no_mem_on_open:
sqliteSetString(pzErrMsg, "out of memory", (char*)0);
sqliteStrRealloc(pzErrMsg);
return 0;
}
int sqlite_last_insert_rowid(sqlite *db){
return db->lastRowid;
}
int sqlite_changes(sqlite *db){
return db->nChange;
}
int sqlite_last_statement_changes(sqlite *db){
return db->lsChange;
}
void sqlite_close(sqlite *db){
HashElem *i;
int j;
db->want_to_close = 1;
if( sqliteSafetyCheck(db) || sqliteSafetyOn(db) ){
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);
}
void sqliteRollbackAll(sqlite *db){
int i;
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pBt ){
sqliteBtreeRollback(db->aDb[i].pBt);
db->aDb[i].inTrans = 0;
}
}
sqliteResetInternalSchema(db, 0);
}
int sqlite_exec(
sqlite *db,
const char *zSql,
sqlite_callback xCallback,
void *pArg,
char **pzErrMsg
){
int rc = SQLITE_OK;
const char *zLeftover;
sqlite_vm *pVm;
int nRetry = 0;
int nChange = 0;
int nCallback;
if( zSql==0 ) return SQLITE_OK;
while( rc==SQLITE_OK && zSql[0] ){
pVm = 0;
rc = sqlite_compile(db, zSql, &zLeftover, &pVm, pzErrMsg);
if( rc!=SQLITE_OK ){
assert( pVm==0 || sqlite_malloc_failed );
return rc;
}
if( pVm==0 ){
break;
}
db->nChange += nChange;
nCallback = 0;
while(1){
int nArg;
char **azArg, **azCol;
rc = sqlite_step(pVm, &nArg, (const char***)&azArg,(const char***)&azCol);
if( rc==SQLITE_ROW ){
if( xCallback!=0 && xCallback(pArg, nArg, azArg, azCol) ){
sqlite_finalize(pVm, 0);
return SQLITE_ABORT;
}
nCallback++;
}else{
if( rc==SQLITE_DONE && nCallback==0
&& (db->flags & SQLITE_NullCallback)!=0 && xCallback!=0 ){
xCallback(pArg, nArg, azArg, azCol);
}
rc = sqlite_finalize(pVm, pzErrMsg);
if( rc==SQLITE_SCHEMA && nRetry<2 ){
nRetry++;
rc = SQLITE_OK;
break;
}
if( db->pVdbe==0 ){
nChange = db->nChange;
}
nRetry = 0;
zSql = zLeftover;
while( isspace(zSql[0]) ) zSql++;
break;
}
}
}
return rc;
}
int sqlite_compile(
sqlite *db,
const char *zSql,
const char **pzTail,
sqlite_vm **ppVm,
char **pzErrMsg
){
Parse sParse;
if( pzErrMsg ) *pzErrMsg = 0;
if( sqliteSafetyOn(db) ) goto exec_misuse;
if( !db->init.busy ){
if( (db->flags & SQLITE_Initialized)==0 ){
int rc, cnt = 1;
while( (rc = sqliteInit(db, pzErrMsg))==SQLITE_BUSY
&& db->xBusyCallback
&& db->xBusyCallback(db->pBusyArg, "", cnt++)!=0 ){}
if( rc!=SQLITE_OK ){
sqliteStrRealloc(pzErrMsg);
sqliteSafetyOff(db);
return rc;
}
if( pzErrMsg ){
sqliteFree(*pzErrMsg);
*pzErrMsg = 0;
}
}
if( db->file_format<3 ){
sqliteSafetyOff(db);
sqliteSetString(pzErrMsg, "obsolete database file format", (char*)0);
return SQLITE_ERROR;
}
}
assert( (db->flags & SQLITE_Initialized)!=0 || db->init.busy );
if( db->pVdbe==0 ){ db->nChange = 0; }
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
sqliteRunParser(&sParse, zSql, pzErrMsg);
if( db->xTrace && !db->init.busy ){
if( sParse.zTail && sParse.zTail!=zSql && *sParse.zTail ){
char *tmpSql = sqliteStrNDup(zSql, sParse.zTail - zSql);
if( tmpSql ){
db->xTrace(db->pTraceArg, tmpSql);
free(tmpSql);
}else{
db->xTrace(db->pTraceArg, zSql);
}
}else{
db->xTrace(db->pTraceArg, zSql);
}
}
if( sqlite_malloc_failed ){
sqliteSetString(pzErrMsg, "out of memory", (char*)0);
sParse.rc = SQLITE_NOMEM;
sqliteRollbackAll(db);
sqliteResetInternalSchema(db, 0);
db->flags &= ~SQLITE_InTrans;
}
if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
if( sParse.rc!=SQLITE_OK && pzErrMsg && *pzErrMsg==0 ){
sqliteSetString(pzErrMsg, sqlite_error_string(sParse.rc), (char*)0);
}
sqliteStrRealloc(pzErrMsg);
if( sParse.rc==SQLITE_SCHEMA ){
sqliteResetInternalSchema(db, 0);
}
assert( ppVm );
*ppVm = (sqlite_vm*)sParse.pVdbe;
if( pzTail ) *pzTail = sParse.zTail;
if( sqliteSafetyOff(db) ) goto exec_misuse;
return sParse.rc;
exec_misuse:
if( pzErrMsg ){
*pzErrMsg = 0;
sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), (char*)0);
sqliteStrRealloc(pzErrMsg);
}
return SQLITE_MISUSE;
}
int sqlite_finalize(
sqlite_vm *pVm,
char **pzErrMsg
){
int rc = sqliteVdbeFinalize((Vdbe*)pVm, pzErrMsg);
sqliteStrRealloc(pzErrMsg);
return rc;
}
int sqlite_reset(
sqlite_vm *pVm,
char **pzErrMsg
){
int rc = sqliteVdbeReset((Vdbe*)pVm, pzErrMsg);
sqliteVdbeMakeReady((Vdbe*)pVm, -1, 0);
sqliteStrRealloc(pzErrMsg);
return rc;
}
const char *sqlite_error_string(int rc){
const char *z;
switch( rc ){
case SQLITE_OK: z = "not an error"; break;
case SQLITE_ERROR: z = "SQL logic error or missing database"; break;
case SQLITE_INTERNAL: z = "internal SQLite implementation flaw"; break;
case SQLITE_PERM: z = "access permission denied"; break;
case SQLITE_ABORT: z = "callback requested query abort"; break;
case SQLITE_BUSY: z = "database is locked"; break;
case SQLITE_LOCKED: z = "database table is locked"; break;
case SQLITE_NOMEM: z = "out of memory"; break;
case SQLITE_READONLY: z = "attempt to write a readonly database"; break;
case SQLITE_INTERRUPT: z = "interrupted"; break;
case SQLITE_IOERR: z = "disk I/O error"; break;
case SQLITE_CORRUPT: z = "database disk image is malformed"; break;
case SQLITE_NOTFOUND: z = "table or record not found"; break;
case SQLITE_FULL: z = "database is full"; break;
case SQLITE_CANTOPEN: z = "unable to open database file"; break;
case SQLITE_PROTOCOL: z = "database locking protocol failure"; break;
case SQLITE_EMPTY: z = "table contains no data"; break;
case SQLITE_SCHEMA: z = "database schema has changed"; break;
case SQLITE_TOOBIG: z = "too much data for one table row"; break;
case SQLITE_CONSTRAINT: z = "constraint failed"; break;
case SQLITE_MISMATCH: z = "datatype mismatch"; break;
case SQLITE_MISUSE: z = "library routine called out of sequence";break;
case SQLITE_NOLFS: z = "kernel lacks large file support"; break;
case SQLITE_AUTH: z = "authorization denied"; break;
case SQLITE_FORMAT: z = "auxiliary database format error"; break;
case SQLITE_RANGE: z = "bind index out of range"; break;
case SQLITE_NOTADB: z = "file is encrypted or is not a database";break;
default: z = "unknown error"; break;
}
return z;
}
static int sqliteDefaultBusyCallback(
void *Timeout,
const char *NotUsed,
int count
){
#if SQLITE_MIN_SLEEP_MS==1
static const char delays[] =
{ 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 50, 100};
static const short int totals[] =
{ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228, 287};
# define NDELAY (sizeof(delays)/sizeof(delays[0]))
int timeout = (int)(long)Timeout;
int delay, prior;
if( count <= NDELAY ){
delay = delays[count-1];
prior = totals[count-1];
}else{
delay = delays[NDELAY-1];
prior = totals[NDELAY-1] + delay*(count-NDELAY-1);
}
if( prior + delay > timeout ){
delay = timeout - prior;
if( delay<=0 ) return 0;
}
sqliteOsSleep(delay);
return 1;
#else
int timeout = (int)(long)Timeout;
if( (count+1)*1000 > timeout ){
return 0;
}
sqliteOsSleep(1000);
return 1;
#endif
}
void sqlite_busy_handler(
sqlite *db,
int (*xBusy)(void*,const char*,int),
void *pArg
){
db->xBusyCallback = xBusy;
db->pBusyArg = pArg;
}
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
void sqlite_progress_handler(
sqlite *db,
int nOps,
int (*xProgress)(void*),
void *pArg
){
if( nOps>0 ){
db->xProgress = xProgress;
db->nProgressOps = nOps;
db->pProgressArg = pArg;
}else{
db->xProgress = 0;
db->nProgressOps = 0;
db->pProgressArg = 0;
}
}
#endif
void sqlite_busy_timeout(sqlite *db, int ms){
if( ms>0 ){
sqlite_busy_handler(db, sqliteDefaultBusyCallback, (void*)(long)ms);
}else{
sqlite_busy_handler(db, 0, 0);
}
}
void sqlite_interrupt(sqlite *db){
db->flags |= SQLITE_Interrupt;
}
void sqlite_freemem(void *p){ free(p); }
const char *sqlite_libversion(void){ return sqlite_version; }
const char *sqlite_libencoding(void){ return sqlite_encoding; }
int sqlite_create_function(
sqlite *db,
const char *zName,
int nArg,
void (*xFunc)(sqlite_func*,int,const char**),
void *pUserData
){
FuncDef *p;
int nName;
if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1;
if( nArg<-1 || nArg>127 ) return 1;
nName = strlen(zName);
if( nName>255 ) return 1;
p = sqliteFindFunction(db, zName, nName, nArg, 1);
if( p==0 ) return 1;
p->xFunc = xFunc;
p->xStep = 0;
p->xFinalize = 0;
p->pUserData = pUserData;
return 0;
}
int sqlite_create_aggregate(
sqlite *db,
const char *zName,
int nArg,
void (*xStep)(sqlite_func*,int,const char**),
void (*xFinalize)(sqlite_func*),
void *pUserData
){
FuncDef *p;
int nName;
if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1;
if( nArg<-1 || nArg>127 ) return 1;
nName = strlen(zName);
if( nName>255 ) return 1;
p = sqliteFindFunction(db, zName, nName, nArg, 1);
if( p==0 ) return 1;
p->xFunc = 0;
p->xStep = xStep;
p->xFinalize = xFinalize;
p->pUserData = pUserData;
return 0;
}
int sqlite_function_type(sqlite *db, const char *zName, int dataType){
FuncDef *p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, strlen(zName));
while( p ){
p->dataType = dataType;
p = p->pNext;
}
return SQLITE_OK;
}
void *sqlite_trace(sqlite *db, void (*xTrace)(void*,const char*), void *pArg){
void *pOld = db->pTraceArg;
db->xTrace = xTrace;
db->pTraceArg = pArg;
return pOld;
}
void *sqlite_commit_hook(
sqlite *db,
int (*xCallback)(void*),
void *pArg
){
void *pOld = db->pCommitArg;
db->xCommitCallback = xCallback;
db->pCommitArg = pArg;
return pOld;
}
int sqliteBtreeFactory(
const sqlite *db,
const char *zFilename,
int omitJournal,
int nCache,
Btree **ppBtree){
assert( ppBtree != 0);
#ifndef SQLITE_OMIT_INMEMORYDB
if( zFilename==0 ){
if (TEMP_STORE == 0) {
return sqliteBtreeOpen(0, omitJournal, nCache, ppBtree);
} else if (TEMP_STORE == 1 || TEMP_STORE == 2) {
int location = db->temp_store==0 ? TEMP_STORE : db->temp_store;
if (location == 1) {
return sqliteBtreeOpen(zFilename, omitJournal, nCache, ppBtree);
} else {
return sqliteRbtreeOpen(0, 0, 0, ppBtree);
}
} else {
return sqliteRbtreeOpen(0, 0, 0, ppBtree);
}
}else if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){
return sqliteRbtreeOpen(0, 0, 0, ppBtree);
}else
#endif
{
return sqliteBtreeOpen(zFilename, omitJournal, nCache, ppBtree);
}
}