Index: main.mk ================================================================== --- main.mk +++ main.mk @@ -68,18 +68,18 @@ LIBOBJ+= vdbe.o parse.o \ alter.o analyze.o attach.o auth.o \ build.o \ - callback.o complete.o ctime.o date.o delete.o expr.o fault.o fkey.o \ - fts5.o fts5func.o \ + callback.o complete.o ctime.o date.o delete.o env.o expr.o \ + fault.o fkey.o fts5.o fts5func.o \ func.o global.o hash.o \ icu.o insert.o kv.o kvlsm.o kvmem.o legacy.o \ lsm_ckpt.o lsm_file.o lsm_log.o lsm_main.o lsm_mem.o lsm_mutex.o \ lsm_shared.o lsm_str.o lsm_sorted.o lsm_tree.o \ lsm_unix.o lsm_varint.o \ - main.o malloc.o math.o mem0.o mem1.o mem2.o mem3.o mem5.o \ + main.o malloc.o math.o mem.o mem0.o mem1.o mem2.o mem3.o mem5.o \ mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ opcodes.o os.o \ pragma.o prepare.o printf.o \ random.o resolve.o rowset.o rtree.o select.o status.o \ tokenize.o trigger.o \ @@ -99,10 +99,11 @@ $(TOP)/src/callback.c \ $(TOP)/src/complete.c \ $(TOP)/src/ctime.c \ $(TOP)/src/date.c \ $(TOP)/src/delete.c \ + $(TOP)/src/env.c \ $(TOP)/src/expr.c \ $(TOP)/src/fault.c \ $(TOP)/src/fkey.c \ $(TOP)/src/fts5.c \ $(TOP)/src/fts5func.c \ @@ -132,10 +133,11 @@ $(TOP)/src/lsm_unix.c \ $(TOP)/src/lsm_varint.c \ $(TOP)/src/main.c \ $(TOP)/src/malloc.c \ $(TOP)/src/math.c \ + $(TOP)/src/mem.o \ $(TOP)/src/mem0.c \ $(TOP)/src/mem1.c \ $(TOP)/src/mem2.c \ $(TOP)/src/mem3.c \ $(TOP)/src/mem5.c \ ADDED src/env.c Index: src/env.c ================================================================== --- /dev/null +++ src/env.c @@ -0,0 +1,442 @@ +/* +** 2013 January 7 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains code used to help implement the sqlite4_env object. +*/ +#include "sqliteInt.h" + +/* +** Initialize SQLite. +** +** This routine must be called to initialize the run-time environment +** As long as you do not compile with SQLITE4_OMIT_AUTOINIT +** this routine will be called automatically by key routines such as +** sqlite4_open(). +** +** This routine is a no-op except on its very first call for a given +** sqlite4_env object, or for the first call after a call to sqlite4_shutdown. +** +** This routine is not threadsafe. It should be called from a single +** thread to initialized the library in a multi-threaded system. Other +** threads should avoid using the sqlite4_env object until after it has +** completely initialized. +*/ +int sqlite4_initialize(sqlite4_env *pEnv){ + MUTEX_LOGIC( sqlite4_mutex *pMaster; ) /* The main static mutex */ + int rc; /* Result code */ + + if( pEnv==0 ) pEnv = &sqlite4DefaultEnv; + + /* If SQLite is already completely initialized, then this call + ** to sqlite4_initialize() should be a no-op. But the initialization + ** must be complete. So isInit must not be set until the very end + ** of this routine. + */ + if( pEnv->isInit ) return SQLITE4_OK; + + /* Initialize the mutex subsystem + */ + rc = sqlite4MutexInit(pEnv); + if( rc ){ + sqlite4MallocEnd(pEnv); + return rc; + } + + /* Initialize the memory allocation subsystem + */ + rc = sqlite4MallocInit(pEnv); + if( rc ) return rc; + + /* Create required mutexes + */ + if( pEnv->bCoreMutex ){ + pEnv->pMemMutex = sqlite4MutexAlloc(pEnv, SQLITE4_MUTEX_FAST); + pEnv->pPrngMutex = sqlite4MutexAlloc(pEnv, SQLITE4_MUTEX_FAST); + pEnv->pFactoryMutex = sqlite4MutexAlloc(pEnv, SQLITE4_MUTEX_FAST); + if( pEnv->pMemMutex==0 + || pEnv->pPrngMutex==0 + || pEnv->pFactoryMutex==0 + ){ + rc = SQLITE4_NOMEM; + } + }else{ + pEnv->pMemMutex = 0; + pEnv->pPrngMutex = 0; + } + pEnv->isInit = 1; + + sqlite4OsInit(pEnv); + + /* Register global functions */ + if( rc==SQLITE4_OK ){ + sqlite4RegisterGlobalFunctions(pEnv); + } + + /* The following is just a sanity check to make sure SQLite has + ** been compiled correctly. It is important to run this code, but + ** we don't want to run it too often and soak up CPU cycles for no + ** reason. So we run it once during initialization. + */ +#ifndef NDEBUG +#ifndef SQLITE4_OMIT_FLOATING_POINT + /* This section of code's only "output" is via assert() statements. */ + if ( rc==SQLITE4_OK ){ + u64 x = (((u64)1)<<63)-1; + double y; + assert(sizeof(x)==8); + assert(sizeof(x)==sizeof(y)); + memcpy(&y, &x, 8); + assert( sqlite4IsNaN(y) ); + } +#endif +#endif + + return rc; +} + +/* +** Undo the effects of sqlite4_initialize(). Must not be called while +** there are outstanding database connections or memory allocations or +** while any part of SQLite is otherwise in use in any thread. This +** routine is not threadsafe. But it is safe to invoke this routine +** on when SQLite is already shut down. If SQLite is already shut down +** when this routine is invoked, then this routine is a harmless no-op. +*/ +int sqlite4_shutdown(sqlite4_env *pEnv){ + if( pEnv==0 ) pEnv = &sqlite4DefaultEnv; + if( pEnv->isInit ){ + KVFactory *pMkr; + sqlite4_mutex_free(pEnv->pFactoryMutex); + sqlite4_mutex_free(pEnv->pPrngMutex); + sqlite4_mutex_free(pEnv->pMemMutex); + pEnv->pMemMutex = 0; + while( (pMkr = pEnv->pFactory)!=0 && pMkr->isPerm==0 ){ + KVFactory *pNext = pMkr->pNext; + sqlite4_free(pEnv, pMkr); + pMkr = pNext; + } + sqlite4MutexEnd(pEnv); + sqlite4MallocEnd(pEnv); + pEnv->isInit = 0; + } + return SQLITE4_OK; +} + +/* +** Return the size of an sqlite4_env object +*/ +int sqlite4_env_size(void){ return sizeof(sqlite4_env); } + +/* +** This API allows applications to modify the configuration described by +** an sqlite4_env object. +*/ +int sqlite4_env_config(sqlite4_env *pEnv, int op, ...){ + va_list ap; + int rc = SQLITE4_OK; + + if( pEnv==0 ) pEnv = sqlite4_env_default(); + + va_start(ap, op); + switch( op ){ + /* + ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_INIT, template); + ** + ** Turn bulk memory into a new sqlite4_env object. The template is + ** a prior sqlite4_env that is used as a template in initializing the + ** new sqlite4_env object. The size of the bulk memory must be at + ** least as many bytes as returned from sqlite4_env_size(). + */ + case SQLITE4_ENVCONFIG_INIT: { + /* Disable all mutexing */ + sqlite4_env *pTemplate = va_arg(ap, sqlite4_env*); + int n = pTemplate->nByte; + if( n>sizeof(sqlite4_env) ) n = sizeof(sqlite4_env); + memcpy(pEnv, pTemplate, n); + pEnv->pFactory = &sqlite4BuiltinFactory; + pEnv->isInit = 0; + break; + } + + /* Mutex configuration options are only available in a threadsafe + ** compile. + */ +#if defined(SQLITE4_THREADSAFE) && SQLITE4_THREADSAFE>0 + /* + ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_SINGLETHREAD); + ** + ** Configure this environment for a single-threaded application. + */ + case SQLITE4_ENVCONFIG_SINGLETHREAD: { + /* Disable all mutexing */ + if( pEnv->isInit ){ rc = SQLITE4_MISUSE; break; } + pEnv->bCoreMutex = 0; + pEnv->bFullMutex = 0; + break; + } + + /* + ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_MULTITHREAD); + ** + ** Configure this environment for a multi-threaded application where + ** the same database connection is never used by more than a single + ** thread at a time. + */ + case SQLITE4_ENVCONFIG_MULTITHREAD: { + /* Disable mutexing of database connections */ + /* Enable mutexing of core data structures */ + if( pEnv->isInit ){ rc = SQLITE4_MISUSE; break; } + pEnv->bCoreMutex = 1; + pEnv->bFullMutex = 0; + break; + } + + /* + ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_SERIALIZED); + ** + ** Configure this environment for an unrestricted multi-threaded + ** application where any thread can do whatever it wants with any + ** database connection at any time. + */ + case SQLITE4_ENVCONFIG_SERIALIZED: { + /* Enable all mutexing */ + if( pEnv->isInit ){ rc = SQLITE4_MISUSE; break; } + pEnv->bCoreMutex = 1; + pEnv->bFullMutex = 1; + break; + } + + /* + ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_MUTEXT, sqlite4_mutex_methods*) + ** + ** Configure this environment to use the mutex routines specified by the + ** argument. + */ + case SQLITE4_ENVCONFIG_MUTEX: { + /* Specify an alternative mutex implementation */ + if( pEnv->isInit ){ rc = SQLITE4_MISUSE; break; } + pEnv->mutex = *va_arg(ap, sqlite4_mutex_methods*); + break; + } + + /* + ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_GETMUTEX, sqlite4_mutex_methods*) + ** + ** Copy the mutex routines in use by this environment into the structure + ** given in the argument. + */ + case SQLITE4_ENVCONFIG_GETMUTEX: { + /* Retrieve the current mutex implementation */ + *va_arg(ap, sqlite4_mutex_methods*) = pEnv->mutex; + break; + } +#endif + + + /* + ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_MALLOC, sqlite4_mem_methods*) + ** + ** Set the memory allocation routines to be used by this environment. + */ + case SQLITE4_ENVCONFIG_MALLOC: { + /* Specify an alternative malloc implementation */ + if( pEnv->isInit ) return SQLITE4_MISUSE; + pEnv->m = *va_arg(ap, sqlite4_mem_methods*); + break; + } + + /* + ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_GETMALLOC, sqlite4_mem_methods*) + ** + ** Copy the memory allocation routines in use by this environment + ** into the structure given in the argument. + */ + case SQLITE4_ENVCONFIG_GETMALLOC: { + /* Retrieve the current malloc() implementation */ + if( pEnv->m.xMalloc==0 ) sqlite4MemSetDefault(pEnv); + *va_arg(ap, sqlite4_mem_methods*) = pEnv->m; + break; + } + + /* sqlite4_env_config(p, SQLITE4_ENVCONFIG_MEMSTAT, int onoff); + ** + ** Enable or disable collection of memory usage statistics according to + ** the onoff parameter. + */ + case SQLITE4_ENVCONFIG_MEMSTATUS: { + /* Enable or disable the malloc status collection */ + pEnv->bMemstat = va_arg(ap, int); + break; + } + + /* + ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_LOOKASIDE, size, count); + ** + ** Set the default lookaside memory settings for all subsequent + ** database connections constructed in this environment. The size + ** parameter is the size of each lookaside memory buffer and the + ** count parameter is the number of lookaside buffers. Set both + ** to zero to disable lookaside memory. + */ + case SQLITE4_ENVCONFIG_LOOKASIDE: { + pEnv->szLookaside = va_arg(ap, int); + pEnv->nLookaside = va_arg(ap, int); + break; + } + + /* + ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_LOG, xOutput, pArg); + ** + ** Set the log function that is called in response to sqlite4_log() + ** calls. + */ + case SQLITE4_ENVCONFIG_LOG: { + /* MSVC is picky about pulling func ptrs from va lists. + ** http://support.microsoft.com/kb/47961 + ** pEnv->xLog = va_arg(ap, void(*)(void*,int,const char*)); + */ + typedef void(*LOGFUNC_t)(void*,int,const char*); + pEnv->xLog = va_arg(ap, LOGFUNC_t); + pEnv->pLogArg = va_arg(ap, void*); + break; + } + + /* + ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_KVSTORE_PUSH, zName,xFactory); + ** + ** Push a new KVStore factory onto the factory stack. The new factory + ** takes priority over prior factories. + */ + case SQLITE4_ENVCONFIG_KVSTORE_PUSH: { + const char *zName = va_arg(ap, const char*); + int nName = sqlite4Strlen30(zName); + KVFactory *pMkr = sqlite4_malloc(pEnv, sizeof(*pMkr)+nName+1); + char *z; + if( pMkr==0 ) return SQLITE4_NOMEM; + z = (char*)&pMkr[1]; + memcpy(z, zName, nName+1); + memset(pMkr, 0, sizeof(*pMkr)); + pMkr->zName = z; + pMkr->xFactory = va_arg(ap, sqlite4_kvfactory); + sqlite4_mutex_enter(pEnv->pFactoryMutex); + pMkr->pNext = pEnv->pFactory; + pEnv->pFactory = pMkr; + sqlite4_mutex_leave(pEnv->pFactoryMutex); + break; + } + + /* + ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_KVSTORE_POP, zName, &pxFact); + ** + ** Remove a KVStore factory from the stack. + */ + /* + ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_KVSTORE_GET, zName, &pxFact); + ** + ** Get the current factory pointer with the given name but leave the + ** factory on the stack. + */ + case SQLITE4_ENVCONFIG_KVSTORE_POP: + case SQLITE4_ENVCONFIG_KVSTORE_GET: { + typedef int (**PxFact)(sqlite4_env*,KVStore**,const char*,unsigned); + const char *zName = va_arg(ap, const char*); + KVFactory *pMkr, **ppPrev; + PxFact pxFact; + + pxFact = va_arg(ap,PxFact); + *pxFact = 0; + sqlite4_mutex_enter(pEnv->pFactoryMutex); + ppPrev = &pEnv->pFactory; + pMkr = *ppPrev; + while( pMkr && strcmp(zName, pMkr->zName)!=0 ){ + ppPrev = &pMkr->pNext; + pMkr = *ppPrev; + } + if( pMkr ){ + *pxFact = pMkr->xFactory; + if( op==SQLITE4_ENVCONFIG_KVSTORE_POP && pMkr->isPerm==0 ){ + *ppPrev = pMkr->pNext; + sqlite4_free(pEnv, pMkr); + } + } + sqlite4_mutex_leave(pEnv->pFactoryMutex); + break; + } + + + default: { + rc = SQLITE4_ERROR; + break; + } + } + va_end(ap); + return rc; +} + + +/* +** Default factory objects +*/ +static KVFactory memFactory = { + 0, + "temp", + sqlite4KVStoreOpenMem, + 1 +}; +KVFactory sqlite4BuiltinFactory = { + &memFactory, + "main", + sqlite4KVStoreOpenLsm, + 1 +}; + +/* +** The following singleton contains the global configuration for +** the SQLite library. +*/ +struct sqlite4_env sqlite4DefaultEnv = { + sizeof(sqlite4_env), /* nByte */ + 1, /* iVersion */ + SQLITE4_DEFAULT_MEMSTATUS, /* bMemstat */ + 1, /* bCoreMutex */ + SQLITE4_THREADSAFE==1, /* bFullMutex */ + 0x7ffffffe, /* mxStrlen */ + 128, /* szLookaside */ + 500, /* nLookaside */ + &sqlite4MMSystem, /* pMM */ + {0,0,0,0,0,0,0,0,0}, /* m */ + {0,0,0,0,0,0,0,0,0,0}, /* mutex */ + (void*)0, /* pHeap */ + 0, /* nHeap */ + 0, 0, /* mnHeap, mxHeap */ + 0, /* mxParserStack */ + &sqlite4BuiltinFactory, /* pFactory */ + sqlite4OsRandomness, /* xRandomness */ + sqlite4OsCurrentTime, /* xCurrentTime */ + /* All the rest should always be initialized to zero */ + 0, /* isInit */ + 0, /* pFactoryMutex */ + 0, /* pPrngMutex */ + 0, 0, /* prngX, prngY */ + 0, /* xLog */ + 0, /* pLogArg */ + 0, /* bLocaltimeFault */ + 0, /* pMemMutex */ + {0,0,0,0}, /* nowValue[] */ + {0,0,0,0}, /* mxValue[] */ + {0,} /* hashGlobalFunc */ +}; + +/* +** Return the default environment +*/ +sqlite4_env *sqlite4_env_default(void){ return &sqlite4DefaultEnv; } Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -1267,19 +1267,10 @@ CountCtx *p; p = sqlite4_aggregate_context(context, sizeof(*p)); if( (argc==0 || SQLITE4_NULL!=sqlite4_value_type(argv[0])) && p ){ p->n++; } - -#ifndef SQLITE4_OMIT_DEPRECATED - /* The sqlite4_aggregate_count() function is deprecated. But just to make - ** sure it still operates correctly, verify that its count agrees with our - ** internal count when using count(*) and when the total count can be - ** expressed as a 32-bit integer. */ - assert( argc==1 || p==0 || p->n>0x7fffffff - || p->n==sqlite4_aggregate_count(context) ); -#endif } static void countFinalize(sqlite4_context *context){ CountCtx *p; p = sqlite4_aggregate_context(context, 0); sqlite4_result_int64(context, p ? p->n : 0); Index: src/global.c ================================================================== --- src/global.c +++ src/global.c @@ -127,67 +127,10 @@ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */ }; #endif -/* -** Default factory objects -*/ -static KVFactory memFactory = { - 0, - "temp", - sqlite4KVStoreOpenMem, - 1 -}; -KVFactory sqlite4BuiltinFactory = { - &memFactory, - "main", - sqlite4KVStoreOpenLsm, - 1 -}; - -/* -** The following singleton contains the global configuration for -** the SQLite library. -*/ -struct sqlite4_env sqlite4DefaultEnv = { - sizeof(sqlite4_env), /* nByte */ - 1, /* iVersion */ - SQLITE4_DEFAULT_MEMSTATUS, /* bMemstat */ - 1, /* bCoreMutex */ - SQLITE4_THREADSAFE==1, /* bFullMutex */ - 0x7ffffffe, /* mxStrlen */ - 128, /* szLookaside */ - 500, /* nLookaside */ - {0,0,0,0,0,0,0,0,0}, /* m */ - {0,0,0,0,0,0,0,0,0,0}, /* mutex */ - (void*)0, /* pHeap */ - 0, /* nHeap */ - 0, 0, /* mnHeap, mxHeap */ - 0, /* mxParserStack */ - &sqlite4BuiltinFactory, /* pFactory */ - sqlite4OsRandomness, /* xRandomness */ - sqlite4OsCurrentTime, /* xCurrentTime */ - /* All the rest should always be initialized to zero */ - 0, /* isInit */ - 0, /* pFactoryMutex */ - 0, /* pPrngMutex */ - 0, 0, /* prngX, prngY */ - 0, /* xLog */ - 0, /* pLogArg */ - 0, /* bLocaltimeFault */ - 0, /* pMemMutex */ - {0,0,0,0}, /* nowValue[] */ - {0,0,0,0}, /* mxValue[] */ - {0,} /* hashGlobalFunc */ -}; - -/* -** Return the default environment -*/ -sqlite4_env *sqlite4_env_default(void){ return &sqlite4DefaultEnv; } - /* ** Constant tokens for values 0 and 1. */ const Token sqlite4IntTokens[] = { Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -62,378 +62,10 @@ ** are intended for debugging activity only. */ void (*sqlite4IoTrace)(const char*, ...) = 0; #endif -/* -** Initialize SQLite. -** -** This routine must be called to initialize the run-time environment -** As long as you do not compile with SQLITE4_OMIT_AUTOINIT -** this routine will be called automatically by key routines such as -** sqlite4_open(). -** -** This routine is a no-op except on its very first call for a given -** sqlite4_env object, or for the first call after a call to sqlite4_shutdown. -** -** This routine is not threadsafe. It should be called from a single -** thread to initialized the library in a multi-threaded system. Other -** threads should avoid using the sqlite4_env object until after it has -** completely initialized. -*/ -int sqlite4_initialize(sqlite4_env *pEnv){ - MUTEX_LOGIC( sqlite4_mutex *pMaster; ) /* The main static mutex */ - int rc; /* Result code */ - - if( pEnv==0 ) pEnv = &sqlite4DefaultEnv; - - /* If SQLite is already completely initialized, then this call - ** to sqlite4_initialize() should be a no-op. But the initialization - ** must be complete. So isInit must not be set until the very end - ** of this routine. - */ - if( pEnv->isInit ) return SQLITE4_OK; - - /* Initialize the mutex subsystem - */ - rc = sqlite4MutexInit(pEnv); - if( rc ){ - sqlite4MallocEnd(pEnv); - return rc; - } - - /* Initialize the memory allocation subsystem - */ - rc = sqlite4MallocInit(pEnv); - if( rc ) return rc; - - /* Create required mutexes - */ - if( pEnv->bCoreMutex ){ - pEnv->pMemMutex = sqlite4MutexAlloc(pEnv, SQLITE4_MUTEX_FAST); - pEnv->pPrngMutex = sqlite4MutexAlloc(pEnv, SQLITE4_MUTEX_FAST); - pEnv->pFactoryMutex = sqlite4MutexAlloc(pEnv, SQLITE4_MUTEX_FAST); - if( pEnv->pMemMutex==0 - || pEnv->pPrngMutex==0 - || pEnv->pFactoryMutex==0 - ){ - rc = SQLITE4_NOMEM; - } - }else{ - pEnv->pMemMutex = 0; - pEnv->pPrngMutex = 0; - } - pEnv->isInit = 1; - - sqlite4OsInit(pEnv); - - /* Register global functions */ - if( rc==SQLITE4_OK ){ - sqlite4RegisterGlobalFunctions(pEnv); - } - - /* The following is just a sanity check to make sure SQLite has - ** been compiled correctly. It is important to run this code, but - ** we don't want to run it too often and soak up CPU cycles for no - ** reason. So we run it once during initialization. - */ -#ifndef NDEBUG -#ifndef SQLITE4_OMIT_FLOATING_POINT - /* This section of code's only "output" is via assert() statements. */ - if ( rc==SQLITE4_OK ){ - u64 x = (((u64)1)<<63)-1; - double y; - assert(sizeof(x)==8); - assert(sizeof(x)==sizeof(y)); - memcpy(&y, &x, 8); - assert( sqlite4IsNaN(y) ); - } -#endif -#endif - - return rc; -} - -/* -** Undo the effects of sqlite4_initialize(). Must not be called while -** there are outstanding database connections or memory allocations or -** while any part of SQLite is otherwise in use in any thread. This -** routine is not threadsafe. But it is safe to invoke this routine -** on when SQLite is already shut down. If SQLite is already shut down -** when this routine is invoked, then this routine is a harmless no-op. -*/ -int sqlite4_shutdown(sqlite4_env *pEnv){ - if( pEnv==0 ) pEnv = &sqlite4DefaultEnv; - if( pEnv->isInit ){ - KVFactory *pMkr; - sqlite4_mutex_free(pEnv->pFactoryMutex); - sqlite4_mutex_free(pEnv->pPrngMutex); - sqlite4_mutex_free(pEnv->pMemMutex); - pEnv->pMemMutex = 0; - while( (pMkr = pEnv->pFactory)!=0 && pMkr->isPerm==0 ){ - KVFactory *pNext = pMkr->pNext; - sqlite4_free(pEnv, pMkr); - pMkr = pNext; - } - sqlite4MutexEnd(pEnv); - sqlite4MallocEnd(pEnv); - pEnv->isInit = 0; - } - return SQLITE4_OK; -} - -/* -** Return the size of an sqlite4_env object -*/ -int sqlite4_env_size(void){ return sizeof(sqlite4_env); } - -/* -** This API allows applications to modify the configuration described by -** an sqlite4_env object. -*/ -int sqlite4_env_config(sqlite4_env *pEnv, int op, ...){ - va_list ap; - int rc = SQLITE4_OK; - - if( pEnv==0 ) pEnv = sqlite4_env_default(); - - va_start(ap, op); - switch( op ){ - /* - ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_INIT, template); - ** - ** Turn bulk memory into a new sqlite4_env object. The template is - ** a prior sqlite4_env that is used as a template in initializing the - ** new sqlite4_env object. The size of the bulk memory must be at - ** least as many bytes as returned from sqlite4_env_size(). - */ - case SQLITE4_ENVCONFIG_INIT: { - /* Disable all mutexing */ - sqlite4_env *pTemplate = va_arg(ap, sqlite4_env*); - int n = pTemplate->nByte; - if( n>sizeof(sqlite4_env) ) n = sizeof(sqlite4_env); - memcpy(pEnv, pTemplate, n); - pEnv->pFactory = &sqlite4BuiltinFactory; - pEnv->isInit = 0; - break; - } - - /* Mutex configuration options are only available in a threadsafe - ** compile. - */ -#if defined(SQLITE4_THREADSAFE) && SQLITE4_THREADSAFE>0 - /* - ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_SINGLETHREAD); - ** - ** Configure this environment for a single-threaded application. - */ - case SQLITE4_ENVCONFIG_SINGLETHREAD: { - /* Disable all mutexing */ - if( pEnv->isInit ){ rc = SQLITE4_MISUSE; break; } - pEnv->bCoreMutex = 0; - pEnv->bFullMutex = 0; - break; - } - - /* - ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_MULTITHREAD); - ** - ** Configure this environment for a multi-threaded application where - ** the same database connection is never used by more than a single - ** thread at a time. - */ - case SQLITE4_ENVCONFIG_MULTITHREAD: { - /* Disable mutexing of database connections */ - /* Enable mutexing of core data structures */ - if( pEnv->isInit ){ rc = SQLITE4_MISUSE; break; } - pEnv->bCoreMutex = 1; - pEnv->bFullMutex = 0; - break; - } - - /* - ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_MULTITHREAD); - ** - ** Configure this environment for an unrestricted multi-threaded - ** application where any thread can do whatever it wants with any - ** database connection at any time. - */ - case SQLITE4_ENVCONFIG_SERIALIZED: { - /* Enable all mutexing */ - if( pEnv->isInit ){ rc = SQLITE4_MISUSE; break; } - pEnv->bCoreMutex = 1; - pEnv->bFullMutex = 1; - break; - } - - /* - ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_MUTEXT, sqlite4_mutex_methods*) - ** - ** Configure this environment to use the mutex routines specified by the - ** argument. - */ - case SQLITE4_ENVCONFIG_MUTEX: { - /* Specify an alternative mutex implementation */ - if( pEnv->isInit ){ rc = SQLITE4_MISUSE; break; } - pEnv->mutex = *va_arg(ap, sqlite4_mutex_methods*); - break; - } - - /* - ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_GETMUTEX, sqlite4_mutex_methods*) - ** - ** Copy the mutex routines in use by this environment into the structure - ** given in the argument. - */ - case SQLITE4_ENVCONFIG_GETMUTEX: { - /* Retrieve the current mutex implementation */ - *va_arg(ap, sqlite4_mutex_methods*) = pEnv->mutex; - break; - } -#endif - - - /* - ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_MALLOC, sqlite4_mem_methods*) - ** - ** Set the memory allocation routines to be used by this environment. - */ - case SQLITE4_ENVCONFIG_MALLOC: { - /* Specify an alternative malloc implementation */ - if( pEnv->isInit ) return SQLITE4_MISUSE; - pEnv->m = *va_arg(ap, sqlite4_mem_methods*); - break; - } - - /* - ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_GETMALLOC, sqlite4_mem_methods*) - ** - ** Copy the memory allocation routines in use by this environment - ** into the structure given in the argument. - */ - case SQLITE4_ENVCONFIG_GETMALLOC: { - /* Retrieve the current malloc() implementation */ - if( pEnv->m.xMalloc==0 ) sqlite4MemSetDefault(pEnv); - *va_arg(ap, sqlite4_mem_methods*) = pEnv->m; - break; - } - - /* sqlite4_env_config(p, SQLITE4_ENVCONFIG_MEMSTAT, int onoff); - ** - ** Enable or disable collection of memory usage statistics according to - ** the onoff parameter. - */ - case SQLITE4_ENVCONFIG_MEMSTATUS: { - /* Enable or disable the malloc status collection */ - pEnv->bMemstat = va_arg(ap, int); - break; - } - - /* - ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_LOOKASIDE, size, count); - ** - ** Set the default lookaside memory settings for all subsequent - ** database connections constructed in this environment. The size - ** parameter is the size of each lookaside memory buffer and the - ** count parameter is the number of lookaside buffers. Set both - ** to zero to disable lookaside memory. - */ - case SQLITE4_ENVCONFIG_LOOKASIDE: { - pEnv->szLookaside = va_arg(ap, int); - pEnv->nLookaside = va_arg(ap, int); - break; - } - - /* - ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_LOG, xOutput, pArg); - ** - ** Set the log function that is called in response to sqlite4_log() - ** calls. - */ - case SQLITE4_ENVCONFIG_LOG: { - /* MSVC is picky about pulling func ptrs from va lists. - ** http://support.microsoft.com/kb/47961 - ** pEnv->xLog = va_arg(ap, void(*)(void*,int,const char*)); - */ - typedef void(*LOGFUNC_t)(void*,int,const char*); - pEnv->xLog = va_arg(ap, LOGFUNC_t); - pEnv->pLogArg = va_arg(ap, void*); - break; - } - - /* - ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_KVSTORE_PUSH, zName,xFactory); - ** - ** Push a new KVStore factory onto the factory stack. The new factory - ** takes priority over prior factories. - */ - case SQLITE4_ENVCONFIG_KVSTORE_PUSH: { - const char *zName = va_arg(ap, const char*); - int nName = sqlite4Strlen30(zName); - KVFactory *pMkr = sqlite4_malloc(pEnv, sizeof(*pMkr)+nName+1); - char *z; - if( pMkr==0 ) return SQLITE4_NOMEM; - z = (char*)&pMkr[1]; - memcpy(z, zName, nName+1); - memset(pMkr, 0, sizeof(*pMkr)); - pMkr->zName = z; - pMkr->xFactory = va_arg(ap, sqlite4_kvfactory); - sqlite4_mutex_enter(pEnv->pFactoryMutex); - pMkr->pNext = pEnv->pFactory; - pEnv->pFactory = pMkr; - sqlite4_mutex_leave(pEnv->pFactoryMutex); - break; - } - - /* - ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_KVSTORE_POP, zName, &pxFact); - ** - ** Remove a KVStore factory from the stack. - */ - /* - ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_KVSTORE_GET, zName, &pxFact); - ** - ** Get the current factory pointer with the given name but leave the - ** factory on the stack. - */ - case SQLITE4_ENVCONFIG_KVSTORE_POP: - case SQLITE4_ENVCONFIG_KVSTORE_GET: { - typedef int (**PxFact)(sqlite4_env*,KVStore**,const char*,unsigned); - const char *zName = va_arg(ap, const char*); - KVFactory *pMkr, **ppPrev; - PxFact pxFact; - - pxFact = va_arg(ap,PxFact); - *pxFact = 0; - sqlite4_mutex_enter(pEnv->pFactoryMutex); - ppPrev = &pEnv->pFactory; - pMkr = *ppPrev; - while( pMkr && strcmp(zName, pMkr->zName)!=0 ){ - ppPrev = &pMkr->pNext; - pMkr = *ppPrev; - } - if( pMkr ){ - *pxFact = pMkr->xFactory; - if( op==SQLITE4_ENVCONFIG_KVSTORE_POP && pMkr->isPerm==0 ){ - *ppPrev = pMkr->pNext; - sqlite4_free(pEnv, pMkr); - } - } - sqlite4_mutex_leave(pEnv->pFactoryMutex); - break; - } - - - default: { - rc = SQLITE4_ERROR; - break; - } - } - va_end(ap); - return rc; -} - /* ** Set up the lookaside buffers for a database connection. ** Return SQLITE4_OK on success. ** If lookaside is already active, return SQLITE4_BUSY. ** @@ -1917,27 +1549,15 @@ sqlite4_mutex_leave(db->mutex); return SQLITE4_OK; } #endif /* SQLITE4_OMIT_UTF16 */ -#ifndef SQLITE4_OMIT_DEPRECATED -/* -** This function is now an anachronism. It used to be used to recover from a -** malloc() failure, but SQLite now does this automatically. -*/ -int sqlite4_global_recover(void){ - return SQLITE4_OK; -} -#endif - /* ** Test to see whether or not the database connection is in autocommit ** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on ** by default. Autocommit is disabled by a BEGIN statement and reenabled ** by the next COMMIT or ROLLBACK. -** -******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** */ int sqlite4_get_autocommit(sqlite4 *db){ return (db->pSavepoint==0); } Index: src/mem.c ================================================================== --- src/mem.c +++ src/mem.c @@ -12,11 +12,10 @@ ** ** This file contains the implementation of the "sqlite4_mm" memory ** allocator object. */ #include "sqlite4.h" -#include "mem.h" #include /************************************************************************* ** The SQLITE4_MM_SYSTEM memory allocator. This allocator uses the ** malloc/realloc/free from the system library. It also tries to use @@ -98,33 +97,33 @@ #endif /* __APPLE__ or not __APPLE__ */ /* ** Implementations of core routines */ -static void *mmSysMalloc(sqlite4_mm *pMM, sqlite4_int64 iSize){ +static void *mmSysMalloc(sqlite4_mm *pMM, sqlite4_size_t iSize){ #ifdef SQLITE4_MALLOCSIZE return SQLITE4_MALLOC(iSize); #else unsigned char *pRes = SQLITE4_MALLOC(iSize+8); if( pRes ){ - *(sqlite4_int64*)pRes = iSize; + *(sqlite4_size_t*)pRes = iSize; pRes += 8; } return pRes; #endif } -static void *mmSysRealloc(sqlite4_mm *pMM, void *pOld, sqlite4_int64 iSz){ +static void *mmSysRealloc(sqlite4_mm *pMM, void *pOld, sqlite4_size_t iSz){ #ifdef SQLITE4_MALLOCSIZE return SQLITE4_REALLOC(pOld, iSz); #else unsigned char *pRes; if( pOld==0 ) return mmSysMalloc(pMM, iSz); pRes = (unsigned char*)pOld; pRes -= 8; pRes = SQLITE4_REALLOC(pRes, iSz+8); if( pRes ){ - *(sqlite4_int64*)pRes = iSz; + *(sqlite4_size_t*)pRes = iSz; pRes += 8; } return pRes; #endif } @@ -137,19 +136,19 @@ pRes = (unsigned char *)pOld; pRes -= 8; SQLITE4_FREE(pRes); #endif } -static sqlite4_int64 mmSysMsize(sqlite4_mm *pNotUsed, void *pOld){ +static sqlite4_size_t mmSysMsize(sqlite4_mm *pNotUsed, void *pOld){ #ifdef SQLITE4_MALLOCSIZE return SQLITE4_MALLOCSIZE(pOld); #else unsigned char *pX; if( pOld==0 ) return 0; pX = (unsigned char *)pOld; pX -= 8; - return *(sqlite4_int64*)pX; + return *(sqlite4_size_t*)pX; #endif } static const sqlite4_mm_methods mmSysMethods = { /* iVersion */ 1, @@ -157,16 +156,20 @@ /* xRealloc */ mmSysRealloc, /* xFree */ mmSysFree, /* xMsize */ mmSysMsize, /* xMember */ 0, /* xBenign */ 0, + /* xStat */ 0, /* xFinal */ 0 }; -static sqlite4_mm mmSystem = { +sqlite4_mm sqlite4MMSystem = { /* pMethods */ &mmSysMethods }; +/* The system memory allocator is the default. */ +sqlite4_mm *sqlite4_mm_default(void){ return &sqlite4MMSystem; } + /************************************************************************* ** The SQLITE4_MM_OVERFLOW memory allocator. ** ** This memory allocator has two child memory allocators, A and B. Always ** try to fulfill the request using A first, then overflow to B if the request @@ -177,20 +180,20 @@ int (*xMemberOfA)(sqlite4_mm*, const void*); sqlite4_mm *pA; /* Primary memory allocator */ sqlite4_mm *pB; /* Backup memory allocator in case pA fails */ }; -static void *mmOvflMalloc(sqlite4_mm *pMM, sqlite4_int64 iSz){ +static void *mmOvflMalloc(sqlite4_mm *pMM, sqlite4_size_t iSz){ const struct mmOvfl *pOvfl = (const struct mmOvfl*)pMM; void *pRes; pRes = pOvfl->pA->pMethods->xMalloc(pOvfl->pA, iSz); if( pRes==0 ){ pRes = pOvfl->pB->pMethods->xMalloc(pOvfl->pB, iSz); } return pRes; } -static void *mmOvflRealloc(sqlite4_mm *pMM, void *pOld, sqlite4_int64 iSz){ +static void *mmOvflRealloc(sqlite4_mm *pMM, void *pOld, sqlite4_size_t iSz){ const struct mmOvfl *pOvfl; void *pRes; if( pOld==0 ) return mmOvflMalloc(pMM, iSz); pOvfl = (const struct mmOvfl*)pMM; if( pOvfl->xMemberOfA(pOvfl->pA, pOld) ){ @@ -208,13 +211,13 @@ pOvfl->pA->pMethods->xFree(pOvfl->pA, pOld); }else{ pOvfl->pB->pMethods->xFree(pOvfl->pB, pOld); } } -static sqlite4_int64 mmOvflMsize(sqlite4_mm *pMM, void *pOld){ +static sqlite4_size_t mmOvflMsize(sqlite4_mm *pMM, void *pOld){ const struct mmOvfl *pOvfl; - sqlite4_int64 iSz; + sqlite4_size_t iSz; if( pOld==0 ) return 0; pOvfl = (const struct mmOvfl*)pMM; if( pOvfl->xMemberOfA(pOvfl->pA, pOld) ){ iSz = sqlite4_mm_msize(pOvfl->pA, pOld); }else{ @@ -253,10 +256,11 @@ /* xRealloc */ mmOvflRealloc, /* xFree */ mmOvflFree, /* xMsize */ mmOvflMsize, /* xMember */ mmOvflMember, /* xBenign */ mmOvflBenign, + /* xStat */ 0, /* xFinal */ mmOvflFinal }; static sqlite4_mm *mmOvflNew(sqlite4_mm *pA, sqlite4_mm *pB){ struct mmOvfl *pOvfl; if( pA->pMethods->xMember==0 ) return 0; @@ -295,11 +299,11 @@ /* A free block in the buffer */ struct mmOneszBlock { struct mmOneszBlock *pNext; /* Next on the freelist */ }; -static void *mmOneszMalloc(sqlite4_mm *pMM, sqlite4_int64 iSz){ +static void *mmOneszMalloc(sqlite4_mm *pMM, sqlite4_size_t iSz){ struct mmOnesz *pOnesz = (struct mmOnesz*)pMM; void *pRes; if( iSz>pOnesz->sz ) return 0; if( pOnesz->pFree==0 ) return 0; pRes = pOnesz->pFree; @@ -312,21 +316,21 @@ struct mmOneszBlock *pBlock = (struct mmOneszBlock*)pOld; pBlock->pNext = pOnesz->pFree; pOnesz->pFree = pBlock; } } -static void *mmOneszRealloc(sqlite4_mm *pMM, void *pOld, sqlite4_int64 iSz){ +static void *mmOneszRealloc(sqlite4_mm *pMM, void *pOld, sqlite4_size_t iSz){ struct mmOnesz *pOnesz = (struct mmOnesz*)pMM; if( pOld==0 ) return mmOneszMalloc(pMM, iSz); if( iSz<=0 ){ mmOneszFree(pMM, pOld); return 0; } if( iSz>pOnesz->sz ) return 0; return pOld; } -static sqlite4_int64 mmOneszMsize(sqlite4_mm *pMM, void *pOld){ +static sqlite4_size_t mmOneszMsize(sqlite4_mm *pMM, void *pOld){ struct mmOnesz *pOnesz = (struct mmOnesz*)pMM; return pOld ? pOnesz->sz : 0; } static int mmOneszMember(sqlite4_mm *pMM, const void *pOld){ struct mmOnesz *pOnesz = (struct mmOnesz*)pMM; @@ -338,10 +342,11 @@ /* xRealloc */ mmOneszRealloc, /* xFree */ mmOneszFree, /* xMsize */ mmOneszMsize, /* xMember */ mmOneszMember, /* xBenign */ 0, + /* xStat */ 0, /* xFinal */ 0 }; static sqlite4_mm *mmOneszNew(void *pSpace, int sz, int cnt){ struct mmOnesz *pOnesz; unsigned char *pMem; @@ -366,34 +371,39 @@ } /************************************************************************* ** Main interfaces. */ -void *sqlite4_mm_malloc(sqlite4_mm *pMM, sqlite4_int64 iSize){ - if( pMM==0 ) pMM = &mmSystem; +void *sqlite4_mm_malloc(sqlite4_mm *pMM, sqlite4_size_t iSize){ + if( pMM==0 ) pMM = &sqlite4MMSystem; return pMM->pMethods->xMalloc(pMM,iSize); } -void *sqlite4_mm_realloc(sqlite4_mm *pMM, void *pOld, sqlite4_int64 iSize){ - if( pMM==0 ) pMM = &mmSystem; +void *sqlite4_mm_realloc(sqlite4_mm *pMM, void *pOld, sqlite4_size_t iSize){ + if( pMM==0 ) pMM = &sqlite4MMSystem; return pMM->pMethods->xRealloc(pMM,pOld,iSize); } void sqlite4_mm_free(sqlite4_mm *pMM, void *pOld){ - if( pMM==0 ) pMM = &mmSystem; + if( pMM==0 ) pMM = &sqlite4MMSystem; pMM->pMethods->xFree(pMM,pOld); } -sqlite4_int64 sqlite4_mm_msize(sqlite4_mm *pMM, void *pOld){ - if( pMM==0 ) pMM = &mmSystem; +sqlite4_size_t sqlite4_mm_msize(sqlite4_mm *pMM, void *pOld){ + if( pMM==0 ) pMM = &sqlite4MMSystem; return pMM->pMethods->xMsize(pMM,pOld); } int sqlite4_mm_member(sqlite4_mm *pMM, const void *pOld){ return (pMM && pMM->pMethods->xMember!=0) ? pMM->pMethods->xMember(pMM,pOld) : -1; } -void sqlite4_mm_benign_failure(sqlite4_mm *pMM, int bEnable){ +void sqlite4_mm_benign_failures(sqlite4_mm *pMM, int bEnable){ if( pMM && pMM->pMethods->xBenign ){ pMM->pMethods->xBenign(pMM, bEnable); } +} +sqlite4_int64 sqlite4_mm_stat(sqlite4_mm *pMM, int eStatType, unsigned flags){ + if( pMM==0 ) return -1; + if( pMM->pMethods->xStat==0 ) return -1; + return pMM->pMethods->xStat(pMM, eStatType, flags); } void sqlite4_mm_destroy(sqlite4_mm *pMM){ if( pMM && pMM->pMethods->xFinal ) pMM->pMethods->xFinal(pMM); } @@ -406,11 +416,11 @@ sqlite4_mm *pMM; va_start(ap, eType); switch( eType ){ case SQLITE4_MM_SYSTEM: { - pMM = &mmSystem; + pMM = &sqlite4MMSystem; break; } case SQLITE4_MM_OVERFLOW: { sqlite4_mm *pA = va_arg(ap, sqlite4_mm*); sqlite4_mm *pB = va_arg(ap, sqlite4_mm*); Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -47,10 +47,146 @@ # undef SQLITE4_VERSION #endif #ifdef SQLITE4_VERSION_NUMBER # undef SQLITE4_VERSION_NUMBER #endif + +/* +** CAPIREF: 64-Bit Integer Types +** KEYWORDS: sqlite4_int64 sqlite4_uint64 +** +** Because there is no cross-platform way to specify 64-bit integer types +** SQLite includes typedefs for 64-bit signed and unsigned integers. +** +** ^The sqlite4_int64 and sqlite_int64 types can store integer values +** between -9223372036854775808 and +9223372036854775807 inclusive. ^The +** sqlite4_uint64 and sqlite_uint64 types can store integer values +** between 0 and +18446744073709551615 inclusive. +*/ +#ifdef SQLITE4_INT64_TYPE + typedef SQLITE4_INT64_TYPE sqlite4_int64_t; + typedef unsigned SQLITE4_INT64_TYPE sqlite4_uint64_t; +#elif defined(_MSC_VER) || defined(__BORLANDC__) + typedef __int64 sqlite4_int64_t; + typedef unsigned __int64 sqlite4_uint64_t; +#else + typedef long long int sqlite4_int64_t; + typedef unsigned long long int sqlite4_uint64_t; +#endif +typedef sqlite4_int64_t sqlite4_int64; +typedef sqlite4_uint64_t sqlite4_uint64; + +/* +** CAPIREF: String length type +** +** A type for measuring the length of the string. Like size_t but +** does not require <stddef.h> +*/ +typedef int sqlite4_size_t; + +/* +** Available memory allocator object subtypes: +*/ +typedef enum { + SQLITE4_MM_SYSTEM = 1, /* Use the system malloc() */ + SQLITE4_MM_ONESIZE = 2, /* All allocations map to a fixed size */ + SQLITE4_MM_OVERFLOW = 3, /* Two allocators. Use A first; failover to B */ + SQLITE4_MM_COMPACT = 4, /* Like memsys3 from SQLite3 */ + SQLITE4_MM_ROBSON = 5, /* Like memsys5 from SQLite3 */ + SQLITE4_MM_LINEAR = 6, /* Allocate from a fixed buffer w/o free */ + SQLITE4_MM_BESPOKE = 7, /* Caller-defined implementation */ + SQLITE4_MM_DEBUG, /* Debugging memory allocator */ + SQLITE4_MM_STATS /* Keep memory statistics */ +} sqlite4_mm_type; + +/* +** Base class for the memory allocator object. +** +** Implementations may extend this with additional +** fields specific to its own needs. This needs to be public so that +** applications can supply their on customized memory allocators. +*/ +typedef struct sqlite4_mm sqlite4_mm; +typedef struct sqlite4_mm_methods sqlite4_mm_methods; +struct sqlite4_mm { + const struct sqlite4_mm_methods *pMethods; +}; +struct sqlite4_mm_methods { + int iVersion; + void *(*xMalloc)(sqlite4_mm*, sqlite4_size_t); + void *(*xRealloc)(sqlite4_mm*, void*, sqlite4_size_t); + void (*xFree)(sqlite4_mm*, void*); + sqlite4_size_t (*xMsize)(sqlite4_mm*, void*); + int (*xMember)(sqlite4_mm*, const void*); + void (*xBenign)(sqlite4_mm*, int); + sqlite4_int64 (*xStat)(sqlite4_mm*, unsigned eType, unsigned bFlags); + void (*xFinal)(sqlite4_mm*); +}; + +/* +** Return a pointer to the default memory allocator, which is basically +** a wrapper around system malloc()/realloc()/free(). +*/ +sqlite4_mm *sqlite4_mm_default(void); + + +/* +** Allocate a new memory manager. Return NULL if unable. +*/ +sqlite4_mm *sqlite4_mm_new(sqlite4_mm_type, ...); + +/* +** Free the sqlite4_mm object. +** +** All outstanding memory for the allocator must be freed prior to +** invoking this interface, or else the behavior is undefined. +*/ +void sqlite4_mm_destroy(sqlite4_mm*); + +/* +** Core memory allocation routines: +*/ +void *sqlite4_mm_malloc(sqlite4_mm*, sqlite4_size_t); +void *sqlite4_mm_realloc(sqlite4_mm*, void*, sqlite4_size_t); +void sqlite4_mm_free(sqlite4_mm*, void*); + +/* +** Return the size of a memory allocation. +** +** All memory allocators in SQLite4 must be able to report their size. +** When using system malloc() on system that lack the malloc_usable_size() +** routine or its equivalent, then the sqlite4_mm object allocates 8 extra +** bytes for each memory allocation and stores the allocation size in those +** initial 8 bytes. +*/ +sqlite4_size_t sqlite4_mm_msize(sqlite4_mm*, void*); + +/* +** Check to see if pOld is a memory allocation from pMM. If it is, return +** 1. If not, return 0. If we cannot determine an answer, return -1. +** +** If pOld is not a valid memory allocation or is a memory allocation that +** has previously been freed, then the result of this routine is undefined. +*/ +int sqlite4_mm_member(sqlite4_mm *pMM, const void *pOld); + +/* +** Return statistics or status information about a memory allocator. +** Not all memory allocators provide all stat values. Some memory +** allocators provides no states at all. If a particular stat for +** a memory allocator is unavailable, then -1 is returned. +*/ +sqlite4_int64 sqlite4_mm_stat(sqlite4_mm *pMM, int eType, unsigned flags); + +/* +** Enable or disable benign failure mode. Benign failure mode can be +** nested. In benign failure mode, OOM errors do not necessarily propagate +** back out to the application but can be dealt with internally. Memory +** allocations that occur in benign failure mode are considered "optional". +*/ +void sqlite4_mm_benign_failures(sqlite4_mm*, int bEnable); + /* ** CAPIREF: Run-time Environment Object ** ** An instance of the following object defines the run-time environment @@ -227,43 +363,10 @@ ** [sqlite4_busy_timeout()] to name but three) that are methods on an ** sqlite4 object. */ typedef struct sqlite4 sqlite4; -/* -** CAPIREF: 64-Bit Integer Types -** KEYWORDS: sqlite4_int64 sqlite4_uint64 -** -** Because there is no cross-platform way to specify 64-bit integer types -** SQLite includes typedefs for 64-bit signed and unsigned integers. -** -** ^The sqlite4_int64 and sqlite_int64 types can store integer values -** between -9223372036854775808 and +9223372036854775807 inclusive. ^The -** sqlite4_uint64 and sqlite_uint64 types can store integer values -** between 0 and +18446744073709551615 inclusive. -*/ -#ifdef SQLITE4_INT64_TYPE - typedef SQLITE4_INT64_TYPE sqlite4_int64_t; - typedef unsigned SQLITE4_INT64_TYPE sqlite4_uint64_t; -#elif defined(_MSC_VER) || defined(__BORLANDC__) - typedef __int64 sqlite4_int64_t; - typedef unsigned __int64 sqlite4_uint64_t; -#else - typedef long long int sqlite4_int64_t; - typedef unsigned long long int sqlite4_uint64_t; -#endif -typedef sqlite4_int64_t sqlite4_int64; -typedef sqlite4_uint64_t sqlite4_uint64; - -/* -** CAPIREF: String length type -** -** A type for measuring the length of the string. Like size_t but -** does not require <stddef.h> -*/ -typedef int sqlite4_size_t; - /* ** If compiling for a processor that lacks floating point support, ** substitute integer for floating-point. */ #ifdef SQLITE4_OMIT_FLOATING_POINT Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -2407,10 +2407,11 @@ int bCoreMutex; /* True to enable core mutexing */ int bFullMutex; /* True to enable full mutexing */ int mxStrlen; /* Maximum string length */ int szLookaside; /* Default lookaside buffer size */ int nLookaside; /* Default lookaside buffer count */ + sqlite4_mm *pMM; /* Memory allocator for this environment */ sqlite4_mem_methods m; /* Low-level memory allocation interface */ sqlite4_mutex_methods mutex; /* Low-level mutex interface */ void *pHeap; /* Heap storage space */ int nHeap; /* Size of pHeap[] */ int mnReq, mxReq; /* Min and max heap requests sizes */ @@ -2482,10 +2483,15 @@ if( (*(zIn++))>=0xc0 ){ \ while( (*zIn & 0xc0)==0x80 ){ zIn++; } \ } \ } +/* +** Default memory allocator +*/ +extern sqlite4_mm sqlite4MMSystem; + /* ** The SQLITE4_*_BKPT macros are substitutes for the error codes with ** the same name but without the _BKPT suffix. These macros invoke ** routines that report the line-number on which the error originated ** using sqlite4_log(). The routines also provide a convenient place Index: src/vdbeapi.c ================================================================== --- src/vdbeapi.c +++ src/vdbeapi.c @@ -14,25 +14,10 @@ ** VDBE. */ #include "sqliteInt.h" #include "vdbeInt.h" -#ifndef SQLITE4_OMIT_DEPRECATED -/* -** Return TRUE (non-zero) of the statement supplied as an argument needs -** to be recompiled. A statement needs to be recompiled whenever the -** execution environment changes in a way that would alter the program -** that sqlite4_prepare() generates. For example, if new functions or -** collating sequences are registered or if an authorizer function is -** added or changed. -*/ -int sqlite4_expired(sqlite4_stmt *pStmt){ - Vdbe *p = (Vdbe*)pStmt; - return p==0 || p->expired; -} -#endif - /* ** Check on a Vdbe to make sure it has not been finalized. Log ** an error and return true if it has been finalized (or is otherwise ** invalid). Return false if it is ok. */ @@ -627,26 +612,10 @@ if( xDelete ){ xDelete(pDeleteArg, pAux); } } -#ifndef SQLITE4_OMIT_DEPRECATED -/* -** Return the number of times the Step function of a aggregate has been -** called. -** -** This function is deprecated. Do not use it for new code. It is -** provide only to avoid breaking legacy code. New aggregate function -** implementations should keep their own counts within their aggregate -** context. -*/ -int sqlite4_aggregate_count(sqlite4_context *p){ - assert( p && p->pMem && p->pFunc && p->pFunc->xStep ); - return p->pMem->n; -} -#endif - /* ** Return the number of columns in the result set for the statement pStmt. */ int sqlite4_column_count(sqlite4_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; @@ -1195,39 +1164,10 @@ } sqlite4_mutex_leave(pTo->db->mutex); return SQLITE4_OK; } -#ifndef SQLITE4_OMIT_DEPRECATED -/* -** Deprecated external interface. Internal/core SQLite code -** should call sqlite4TransferBindings. -** -** Is is misuse to call this routine with statements from different -** database connections. But as this is a deprecated interface, we -** will not bother to check for that condition. -** -** If the two statements contain a different number of bindings, then -** an SQLITE4_ERROR is returned. Nothing else can go wrong, so otherwise -** SQLITE4_OK is returned. -*/ -int sqlite4_transfer_bindings(sqlite4_stmt *pFromStmt, sqlite4_stmt *pToStmt){ - Vdbe *pFrom = (Vdbe*)pFromStmt; - Vdbe *pTo = (Vdbe*)pToStmt; - if( pFrom->nVar!=pTo->nVar ){ - return SQLITE4_ERROR; - } - if( pTo->expmask ){ - pTo->expired = 1; - } - if( pFrom->expmask ){ - pFrom->expired = 1; - } - return sqlite4TransferBindings(pFromStmt, pToStmt); -} -#endif - /* ** Return the sqlite4* database handle to which the prepared statement given ** in the argument belongs. This is the same database handle that was ** the first argument to the sqlite4_prepare() that was used to create ** the statement in the first place. DELETED test/bindxfer.test Index: test/bindxfer.test ================================================================== --- test/bindxfer.test +++ /dev/null @@ -1,76 +0,0 @@ -# 2005 April 21 -# -# The author disclaims copyright to this source code. In place of -# a legal notice, here is a blessing: -# -# May you do good and not evil. -# May you find forgiveness for yourself and forgive others. -# May you share freely, never taking more than you give. -# -#*********************************************************************** -# This file implements regression tests for SQLite library. The -# focus of this script testing the sqlite_transfer_bindings() API. -# -# $Id: bindxfer.test,v 1.9 2009/04/17 11:56:28 drh Exp $ -# - -set testdir [file dirname $argv0] -source $testdir/tester.tcl - -proc sqlite_step {stmt VALS COLS} { - upvar #0 $VALS vals - upvar #0 $COLS cols - set vals [list] - set cols [list] - - set rc [sqlite4_step $stmt] - for {set i 0} {$i < [sqlite4_column_count $stmt]} {incr i} { - lappend cols [sqlite4_column_name $stmt $i] - } - for {set i 0} {$i < [sqlite4_data_count $stmt]} {incr i} { - lappend vals [sqlite4_column_text $stmt $i] - } - - return $rc -} - -do_test bindxfer-1.1 { - set DB [sqlite4_connection_pointer db] - execsql {CREATE TABLE t1(a,b,c);} - set VM1 [sqlite4_prepare $DB {SELECT ?, ?, ?} -1 TAIL] - set TAIL -} {} -do_test bindxfer-1.2 { - sqlite4_bind_parameter_count $VM1 -} 3 -do_test bindxfer-1.3 { - set VM2 [sqlite4_prepare $DB {SELECT ?, ?, ?} -1 TAIL] - set TAIL -} {} -do_test bindxfer-1.4 { - sqlite4_bind_parameter_count $VM2 -} 3 -ifcapable deprecated { - do_test bindxfer-1.5 { - sqlite_bind $VM1 1 one normal - set sqlite_static_bind_value two - sqlite_bind $VM1 2 {} static - sqlite_bind $VM1 3 {} null - sqlite4_transfer_bindings $VM1 $VM2 - sqlite_step $VM1 VALUES COLNAMES - } SQLITE4_ROW - do_test bindxfer-1.6 { - set VALUES - } {{} {} {}} - do_test bindxfer-1.7 { - sqlite_step $VM2 VALUES COLNAMES - } SQLITE4_ROW - do_test bindxfer-1.8 { - set VALUES - } {one two {}} -} -catch {sqlite4_finalize $VM1} -catch {sqlite4_finalize $VM2} - - -finish_test Index: test/enc4.test ================================================================== --- test/enc4.test +++ test/enc4.test @@ -52,15 +52,11 @@ } $enc set j 1 foreach init $inits { - do_test enc4-$i.$j.2 { - set S [sqlite4_prepare db "SELECT $init+?" -1 dummy] - sqlite4_expired $S - } {0} - + set S [sqlite4_prepare db "SELECT $init+?" -1 dummy] set k 1 foreach val $vals { for {set x 1} {$x<16} {incr x} { set part [expr $init + [string range $val 0 [expr $x-1]]] Index: test/permutations.test ================================================================== --- test/permutations.test +++ test/permutations.test @@ -147,11 +147,10 @@ autoindex1.test badutf.test between.test bigrow.test bind.test - bindxfer.test boundary1.test boundary4.test cast.test coalesce.test collate1.test collate2.test collate3.test collate4.test collate5.test Index: test/test_main.c ================================================================== --- test/test_main.c +++ test/test_main.c @@ -1010,24 +1010,10 @@ sqlite4_result_int(context, p ? p->n : 0); } } } -#ifndef SQLITE4_OMIT_DEPRECATED -static void legacyCountStep( - sqlite4_context *context, - int argc, - sqlite4_value **argv -){ - /* no-op */ -} - -static void legacyCountFinalize(sqlite4_context *context){ - sqlite4_result_int(context, sqlite4_aggregate_count(context)); -} -#endif - /* ** Usage: sqlite4_create_aggregate DB ** ** Call the sqlite4_create_function API on the given database in order ** to create a function named "x_count". This function is similar @@ -1063,17 +1049,10 @@ t1CountStep,t1CountFinalize); if( rc==SQLITE4_OK ){ rc = sqlite4_create_function(db, "x_count", 1, SQLITE4_UTF8, 0, 0, t1CountStep,t1CountFinalize); } -#ifndef SQLITE4_OMIT_DEPRECATED - if( rc==SQLITE4_OK ){ - rc = sqlite4_create_function(db, "legacy_count", 0, SQLITE4_ANY, 0, 0, - legacyCountStep, legacyCountFinalize - ); - } -#endif if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR; Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); return TCL_OK; } @@ -1961,60 +1940,10 @@ /* if( rc ){ return TCL_ERROR; } */ - return TCL_OK; -} - -/* -** Usage: sqlite4_expired STMT -** -** Return TRUE if a recompilation of the statement is recommended. -*/ -static int test_expired( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE4_OMIT_DEPRECATED - sqlite4_stmt *pStmt; - if( objc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " ", 0); - return TCL_ERROR; - } - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite4_expired(pStmt))); -#endif - return TCL_OK; -} - -/* -** Usage: sqlite4_transfer_bindings FROMSTMT TOSTMT -** -** Transfer all bindings from FROMSTMT over to TOSTMT -*/ -static int test_transfer_bind( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE4_OMIT_DEPRECATED - sqlite4_stmt *pStmt1, *pStmt2; - if( objc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", - Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0); - return TCL_ERROR; - } - if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR; - if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR; - Tcl_SetObjResult(interp, - Tcl_NewIntObj(sqlite4_transfer_bindings(pStmt1,pStmt2))); -#endif return TCL_OK; } /* ** Usage: sqlite4_changes DB @@ -3490,28 +3419,10 @@ Tcl_SetResult(interp, (char *)zRet, 0); } return TCL_OK; } -static int test_global_recover( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifndef SQLITE4_OMIT_DEPRECATED - int rc; - if( objc!=1 ){ - Tcl_WrongNumArgs(interp, 1, objv, ""); - return TCL_ERROR; - } - rc = sqlite4_global_recover(); - Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); -#endif - return TCL_OK; -} - /* ** Usage: sqlite4_column_text STMT column ** ** Usage: sqlite4_column_decltype STMT column ** @@ -4580,12 +4491,10 @@ { "sqlite4_prepare", test_prepare ,0 }, { "sqlite4_prepare_tkt3134", test_prepare_tkt3134, 0}, { "sqlite4_finalize", test_finalize ,0 }, { "sqlite4_stmt_status", test_stmt_status ,0 }, { "sqlite4_reset", test_reset ,0 }, - { "sqlite4_expired", test_expired ,0 }, - { "sqlite4_transfer_bindings", test_transfer_bind ,0 }, { "sqlite4_changes", test_changes ,0 }, { "sqlite4_step", test_step ,0 }, { "sqlite4_sql", test_sql ,0 }, { "sqlite4_next_stmt", test_next_stmt ,0 }, { "sqlite4_stmt_readonly", test_stmt_readonly ,0 }, @@ -4636,11 +4545,10 @@ {"sqlite4_column_table_name16", test_stmt_utf16, (void*)sqlite4_column_table_name16}, {"sqlite4_column_origin_name16", test_stmt_utf16, (void*)sqlite4_column_origin_name16}, #endif #endif { "sqlite4_create_collation", test_create_collation, 0 }, - { "sqlite4_global_recover", test_global_recover, 0 }, { "working_64bit_int", working_64bit_int, 0 }, { "sqlite4_create_function_v2", test_create_function_v2, 0 }, /* Functions from os.h */ #ifndef SQLITE4_OMIT_UTF16