Index: src/analyze.c ================================================================== --- src/analyze.c +++ src/analyze.c @@ -930,11 +930,11 @@ Index *pPrevIdx = 0; /* Previous index in the loop */ int idx = 0; /* slot in pIdx->aSample[] for next sample */ int eType; /* Datatype of a sample */ IndexSample *pSample; /* A slot in pIdx->aSample[] */ - assert( db->lookaside.bEnabled==0 ); + assert( db->lookaside.sz==0 ); if( !sqlite3FindTable(db, "sqlite_stat3", zDb) ){ return SQLITE_OK; } zSql = sqlite3MPrintf(db, @@ -1106,14 +1106,14 @@ /* Load the statistics from the sqlite_stat3 table. */ #ifdef SQLITE_ENABLE_STAT3 if( rc==SQLITE_OK ){ - int lookasideEnabled = db->lookaside.bEnabled; - db->lookaside.bEnabled = 0; + int lookasideSz = db->lookaside.sz; + db->lookaside.sz = 0; rc = loadStat3(db, sInfo.zDatabase); - db->lookaside.bEnabled = lookasideEnabled; + db->lookaside.sz = lookasideSz; } #endif if( rc==SQLITE_NOMEM ){ db->mallocFailed = 1; Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -1814,24 +1814,24 @@ ** statement that defines the view. */ assert( pTable->pSelect ); pSel = sqlite3SelectDup(db, pTable->pSelect, 0); if( pSel ){ - u8 enableLookaside = db->lookaside.bEnabled; + u16 lookasideSz = db->lookaside.sz; n = pParse->nTab; sqlite3SrcListAssignCursors(pParse, pSel->pSrc); pTable->nCol = -1; - db->lookaside.bEnabled = 0; + db->lookaside.sz = 0; #ifndef SQLITE_OMIT_AUTHORIZATION xAuth = db->xAuth; db->xAuth = 0; pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); db->xAuth = xAuth; #else pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); #endif - db->lookaside.bEnabled = enableLookaside; + db->lookaside.sz = lookasideSz; pParse->nTab = n; if( pSelTab ){ assert( pTable->aCol==0 ); pTable->nCol = pSelTab->nCol; pTable->aCol = pSelTab->aCol; Index: src/fkey.c ================================================================== --- src/fkey.c +++ src/fkey.c @@ -979,11 +979,11 @@ action = pFKey->aAction[iAction]; pTrigger = pFKey->apTrigger[iAction]; if( action!=OE_None && !pTrigger ){ - u8 enableLookaside; /* Copy of db->lookaside.bEnabled */ + u16 lookasideSz; /* Copy of db->lookaside.sz */ char const *zFrom; /* Name of child table */ int nFrom; /* Length in bytes of zFrom */ Index *pIdx = 0; /* Parent key index for this FK */ int *aiCol = 0; /* child table cols -> parent key cols */ TriggerStep *pStep = 0; /* First (only) step of trigger program */ @@ -1088,12 +1088,12 @@ ); pWhere = 0; } /* Disable lookaside memory allocation */ - enableLookaside = db->lookaside.bEnabled; - db->lookaside.bEnabled = 0; + lookasideSz = db->lookaside.sz; + db->lookaside.sz = 0; pTrigger = (Trigger *)sqlite3DbMallocZero(db, sizeof(Trigger) + /* struct Trigger */ sizeof(TriggerStep) + /* Single step in trigger program */ nFrom + 1 /* Space for pStep->target.z */ @@ -1112,11 +1112,11 @@ pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); } } /* Re-enable the lookaside buffer, if it was disabled earlier. */ - db->lookaside.bEnabled = enableLookaside; + db->lookaside.sz = lookasideSz; sqlite3ExprDelete(db, pWhere); sqlite3ExprDelete(db, pWhen); sqlite3ExprListDelete(db, pList); sqlite3SelectDelete(db, pSelect); Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -299,10 +299,21 @@ sqlite3GlobalConfig.isMutexInit = 0; } return SQLITE_OK; } + +/* +** If a custom memory allocator is configured using the legacy +** SQLITE_CONFIG_MALLOC interface, this function is used as the xCalloc() +** method. +*/ +static void *syntheticCalloc(int nByte){ + void *pRet = sqlite3GlobalConfig.m.xMalloc(nByte); + if( pRet ) memset(pRet, 0, nByte); + return pRet; +} /* ** This API allows applications to modify the global configuration of ** the SQLite library at run-time. ** @@ -355,22 +366,37 @@ *va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex; break; } #endif - case SQLITE_CONFIG_MALLOC: { + /* Specify an alternative malloc implementation */ + int nCopy = offsetof(sqlite3_mem_methods, xCalloc); + memcpy(&sqlite3GlobalConfig.m, va_arg(ap, sqlite3_mem_methods*), nCopy); + sqlite3GlobalConfig.m.xCalloc = syntheticCalloc; + break; + } + case SQLITE_CONFIG_GETMALLOC: { + /* Retrieve the current malloc() implementation */ + int nCopy = offsetof(sqlite3_mem_methods, xCalloc); + if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault(); + memcpy(va_arg(ap, sqlite3_mem_methods*), &sqlite3GlobalConfig.m, nCopy); + break; + } + + case SQLITE_CONFIG_MALLOC2: { /* Specify an alternative malloc implementation */ sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*); break; } - case SQLITE_CONFIG_GETMALLOC: { + case SQLITE_CONFIG_GETMALLOC2: { /* Retrieve the current malloc() implementation */ if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault(); *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m; break; } + case SQLITE_CONFIG_MEMSTATUS: { /* Enable or disable the malloc status collection */ sqlite3GlobalConfig.bMemstat = va_arg(ap, int); break; } @@ -524,11 +550,11 @@ }else{ pStart = pBuf; } db->lookaside.pStart = pStart; db->lookaside.pFree = 0; - db->lookaside.sz = (u16)sz; + db->lookaside.szEnabled = db->lookaside.sz = (u16)sz; if( pStart ){ int i; LookasideSlot *p; assert( sz > (int)sizeof(LookasideSlot*) ); p = (LookasideSlot*)pStart; @@ -536,16 +562,16 @@ p->pNext = db->lookaside.pFree; db->lookaside.pFree = p; p = (LookasideSlot*)&((u8*)p)[sz]; } db->lookaside.pEnd = p; - db->lookaside.bEnabled = 1; db->lookaside.bMalloced = pBuf==0 ?1:0; + assert( db->lookaside.sz>0 ); }else{ db->lookaside.pEnd = 0; - db->lookaside.bEnabled = 0; db->lookaside.bMalloced = 0; + db->lookaside.sz = 0; } return SQLITE_OK; } /* Index: src/malloc.c ================================================================== --- src/malloc.c +++ src/malloc.c @@ -257,46 +257,65 @@ /* ** Do a memory allocation with statistics and alarms. Assume the ** lock is already held. */ -static int mallocWithAlarm(int n, void **pp){ - int nFull; - void *p; +static void *mallocWithAlarm( + void *(*xAlloc)(int), /* Memory allocation function */ + int n /* Bytes of memory to allocate */ +){ + void *p; /* Pointer to allocated memory */ + int nFull; /* Value returned by xRoundup (if required) */ + assert( sqlite3_mutex_held(mem0.mutex) ); - nFull = sqlite3GlobalConfig.m.xRoundup(n); + assert( xAlloc==sqlite3GlobalConfig.m.xMalloc + || xAlloc==sqlite3GlobalConfig.m.xCalloc + ); + + /* Note: At one point this function would call xRoundup() and use the + ** resulting value as the argument to xAlloc(). However, this is not + ** required. And it is a (small) drag on performance. */ + /* nFull = sqlite3GlobalConfig.m.xRoundup(n); */ + sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n); - if( mem0.alarmCallback!=0 ){ + if( mem0.alarmCallback ){ int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); + nFull = sqlite3GlobalConfig.m.xRoundup(n); if( nUsed >= mem0.alarmThreshold - nFull ){ mem0.nearlyFull = 1; sqlite3MallocAlarm(nFull); }else{ mem0.nearlyFull = 0; } } - p = sqlite3GlobalConfig.m.xMalloc(nFull); + + p = xAlloc(n); #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT if( p==0 && mem0.alarmCallback ){ sqlite3MallocAlarm(nFull); - p = sqlite3GlobalConfig.m.xMalloc(nFull); + p = xAlloc(nFull); } #endif if( p ){ - nFull = sqlite3MallocSize(p); - sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull); + sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p)); sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1); + }else{ + testcase( sqlite3GlobalConfig.xLog!=0 ); + sqlite3_log(SQLITE_NOMEM, "failed to allocate %d bytes of memory", n); } - *pp = p; - return nFull; + + return p; } /* -** Allocate memory. This routine is like sqlite3_malloc() except that it -** assumes the memory subsystem has already been initialized. +** Use allocator function xAlloc to allocate n bytes of memory. */ -void *sqlite3Malloc(int n){ +static void *memAllocate( + sqlite3 *db, + void *(*xAlloc)(int), /* Memory allocation function */ + int n /* Bytes of space to allocate */ +){ void *p; if( n<=0 /* IMP: R-65312-04917 */ || n>=0x7fffff00 ){ /* A memory allocation of a number of bytes which is near the maximum @@ -303,21 +322,46 @@ ** signed integer value might cause an integer overflow inside of the ** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving ** 255 bytes of overhead. SQLite itself will never use anything near ** this amount. The only way to reach the limit is with sqlite3_malloc() */ p = 0; - }else if( sqlite3GlobalConfig.bMemstat ){ - sqlite3_mutex_enter(mem0.mutex); - mallocWithAlarm(n, &p); - sqlite3_mutex_leave(mem0.mutex); }else{ - p = sqlite3GlobalConfig.m.xMalloc(n); + if( sqlite3GlobalConfig.bMemstat ){ + sqlite3_mutex_enter(mem0.mutex); + p = mallocWithAlarm(xAlloc, n); + sqlite3_mutex_leave(mem0.mutex); + }else{ + p = xAlloc(n); + } + if( !p && db ) db->mallocFailed = 1; } + assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-04675-44850 */ + if( db ){ + sqlite3MemdebugSetType(p, MEMTYPE_DB | + ((db && db->lookaside.sz) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP) + ); + } return p; } + +/* +** Allocate memory. This routine is like sqlite3_malloc() except that it +** assumes the memory subsystem has already been initialized. +*/ +void *sqlite3Malloc(int n){ + return memAllocate(0, sqlite3GlobalConfig.m.xMalloc, n); +} + +/* +** Allocate and zero memory. +*/ +void *sqlite3MallocZero(int n){ + return memAllocate(0, sqlite3GlobalConfig.m.xCalloc, n); +} + /* ** This version of the memory allocation is for use by the application. ** First make sure the memory subsystem is initialized, then do the ** allocation. */ @@ -360,12 +404,15 @@ sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); sqlite3_mutex_leave(mem0.mutex); }else{ if( sqlite3GlobalConfig.bMemstat ){ sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); - n = mallocWithAlarm(n, &p); - if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n); + p = mallocWithAlarm(sqlite3GlobalConfig.m.xMalloc, n); + if( p ){ + n = sqlite3MallocSize(p); + sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n); + } sqlite3_mutex_leave(mem0.mutex); }else{ sqlite3_mutex_leave(mem0.mutex); p = sqlite3GlobalConfig.m.xMalloc(n); } @@ -568,37 +615,46 @@ if( sqlite3_initialize() ) return 0; #endif return sqlite3Realloc(pOld, n); } - -/* -** Allocate and zero memory. -*/ -void *sqlite3MallocZero(int n){ - void *p = sqlite3Malloc(n); - if( p ){ - memset(p, 0, n); - } - return p; -} - -/* -** Allocate and zero memory. If the allocation fails, make -** the mallocFailed flag in the connection pointer. -*/ -void *sqlite3DbMallocZero(sqlite3 *db, int n){ - void *p = sqlite3DbMallocRaw(db, n); - if( p ){ - memset(p, 0, n); - } - return p; -} - -/* -** Allocate and zero memory. If the allocation fails, make -** the mallocFailed flag in the connection pointer. +/* +** Attempt to allocate an n byte block from the lookaside buffer of +** connection db. If successful, return a pointer to the new allocation. +** Otherwise, return a NULL pointer. +*/ +#ifndef SQLITE_OMIT_LOOKASIDE +static void *lookasideAlloc(sqlite3 *db, int n){ + assert( db->lookaside.sz==0 || db->lookaside.sz==db->lookaside.szEnabled ); + if( n>db->lookaside.sz ){ + /* If db->lookaside.sz is 0, then the lookaside buffer is currently + ** disabled. In this case do not increment the "size misses" stat. */ + if( db->lookaside.sz ) db->lookaside.anStat[1]++; + }else{ + LookasideSlot *pBuf; + if( (pBuf = db->lookaside.pFree)==0 ){ + db->lookaside.anStat[2]++; + }else{ + db->lookaside.pFree = pBuf->pNext; + db->lookaside.nOut++; + db->lookaside.anStat[0]++; + if( db->lookaside.nOut>db->lookaside.mxOut ){ + db->lookaside.mxOut = db->lookaside.nOut; + } + } + sqlite3MemdebugSetType((void *)pBuf, MEMTYPE_DB | MEMTYPE_LOOKASIDE); + return (void*)pBuf; + } + return 0; +} +#else +# define lookasideAlloc(x,y) 0 +#endif + +/* +** Allocate and zero memory. If the allocation fails, set the +** mallocFailed flag in the connection pointer. ** ** If db!=0 and db->mallocFailed is true (indicating a prior malloc ** failure on the same database connection) then always return 0. ** Hence for a particular database connection, once malloc starts ** failing, it fails consistently until mallocFailed is reset. @@ -610,48 +666,41 @@ ** if( b ) a[10] = 9; ** ** In other words, if a subsequent malloc (ex: "b") worked, it is assumed ** that all prior mallocs (ex: "a") worked too. */ -void *sqlite3DbMallocRaw(sqlite3 *db, int n){ - void *p; - assert( db==0 || sqlite3_mutex_held(db->mutex) ); - assert( db==0 || db->pnBytesFreed==0 ); -#ifndef SQLITE_OMIT_LOOKASIDE - if( db ){ - LookasideSlot *pBuf; - if( db->mallocFailed ){ - return 0; - } - if( db->lookaside.bEnabled ){ - if( n>db->lookaside.sz ){ - db->lookaside.anStat[1]++; - }else if( (pBuf = db->lookaside.pFree)==0 ){ - db->lookaside.anStat[2]++; - }else{ - db->lookaside.pFree = pBuf->pNext; - db->lookaside.nOut++; - db->lookaside.anStat[0]++; - if( db->lookaside.nOut>db->lookaside.mxOut ){ - db->lookaside.mxOut = db->lookaside.nOut; - } - return (void*)pBuf; - } - } - } -#else - if( db && db->mallocFailed ){ - return 0; - } -#endif - p = sqlite3Malloc(n); - if( !p && db ){ - db->mallocFailed = 1; - } - sqlite3MemdebugSetType(p, MEMTYPE_DB | - ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); - return p; +void *sqlite3DbMallocZero(sqlite3 *db, int n){ + void *p; + if( db ){ + if( db->mallocFailed ) return 0; + if( (p = lookasideAlloc(db, n)) ){ + memset(p, 0, n); + return p; + } + } + + return memAllocate(db, sqlite3GlobalConfig.m.xCalloc, n); +} + +/* +** Allocate memory. If the allocation fails, make the mallocFailed +** flag in the connection pointer. +** +** If db!=0 and db->mallocFailed is true (indicating a prior malloc +** failure on the same database connection) then always return 0. +** See also comments above sqlite3DbMallocZero() for details. +*/ +void *sqlite3DbMallocRaw(sqlite3 *db, int n){ + void *p; + if( db ){ + if( db->mallocFailed ) return 0; + if( (p = lookasideAlloc(db, n)) ){ + return p; + } + } + + return memAllocate(db, sqlite3GlobalConfig.m.xMalloc, n); } /* ** Resize the block of memory pointed to by p to n bytes. If the ** resize fails, set the mallocFailed flag in the connection object. @@ -663,16 +712,16 @@ if( db->mallocFailed==0 ){ if( p==0 ){ return sqlite3DbMallocRaw(db, n); } if( isLookaside(db, p) ){ - if( n<=db->lookaside.sz ){ + if( n<=db->lookaside.szEnabled ){ return p; } pNew = sqlite3DbMallocRaw(db, n); if( pNew ){ - memcpy(pNew, p, db->lookaside.sz); + memcpy(pNew, p, db->lookaside.szEnabled); sqlite3DbFree(db, p); } }else{ assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) ); @@ -681,11 +730,11 @@ if( !pNew ){ sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP); db->mallocFailed = 1; } sqlite3MemdebugSetType(pNew, MEMTYPE_DB | - (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); + (db->lookaside.sz ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); } } return pNew; } Index: src/mem1.c ================================================================== --- src/mem1.c +++ src/mem1.c @@ -68,10 +68,11 @@ #include #include #include static malloc_zone_t* _sqliteZone_; #define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x)) +#define SQLITE_CALLOC(x) malloc_zone_calloc(_sqliteZone_, (x), 1) #define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x)); #define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y)) #define SQLITE_MALLOCSIZE(x) \ (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x)) @@ -80,10 +81,11 @@ /* ** Use standard C library malloc and free on non-Apple systems. ** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined. */ #define SQLITE_MALLOC(x) malloc(x) +#define SQLITE_CALLOC(x) calloc((x), 1) #define SQLITE_FREE(x) free(x) #define SQLITE_REALLOC(x,y) realloc((x),(y)) #if (defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)) \ || (defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE)) @@ -98,37 +100,43 @@ #endif #endif /* __APPLE__ or not __APPLE__ */ /* -** Like malloc(), but remember the size of the allocation -** so that we can find it later using sqlite3MemSize(). +** Allocate nByte bytes of memory. ** ** For this low-level routine, we are guaranteed that nByte>0 because ** cases of nByte<=0 will be intercepted and dealt with by higher level ** routines. */ static void *sqlite3MemMalloc(int nByte){ #ifdef SQLITE_MALLOCSIZE - void *p = SQLITE_MALLOC( nByte ); - if( p==0 ){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); - } - return p; + return SQLITE_MALLOC( ROUND8(nByte) ); +#else + i64 *p; + nByte = ROUND8(nByte); + p = SQLITE_MALLOC(nByte+8); + if( p ) *(p++) = (i64)nByte; + return (void *)p; +#endif +} + +/* +** Allocate and zero nByte bytes of memory. +** +** For this low-level routine, we are guaranteed that nByte>0 because +** cases of nByte<=0 will be intercepted and dealt with by higher level +** routines. +*/ +static void *sqlite3MemCalloc(int nByte){ +#ifdef SQLITE_MALLOCSIZE + return SQLITE_CALLOC( ROUND8(nByte) ); #else - sqlite3_int64 *p; - assert( nByte>0 ); + i64 *p; nByte = ROUND8(nByte); - p = SQLITE_MALLOC( nByte+8 ); - if( p ){ - p[0] = nByte; - p++; - }else{ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); - } + p = SQLITE_CALLOC(nByte+8); + if( p ) *(p++) = (i64)nByte; return (void *)p; #endif } /* @@ -269,11 +277,12 @@ sqlite3MemRealloc, sqlite3MemSize, sqlite3MemRoundup, sqlite3MemInit, sqlite3MemShutdown, - 0 + 0, + sqlite3MemCalloc }; sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); } #endif /* SQLITE_SYSTEM_MALLOC */ Index: src/parse.y ================================================================== --- src/parse.y +++ src/parse.y @@ -150,11 +150,11 @@ cmd ::= create_table create_table_args. create_table ::= createkw temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z). { sqlite3StartTable(pParse,&Y,&Z,T,0,0,E); } createkw(A) ::= CREATE(X). { - pParse->db->lookaside.bEnabled = 0; + pParse->db->lookaside.sz = 0; A = X; } %type ifnotexists {int} ifnotexists(A) ::= . {A = 0;} ifnotexists(A) ::= IF NOT EXISTS. {A = 1;} @@ -1376,11 +1376,11 @@ } cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column(Y). { sqlite3AlterFinishAddColumn(pParse, &Y); } add_column_fullname ::= fullname(X). { - pParse->db->lookaside.bEnabled = 0; + pParse->db->lookaside.sz = 0; sqlite3AlterBeginAddColumn(pParse, X); } kwcolumn_opt ::= . kwcolumn_opt ::= COLUMNKW. %endif SQLITE_OMIT_ALTERTABLE Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -1396,13 +1396,13 @@ db->flags = savedFlags; pTab = sqlite3DbMallocZero(db, sizeof(Table) ); if( pTab==0 ){ return 0; } - /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside - ** is disabled */ - assert( db->lookaside.bEnabled==0 ); + /* The sqlite3ResultSetOfSelect() should only used in contexts where the + ** lookaside buffer is disabled. */ + assert( db->lookaside.sz==0 ); pTab->nRef = 1; pTab->zName = 0; pTab->nRowEst = 1000000; selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect); Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -1339,10 +1339,11 @@ int (*xSize)(void*); /* Return the size of an allocation */ int (*xRoundup)(int); /* Round up request size to allocation size */ int (*xInit)(void*); /* Initialize the memory allocator */ void (*xShutdown)(void*); /* Deinitialize the memory allocator */ void *pAppData; /* Argument to xInit() and xShutdown() */ + void *(*xCalloc)(int); /* Zeroed memory allocation function */ }; /* ** CAPI3REF: Configuration Options ** KEYWORDS: {configuration option} @@ -1575,20 +1576,22 @@ #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ #define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ #define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ #define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ -#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ -#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ +#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* no xCalloc() */ +#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* no xCalloc() */ /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ #define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ #define SQLITE_CONFIG_PCACHE 14 /* no-op */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_MALLOC2 20 /* sqlite3_mem_methods* incl xCalloc() */ +#define SQLITE_CONFIG_GETMALLOC2 21 /* sqlite3_mem_methods* incl xCalloc() */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -781,16 +781,18 @@ ** ** Lookaside allocations are only allowed for objects that are associated ** with a particular database connection. Hence, schema information cannot ** be stored in lookaside because in shared cache mode the schema information ** is shared by multiple database connections. Therefore, while parsing -** schema information, the Lookaside.bEnabled flag is cleared so that -** lookaside allocations are not used to construct the schema objects. +** schema information, the Lookaside.sz variable is temporarily set to +** zero so that lookaside allocations are not used to construct the schema +** objects. Lookaside.szEnabled always contains the allocation size that +** Lookaside.sz is set to when the buffer is enabled. */ struct Lookaside { u16 sz; /* Size of each buffer in bytes */ - u8 bEnabled; /* False to disable new lookaside allocations */ + u16 szEnabled; /* Value of 'sz' when buffer is enabled. */ u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ int nOut; /* Number of buffers currently checked out */ int mxOut; /* Highwater mark for nOut */ int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ LookasideSlot *pFree; /* List of available buffers */ Index: src/tokenize.c ================================================================== --- src/tokenize.c +++ src/tokenize.c @@ -388,11 +388,11 @@ int nErr = 0; /* Number of errors encountered */ int i; /* Loop counter */ void *pEngine; /* The LEMON-generated LALR(1) parser */ int tokenType; /* type of the next token */ int lastTokenParsed = -1; /* type of the previous token */ - u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ + u16 lookasideSz; /* Saved value of db->lookaside.sz */ sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; @@ -411,12 +411,14 @@ assert( pParse->pNewTable==0 ); assert( pParse->pNewTrigger==0 ); assert( pParse->nVar==0 ); assert( pParse->nzVar==0 ); assert( pParse->azVar==0 ); - enableLookaside = db->lookaside.bEnabled; - if( db->lookaside.pStart ) db->lookaside.bEnabled = 1; + lookasideSz = db->lookaside.sz; + if( db->lookaside.pStart ){ + db->lookaside.sz = db->lookaside.szEnabled; + } while( !db->mallocFailed && zSql[i]!=0 ){ assert( i>=0 ); pParse->sLastToken.z = &zSql[i]; pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); i += pParse->sLastToken.n; @@ -466,11 +468,11 @@ sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK, sqlite3ParserStackPeak(pEngine) ); #endif /* YYDEBUG */ sqlite3ParserFree(pEngine, sqlite3_free); - db->lookaside.bEnabled = enableLookaside; + db->lookaside.sz = lookasideSz; if( db->mallocFailed ){ pParse->rc = SQLITE_NOMEM; } if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc));