Implement the "lookaside" memory allocation cache. Use of this cache makes
the speed1.test script run about 15% faster. Added new interfaces to
control the cache. (CVS 5488)
FossilOrigin-Name: e48f9697e9fea339e150ddc32940760027dd07d9
diff --git a/src/alter.c b/src/alter.c
index c0a8109..ba929be 100644
--- a/src/alter.c
+++ b/src/alter.c
@@ -12,7 +12,7 @@
** This file contains C code routines that used to generate VDBE code
** that implements the ALTER TABLE command.
**
-** $Id: alter.c,v 1.46 2008/07/15 14:47:19 drh Exp $
+** $Id: alter.c,v 1.47 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -80,7 +80,7 @@
zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql,
zTableName, tname.z+tname.n);
- sqlite3_result_text(context, zRet, -1, sqlite3_free);
+ sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
}
}
@@ -155,7 +155,7 @@
*/
zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql,
zTableName, tname.z+tname.n);
- sqlite3_result_text(context, zRet, -1, sqlite3_free);
+ sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
}
}
#endif /* !SQLITE_OMIT_TRIGGER */
@@ -198,7 +198,7 @@
}else{
tmp = zWhere;
zWhere = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, pTrig->name);
- sqlite3_free(tmp);
+ sqlite3DbFree(db, tmp);
}
}
}
@@ -409,7 +409,7 @@
"sql = sqlite_rename_trigger(sql, %Q), "
"tbl_name = %Q "
"WHERE %s;", zName, zName, zWhere);
- sqlite3_free(zWhere);
+ sqlite3DbFree(db, zWhere);
}
#endif
@@ -417,8 +417,8 @@
reloadTableSchema(pParse, pTab, zName);
exit_rename_table:
- sqlite3SrcListDelete(pSrc);
- sqlite3_free(zName);
+ sqlite3SrcListDelete(db, pSrc);
+ sqlite3DbFree(db, zName);
}
@@ -518,7 +518,7 @@
zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
zTab
);
- sqlite3_free(zCol);
+ sqlite3DbFree(db, zCol);
}
/* If the default value of the new column is NULL, then set the file
@@ -585,6 +585,7 @@
if( !pNew ) goto exit_begin_add_column;
pParse->pNewTable = pNew;
pNew->nRef = 1;
+ pNew->db = db;
pNew->nCol = pTab->nCol;
assert( pNew->nCol>0 );
nAlloc = (((pNew->nCol-1)/8)*8)+8;
@@ -614,7 +615,7 @@
sqlite3ChangeCookie(pParse, iDb);
exit_begin_add_column:
- sqlite3SrcListDelete(pSrc);
+ sqlite3SrcListDelete(db, pSrc);
return;
}
#endif /* SQLITE_ALTER_TABLE */
diff --git a/src/analyze.c b/src/analyze.c
index aeb9972..2c57d7f 100644
--- a/src/analyze.c
+++ b/src/analyze.c
@@ -11,7 +11,7 @@
*************************************************************************
** This file contains code associated with the ANALYZE command.
**
-** @(#) $Id: analyze.c,v 1.42 2008/03/25 09:47:35 danielk1977 Exp $
+** @(#) $Id: analyze.c,v 1.43 2008/07/28 19:34:53 drh Exp $
*/
#ifndef SQLITE_OMIT_ANALYZE
#include "sqliteInt.h"
@@ -316,7 +316,7 @@
z = sqlite3NameFromToken(db, pName1);
if( z ){
pTab = sqlite3LocateTable(pParse, 0, z, 0);
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
if( pTab ){
analyzeTable(pParse, pTab);
}
@@ -330,7 +330,7 @@
z = sqlite3NameFromToken(db, pTableName);
if( z ){
pTab = sqlite3LocateTable(pParse, 0, z, zDb);
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
if( pTab ){
analyzeTable(pParse, pTab);
}
@@ -417,7 +417,7 @@
(void)sqlite3SafetyOff(db);
rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
(void)sqlite3SafetyOn(db);
- sqlite3_free(zSql);
+ sqlite3DbFree(db, zSql);
return rc;
}
diff --git a/src/attach.c b/src/attach.c
index 3964f37..b8668f5 100644
--- a/src/attach.c
+++ b/src/attach.c
@@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
-** $Id: attach.c,v 1.76 2008/06/15 02:51:47 drh Exp $
+** $Id: attach.c,v 1.77 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
@@ -214,7 +214,7 @@
/* Return an error if we get here */
if( zErrDyn ){
sqlite3_result_error(context, zErrDyn, -1);
- sqlite3_free(zErrDyn);
+ sqlite3DbFree(db, zErrDyn);
}else{
zErr[sizeof(zErr)-1] = 0;
sqlite3_result_error(context, zErr, -1);
@@ -305,7 +305,7 @@
goto attach_end;
}
rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
- sqlite3_free(zAuthArg);
+ sqlite3DbFree(db, zAuthArg);
if(rc!=SQLITE_OK ){
goto attach_end;
}
@@ -345,9 +345,9 @@
}
attach_end:
- sqlite3ExprDelete(pFilename);
- sqlite3ExprDelete(pDbname);
- sqlite3ExprDelete(pKey);
+ sqlite3ExprDelete(db, pFilename);
+ sqlite3ExprDelete(db, pDbname);
+ sqlite3ExprDelete(db, pKey);
}
/*
diff --git a/src/btree.c b/src/btree.c
index a51ed1b..0e91a5f 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.491 2008/07/19 14:25:16 danielk1977 Exp $
+** $Id: btree.c,v 1.492 2008/07/28 19:34:53 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
@@ -6814,7 +6814,7 @@
nRef = sqlite3PagerRefcount(pBt->pPager);
if( lockBtreeWithRetry(p)!=SQLITE_OK ){
sqlite3BtreeLeave(p);
- return sqlite3StrDup("Unable to acquire a read lock on the database");
+ return sqlite3DbStrDup(0, "Unable to acquire a read lock on the database");
}
sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager;
diff --git a/src/build.c b/src/build.c
index 8a1d4bb..19f09dc 100644
--- a/src/build.c
+++ b/src/build.c
@@ -22,7 +22,7 @@
** COMMIT
** ROLLBACK
**
-** $Id: build.c,v 1.490 2008/07/08 23:40:20 drh Exp $
+** $Id: build.c,v 1.491 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -239,24 +239,24 @@
va_list ap;
char *zSql;
char *zErrMsg = 0;
+ sqlite3 *db = pParse->db;
# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar))
char saveBuf[SAVE_SZ];
if( pParse->nErr ) return;
assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
va_start(ap, zFormat);
- zSql = sqlite3VMPrintf(pParse->db, zFormat, ap);
+ zSql = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
if( zSql==0 ){
- pParse->db->mallocFailed = 1;
return; /* A malloc must have failed */
}
pParse->nested++;
memcpy(saveBuf, &pParse->nVar, SAVE_SZ);
memset(&pParse->nVar, 0, SAVE_SZ);
sqlite3RunParser(pParse, zSql, &zErrMsg);
- sqlite3_free(zErrMsg);
- sqlite3_free(zSql);
+ sqlite3DbFree(db, zErrMsg);
+ sqlite3DbFree(db, zSql);
memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
pParse->nested--;
}
@@ -358,8 +358,9 @@
** Reclaim the memory used by an index
*/
static void freeIndex(Index *p){
- sqlite3_free(p->zColAff);
- sqlite3_free(p);
+ sqlite3 *db = p->pTable->db;
+ sqlite3DbFree(db, p->zColAff);
+ sqlite3DbFree(db, p);
}
/*
@@ -453,7 +454,7 @@
for(i=j=2; i<db->nDb; i++){
struct Db *pDb = &db->aDb[i];
if( pDb->pBt==0 ){
- sqlite3_free(pDb->zName);
+ sqlite3DbFree(db, pDb->zName);
pDb->zName = 0;
continue;
}
@@ -466,7 +467,7 @@
db->nDb = j;
if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
- sqlite3_free(db->aDb);
+ sqlite3DbFree(db, db->aDb);
db->aDb = db->aDbStatic;
}
}
@@ -484,15 +485,16 @@
static void sqliteResetColumnNames(Table *pTable){
int i;
Column *pCol;
+ sqlite3 *db = pTable->db;
assert( pTable!=0 );
if( (pCol = pTable->aCol)!=0 ){
for(i=0; i<pTable->nCol; i++, pCol++){
- sqlite3_free(pCol->zName);
- sqlite3ExprDelete(pCol->pDflt);
- sqlite3_free(pCol->zType);
- sqlite3_free(pCol->zColl);
+ sqlite3DbFree(db, pCol->zName);
+ sqlite3ExprDelete(db, pCol->pDflt);
+ sqlite3DbFree(db, pCol->zType);
+ sqlite3DbFree(db, pCol->zColl);
}
- sqlite3_free(pTable->aCol);
+ sqlite3DbFree(db, pTable->aCol);
}
pTable->aCol = 0;
pTable->nCol = 0;
@@ -511,8 +513,10 @@
void sqlite3DeleteTable(Table *pTable){
Index *pIndex, *pNext;
FKey *pFKey, *pNextFKey;
+ sqlite3 *db;
if( pTable==0 ) return;
+ db = pTable->db;
/* Do not delete the table until the reference count reaches zero. */
pTable->nRef--;
@@ -537,21 +541,21 @@
pNextFKey = pFKey->pNextFrom;
assert( sqlite3HashFind(&pTable->pSchema->aFKey,
pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
- sqlite3_free(pFKey);
+ sqlite3DbFree(db, pFKey);
}
#endif
/* Delete the Table structure itself.
*/
sqliteResetColumnNames(pTable);
- sqlite3_free(pTable->zName);
- sqlite3_free(pTable->zColAff);
- sqlite3SelectDelete(pTable->pSelect);
+ sqlite3DbFree(db, pTable->zName);
+ sqlite3DbFree(db, pTable->zColAff);
+ sqlite3SelectDelete(db, pTable->pSelect);
#ifndef SQLITE_OMIT_CHECK
- sqlite3ExprDelete(pTable->pCheck);
+ sqlite3ExprDelete(db, pTable->pCheck);
#endif
sqlite3VtabClear(pTable);
- sqlite3_free(pTable);
+ sqlite3DbFree(db, pTable);
}
/*
@@ -641,7 +645,7 @@
break;
}
}
- sqlite3_free(zName);
+ sqlite3DbFree(db, zName);
}
return i;
}
@@ -832,6 +836,7 @@
pTable->iPKey = -1;
pTable->pSchema = db->aDb[iDb].pSchema;
pTable->nRef = 1;
+ pTable->db = db;
if( pParse->pNewTable ) sqlite3DeleteTable(pParse->pNewTable);
pParse->pNewTable = pTable;
@@ -911,7 +916,7 @@
/* If an error occurs, we jump here */
begin_table_error:
- sqlite3_free(zName);
+ sqlite3DbFree(db, zName);
return;
}
@@ -954,7 +959,7 @@
for(i=0; i<p->nCol; i++){
if( STRICMP(z, p->aCol[i].zName) ){
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
return;
}
}
@@ -962,7 +967,7 @@
Column *aNew;
aNew = sqlite3DbRealloc(pParse->db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0]));
if( aNew==0 ){
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
return;
}
p->aCol = aNew;
@@ -1069,13 +1074,15 @@
Table *p;
int i;
Column *pCol;
+ sqlite3 *db;
if( (p = pParse->pNewTable)==0 ) return;
i = p->nCol-1;
if( i<0 ) return;
pCol = &p->aCol[i];
- sqlite3_free(pCol->zType);
- pCol->zType = sqlite3NameFromToken(pParse->db, pType);
+ db = pParse->db;
+ sqlite3DbFree(db, pCol->zType);
+ pCol->zType = sqlite3NameFromToken(db, pType);
pCol->affinity = sqlite3AffinityType(pType);
}
@@ -1092,6 +1099,7 @@
void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
Table *p;
Column *pCol;
+ sqlite3 *db = pParse->db;
if( (p = pParse->pNewTable)!=0 ){
pCol = &(p->aCol[p->nCol-1]);
if( !sqlite3ExprIsConstantOrFunction(pExpr) ){
@@ -1099,15 +1107,14 @@
pCol->zName);
}else{
Expr *pCopy;
- sqlite3 *db = pParse->db;
- sqlite3ExprDelete(pCol->pDflt);
+ sqlite3ExprDelete(db, pCol->pDflt);
pCol->pDflt = pCopy = sqlite3ExprDup(db, pExpr);
if( pCopy ){
sqlite3TokenCopy(db, &pCopy->span, &pExpr->span);
}
}
}
- sqlite3ExprDelete(pExpr);
+ sqlite3ExprDelete(db, pExpr);
}
/*
@@ -1180,7 +1187,7 @@
}
primary_key_exit:
- sqlite3ExprListDelete(pList);
+ sqlite3ExprListDelete(pParse->db, pList);
return;
}
@@ -1191,9 +1198,9 @@
Parse *pParse, /* Parsing context */
Expr *pCheckExpr /* The check expression */
){
+ sqlite3 *db = pParse->db;
#ifndef SQLITE_OMIT_CHECK
Table *pTab = pParse->pNewTable;
- sqlite3 *db = pParse->db;
if( pTab && !IN_DECLARE_VTAB ){
/* The CHECK expression must be duplicated so that tokens refer
** to malloced space and not the (ephemeral) text of the CREATE TABLE
@@ -1202,7 +1209,7 @@
sqlite3ExprDup(db, pCheckExpr));
}
#endif
- sqlite3ExprDelete(pCheckExpr);
+ sqlite3ExprDelete(db, pCheckExpr);
}
/*
@@ -1213,11 +1220,12 @@
Table *p;
int i;
char *zColl; /* Dequoted name of collation sequence */
+ sqlite3 *db;
if( (p = pParse->pNewTable)==0 ) return;
i = p->nCol-1;
-
- zColl = sqlite3NameFromToken(pParse->db, pToken);
+ db = pParse->db;
+ zColl = sqlite3NameFromToken(db, pToken);
if( !zColl ) return;
if( sqlite3LocateCollSeq(pParse, zColl, -1) ){
@@ -1235,7 +1243,7 @@
}
}
}else{
- sqlite3_free(zColl);
+ sqlite3DbFree(db, zColl);
}
}
@@ -1568,7 +1576,7 @@
zStmt,
pParse->regRowid
);
- sqlite3_free(zStmt);
+ sqlite3DbFree(db, zStmt);
sqlite3ChangeCookie(pParse, iDb);
#ifndef SQLITE_OMIT_AUTOINCREMENT
@@ -1658,13 +1666,13 @@
if( pParse->nVar>0 ){
sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
- sqlite3SelectDelete(pSelect);
+ sqlite3SelectDelete(db, pSelect);
return;
}
sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
p = pParse->pNewTable;
if( p==0 || pParse->nErr ){
- sqlite3SelectDelete(pSelect);
+ sqlite3SelectDelete(db, pSelect);
return;
}
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
@@ -1672,7 +1680,7 @@
if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName)
&& sqlite3FixSelect(&sFix, pSelect)
){
- sqlite3SelectDelete(pSelect);
+ sqlite3SelectDelete(db, pSelect);
return;
}
@@ -1682,7 +1690,7 @@
** they will persist after the current sqlite3_exec() call returns.
*/
p->pSelect = sqlite3SelectDup(db, pSelect);
- sqlite3SelectDelete(pSelect);
+ sqlite3SelectDelete(db, pSelect);
if( db->mallocFailed ){
return;
}
@@ -1789,7 +1797,7 @@
pTable->nCol = 0;
nErr++;
}
- sqlite3SelectDelete(pSel);
+ sqlite3SelectDelete(db, pSel);
} else {
nErr++;
}
@@ -2105,7 +2113,7 @@
sqliteViewResetAll(db, iDb);
exit_drop_table:
- sqlite3SrcListDelete(pName);
+ sqlite3SrcListDelete(db, pName);
}
/*
@@ -2140,8 +2148,10 @@
int i;
int nCol;
char *z;
+ sqlite3 *db;
assert( pTo!=0 );
+ db = pParse->db;
if( p==0 || pParse->nErr || IN_DECLARE_VTAB ) goto fk_end;
if( pFromCol==0 ){
int iCol = p->nCol-1;
@@ -2167,7 +2177,7 @@
nByte += strlen(pToCol->a[i].zName) + 1;
}
}
- pFKey = sqlite3DbMallocZero(pParse->db, nByte );
+ pFKey = sqlite3DbMallocZero(db, nByte );
if( pFKey==0 ){
goto fk_end;
}
@@ -2221,10 +2231,10 @@
pFKey = 0;
fk_end:
- sqlite3_free(pFKey);
+ sqlite3DbFree(db, pFKey);
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
- sqlite3ExprListDelete(pFromCol);
- sqlite3ExprListDelete(pToCol);
+ sqlite3ExprListDelete(db, pFromCol);
+ sqlite3ExprListDelete(db, pToCol);
}
/*
@@ -2711,7 +2721,7 @@
iMem,
zStmt
);
- sqlite3_free(zStmt);
+ sqlite3DbFree(db, zStmt);
/* Fill the index with data and reparse the schema. Code an OP_Expire
** to invalidate all pre-compiled statements.
@@ -2751,9 +2761,9 @@
if( pIndex ){
freeIndex(pIndex);
}
- sqlite3ExprListDelete(pList);
- sqlite3SrcListDelete(pTblName);
- sqlite3_free(zName);
+ sqlite3ExprListDelete(db, pList);
+ sqlite3SrcListDelete(db, pTblName);
+ sqlite3DbFree(db, zName);
return;
}
@@ -2882,7 +2892,7 @@
}
exit_drop_index:
- sqlite3SrcListDelete(pName);
+ sqlite3SrcListDelete(db, pName);
}
/*
@@ -2952,7 +2962,7 @@
&i
);
if( i<0 ){
- sqlite3IdListDelete(pList);
+ sqlite3IdListDelete(db, pList);
return 0;
}
pList->a[i].zName = sqlite3NameFromToken(db, pToken);
@@ -2962,14 +2972,14 @@
/*
** Delete an IdList.
*/
-void sqlite3IdListDelete(IdList *pList){
+void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
int i;
if( pList==0 ) return;
for(i=0; i<pList->nId; i++){
- sqlite3_free(pList->a[i].zName);
+ sqlite3DbFree(db, pList->a[i].zName);
}
- sqlite3_free(pList->a);
- sqlite3_free(pList);
+ sqlite3DbFree(db, pList->a);
+ sqlite3DbFree(db, pList);
}
/*
@@ -3028,7 +3038,7 @@
pNew = sqlite3DbRealloc(db, pList,
sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) );
if( pNew==0 ){
- sqlite3SrcListDelete(pList);
+ sqlite3SrcListDelete(db, pList);
return 0;
}
pList = pNew;
@@ -3072,20 +3082,20 @@
/*
** Delete an entire SrcList including all its substructure.
*/
-void sqlite3SrcListDelete(SrcList *pList){
+void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
int i;
struct SrcList_item *pItem;
if( pList==0 ) return;
for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
- sqlite3_free(pItem->zDatabase);
- sqlite3_free(pItem->zName);
- sqlite3_free(pItem->zAlias);
+ sqlite3DbFree(db, pItem->zDatabase);
+ sqlite3DbFree(db, pItem->zName);
+ sqlite3DbFree(db, pItem->zAlias);
sqlite3DeleteTable(pItem->pTab);
- sqlite3SelectDelete(pItem->pSelect);
- sqlite3ExprDelete(pItem->pOn);
- sqlite3IdListDelete(pItem->pUsing);
+ sqlite3SelectDelete(db, pItem->pSelect);
+ sqlite3ExprDelete(db, pItem->pOn);
+ sqlite3IdListDelete(db, pItem->pUsing);
}
- sqlite3_free(pList);
+ sqlite3DbFree(db, pList);
}
/*
@@ -3118,9 +3128,9 @@
sqlite3 *db = pParse->db;
p = sqlite3SrcListAppend(db, p, pTable, pDatabase);
if( p==0 || p->nSrc==0 ){
- sqlite3ExprDelete(pOn);
- sqlite3IdListDelete(pUsing);
- sqlite3SelectDelete(pSubquery);
+ sqlite3ExprDelete(db, pOn);
+ sqlite3IdListDelete(db, pUsing);
+ sqlite3SelectDelete(db, pSubquery);
return p;
}
pItem = &p->a[p->nSrc-1];
@@ -3425,11 +3435,11 @@
if( pColl ){
if( zColl ){
reindexDatabases(pParse, zColl);
- sqlite3_free(zColl);
+ sqlite3DbFree(db, zColl);
}
return;
}
- sqlite3_free(zColl);
+ sqlite3DbFree(db, zColl);
}
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName);
if( iDb<0 ) return;
@@ -3439,11 +3449,11 @@
pTab = sqlite3FindTable(db, z, zDb);
if( pTab ){
reindexTable(pParse, pTab, 0);
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
return;
}
pIndex = sqlite3FindIndex(db, z, zDb);
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
if( pIndex ){
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3RefillIndex(pParse, pIndex, -1);
@@ -3458,7 +3468,7 @@
** with OP_OpenRead or OP_OpenWrite to access database index pIdx.
**
** If successful, a pointer to the new structure is returned. In this case
-** the caller is responsible for calling sqlite3_free() on the returned
+** the caller is responsible for calling sqlite3DbFree(db, ) on the returned
** pointer. If an error occurs (out of memory or missing collation
** sequence), NULL is returned and the state of pParse updated to reflect
** the error.
@@ -3467,7 +3477,8 @@
int i;
int nCol = pIdx->nColumn;
int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol;
- KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(pParse->db, nBytes);
+ sqlite3 *db = pParse->db;
+ KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(db, nBytes);
if( pKey ){
pKey->db = pParse->db;
@@ -3483,7 +3494,7 @@
}
if( pParse->nErr ){
- sqlite3_free(pKey);
+ sqlite3DbFree(db, pKey);
pKey = 0;
}
return pKey;
diff --git a/src/callback.c b/src/callback.c
index 09f6841..a77f994 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -13,7 +13,7 @@
** This file contains functions used to access the internal hash tables
** of user defined functions and collation sequences.
**
-** $Id: callback.c,v 1.25 2008/07/08 14:52:10 drh Exp $
+** $Id: callback.c,v 1.26 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
@@ -30,7 +30,7 @@
char *zExternal = sqlite3DbStrNDup(db, zName, nName);
if( !zExternal ) return;
db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal);
- sqlite3_free(zExternal);
+ sqlite3DbFree(db, zExternal);
}
#ifndef SQLITE_OMIT_UTF16
if( db->xCollNeeded16 ){
@@ -182,7 +182,7 @@
assert( pDel==0 || pDel==pColl );
if( pDel!=0 ){
db->mallocFailed = 1;
- sqlite3_free(pDel);
+ sqlite3DbFree(db, pDel);
pColl = 0;
}
}
@@ -312,7 +312,7 @@
pBest->zName[nName] = 0;
if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){
db->mallocFailed = 1;
- sqlite3_free(pBest);
+ sqlite3DbFree(db, pBest);
return 0;
}
}
@@ -325,7 +325,7 @@
/*
** Free all resources held by the schema structure. The void* argument points
-** at a Schema struct. This function does not call sqlite3_free() on the
+** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the
** pointer itself, it just cleans up subsiduary resources (i.e. the contents
** of the schema hash tables).
**
@@ -343,7 +343,7 @@
sqlite3HashClear(&pSchema->aFKey);
sqlite3HashClear(&pSchema->idxHash);
for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
- sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem));
+ sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem));
}
sqlite3HashClear(&temp2);
sqlite3HashInit(&pSchema->tblHash, SQLITE_HASH_STRING, 0);
diff --git a/src/date.c b/src/date.c
index d9b39b8..08ee30c 100644
--- a/src/date.c
+++ b/src/date.c
@@ -16,7 +16,7 @@
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: date.c,v 1.86 2008/07/25 16:39:25 drh Exp $
+** $Id: date.c,v 1.87 2008/07/28 19:34:53 drh Exp $
**
** SQLite processes all times and dates as Julian Day numbers. The
** dates and times are stored as the number of days since noon
@@ -849,9 +849,11 @@
u64 n;
int i, j;
char *z;
+ sqlite3 *db;
const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
char zBuf[100];
if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
+ db = sqlite3_context_db_handle(context);
for(i=0, n=1; zFmt[i]; i++, n++){
if( zFmt[i]=='%' ){
switch( zFmt[i+1] ){
@@ -887,11 +889,11 @@
}
if( n<sizeof(zBuf) ){
z = zBuf;
- }else if( n>sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH] ){
+ }else if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
return;
}else{
- z = sqlite3Malloc( n );
+ z = sqlite3DbMallocRaw(db, n);
if( z==0 ){
sqlite3_result_error_nomem(context);
return;
@@ -956,7 +958,7 @@
}
z[j] = 0;
sqlite3_result_text(context, z, -1,
- z==zBuf ? SQLITE_TRANSIENT : sqlite3_free);
+ z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC);
}
/*
diff --git a/src/delete.c b/src/delete.c
index 654570b..2682424 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
-** $Id: delete.c,v 1.170 2008/07/08 23:40:20 drh Exp $
+** $Id: delete.c,v 1.171 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
@@ -107,7 +107,7 @@
}
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
sqlite3Select(pParse, pDup, &dest, 0, 0, 0);
- sqlite3SelectDelete(pDup);
+ sqlite3SelectDelete(db, pDup);
}
#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
@@ -415,8 +415,8 @@
delete_from_cleanup:
sqlite3AuthContextPop(&sContext);
- sqlite3SrcListDelete(pTabList);
- sqlite3ExprDelete(pWhere);
+ sqlite3SrcListDelete(db, pTabList);
+ sqlite3ExprDelete(db, pWhere);
return;
}
diff --git a/src/expr.c b/src/expr.c
index 87be4a9..e8d8a1e 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.386 2008/07/18 17:03:53 drh Exp $
+** $Id: expr.c,v 1.387 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -56,7 +56,8 @@
Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){
char *zColl = 0; /* Dequoted name of collation sequence */
CollSeq *pColl;
- zColl = sqlite3NameFromToken(pParse->db, pName);
+ sqlite3 *db = pParse->db;
+ zColl = sqlite3NameFromToken(db, pName);
if( pExpr && zColl ){
pColl = sqlite3LocateCollSeq(pParse, zColl, -1);
if( pColl ){
@@ -64,7 +65,7 @@
pExpr->flags |= EP_ExpCollate;
}
}
- sqlite3_free(zColl);
+ sqlite3DbFree(db, zColl);
return pExpr;
}
@@ -367,8 +368,8 @@
** this function must always be allocated with sqlite3Expr() for this
** reason.
*/
- sqlite3ExprDelete(pLeft);
- sqlite3ExprDelete(pRight);
+ sqlite3ExprDelete(db, pLeft);
+ sqlite3ExprDelete(db, pRight);
return 0;
}
pNew->op = op;
@@ -477,10 +478,11 @@
*/
Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
Expr *pNew;
+ sqlite3 *db = pParse->db;
assert( pToken );
- pNew = sqlite3DbMallocZero(pParse->db, sizeof(Expr) );
+ pNew = sqlite3DbMallocZero(db, sizeof(Expr) );
if( pNew==0 ){
- sqlite3ExprListDelete(pList); /* Avoid leaking memory when malloc fails */
+ sqlite3ExprListDelete(db, pList); /* Avoid leaking memory when malloc fails */
return 0;
}
pNew->op = TK_FUNCTION;
@@ -578,15 +580,15 @@
/*
** Recursively delete an expression tree.
*/
-void sqlite3ExprDelete(Expr *p){
+void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p==0 ) return;
- if( p->span.dyn ) sqlite3_free((char*)p->span.z);
- if( p->token.dyn ) sqlite3_free((char*)p->token.z);
- sqlite3ExprDelete(p->pLeft);
- sqlite3ExprDelete(p->pRight);
- sqlite3ExprListDelete(p->pList);
- sqlite3SelectDelete(p->pSelect);
- sqlite3_free(p);
+ if( p->span.dyn ) sqlite3DbFree(db, (char*)p->span.z);
+ if( p->token.dyn ) sqlite3DbFree(db, (char*)p->token.z);
+ sqlite3ExprDelete(db, p->pLeft);
+ sqlite3ExprDelete(db, p->pRight);
+ sqlite3ExprListDelete(db, p->pList);
+ sqlite3SelectDelete(db, p->pSelect);
+ sqlite3DbFree(db, p);
}
/*
@@ -637,7 +639,7 @@
return pNew;
}
void sqlite3TokenCopy(sqlite3 *db, Token *pTo, Token *pFrom){
- if( pTo->dyn ) sqlite3_free((char*)pTo->z);
+ if( pTo->dyn ) sqlite3DbFree(db, (char*)pTo->z);
if( pFrom->z ){
pTo->n = pFrom->n;
pTo->z = (u8*)sqlite3DbStrNDup(db, (char*)pFrom->z, pFrom->n);
@@ -657,7 +659,7 @@
pNew->nExpr = pNew->nAlloc = p->nExpr;
pNew->a = pItem = sqlite3DbMallocRaw(db, p->nExpr*sizeof(p->a[0]) );
if( pItem==0 ){
- sqlite3_free(pNew);
+ sqlite3DbFree(db, pNew);
return 0;
}
pOldItem = p->a;
@@ -728,7 +730,7 @@
pNew->nId = pNew->nAlloc = p->nId;
pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) );
if( pNew->a==0 ){
- sqlite3_free(pNew);
+ sqlite3DbFree(db, pNew);
return 0;
}
for(i=0; i<p->nId; i++){
@@ -814,8 +816,8 @@
no_mem:
/* Avoid leaking memory if malloc has failed. */
- sqlite3ExprDelete(pExpr);
- sqlite3ExprListDelete(pList);
+ sqlite3ExprDelete(db, pExpr);
+ sqlite3ExprListDelete(db, pList);
return 0;
}
@@ -839,18 +841,18 @@
/*
** Delete an entire expression list.
*/
-void sqlite3ExprListDelete(ExprList *pList){
+void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
int i;
struct ExprList_item *pItem;
if( pList==0 ) return;
assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) );
assert( pList->nExpr<=pList->nAlloc );
for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
- sqlite3ExprDelete(pItem->pExpr);
- sqlite3_free(pItem->zName);
+ sqlite3ExprDelete(db, pItem->pExpr);
+ sqlite3DbFree(db, pItem->zName);
}
- sqlite3_free(pList->a);
- sqlite3_free(pList);
+ sqlite3DbFree(db, pList->a);
+ sqlite3DbFree(db, pList);
}
/*
@@ -1264,7 +1266,7 @@
pOrig = pEList->a[j].pExpr;
if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
- sqlite3_free(zCol);
+ sqlite3DbFree(db, zCol);
return 2;
}
pDup = sqlite3ExprDup(db, pOrig);
@@ -1272,10 +1274,10 @@
pDup->pColl = pExpr->pColl;
pDup->flags |= EP_ExpCollate;
}
- if( pExpr->span.dyn ) sqlite3_free((char*)pExpr->span.z);
- if( pExpr->token.dyn ) sqlite3_free((char*)pExpr->token.z);
+ if( pExpr->span.dyn ) sqlite3DbFree(db, (char*)pExpr->span.z);
+ if( pExpr->token.dyn ) sqlite3DbFree(db, (char*)pExpr->token.z);
memcpy(pExpr, pDup, sizeof(*pExpr));
- sqlite3_free(pDup);
+ sqlite3DbFree(db, pDup);
cnt = 1;
pMatch = 0;
assert( zTab==0 && zDb==0 );
@@ -1303,7 +1305,7 @@
** fields are not changed in any context.
*/
if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
- sqlite3_free(zCol);
+ sqlite3DbFree(db, zCol);
return 0;
}
@@ -1343,15 +1345,15 @@
lookupname_end:
/* Clean up and return
*/
- sqlite3_free(zDb);
- sqlite3_free(zTab);
- sqlite3ExprDelete(pExpr->pLeft);
+ sqlite3DbFree(db, zDb);
+ sqlite3DbFree(db, zTab);
+ sqlite3ExprDelete(db, pExpr->pLeft);
pExpr->pLeft = 0;
- sqlite3ExprDelete(pExpr->pRight);
+ sqlite3ExprDelete(db, pExpr->pRight);
pExpr->pRight = 0;
pExpr->op = TK_COLUMN;
lookupname_end_2:
- sqlite3_free(zCol);
+ sqlite3DbFree(db, zCol);
if( cnt==1 ){
assert( pNC!=0 );
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
@@ -1966,7 +1968,7 @@
sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iParm);
VdbeComment((v, "Init EXISTS result"));
}
- sqlite3ExprDelete(pSel->pLimit);
+ sqlite3ExprDelete(pParse->db, pSel->pLimit);
pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one);
if( sqlite3Select(pParse, pSel, &dest, 0, 0, 0) ){
return;
diff --git a/src/func.c b/src/func.c
index 47709ca..d4489f9 100644
--- a/src/func.c
+++ b/src/func.c
@@ -16,7 +16,7 @@
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: func.c,v 1.195 2008/07/08 22:28:49 shane Exp $
+** $Id: func.c,v 1.196 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -832,14 +832,14 @@
nOut += nRep - nPattern;
if( nOut>=db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
- sqlite3_free(zOut);
+ sqlite3DbFree(db, zOut);
return;
}
zOld = zOut;
zOut = sqlite3_realloc(zOut, (int)nOut);
if( zOut==0 ){
sqlite3_result_error_nomem(context);
- sqlite3_free(zOld);
+ sqlite3DbFree(db, zOld);
return;
}
memcpy(&zOut[j], zRep, nRep);
diff --git a/src/global.c b/src/global.c
index 4211c58..fa59d4a 100644
--- a/src/global.c
+++ b/src/global.c
@@ -12,7 +12,7 @@
**
** This file contains definitions of global variables and contants.
**
-** $Id: global.c,v 1.3 2008/07/08 14:52:10 drh Exp $
+** $Id: global.c,v 1.4 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
@@ -66,4 +66,12 @@
** The following singleton contains the global configuration for
** the SQLite library.
*/
-struct Sqlite3Config sqlite3Config = { 1, 1, 1, 0x7ffffffe };
+struct Sqlite3Config sqlite3Config = {
+ 1, /* bMemstat */
+ 1, /* bCoreMutex */
+ 1, /* bFullMutex */
+ 0x7ffffffe, /* mxStrlen */
+ 100, /* szLookaside */
+ 500, /* nLookaside */
+ /* Other fields all default to zero */
+};
diff --git a/src/insert.c b/src/insert.c
index 9dda395..9a3d46f 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.247 2008/07/08 23:40:20 drh Exp $
+** $Id: insert.c,v 1.248 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
@@ -45,8 +45,9 @@
int n;
Table *pTab = pIdx->pTable;
sqlite3 *db = sqlite3VdbeDb(v);
- pIdx->zColAff = (char *)sqlite3DbMallocRaw(db, pIdx->nColumn+2);
+ pIdx->zColAff = (char *)sqlite3Malloc(pIdx->nColumn+2);
if( !pIdx->zColAff ){
+ db->mallocFailed = 1;
return;
}
for(n=0; n<pIdx->nColumn; n++){
@@ -86,8 +87,9 @@
int i;
sqlite3 *db = sqlite3VdbeDb(v);
- zColAff = (char *)sqlite3DbMallocRaw(db, pTab->nCol+1);
+ zColAff = (char *)sqlite3Malloc(pTab->nCol+1);
if( !zColAff ){
+ db->mallocFailed = 1;
return;
}
@@ -994,11 +996,11 @@
}
insert_cleanup:
- sqlite3SrcListDelete(pTabList);
- sqlite3ExprListDelete(pList);
- sqlite3SelectDelete(pSelect);
- sqlite3IdListDelete(pColumn);
- sqlite3_free(aRegIdx);
+ sqlite3SrcListDelete(db, pTabList);
+ sqlite3ExprListDelete(db, pList);
+ sqlite3SelectDelete(db, pSelect);
+ sqlite3IdListDelete(db, pColumn);
+ sqlite3DbFree(db, aRegIdx);
}
/*
diff --git a/src/legacy.c b/src/legacy.c
index 6d84d70..825c57b 100644
--- a/src/legacy.c
+++ b/src/legacy.c
@@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: legacy.c,v 1.27 2008/06/15 02:51:47 drh Exp $
+** $Id: legacy.c,v 1.28 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
@@ -122,13 +122,13 @@
}
}
- sqlite3_free(azCols);
+ sqlite3DbFree(db, azCols);
azCols = 0;
}
exec_out:
if( pStmt ) sqlite3_finalize(pStmt);
- if( azCols ) sqlite3_free(azCols);
+ sqlite3DbFree(db, azCols);
rc = sqlite3ApiExit(db, rc);
if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){
diff --git a/src/loadext.c b/src/loadext.c
index b9b47b6..2d44f31 100644
--- a/src/loadext.c
+++ b/src/loadext.c
@@ -12,7 +12,7 @@
** This file contains code used to dynamically load extensions into
** the SQLite library.
**
-** $Id: loadext.c,v 1.51 2008/07/08 14:17:35 danielk1977 Exp $
+** $Id: loadext.c,v 1.52 2008/07/28 19:34:53 drh Exp $
*/
#ifndef SQLITE_CORE
@@ -326,7 +326,7 @@
**
** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with
** error message text. The calling function should free this memory
-** by calling sqlite3_free().
+** by calling sqlite3DbFree(db, ).
*/
static int sqlite3LoadExtension(
sqlite3 *db, /* Load the extension into this database connection */
@@ -365,7 +365,7 @@
sqlite3_snprintf(sizeof(zErr)-1, zErr,
"unable to open shared library [%s]", zFile);
sqlite3OsDlError(pVfs, sizeof(zErr)-1, zErr);
- *pzErrMsg = sqlite3DbStrDup(db, zErr);
+ *pzErrMsg = sqlite3DbStrDup(0, zErr);
}
return SQLITE_ERROR;
}
@@ -378,7 +378,7 @@
sqlite3_snprintf(sizeof(zErr)-1, zErr,
"no entry point [%s] in shared library [%s]", zProc,zFile);
sqlite3OsDlError(pVfs, sizeof(zErr)-1, zErr);
- *pzErrMsg = sqlite3DbStrDup(db, zErr);
+ *pzErrMsg = sqlite3DbStrDup(0, zErr);
sqlite3OsDlClose(pVfs, handle);
}
return SQLITE_ERROR;
@@ -400,7 +400,7 @@
if( db->nExtension>0 ){
memcpy(aHandle, db->aExtension, sizeof(handle)*(db->nExtension-1));
}
- sqlite3_free(db->aExtension);
+ sqlite3DbFree(db, db->aExtension);
db->aExtension = aHandle;
db->aExtension[db->nExtension-1] = handle;
@@ -429,7 +429,7 @@
for(i=0; i<db->nExtension; i++){
sqlite3OsDlClose(db->pVfs, db->aExtension[i]);
}
- sqlite3_free(db->aExtension);
+ sqlite3DbFree(db, db->aExtension);
}
/*
diff --git a/src/main.c b/src/main.c
index cf55878..92e259f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.482 2008/07/25 08:49:00 danielk1977 Exp $
+** $Id: main.c,v 1.483 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -275,6 +275,12 @@
}
#endif
+ case SQLITE_CONFIG_LOOKASIDE: {
+ sqlite3Config.szLookaside = va_arg(ap, int);
+ sqlite3Config.nLookaside = va_arg(ap, int);
+ break;
+ }
+
default: {
rc = SQLITE_ERROR;
break;
@@ -285,6 +291,60 @@
}
/*
+** Set up the lookaside buffers for a database connection.
+** Return SQLITE_OK on success.
+** If lookaside is already active, return SQLITE_BUSY.
+*/
+static int setupLookaside(sqlite3 *db, int sz, int cnt){
+ void *pStart;
+ if( db->lookaside.nOut ){
+ return SQLITE_BUSY;
+ }
+ if( sz<0 ) sz = 0;
+ if( cnt<0 ) cnt = 0;
+ sz = (sz+7)&~7;
+ sqlite3BeginBenignMalloc();
+ pStart = sqlite3Malloc( sz*cnt );
+ sqlite3EndBenignMalloc();
+ if( pStart ){
+ int i;
+ LookasideSlot *p;
+ sqlite3_free(db->lookaside.pStart);
+ db->lookaside.pFree = 0;
+ db->lookaside.pStart = pStart;
+ p = (LookasideSlot*)pStart;
+ for(i=cnt-1; i>=0; i--){
+ p->pNext = db->lookaside.pFree;
+ db->lookaside.pFree = p;
+ p = (LookasideSlot*)&((u8*)p)[sz];
+ }
+ db->lookaside.pEnd = p;
+ db->lookaside.bEnabled = 1;
+ db->lookaside.sz = sz;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Configuration settings for an individual database connection
+*/
+int sqlite3_db_config(sqlite3 *db, int op, ...){
+ va_list ap;
+ int rc = SQLITE_OK;
+ va_start(ap, op);
+ switch( op ){
+ case SQLITE_CONFIG_LOOKASIDE: {
+ int sz = va_arg(ap, int);
+ int cnt = va_arg(ap, int);
+ rc = setupLookaside(db, sz, cnt);
+ break;
+ }
+ }
+ va_end(ap);
+ return rc;
+}
+
+/*
** Routine needed to support the testcase() macro.
*/
#ifdef SQLITE_COVERAGE_TEST
@@ -433,7 +493,7 @@
FuncDef *pFunc, *pNext;
for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
pNext = pFunc->pNext;
- sqlite3_free(pFunc);
+ sqlite3DbFree(db, pFunc);
}
}
@@ -445,7 +505,7 @@
pColl[j].xDel(pColl[j].pUser);
}
}
- sqlite3_free(pColl);
+ sqlite3DbFree(db, pColl);
}
sqlite3HashClear(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -454,7 +514,7 @@
if( pMod->xDestroy ){
pMod->xDestroy(pMod->pAux);
}
- sqlite3_free(pMod);
+ sqlite3DbFree(db, pMod);
}
sqlite3HashClear(&db->aModule);
#endif
@@ -474,10 +534,11 @@
** the same sqliteMalloc() as the one that allocates the database
** structure?
*/
- sqlite3_free(db->aDb[1].pSchema);
+ sqlite3DbFree(db, db->aDb[1].pSchema);
sqlite3_mutex_leave(db->mutex);
db->magic = SQLITE_MAGIC_CLOSED;
sqlite3_mutex_free(db->mutex);
+ sqlite3_free(db->lookaside.pStart);
sqlite3_free(db);
return SQLITE_OK;
}
@@ -807,7 +868,7 @@
assert( !db->mallocFailed );
zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1);
rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal);
- sqlite3_free(zFunc8);
+ sqlite3DbFree(db, zFunc8);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
@@ -1312,6 +1373,7 @@
db->nDb = 2;
db->magic = SQLITE_MAGIC_BUSY;
db->aDb = db->aDbStatic;
+
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
db->autoCommit = 1;
@@ -1453,6 +1515,9 @@
SQLITE_DEFAULT_LOCKING_MODE);
#endif
+ /* Enable the lookaside-malloc subsystem */
+ setupLookaside(db, sqlite3Config.szLookaside, sqlite3Config.nLookaside);
+
opendb_out:
if( db ){
assert( db->mutex!=0 || isThreadsafe==0 || sqlite3Config.bFullMutex==0 );
@@ -1580,7 +1645,7 @@
zName8 = sqlite3Utf16to8(db, zName, -1);
if( zName8 ){
rc = createCollation(db, zName8, enc, pCtx, xCompare, 0);
- sqlite3_free(zName8);
+ sqlite3DbFree(db, zName8);
}
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
@@ -1769,13 +1834,13 @@
if( pAutoinc ) *pAutoinc = autoinc;
if( SQLITE_OK==rc && !pTab ){
- sqlite3_free(zErrMsg);
+ sqlite3DbFree(db, zErrMsg);
zErrMsg = sqlite3MPrintf(db, "no such table column: %s.%s", zTableName,
zColumnName);
rc = SQLITE_ERROR;
}
sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg);
- sqlite3_free(zErrMsg);
+ sqlite3DbFree(db, zErrMsg);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
diff --git a/src/malloc.c b/src/malloc.c
index 86ba2be..f90e627 100644
--- a/src/malloc.c
+++ b/src/malloc.c
@@ -12,7 +12,7 @@
**
** Memory allocation functions used throughout sqlite.
**
-** $Id: malloc.c,v 1.29 2008/07/18 18:56:17 drh Exp $
+** $Id: malloc.c,v 1.30 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
@@ -454,12 +454,26 @@
}
/*
+** TRUE if p is a lookaside memory allocation from db
+*/
+static int isLookaside(sqlite3 *db, void *p){
+ return db && p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
+}
+
+/*
** Return the size of a memory allocation previously obtained from
** sqlite3Malloc() or sqlite3_malloc().
*/
int sqlite3MallocSize(void *p){
return sqlite3Config.m.xSize(p);
}
+int sqlite3DbMallocSize(sqlite3 *db, void *p){
+ if( isLookaside(db, p) ){
+ return db->lookaside.sz;
+ }else{
+ return sqlite3Config.m.xSize(p);
+ }
+}
/*
** Free memory previously obtained from sqlite3Malloc().
@@ -477,6 +491,21 @@
}
/*
+** Free memory that might be associated with a particular database
+** connection.
+*/
+void sqlite3DbFree(sqlite3 *db, void *p){
+ if( isLookaside(db, p) ){
+ LookasideSlot *pBuf = (LookasideSlot*)p;
+ pBuf->pNext = db->lookaside.pFree;
+ db->lookaside.pFree = pBuf;
+ db->lookaside.nOut--;
+ }else{
+ sqlite3_free(p);
+ }
+}
+
+/*
** Change the size of an existing memory allocation
*/
void *sqlite3Realloc(void *pOld, int nBytes){
@@ -558,26 +587,53 @@
** the mallocFailed flag in the connection pointer.
*/
void *sqlite3DbMallocRaw(sqlite3 *db, int n){
- void *p = 0;
- if( !db || db->mallocFailed==0 ){
- p = sqlite3Malloc(n);
- if( !p && db ){
- db->mallocFailed = 1;
+ void *p;
+ if( db ){
+ LookasideSlot *pBuf;
+ if( db->mallocFailed ){
+ return 0;
}
+ if( db->lookaside.bEnabled && n<=db->lookaside.sz
+ && (pBuf = db->lookaside.pFree)!=0 ){
+ db->lookaside.pFree = pBuf->pNext;
+ db->lookaside.nOut++;
+ if( db->lookaside.nOut>db->lookaside.mxOut ){
+ db->lookaside.mxOut = db->lookaside.nOut;
+ }
+ return (void*)pBuf;
+ }
+ }
+ p = sqlite3Malloc(n);
+ if( !p && db ){
+ db->mallocFailed = 1;
}
return p;
}
/*
** Resize the block of memory pointed to by p to n bytes. If the
-** resize fails, set the mallocFailed flag inthe connection object.
+** resize fails, set the mallocFailed flag in the connection object.
*/
void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
void *pNew = 0;
if( db->mallocFailed==0 ){
- pNew = sqlite3_realloc(p, n);
- if( !pNew ){
- db->mallocFailed = 1;
+ if( p==0 ){
+ return sqlite3DbMallocRaw(db, n);
+ }
+ if( isLookaside(db, p) ){
+ if( n<=db->lookaside.sz ){
+ return p;
+ }
+ pNew = sqlite3DbMallocRaw(db, n);
+ if( pNew ){
+ memcpy(pNew, p, db->lookaside.sz);
+ sqlite3DbFree(db, p);
+ }
+ }else{
+ pNew = sqlite3_realloc(p, n);
+ if( !pNew ){
+ db->mallocFailed = 1;
+ }
}
}
return pNew;
@@ -591,7 +647,7 @@
void *pNew;
pNew = sqlite3DbRealloc(db, p, n);
if( !pNew ){
- sqlite3_free(p);
+ sqlite3DbFree(db, p);
}
return pNew;
}
@@ -603,37 +659,30 @@
** called via macros that record the current file and line number in the
** ThreadData structure.
*/
-char *sqlite3StrDup(const char *z){
+char *sqlite3DbStrDup(sqlite3 *db, const char *z){
char *zNew;
- int n;
- if( z==0 ) return 0;
+ size_t n;
+ if( z==0 ){
+ return 0;
+ }
n = strlen(z)+1;
- zNew = sqlite3Malloc(n);
- if( zNew ) memcpy(zNew, z, n);
- return zNew;
-}
-char *sqlite3StrNDup(const char *z, int n){
- char *zNew;
- if( z==0 ) return 0;
- zNew = sqlite3Malloc(n+1);
+ assert( (n&0x7fffffff)==n );
+ zNew = sqlite3DbMallocRaw(db, (int)n);
if( zNew ){
memcpy(zNew, z, n);
- zNew[n] = 0;
- }
- return zNew;
-}
-
-char *sqlite3DbStrDup(sqlite3 *db, const char *z){
- char *zNew = sqlite3StrDup(z);
- if( z && !zNew ){
- db->mallocFailed = 1;
}
return zNew;
}
char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){
- char *zNew = sqlite3StrNDup(z, n);
- if( z && !zNew ){
- db->mallocFailed = 1;
+ char *zNew;
+ if( z==0 ){
+ return 0;
+ }
+ assert( (n&0x7fffffff)==n );
+ zNew = sqlite3DbMallocRaw(db, n+1);
+ if( zNew ){
+ memcpy(zNew, z, n);
+ zNew[n] = 0;
}
return zNew;
}
@@ -650,7 +699,7 @@
va_start(ap, zFormat);
z = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
- sqlite3_free(*pz);
+ sqlite3DbFree(db, *pz);
*pz = z;
}
diff --git a/src/mem6.c b/src/mem6.c
index aafa568..95723ad 100644
--- a/src/mem6.c
+++ b/src/mem6.c
@@ -32,7 +32,7 @@
** fragmentation. On some systems, heap fragmentation can cause a
** significant real-time slowdown.
**
-** $Id: mem6.c,v 1.6 2008/07/25 16:07:01 danielk1977 Exp $
+** $Id: mem6.c,v 1.7 2008/07/28 19:34:53 drh Exp $
*/
#ifdef SQLITE_ENABLE_MEMSYS6
@@ -418,8 +418,9 @@
void *p = &((u32 *)pPrior)[-2];
iSlot = ((u32 *)p)[0];
if( iSlot ){
+ Mem6Chunk *pChunk;
mem6Enter();
- Mem6Chunk *pChunk = (Mem6Chunk *)(&((u8 *)p)[-1 * iSlot]);
+ pChunk = (Mem6Chunk *)(&((u8 *)p)[-1 * iSlot]);
chunkFree(pChunk, p);
if( chunkIsEmpty(pChunk) ){
freeChunk(pChunk);
diff --git a/src/os.c b/src/os.c
index 9d066d0..0f141c3 100644
--- a/src/os.c
+++ b/src/os.c
@@ -13,7 +13,7 @@
** This file contains OS interface code that is common to all
** architectures.
**
-** $Id: os.c,v 1.119 2008/06/26 18:16:06 drh Exp $
+** $Id: os.c,v 1.120 2008/07/28 19:34:53 drh Exp $
*/
#define _SQLITE_OS_C_ 1
#include "sqliteInt.h"
@@ -36,7 +36,7 @@
** sqlite3OsLock()
**
*/
-#if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0)
+#if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0) && 0
#define DO_OS_MALLOC_TEST if (1) { \
void *pTstAlloc = sqlite3Malloc(10); \
if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \
diff --git a/src/parse.y b/src/parse.y
index 7642fe9..8fe3acb 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -14,7 +14,7 @@
** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
-** @(#) $Id: parse.y,v 1.246 2008/07/18 17:03:53 drh Exp $
+** @(#) $Id: parse.y,v 1.247 2008/07/28 19:34:53 drh Exp $
*/
// All token codes are small integers with #defines that begin with "TK_"
@@ -135,7 +135,7 @@
}
create_table_args ::= AS select(S). {
sqlite3EndTable(pParse,0,0,S);
- sqlite3SelectDelete(S);
+ sqlite3SelectDelete(pParse->db, S);
}
columnlist ::= columnlist COMMA column.
columnlist ::= column.
@@ -362,13 +362,13 @@
cmd ::= select(X). {
SelectDest dest = {SRT_Callback, 0, 0, 0, 0};
sqlite3Select(pParse, X, &dest, 0, 0, 0);
- sqlite3SelectDelete(X);
+ sqlite3SelectDelete(pParse->db, X);
}
%type select {Select*}
-%destructor select {sqlite3SelectDelete($$);}
+%destructor select {sqlite3SelectDelete(pParse->db, $$);}
%type oneselect {Select*}
-%destructor oneselect {sqlite3SelectDelete($$);}
+%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);}
select(A) ::= oneselect(X). {A = X;}
%ifndef SQLITE_OMIT_COMPOUND_SELECT
@@ -377,7 +377,7 @@
Z->op = Y;
Z->pPrior = X;
}else{
- sqlite3SelectDelete(X);
+ sqlite3SelectDelete(pParse->db, X);
}
A = Z;
}
@@ -405,9 +405,9 @@
// opcode of TK_ALL.
//
%type selcollist {ExprList*}
-%destructor selcollist {sqlite3ExprListDelete($$);}
+%destructor selcollist {sqlite3ExprListDelete(pParse->db, $$);}
%type sclp {ExprList*}
-%destructor sclp {sqlite3ExprListDelete($$);}
+%destructor sclp {sqlite3ExprListDelete(pParse->db, $$);}
sclp(A) ::= selcollist(X) COMMA. {A = X;}
sclp(A) ::= . {A = 0;}
selcollist(A) ::= sclp(P) expr(X) as(Y). {
@@ -434,11 +434,11 @@
%type seltablist {SrcList*}
-%destructor seltablist {sqlite3SrcListDelete($$);}
+%destructor seltablist {sqlite3SrcListDelete(pParse->db, $$);}
%type stl_prefix {SrcList*}
-%destructor stl_prefix {sqlite3SrcListDelete($$);}
+%destructor stl_prefix {sqlite3SrcListDelete(pParse->db, $$);}
%type from {SrcList*}
-%destructor from {sqlite3SrcListDelete($$);}
+%destructor from {sqlite3SrcListDelete(pParse->db, $$);}
// A complete FROM clause.
//
@@ -470,7 +470,7 @@
// a grouping of table and subqueries.
//
%type seltablist_paren {Select*}
- %destructor seltablist_paren {sqlite3SelectDelete($$);}
+ %destructor seltablist_paren {sqlite3SelectDelete(pParse->db, $$);}
seltablist_paren(A) ::= select(S). {A = S;}
seltablist_paren(A) ::= seltablist(F). {
sqlite3SrcListShiftJoinType(F);
@@ -483,7 +483,7 @@
dbnm(A) ::= DOT nm(X). {A = X;}
%type fullname {SrcList*}
-%destructor fullname {sqlite3SrcListDelete($$);}
+%destructor fullname {sqlite3SrcListDelete(pParse->db, $$);}
fullname(A) ::= nm(X) dbnm(Y). {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y);}
%type joinop {int}
@@ -495,22 +495,22 @@
{ X = sqlite3JoinType(pParse,&A,&B,&C); }
%type on_opt {Expr*}
-%destructor on_opt {sqlite3ExprDelete($$);}
+%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);}
on_opt(N) ::= ON expr(E). {N = E;}
on_opt(N) ::= . {N = 0;}
%type using_opt {IdList*}
-%destructor using_opt {sqlite3IdListDelete($$);}
+%destructor using_opt {sqlite3IdListDelete(pParse->db, $$);}
using_opt(U) ::= USING LP inscollist(L) RP. {U = L;}
using_opt(U) ::= . {U = 0;}
%type orderby_opt {ExprList*}
-%destructor orderby_opt {sqlite3ExprListDelete($$);}
+%destructor orderby_opt {sqlite3ExprListDelete(pParse->db, $$);}
%type sortlist {ExprList*}
-%destructor sortlist {sqlite3ExprListDelete($$);}
+%destructor sortlist {sqlite3ExprListDelete(pParse->db, $$);}
%type sortitem {Expr*}
-%destructor sortitem {sqlite3ExprDelete($$);}
+%destructor sortitem {sqlite3ExprDelete(pParse->db, $$);}
orderby_opt(A) ::= . {A = 0;}
orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;}
@@ -531,12 +531,12 @@
sortorder(A) ::= . {A = SQLITE_SO_ASC;}
%type groupby_opt {ExprList*}
-%destructor groupby_opt {sqlite3ExprListDelete($$);}
+%destructor groupby_opt {sqlite3ExprListDelete(pParse->db, $$);}
groupby_opt(A) ::= . {A = 0;}
groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}
%type having_opt {Expr*}
-%destructor having_opt {sqlite3ExprDelete($$);}
+%destructor having_opt {sqlite3ExprDelete(pParse->db, $$);}
having_opt(A) ::= . {A = 0;}
having_opt(A) ::= HAVING expr(X). {A = X;}
@@ -550,8 +550,8 @@
// except as a transient. So there is never anything to destroy.
//
//%destructor limit_opt {
-// sqlite3ExprDelete($$.pLimit);
-// sqlite3ExprDelete($$.pOffset);
+// sqlite3ExprDelete(pParse->db, $$.pLimit);
+// sqlite3ExprDelete(pParse->db, $$.pOffset);
//}
limit_opt(A) ::= . {A.pLimit = 0; A.pOffset = 0;}
limit_opt(A) ::= LIMIT expr(X). {A.pLimit = X; A.pOffset = 0;}
@@ -565,7 +565,7 @@
cmd ::= DELETE FROM fullname(X) where_opt(Y). {sqlite3DeleteFrom(pParse,X,Y);}
%type where_opt {Expr*}
-%destructor where_opt {sqlite3ExprDelete($$);}
+%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}
where_opt(A) ::= . {A = 0;}
where_opt(A) ::= WHERE expr(X). {A = X;}
@@ -578,7 +578,7 @@
}
%type setlist {ExprList*}
-%destructor setlist {sqlite3ExprListDelete($$);}
+%destructor setlist {sqlite3ExprListDelete(pParse->db, $$);}
setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y).
{A = sqlite3ExprListAppend(pParse,Z,Y,&X);}
@@ -601,7 +601,7 @@
%type itemlist {ExprList*}
-%destructor itemlist {sqlite3ExprListDelete($$);}
+%destructor itemlist {sqlite3ExprListDelete(pParse->db, $$);}
itemlist(A) ::= itemlist(X) COMMA expr(Y).
{A = sqlite3ExprListAppend(pParse,X,Y,0);}
@@ -609,9 +609,9 @@
{A = sqlite3ExprListAppend(pParse,0,X,0);}
%type inscollist_opt {IdList*}
-%destructor inscollist_opt {sqlite3IdListDelete($$);}
+%destructor inscollist_opt {sqlite3IdListDelete(pParse->db, $$);}
%type inscollist {IdList*}
-%destructor inscollist {sqlite3IdListDelete($$);}
+%destructor inscollist {sqlite3IdListDelete(pParse->db, $$);}
inscollist_opt(A) ::= . {A = 0;}
inscollist_opt(A) ::= LP inscollist(X) RP. {A = X;}
@@ -624,9 +624,9 @@
//
%type expr {Expr*}
-%destructor expr {sqlite3ExprDelete($$);}
+%destructor expr {sqlite3ExprDelete(pParse->db, $$);}
%type term {Expr*}
-%destructor term {sqlite3ExprDelete($$);}
+%destructor term {sqlite3ExprDelete(pParse->db, $$);}
expr(A) ::= term(X). {A = X;}
expr(A) ::= LP(B) expr(X) RP(E). {A = X; sqlite3ExprSpan(A,&B,&E); }
@@ -702,7 +702,7 @@
likeop(A) ::= MATCH(X). {A.eOperator = X; A.not = 0;}
likeop(A) ::= NOT MATCH(X). {A.eOperator = X; A.not = 1;}
%type escape {Expr*}
-%destructor escape {sqlite3ExprDelete($$);}
+%destructor escape {sqlite3ExprDelete(pParse->db, $$);}
escape(X) ::= ESCAPE expr(A). [ESCAPE] {X = A;}
escape(X) ::= . [ESCAPE] {X = 0;}
expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE_KW] {
@@ -760,7 +760,7 @@
if( A ){
A->pList = pList;
}else{
- sqlite3ExprListDelete(pList);
+ sqlite3ExprListDelete(pParse->db, pList);
}
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0);
sqlite3ExprSpan(A,&W->span,&Y->span);
@@ -775,7 +775,7 @@
A->pList = Y;
sqlite3ExprSetHeight(pParse, A);
}else{
- sqlite3ExprListDelete(Y);
+ sqlite3ExprListDelete(pParse->db, Y);
}
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0);
sqlite3ExprSpan(A,&X->span,&E);
@@ -786,7 +786,7 @@
A->pSelect = X;
sqlite3ExprSetHeight(pParse, A);
}else{
- sqlite3SelectDelete(X);
+ sqlite3SelectDelete(pParse->db, X);
}
sqlite3ExprSpan(A,&B,&E);
}
@@ -796,7 +796,7 @@
A->pSelect = Y;
sqlite3ExprSetHeight(pParse, A);
}else{
- sqlite3SelectDelete(Y);
+ sqlite3SelectDelete(pParse->db, Y);
}
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0);
sqlite3ExprSpan(A,&X->span,&E);
@@ -808,7 +808,7 @@
A->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
sqlite3ExprSetHeight(pParse, A);
}else{
- sqlite3SrcListDelete(pSrc);
+ sqlite3SrcListDelete(pParse->db, pSrc);
}
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0);
sqlite3ExprSpan(A,&X->span,Z.z?&Z:&Y);
@@ -820,7 +820,7 @@
sqlite3ExprSpan(p,&B,&E);
sqlite3ExprSetHeight(pParse, A);
}else{
- sqlite3SelectDelete(Y);
+ sqlite3SelectDelete(pParse->db, Y);
}
}
%endif SQLITE_OMIT_SUBQUERY
@@ -832,12 +832,12 @@
A->pList = Y;
sqlite3ExprSetHeight(pParse, A);
}else{
- sqlite3ExprListDelete(Y);
+ sqlite3ExprListDelete(pParse->db, Y);
}
sqlite3ExprSpan(A, &C, &E);
}
%type case_exprlist {ExprList*}
-%destructor case_exprlist {sqlite3ExprListDelete($$);}
+%destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);}
case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). {
A = sqlite3ExprListAppend(pParse,X, Y, 0);
A = sqlite3ExprListAppend(pParse,A, Z, 0);
@@ -847,18 +847,18 @@
A = sqlite3ExprListAppend(pParse,A, Z, 0);
}
%type case_else {Expr*}
-%destructor case_else {sqlite3ExprDelete($$);}
+%destructor case_else {sqlite3ExprDelete(pParse->db, $$);}
case_else(A) ::= ELSE expr(X). {A = X;}
case_else(A) ::= . {A = 0;}
%type case_operand {Expr*}
-%destructor case_operand {sqlite3ExprDelete($$);}
+%destructor case_operand {sqlite3ExprDelete(pParse->db, $$);}
case_operand(A) ::= expr(X). {A = X;}
case_operand(A) ::= . {A = 0;}
%type exprlist {ExprList*}
-%destructor exprlist {sqlite3ExprListDelete($$);}
+%destructor exprlist {sqlite3ExprListDelete(pParse->db, $$);}
%type nexprlist {ExprList*}
-%destructor nexprlist {sqlite3ExprListDelete($$);}
+%destructor nexprlist {sqlite3ExprListDelete(pParse->db, $$);}
exprlist(A) ::= nexprlist(X). {A = X;}
exprlist(A) ::= . {A = 0;}
@@ -882,9 +882,9 @@
uniqueflag(A) ::= . {A = OE_None;}
%type idxlist {ExprList*}
-%destructor idxlist {sqlite3ExprListDelete($$);}
+%destructor idxlist {sqlite3ExprListDelete(pParse->db, $$);}
%type idxlist_opt {ExprList*}
-%destructor idxlist_opt {sqlite3ExprListDelete($$);}
+%destructor idxlist_opt {sqlite3ExprListDelete(pParse->db, $$);}
%type idxitem {Token}
idxlist_opt(A) ::= . {A = 0;}
@@ -974,7 +974,7 @@
trigger_time(A) ::= . { A = TK_BEFORE; }
%type trigger_event {struct TrigEvent}
-%destructor trigger_event {sqlite3IdListDelete($$.b);}
+%destructor trigger_event {sqlite3IdListDelete(pParse->db, $$.b);}
trigger_event(A) ::= DELETE|INSERT(OP). {A.a = @OP; A.b = 0;}
trigger_event(A) ::= UPDATE(OP). {A.a = @OP; A.b = 0;}
trigger_event(A) ::= UPDATE OF inscollist(X). {A.a = TK_UPDATE; A.b = X;}
@@ -983,12 +983,12 @@
foreach_clause ::= FOR EACH ROW.
%type when_clause {Expr*}
-%destructor when_clause {sqlite3ExprDelete($$);}
+%destructor when_clause {sqlite3ExprDelete(pParse->db, $$);}
when_clause(A) ::= . { A = 0; }
when_clause(A) ::= WHEN expr(X). { A = X; }
%type trigger_cmd_list {TriggerStep*}
-%destructor trigger_cmd_list {sqlite3DeleteTriggerStep($$);}
+%destructor trigger_cmd_list {sqlite3DeleteTriggerStep(pParse->db, $$);}
trigger_cmd_list(A) ::= trigger_cmd_list(Y) trigger_cmd(X) SEMI. {
if( Y ){
Y->pLast->pNext = X;
@@ -1001,7 +1001,7 @@
trigger_cmd_list(A) ::= . { A = 0; }
%type trigger_cmd {TriggerStep*}
-%destructor trigger_cmd {sqlite3DeleteTriggerStep($$);}
+%destructor trigger_cmd {sqlite3DeleteTriggerStep(pParse->db, $$);}
// UPDATE
trigger_cmd(A) ::= UPDATE orconf(R) nm(X) SET setlist(Y) where_opt(Z).
{ A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R); }
@@ -1061,7 +1061,7 @@
}
%type key_opt {Expr*}
-%destructor key_opt {sqlite3ExprDelete($$);}
+%destructor key_opt {sqlite3ExprDelete(pParse->db, $$);}
key_opt(A) ::= . { A = 0; }
key_opt(A) ::= KEY expr(X). { A = X; }
diff --git a/src/pragma.c b/src/pragma.c
index bac601c..6ffc60d 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
-** $Id: pragma.c,v 1.182 2008/07/08 07:35:52 danielk1977 Exp $
+** $Id: pragma.c,v 1.183 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -682,8 +682,7 @@
}
sqlite3_free(sqlite3_temp_directory);
if( zRight[0] ){
- sqlite3_temp_directory = zRight;
- zRight = 0;
+ sqlite3_temp_directory = sqlite3DbStrDup(0, zRight);
}else{
sqlite3_temp_directory = 0;
}
@@ -1323,8 +1322,8 @@
#endif
}
pragma_out:
- sqlite3_free(zLeft);
- sqlite3_free(zRight);
+ sqlite3DbFree(db, zLeft);
+ sqlite3DbFree(db, zRight);
}
#endif /* SQLITE_OMIT_PRAGMA || SQLITE_OMIT_PARSER */
diff --git a/src/prepare.c b/src/prepare.c
index 6d984f1..a8d98bd 100644
--- a/src/prepare.c
+++ b/src/prepare.c
@@ -13,7 +13,7 @@
** interface, and routines that contribute to loading the database schema
** from disk.
**
-** $Id: prepare.c,v 1.89 2008/07/08 19:34:07 drh Exp $
+** $Id: prepare.c,v 1.90 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -32,7 +32,7 @@
sqlite3SetString(pData->pzErrMsg, pData->db,
"malformed database schema (%s)", zObj);
if( zExtra && zExtra[0] ){
- *pData->pzErrMsg = sqlite3MPrintf(pData->db, "%z - %s",
+ *pData->pzErrMsg = sqlite3MAppendf(pData->db, *pData->pzErrMsg, "%s - %s",
*pData->pzErrMsg, zExtra);
}
}
@@ -79,11 +79,15 @@
*/
char *zErr;
int rc;
+ u8 lookasideEnabled;
assert( db->init.busy );
db->init.iDb = iDb;
db->init.newTnum = atoi(argv[1]);
+ lookasideEnabled = db->lookaside.bEnabled;
+ db->lookaside.bEnabled = 0;
rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
db->init.iDb = 0;
+ db->lookaside.bEnabled = lookasideEnabled;
assert( rc!=SQLITE_OK || zErr==0 );
if( SQLITE_OK!=rc ){
pData->rc = rc;
@@ -92,7 +96,7 @@
}else if( rc!=SQLITE_INTERRUPT ){
corruptSchema(pData, argv[0], zErr);
}
- sqlite3_free(zErr);
+ sqlite3DbFree(db, zErr);
return 1;
}
}else if( argv[0]==0 ){
@@ -336,7 +340,7 @@
#endif
if( rc==SQLITE_ABORT ) rc = initData.rc;
(void)sqlite3SafetyOn(db);
- sqlite3_free(zSql);
+ sqlite3DbFree(db, zSql);
#ifndef SQLITE_OMIT_ANALYZE
if( rc==SQLITE_OK ){
sqlite3AnalysisLoad(db, iDb);
@@ -568,7 +572,7 @@
zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
if( zSqlCopy ){
sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
- sqlite3_free(zSqlCopy);
+ sqlite3DbFree(db, zSqlCopy);
sParse.zTail = &zSql[sParse.zTail-zSqlCopy];
}else{
sParse.zTail = &zSql[nBytes];
@@ -632,7 +636,7 @@
if( zErrMsg ){
sqlite3Error(db, rc, "%s", zErrMsg);
- sqlite3_free(zErrMsg);
+ sqlite3DbFree(db, zErrMsg);
}else{
sqlite3Error(db, rc, 0);
}
@@ -767,7 +771,7 @@
int chars_parsed = sqlite3Utf8CharLen(zSql8, zTail8-zSql8);
*pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
}
- sqlite3_free(zSql8);
+ sqlite3DbFree(db, zSql8);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
diff --git a/src/printf.c b/src/printf.c
index 5935f97..b88a7d8 100644
--- a/src/printf.c
+++ b/src/printf.c
@@ -5,7 +5,7 @@
** an historical reference. Most of the "enhancements" have been backed
** out so that the functionality is now the same as standard printf().
**
-** $Id: printf.c,v 1.92 2008/07/15 00:27:35 drh Exp $
+** $Id: printf.c,v 1.93 2008/07/28 19:34:53 drh Exp $
**
**************************************************************************
**
@@ -746,7 +746,7 @@
}else{
p->nAlloc = szNew;
}
- zNew = sqlite3Malloc( p->nAlloc );
+ zNew = sqlite3DbMallocRaw(p->db, p->nAlloc );
if( zNew ){
memcpy(zNew, p->zText, p->nChar);
sqlite3StrAccumReset(p);
@@ -771,7 +771,7 @@
if( p->zText ){
p->zText[p->nChar] = 0;
if( p->useMalloc && p->zText==p->zBase ){
- p->zText = sqlite3Malloc( p->nChar+1 );
+ p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
if( p->zText ){
memcpy(p->zText, p->zBase, p->nChar+1);
}else{
@@ -787,7 +787,7 @@
*/
void sqlite3StrAccumReset(StrAccum *p){
if( p->zText!=p->zBase ){
- sqlite3_free(p->zText);
+ sqlite3DbFree(p->db, p->zText);
}
p->zText = 0;
}
@@ -797,6 +797,7 @@
*/
void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
p->zText = p->zBase = zBase;
+ p->db = 0;
p->nChar = 0;
p->nAlloc = n;
p->mxAlloc = mx;
@@ -815,6 +816,7 @@
StrAccum acc;
sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH);
+ acc.db = db;
sqlite3VXPrintf(&acc, 1, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
if( acc.mallocFailed && db ){
@@ -837,6 +839,24 @@
}
/*
+** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting
+** the string and before returnning. This routine is intended to be used
+** to modify an existing string. For example:
+**
+** x = sqlite3MPrintf(db, x, "prefix %s suffix", x);
+**
+*/
+char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zFormat, ...){
+ va_list ap;
+ char *z;
+ va_start(ap, zFormat);
+ z = sqlite3VMPrintf(db, zFormat, ap);
+ va_end(ap);
+ sqlite3DbFree(db, zStr);
+ return z;
+}
+
+/*
** Print into memory obtained from sqlite3_malloc(). Omit the internal
** %-conversion extensions.
*/
diff --git a/src/select.c b/src/select.c
index 353ef06..56a75c9 100644
--- a/src/select.c
+++ b/src/select.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.459 2008/07/24 15:50:41 drh Exp $
+** $Id: select.c,v 1.460 2008/07/28 19:34:53 drh Exp $
*/
#include "sqliteInt.h"
@@ -21,16 +21,16 @@
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.
*/
-static void clearSelect(Select *p){
- sqlite3ExprListDelete(p->pEList);
- sqlite3SrcListDelete(p->pSrc);
- sqlite3ExprDelete(p->pWhere);
- sqlite3ExprListDelete(p->pGroupBy);
- sqlite3ExprDelete(p->pHaving);
- sqlite3ExprListDelete(p->pOrderBy);
- sqlite3SelectDelete(p->pPrior);
- sqlite3ExprDelete(p->pLimit);
- sqlite3ExprDelete(p->pOffset);
+static void clearSelect(sqlite3 *db, Select *p){
+ sqlite3ExprListDelete(db, p->pEList);
+ sqlite3SrcListDelete(db, p->pSrc);
+ sqlite3ExprDelete(db, p->pWhere);
+ sqlite3ExprListDelete(db, p->pGroupBy);
+ sqlite3ExprDelete(db, p->pHaving);
+ sqlite3ExprListDelete(db, p->pOrderBy);
+ sqlite3SelectDelete(db, p->pPrior);
+ sqlite3ExprDelete(db, p->pLimit);
+ sqlite3ExprDelete(db, p->pOffset);
}
/*
@@ -88,7 +88,7 @@
pNew->addrOpenEphm[1] = -1;
pNew->addrOpenEphm[2] = -1;
if( pNew==&standin) {
- clearSelect(pNew);
+ clearSelect(db, pNew);
pNew = 0;
}
return pNew;
@@ -97,10 +97,10 @@
/*
** Delete the given Select structure and all of its substructures.
*/
-void sqlite3SelectDelete(Select *p){
+void sqlite3SelectDelete(sqlite3 *db, Select *p){
if( p ){
- clearSelect(p);
- sqlite3_free(p);
+ clearSelect(db, p);
+ sqlite3DbFree(db, p);
}
}
@@ -1163,6 +1163,7 @@
if( pTab==0 ){
return 0;
}
+ pTab->db = db;
pTab->nRef = 1;
pTab->zName = zTabName ? sqlite3DbStrDup(db, zTabName) : 0;
pEList = pSelect->pEList;
@@ -1196,7 +1197,7 @@
zName = sqlite3MPrintf(db, "%T", &p->span);
}
if( db->mallocFailed ){
- sqlite3_free(zName);
+ sqlite3DbFree(db, zName);
break;
}
sqlite3Dequote(zName);
@@ -1207,8 +1208,11 @@
nName = strlen(zName);
for(j=cnt=0; j<i; j++){
if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
+ char *zNewName;
zName[nName] = 0;
- zName = sqlite3MPrintf(db, "%z:%d", zName, ++cnt);
+ zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
+ sqlite3DbFree(db, zName);
+ zName = zNewName;
j = -1;
if( zName==0 ) break;
}
@@ -1474,10 +1478,10 @@
}
rc = 1;
}
- sqlite3_free(zTName);
+ sqlite3DbFree(db, zTName);
}
}
- sqlite3ExprListDelete(pEList);
+ sqlite3ExprListDelete(db, pEList);
p->pEList = pNew;
}
#if SQLITE_MAX_COLUMN
@@ -1538,11 +1542,11 @@
for(i=0; i<pEList->nExpr; i++){
char *zAs = pEList->a[i].zName;
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
- sqlite3_free(zCol);
+ sqlite3DbFree(db, zCol);
return i+1;
}
}
- sqlite3_free(zCol);
+ sqlite3DbFree(db, zCol);
}
/* Resolve all names in the ORDER BY term expression
@@ -1631,7 +1635,7 @@
if( iCol>0 ){
CollSeq *pColl = pE->pColl;
int flags = pE->flags & EP_ExpCollate;
- sqlite3ExprDelete(pE);
+ sqlite3ExprDelete(db, pE);
pE = sqlite3ExprDup(db, pEList->a[iCol-1].pExpr);
pOrderBy->a[i].pExpr = pE;
if( pE && pColl && flags ){
@@ -1702,7 +1706,7 @@
assert(pDup);
iCol = matchOrderByTermToExprList(pParse, pSelect, pDup, i+1, 1, 0);
}
- sqlite3ExprDelete(pDup);
+ sqlite3ExprDelete(db, pDup);
if( iCol<0 ){
return 1;
}
@@ -1882,6 +1886,7 @@
Vdbe *v; /* Generate code to this VDBE */
SelectDest dest; /* Alternative data destination */
Select *pDelete = 0; /* Chain of simple selects to delete */
+ sqlite3 *db; /* Database connection */
/* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only
** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
@@ -1890,6 +1895,7 @@
rc = 1;
goto multi_select_end;
}
+ db = pParse->db;
pPrior = p->pPrior;
assert( pPrior->pRightmost!=pPrior );
assert( pPrior->pRightmost==p->pRightmost );
@@ -2026,11 +2032,11 @@
rc = sqlite3Select(pParse, p, &uniondest, 0, 0, 0);
/* Query flattening in sqlite3Select() might refill p->pOrderBy.
** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
- sqlite3ExprListDelete(p->pOrderBy);
+ sqlite3ExprListDelete(db, p->pOrderBy);
pDelete = p->pPrior;
p->pPrior = pPrior;
p->pOrderBy = 0;
- sqlite3ExprDelete(p->pLimit);
+ sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit;
p->pOffset = pOffset;
p->iLimit = 0;
@@ -2109,7 +2115,7 @@
rc = sqlite3Select(pParse, p, &intersectdest, 0, 0, 0);
pDelete = p->pPrior;
p->pPrior = pPrior;
- sqlite3ExprDelete(p->pLimit);
+ sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit;
p->pOffset = pOffset;
if( rc ){
@@ -2162,20 +2168,20 @@
assert( p->pRightmost==p );
nCol = p->pEList->nExpr;
- pKeyInfo = sqlite3DbMallocZero(pParse->db,
+ pKeyInfo = sqlite3DbMallocZero(db,
sizeof(*pKeyInfo)+nCol*(sizeof(CollSeq*) + 1));
if( !pKeyInfo ){
rc = SQLITE_NOMEM;
goto multi_select_end;
}
- pKeyInfo->enc = ENC(pParse->db);
+ pKeyInfo->enc = ENC(db);
pKeyInfo->nField = nCol;
for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
*apColl = multiSelectCollSeq(pParse, p, i);
if( 0==*apColl ){
- *apColl = pParse->db->pDfltColl;
+ *apColl = db->pDfltColl;
}
}
@@ -2193,13 +2199,13 @@
pLoop->addrOpenEphm[i] = -1;
}
}
- sqlite3_free(pKeyInfo);
+ sqlite3DbFree(db, pKeyInfo);
}
multi_select_end:
pDest->iMem = dest.iMem;
pDest->nMem = dest.nMem;
- sqlite3SelectDelete(pDelete);
+ sqlite3SelectDelete(db, pDelete);
return rc;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
@@ -2622,9 +2628,9 @@
}else{
regLimitA = regLimitB = 0;
}
- sqlite3ExprDelete(p->pLimit);
+ sqlite3ExprDelete(db, p->pLimit);
p->pLimit = 0;
- sqlite3ExprDelete(p->pOffset);
+ sqlite3ExprDelete(db, p->pOffset);
p->pOffset = 0;
regAddrA = ++pParse->nMem;
@@ -2786,7 +2792,7 @@
/* Reassembly the compound query so that it will be freed correctly
** by the calling function */
if( p->pPrior ){
- sqlite3SelectDelete(p->pPrior);
+ sqlite3SelectDelete(db, p->pPrior);
}
p->pPrior = pPrior;
@@ -3155,9 +3161,9 @@
nSubSrc = pSubSrc->nSrc;
jointype = pSubitem->jointype;
sqlite3DeleteTable(pSubitem->pTab);
- sqlite3_free(pSubitem->zDatabase);
- sqlite3_free(pSubitem->zName);
- sqlite3_free(pSubitem->zAlias);
+ sqlite3DbFree(db, pSubitem->zDatabase);
+ sqlite3DbFree(db, pSubitem->zName);
+ sqlite3DbFree(db, pSubitem->zAlias);
pSubitem->pTab = 0;
pSubitem->zDatabase = 0;
pSubitem->zName = 0;
@@ -3254,7 +3260,7 @@
/* Finially, delete what is left of the subquery and return
** success.
*/
- sqlite3SelectDelete(pSub1);
+ sqlite3SelectDelete(db, pSub1);
return 1;
}
@@ -3525,33 +3531,6 @@
pAggInfo->directMode = 0;
}
-#if 0
-/*
-** This function is used when a SELECT statement is used to create a
-** temporary table for iterating through when running an INSTEAD OF
-** UPDATE or INSTEAD OF DELETE trigger.
-**
-** If possible, the SELECT statement is modified so that NULL values
-** are stored in the temporary table for all columns for which the
-** corresponding bit in argument mask is not set. If mask takes the
-** special value 0xffffffff, then all columns are populated.
-*/
-void sqlite3SelectMask(Parse *pParse, Select *p, u32 mask){
- if( p && !p->pPrior && !p->isDistinct && mask!=0xffffffff ){
- ExprList *pEList;
- int i;
- sqlite3SelectResolve(pParse, p, 0);
- pEList = p->pEList;
- for(i=0; pEList && i<pEList->nExpr && i<32; i++){
- if( !(mask&((u32)1<<i)) ){
- sqlite3ExprDelete(pEList->a[i].pExpr);
- pEList->a[i].pExpr = sqlite3Expr(pParse->db, TK_NULL, 0, 0, 0);
- }
- }
- }
-}
-#endif
-
/*
** Generate code for the given SELECT statement.
**
@@ -4144,7 +4123,7 @@
resetAccumulator(pParse, &sAggInfo);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
if( pWInfo==0 ){
- sqlite3ExprListDelete(pDel);
+ sqlite3ExprListDelete(db, pDel);
goto select_end;
}
updateAccumulator(pParse, &sAggInfo);
@@ -4161,7 +4140,7 @@
selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1,
pDest, addrEnd, addrEnd);
- sqlite3ExprListDelete(pDel);
+ sqlite3ExprListDelete(db, pDel);
}
sqlite3VdbeResolveLabel(v, addrEnd);
@@ -4208,8 +4187,8 @@
generateColumnNames(pParse, pTabList, pEList);
}
- sqlite3_free(sAggInfo.aCol);
- sqlite3_free(sAggInfo.aFunc);
+ sqlite3DbFree(db, sAggInfo.aCol);
+ sqlite3DbFree(db, sAggInfo.aFunc);
return rc;
}
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 10434e0..13d6fe5 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -30,7 +30,7 @@
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
-** @(#) $Id: sqlite.h.in,v 1.381 2008/07/28 05:22:36 danielk1977 Exp $
+** @(#) $Id: sqlite.h.in,v 1.382 2008/07/28 19:34:53 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
@@ -972,6 +972,14 @@
int sqlite3_config(int, ...);
/*
+** CAPI3REF: Configure database connections {H10180} <S20000>
+**
+** The sqlite3_db_config() interface is used to make configuration
+** changes to a [database connection].
+*/
+int sqlite3_db_config(sqlite3*, int, ...);
+
+/*
** CAPI3REF: Memory Allocation Routines {H10155} <S20120>
**
** An instance of this object defines the interface between SQLite
@@ -1146,6 +1154,14 @@
** This option can be used to overload the default mutex allocation
** routines with a wrapper used to track mutex usage for performance
** profiling or testing, for example.</dd>
+**
+** <dt>SQLITE_CONFIG_LOOKASIDE</dt>
+** <dd>This option takes two arguments that determine the default
+** memory allcation lookaside optimization. The first argument is the
+** size of each lookaside buffer slot and the second is the number of
+** slots allocated to each database connection.</dd>
+**
+** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
@@ -1159,6 +1175,7 @@
#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_CHUNKALLOC 12 /* int threshold */
+#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
/*
@@ -6073,6 +6090,7 @@
** removal in future releases of SQLite.
*/
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
/*
** CAPI3REF: Status Parameters {H17250} <H17200>
@@ -6136,6 +6154,18 @@
#define SQLITE_STATUS_MALLOC_SIZE 5
#define SQLITE_STATUS_PARSER_STACK 6
+/*
+** CAPI3REF: Status Parameters for database connections {H17275} <H17200>
+**
+** Status verbs for [sqlite3_db_status()].
+**
+** <dl>
+** <dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
+** <dd>This parameter returns the number of lookaside memory slots currently
+** checked out.</dd>
+** </dl>
+*/
+#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
/*
** Undo the hack that converts floating point types to integer for
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 5672394..518fa76 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.746 2008/07/25 15:39:04 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.747 2008/07/28 19:34:54 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -431,6 +431,12 @@
#define ArraySize(X) (sizeof(X)/sizeof(X[0]))
/*
+** The following value as a destructor means to use sqlite3DbFree().
+** This is an internal extension to SQLITE_STATIC and SQLITE_TRANSIENT.
+*/
+#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3DbFree)
+
+/*
** Forward references to structures
*/
typedef struct AggInfo AggInfo;
@@ -448,6 +454,8 @@
typedef struct Index Index;
typedef struct KeyClass KeyClass;
typedef struct KeyInfo KeyInfo;
+typedef struct Lookaside Lookaside;
+typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
typedef struct Parse Parse;
@@ -550,6 +558,32 @@
#define SQLITE_N_LIMIT (SQLITE_LIMIT_VARIABLE_NUMBER+1)
/*
+** Lookaside malloc is a set of fixed-size buffers that can be used
+** to satisify small transient memory allocation requests for objects
+** associated with a particular database connection. The use of
+** lookaside malloc provides a significant performance enhancement
+** (approx 10%) by avoiding numerous malloc/free requests while parsing
+** SQL statements.
+**
+** The Lookaside structure holds configuration information about the
+** lookaside malloc subsystem. Each available memory allocation in
+** the lookaside subsystem is stored on a linked list of LookasideSlot
+** objects.
+*/
+struct Lookaside {
+ u16 sz; /* Size of each buffer in bytes */
+ u8 bEnabled; /* True if use lookaside. False to ignore it */
+ int nOut; /* Number of buffers currently checked out */
+ int mxOut; /* Highwater mark for nOut */
+ LookasideSlot *pFree; /* List if available buffers */
+ void *pStart; /* First byte of available memory space */
+ void *pEnd; /* First byte past end of available space */
+};
+struct LookasideSlot {
+ LookasideSlot *pNext; /* Next buffer in the list of free buffers */
+};
+
+/*
** Each database is an instance of the following structure.
**
** The sqlite.lastRowid records the last insert rowid generated by an
@@ -628,6 +662,7 @@
int isInterrupted; /* True if sqlite3_interrupt has been called */
double notUsed1; /* Spacer */
} u1;
+ Lookaside lookaside; /* Lookaside malloc configuration */
#ifndef SQLITE_OMIT_AUTHORIZATION
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
/* Access authorization function */
@@ -867,6 +902,7 @@
** of a SELECT statement.
*/
struct Table {
+ sqlite3 *db; /* Associated database connection. Might be NULL. */
char *zName; /* Name of the table */
int nCol; /* Number of columns in this table */
Column *aCol; /* Information about each column */
@@ -1744,10 +1780,11 @@
** do not necessarily know how big the string will be in the end.
*/
struct StrAccum {
- char *zBase; /* A base allocation. Not from malloc. */
- char *zText; /* The string collected so far */
- int nChar; /* Length of the string so far */
- int nAlloc; /* Amount of space allocated in zText */
+ sqlite3 *db; /* Optional database for lookaside. Can be NULL */
+ char *zBase; /* A base allocation. Not from malloc. */
+ char *zText; /* The string collected so far */
+ int nChar; /* Length of the string so far */
+ int nAlloc; /* Amount of space allocated in zText */
int mxAlloc; /* Maximum allowed string length */
u8 mallocFailed; /* Becomes true if any memory allocation fails */
u8 useMalloc; /* True if zText is enlargable using realloc */
@@ -1775,6 +1812,8 @@
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 */
sqlite3_mem_methods m; /* Low-level memory allocation interface */
sqlite3_mutex_methods mutex; /* Low-level mutex interface */
void *pHeap; /* Heap storage space */
@@ -1830,14 +1869,14 @@
void *sqlite3MallocZero(int);
void *sqlite3DbMallocZero(sqlite3*, int);
void *sqlite3DbMallocRaw(sqlite3*, int);
-char *sqlite3StrDup(const char*);
-char *sqlite3StrNDup(const char*, int);
char *sqlite3DbStrDup(sqlite3*,const char*);
char *sqlite3DbStrNDup(sqlite3*,const char*, int);
void *sqlite3Realloc(void*, int);
void *sqlite3DbReallocOrFree(sqlite3 *, void *, int);
void *sqlite3DbRealloc(sqlite3 *, void *, int);
-int sqlite3MallocSize(void *);
+void sqlite3DbFree(sqlite3*, void*);
+int sqlite3MallocSize(void*);
+int sqlite3DbMallocSize(sqlite3*, void*);
void *sqlite3ScratchMalloc(int);
void sqlite3ScratchFree(void*);
void *sqlite3PageMalloc(int);
@@ -1866,6 +1905,7 @@
void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
char *sqlite3MPrintf(sqlite3*,const char*, ...);
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
+char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
void sqlite3DebugPrintf(const char*, ...);
#endif
@@ -1891,9 +1931,9 @@
void sqlite3ExprSpan(Expr*,Token*,Token*);
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*);
-void sqlite3ExprDelete(Expr*);
+void sqlite3ExprDelete(sqlite3*, Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*,Token*);
-void sqlite3ExprListDelete(ExprList*);
+void sqlite3ExprListDelete(sqlite3*, ExprList*);
int sqlite3Init(sqlite3*, char**);
int sqlite3InitCallback(void*, int, char**, char**);
void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
@@ -1938,15 +1978,15 @@
Select*, Expr*, IdList*);
void sqlite3SrcListShiftJoinType(SrcList*);
void sqlite3SrcListAssignCursors(Parse*, SrcList*);
-void sqlite3IdListDelete(IdList*);
-void sqlite3SrcListDelete(SrcList*);
+void sqlite3IdListDelete(sqlite3*, IdList*);
+void sqlite3SrcListDelete(sqlite3*, SrcList*);
void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Token*, int, int);
void sqlite3DropIndex(Parse*, SrcList*, int);
int sqlite3Select(Parse*, Select*, SelectDest*, Select*, int, int*);
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,int,Expr*,Expr*);
-void sqlite3SelectDelete(Select*);
+void sqlite3SelectDelete(sqlite3*, Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
@@ -2035,17 +2075,17 @@
int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int,
int, int, u32*, u32*);
void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
- void sqlite3DeleteTriggerStep(TriggerStep*);
+ void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*);
TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
ExprList*,Select*,int);
TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, int);
TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
- void sqlite3DeleteTrigger(Trigger*);
+ void sqlite3DeleteTrigger(sqlite3*, Trigger*);
void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
#else
# define sqlite3TriggersExist(A,B,C,D,E,F) 0
-# define sqlite3DeleteTrigger(A)
+# define sqlite3DeleteTrigger(A,B)
# define sqlite3DropTriggerPtr(A,B)
# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J,K) 0
diff --git a/src/status.c b/src/status.c
index 504f44e..a5e45dd 100644
--- a/src/status.c
+++ b/src/status.c
@@ -13,7 +13,7 @@
** This module implements the sqlite3_status() interface and related
** functionality.
**
-** $Id: status.c,v 1.4 2008/07/25 15:39:04 drh Exp $
+** $Id: status.c,v 1.5 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
@@ -83,3 +83,26 @@
}
return SQLITE_OK;
}
+
+/*
+** Query status information for a single database connection
+*/
+int sqlite3_db_status(
+ sqlite3 *db, /* The database connection whose status is desired */
+ int op, /* Status verb */
+ int *pCurrent, /* Write current value here */
+ int *pHighwater, /* Write high-water mark here */
+ int resetFlag /* Reset high-water mark if true */
+){
+ switch( op ){
+ case SQLITE_DBSTATUS_LOOKASIDE_USED: {
+ *pCurrent = db->lookaside.nOut;
+ *pHighwater = db->lookaside.mxOut;
+ if( resetFlag ){
+ db->lookaside.mxOut = db->lookaside.nOut;
+ }
+ break;
+ }
+ }
+ return SQLITE_OK;
+}
diff --git a/src/test4.c b/src/test4.c
index 622ca93..de5d3a2 100644
--- a/src/test4.c
+++ b/src/test4.c
@@ -11,7 +11,7 @@
*************************************************************************
** Code for testing the the SQLite library in a multithreaded environment.
**
-** $Id: test4.c,v 1.22 2008/06/26 10:41:19 danielk1977 Exp $
+** $Id: test4.c,v 1.23 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -142,7 +142,7 @@
}
threadset[i].busy = 1;
sqlite3_free(threadset[i].zFilename);
- threadset[i].zFilename = sqlite3StrDup(argv[2]);
+ threadset[i].zFilename = sqlite3DbStrDup(0, argv[2]);
threadset[i].opnum = 1;
threadset[i].completed = 0;
rc = pthread_create(&x, 0, thread_main, &threadset[i]);
@@ -476,7 +476,7 @@
thread_wait(&threadset[i]);
threadset[i].xOp = do_compile;
sqlite3_free(threadset[i].zArg);
- threadset[i].zArg = sqlite3StrDup(argv[2]);
+ threadset[i].zArg = sqlite3DbStrDup(0, argv[2]);
threadset[i].opnum++;
return TCL_OK;
}
diff --git a/src/test5.c b/src/test5.c
index 58d65aa..cbb8840 100644
--- a/src/test5.c
+++ b/src/test5.c
@@ -15,7 +15,7 @@
** is used for testing the SQLite routines for converting between
** the various supported unicode encodings.
**
-** $Id: test5.c,v 1.20 2007/08/21 19:33:57 drh Exp $
+** $Id: test5.c,v 1.21 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
@@ -154,7 +154,7 @@
if( enc_from==SQLITE_UTF8 ){
z = Tcl_GetString(objv[1]);
if( objc==5 ){
- z = sqlite3StrDup(z);
+ z = sqlite3DbStrDup(0, z);
}
sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel);
}else{
diff --git a/src/test7.c b/src/test7.c
index 04a10fa..78754bf 100644
--- a/src/test7.c
+++ b/src/test7.c
@@ -12,7 +12,7 @@
** Code for testing the client/server version of the SQLite library.
** Derived from test4.c.
**
-** $Id: test7.c,v 1.11 2008/06/26 10:41:19 danielk1977 Exp $
+** $Id: test7.c,v 1.12 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -164,7 +164,7 @@
}
threadset[i].busy = 1;
sqlite3_free(threadset[i].zFilename);
- threadset[i].zFilename = sqlite3StrDup(argv[2]);
+ threadset[i].zFilename = sqlite3DbStrDup(0, argv[2]);
threadset[i].opnum = 1;
threadset[i].completed = 0;
rc = pthread_create(&x, 0, client_main, &threadset[i]);
@@ -507,7 +507,7 @@
client_wait(&threadset[i]);
threadset[i].xOp = do_compile;
sqlite3_free(threadset[i].zArg);
- threadset[i].zArg = sqlite3StrDup(argv[2]);
+ threadset[i].zArg = sqlite3DbStrDup(0, argv[2]);
threadset[i].opnum++;
return TCL_OK;
}
diff --git a/src/test8.c b/src/test8.c
index c64e55d..effd768 100644
--- a/src/test8.c
+++ b/src/test8.c
@@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test8.c,v 1.68 2008/07/23 18:17:32 drh Exp $
+** $Id: test8.c,v 1.69 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -459,7 +459,7 @@
rc = sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
if( rc!=SQLITE_OK ){
- *pzErr = sqlite3StrDup(sqlite3_errmsg(db));
+ *pzErr = sqlite3DbStrDup(0, sqlite3_errmsg(db));
}
}
diff --git a/src/test_malloc.c b/src/test_malloc.c
index 0c963ad..d8cc158 100644
--- a/src/test_malloc.c
+++ b/src/test_malloc.c
@@ -13,7 +13,7 @@
** This file contains code used to implement test interfaces to the
** memory allocation subsystem.
**
-** $Id: test_malloc.c,v 1.41 2008/07/25 15:39:04 drh Exp $
+** $Id: test_malloc.c,v 1.42 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -979,6 +979,56 @@
}
/*
+** Usage: sqlite3_config_lookaside SIZE COUNT
+**
+*/
+static int test_config_lookaside(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ int rc;
+ int sz, cnt;
+ if( objc!=3 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "SIZE COUNT");
+ return TCL_ERROR;
+ }
+ if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
+ if( Tcl_GetIntFromObj(interp, objv[2], &cnt) ) return TCL_ERROR;
+ rc = sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, cnt);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
+ return TCL_OK;
+}
+
+
+/*
+** Usage: sqlite3_db_config_lookaside CONNECTION SIZE COUNT
+**
+*/
+static int test_db_config_lookaside(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ int rc;
+ int sz, cnt;
+ sqlite3 *db;
+ int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
+ if( objc!=4 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "SIZE COUNT");
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+ if( Tcl_GetIntFromObj(interp, objv[2], &sz) ) return TCL_ERROR;
+ if( Tcl_GetIntFromObj(interp, objv[3], &cnt) ) return TCL_ERROR;
+ rc = sqlite3_db_config(db, SQLITE_CONFIG_LOOKASIDE, sz, cnt);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
+ return TCL_OK;
+}
+
+/*
** Usage:
**
** sqlite3_config_heap NBYTE NMINALLOC
@@ -1113,6 +1163,57 @@
}
/*
+** Usage: sqlite3_db_status DATABASE OPCODE RESETFLAG
+**
+** Return a list of three elements which are the sqlite3_db_status() return
+** code, the current value, and the high-water mark value.
+*/
+static int test_db_status(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ int rc, iValue, mxValue;
+ int i, op, resetFlag;
+ const char *zOpName;
+ sqlite3 *db;
+ int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
+ static const struct {
+ const char *zName;
+ int op;
+ } aOp[] = {
+ { "SQLITE_DBSTATUS_LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED },
+ };
+ Tcl_Obj *pResult;
+ if( objc!=4 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG");
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+ zOpName = Tcl_GetString(objv[2]);
+ for(i=0; i<ArraySize(aOp); i++){
+ if( strcmp(aOp[i].zName, zOpName)==0 ){
+ op = aOp[i].op;
+ break;
+ }
+ }
+ if( i>=ArraySize(aOp) ){
+ if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
+ }
+ if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
+ iValue = 0;
+ mxValue = 0;
+ rc = sqlite3_db_status(db, op, &iValue, &mxValue, resetFlag);
+ pResult = Tcl_NewObj();
+ Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
+ Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue));
+ Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue));
+ Tcl_SetObjResult(interp, pResult);
+ return TCL_OK;
+}
+
+/*
** install_malloc_faultsim BOOLEAN
*/
static int test_install_malloc_faultsim(
@@ -1162,10 +1263,13 @@
{ "sqlite3_config_scratch", test_config_scratch ,0 },
{ "sqlite3_config_pagecache", test_config_pagecache ,0 },
{ "sqlite3_status", test_status ,0 },
+ { "sqlite3_db_status", test_db_status ,0 },
{ "install_malloc_faultsim", test_install_malloc_faultsim ,0 },
{ "sqlite3_config_heap", test_config_heap ,0 },
{ "sqlite3_config_memstatus", test_config_memstatus ,0 },
{ "sqlite3_config_chunkalloc", test_config_chunkalloc ,0 },
+ { "sqlite3_config_lookaside", test_config_lookaside ,0 },
+ { "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 },
{ "sqlite3_dump_memsys3", test_dump_memsys3 ,3 },
{ "sqlite3_dump_memsys5", test_dump_memsys3 ,5 }
};
diff --git a/src/tokenize.c b/src/tokenize.c
index 70b2d3a..bea8d5e 100644
--- a/src/tokenize.c
+++ b/src/tokenize.c
@@ -15,7 +15,7 @@
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
-** $Id: tokenize.c,v 1.147 2008/07/25 15:39:04 drh Exp $
+** $Id: tokenize.c,v 1.148 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -427,7 +427,7 @@
break;
}
case TK_ILLEGAL: {
- sqlite3_free(*pzErrMsg);
+ sqlite3DbFree(db, *pzErrMsg);
*pzErrMsg = sqlite3MPrintf(db, "unrecognized token: \"%T\"",
&pParse->sLastToken);
nErr++;
@@ -471,7 +471,7 @@
if( *pzErrMsg==0 ){
*pzErrMsg = pParse->zErrMsg;
}else{
- sqlite3_free(pParse->zErrMsg);
+ sqlite3DbFree(db, pParse->zErrMsg);
}
pParse->zErrMsg = 0;
nErr++;
@@ -482,13 +482,13 @@
}
#ifndef SQLITE_OMIT_SHARED_CACHE
if( pParse->nested==0 ){
- sqlite3_free(pParse->aTableLock);
+ sqlite3DbFree(db, pParse->aTableLock);
pParse->aTableLock = 0;
pParse->nTableLock = 0;
}
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3_free(pParse->apVtabLock);
+ sqlite3DbFree(db, pParse->apVtabLock);
#endif
if( !IN_DECLARE_VTAB ){
@@ -499,8 +499,8 @@
sqlite3DeleteTable(pParse->pNewTable);
}
- sqlite3DeleteTrigger(pParse->pNewTrigger);
- sqlite3_free(pParse->apVarExpr);
+ sqlite3DeleteTrigger(db, pParse->pNewTrigger);
+ sqlite3DbFree(db, pParse->apVarExpr);
if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
pParse->rc = SQLITE_ERROR;
}
diff --git a/src/trigger.c b/src/trigger.c
index ccee829..760c708 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -10,7 +10,7 @@
*************************************************************************
**
**
-** $Id: trigger.c,v 1.127 2008/07/08 23:40:20 drh Exp $
+** $Id: trigger.c,v 1.128 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
@@ -18,18 +18,18 @@
/*
** Delete a linked list of TriggerStep structures.
*/
-void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){
+void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){
while( pTriggerStep ){
TriggerStep * pTmp = pTriggerStep;
pTriggerStep = pTriggerStep->pNext;
- if( pTmp->target.dyn ) sqlite3_free((char*)pTmp->target.z);
- sqlite3ExprDelete(pTmp->pWhere);
- sqlite3ExprListDelete(pTmp->pExprList);
- sqlite3SelectDelete(pTmp->pSelect);
- sqlite3IdListDelete(pTmp->pIdList);
+ if( pTmp->target.dyn ) sqlite3DbFree(db, (char*)pTmp->target.z);
+ sqlite3ExprDelete(db, pTmp->pWhere);
+ sqlite3ExprListDelete(db, pTmp->pExprList);
+ sqlite3SelectDelete(db, pTmp->pSelect);
+ sqlite3IdListDelete(db, pTmp->pIdList);
- sqlite3_free(pTmp);
+ sqlite3DbFree(db, pTmp);
}
}
@@ -186,12 +186,12 @@
pParse->pNewTrigger = pTrigger;
trigger_cleanup:
- sqlite3_free(zName);
- sqlite3SrcListDelete(pTableName);
- sqlite3IdListDelete(pColumns);
- sqlite3ExprDelete(pWhen);
+ sqlite3DbFree(db, zName);
+ sqlite3SrcListDelete(db, pTableName);
+ sqlite3IdListDelete(db, pColumns);
+ sqlite3ExprDelete(db, pWhen);
if( !pParse->pNewTrigger ){
- sqlite3DeleteTrigger(pTrigger);
+ sqlite3DeleteTrigger(db, pTrigger);
}else{
assert( pParse->pNewTrigger==pTrigger );
}
@@ -241,7 +241,7 @@
"INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrig->name,
pTrig->table, z);
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(
db, "type='trigger' AND name='%q'", pTrig->name), P4_DYNAMIC
@@ -268,9 +268,9 @@
}
triggerfinish_cleanup:
- sqlite3DeleteTrigger(pTrig);
+ sqlite3DeleteTrigger(db, pTrig);
assert( !pParse->pNewTrigger );
- sqlite3DeleteTriggerStep(pStepList);
+ sqlite3DeleteTriggerStep(db, pStepList);
}
/*
@@ -290,22 +290,22 @@
}
if( p->pSelect ){
Select *pNew = sqlite3SelectDup(db, p->pSelect);
- sqlite3SelectDelete(p->pSelect);
+ sqlite3SelectDelete(db, p->pSelect);
p->pSelect = pNew;
}
if( p->pWhere ){
Expr *pNew = sqlite3ExprDup(db, p->pWhere);
- sqlite3ExprDelete(p->pWhere);
+ sqlite3ExprDelete(db, p->pWhere);
p->pWhere = pNew;
}
if( p->pExprList ){
ExprList *pNew = sqlite3ExprListDup(db, p->pExprList);
- sqlite3ExprListDelete(p->pExprList);
+ sqlite3ExprListDelete(db, p->pExprList);
p->pExprList = pNew;
}
if( p->pIdList ){
IdList *pNew = sqlite3IdListDup(db, p->pIdList);
- sqlite3IdListDelete(p->pIdList);
+ sqlite3IdListDelete(db, p->pIdList);
p->pIdList = pNew;
}
}
@@ -320,7 +320,7 @@
TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
if( pTriggerStep==0 ) {
- sqlite3SelectDelete(pSelect);
+ sqlite3SelectDelete(db, pSelect);
return 0;
}
@@ -362,9 +362,9 @@
pTriggerStep->orconf = orconf;
sqlitePersistTriggerStep(db, pTriggerStep);
}else{
- sqlite3IdListDelete(pColumn);
- sqlite3ExprListDelete(pEList);
- sqlite3SelectDelete(pSelect);
+ sqlite3IdListDelete(db, pColumn);
+ sqlite3ExprListDelete(db, pEList);
+ sqlite3SelectDelete(db, pSelect);
}
return pTriggerStep;
@@ -384,8 +384,8 @@
){
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
if( pTriggerStep==0 ){
- sqlite3ExprListDelete(pEList);
- sqlite3ExprDelete(pWhere);
+ sqlite3ExprListDelete(db, pEList);
+ sqlite3ExprDelete(db, pWhere);
return 0;
}
@@ -411,7 +411,7 @@
){
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
if( pTriggerStep==0 ){
- sqlite3ExprDelete(pWhere);
+ sqlite3ExprDelete(db, pWhere);
return 0;
}
@@ -427,15 +427,15 @@
/*
** Recursively delete a Trigger structure
*/
-void sqlite3DeleteTrigger(Trigger *pTrigger){
+void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
if( pTrigger==0 ) return;
- sqlite3DeleteTriggerStep(pTrigger->step_list);
- sqlite3_free(pTrigger->name);
- sqlite3_free(pTrigger->table);
- sqlite3ExprDelete(pTrigger->pWhen);
- sqlite3IdListDelete(pTrigger->pColumns);
- if( pTrigger->nameToken.dyn ) sqlite3_free((char*)pTrigger->nameToken.z);
- sqlite3_free(pTrigger);
+ sqlite3DeleteTriggerStep(db, pTrigger->step_list);
+ sqlite3DbFree(db, pTrigger->name);
+ sqlite3DbFree(db, pTrigger->table);
+ sqlite3ExprDelete(db, pTrigger->pWhen);
+ sqlite3IdListDelete(db, pTrigger->pColumns);
+ if( pTrigger->nameToken.dyn ) sqlite3DbFree(db, (char*)pTrigger->nameToken.z);
+ sqlite3DbFree(db, pTrigger);
}
/*
@@ -478,7 +478,7 @@
sqlite3DropTriggerPtr(pParse, pTrigger);
drop_trigger_cleanup:
- sqlite3SrcListDelete(pName);
+ sqlite3SrcListDelete(db, pName);
}
/*
@@ -570,7 +570,7 @@
}
assert(cc);
}
- sqlite3DeleteTrigger(pTrigger);
+ sqlite3DeleteTrigger(db, pTrigger);
db->flags |= SQLITE_InternChanges;
}
}
@@ -681,7 +681,7 @@
sqlite3SelectDestInit(&dest, SRT_Discard, 0);
sqlite3SelectResolve(pParse, ss, 0);
sqlite3Select(pParse, ss, &dest, 0, 0, 0);
- sqlite3SelectDelete(ss);
+ sqlite3SelectDelete(db, ss);
}
break;
}
@@ -831,11 +831,11 @@
whenExpr = sqlite3ExprDup(db, p->pWhen);
if( db->mallocFailed || sqlite3ExprResolveNames(&sNC, whenExpr) ){
pParse->trigStack = trigStackEntry.pNext;
- sqlite3ExprDelete(whenExpr);
+ sqlite3ExprDelete(db, whenExpr);
return 1;
}
sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, SQLITE_JUMPIFNULL);
- sqlite3ExprDelete(whenExpr);
+ sqlite3ExprDelete(db, whenExpr);
codeTriggerProgram(pParse, p->step_list, orconf);
diff --git a/src/update.c b/src/update.c
index 9df8366..7647d4a 100644
--- a/src/update.c
+++ b/src/update.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.180 2008/07/09 16:51:51 drh Exp $
+** $Id: update.c,v 1.181 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
@@ -570,11 +570,11 @@
update_cleanup:
sqlite3AuthContextPop(&sContext);
- sqlite3_free(aRegIdx);
- sqlite3_free(aXRef);
- sqlite3SrcListDelete(pTabList);
- sqlite3ExprListDelete(pChanges);
- sqlite3ExprDelete(pWhere);
+ sqlite3DbFree(db, aRegIdx);
+ sqlite3DbFree(db, aXRef);
+ sqlite3SrcListDelete(db, pTabList);
+ sqlite3ExprListDelete(db, pChanges);
+ sqlite3ExprDelete(db, pWhere);
return;
}
@@ -668,7 +668,7 @@
sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
/* Cleanup */
- sqlite3SelectDelete(pSelect);
+ sqlite3SelectDelete(db, pSelect);
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/src/util.c b/src/util.c
index 1834083..919452c 100644
--- a/src/util.c
+++ b/src/util.c
@@ -14,7 +14,7 @@
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
-** $Id: util.c,v 1.240 2008/07/24 17:06:48 drh Exp $
+** $Id: util.c,v 1.241 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
@@ -98,7 +98,7 @@
va_start(ap, zFormat);
z = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
- sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, sqlite3_free);
+ sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
}else{
sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
}
@@ -124,10 +124,11 @@
*/
void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
va_list ap;
+ sqlite3 *db = pParse->db;
pParse->nErr++;
- sqlite3_free(pParse->zErrMsg);
+ sqlite3DbFree(db, pParse->zErrMsg);
va_start(ap, zFormat);
- pParse->zErrMsg = sqlite3VMPrintf(pParse->db, zFormat, ap);
+ pParse->zErrMsg = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
if( pParse->rc==SQLITE_OK ){
pParse->rc = SQLITE_ERROR;
@@ -138,7 +139,7 @@
** Clear the error message in pParse, if any
*/
void sqlite3ErrorClear(Parse *pParse){
- sqlite3_free(pParse->zErrMsg);
+ sqlite3DbFree(pParse->db, pParse->zErrMsg);
pParse->zErrMsg = 0;
pParse->nErr = 0;
}
diff --git a/src/vdbe.c b/src/vdbe.c
index caf6d5c..cab2cde 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.765 2008/07/26 18:47:27 danielk1977 Exp $
+** $Id: vdbe.c,v 1.766 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -895,7 +895,7 @@
pOut->flags |= MEM_Static;
pOut->flags &= ~MEM_Dyn;
if( pOp->p4type==P4_DYNAMIC ){
- sqlite3_free(pOp->p4.z);
+ sqlite3DbFree(db, pOp->p4.z);
}
pOp->p4type = P4_DYNAMIC;
pOp->p4.z = pOut->z;
@@ -2605,7 +2605,7 @@
iMeta = 0;
}
if( rc==SQLITE_OK && iMeta!=pOp->p2 ){
- sqlite3_free(p->zErrMsg);
+ sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
/* If the schema-cookie from the database file matches the cookie
** stored with the in-memory representation of the schema, do
@@ -3470,7 +3470,7 @@
}
if( pC->pseudoTable ){
if( !pC->ephemPseudoTable ){
- sqlite3_free(pC->pData);
+ sqlite3DbFree(db, pC->pData);
}
pC->iKey = iKey;
pC->nData = pData->n;
@@ -4149,7 +4149,7 @@
assert( !db->mallocFailed );
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
if( rc==SQLITE_ABORT ) rc = initData.rc;
- sqlite3_free(zSql);
+ sqlite3DbFree(db, zSql);
db->init.busy = 0;
(void)sqlite3SafetyOn(db);
if( rc==SQLITE_NOMEM ){
@@ -4241,7 +4241,7 @@
nRoot = pOp->p2;
assert( nRoot>0 );
- aRoot = sqlite3Malloc( sizeof(int)*(nRoot+1) );
+ aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) );
if( aRoot==0 ) goto no_mem;
assert( pOp->p3>0 && pOp->p3<=p->nMem );
pnErr = &p->aMem[pOp->p3];
@@ -4265,7 +4265,7 @@
}
UPDATE_MAX_BLOBSIZE(pIn1);
sqlite3VdbeChangeEncoding(pIn1, encoding);
- sqlite3_free(aRoot);
+ sqlite3DbFree(db, aRoot);
break;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
@@ -4275,6 +4275,7 @@
** Write the integer from register P1 into the Fifo.
*/
case OP_FifoWrite: { /* in1 */
+ p->sFifo.db = db;
if( sqlite3VdbeFifoPush(&p->sFifo, sqlite3VdbeIntValue(pIn1))==SQLITE_NOMEM ){
goto no_mem;
}
@@ -4322,7 +4323,7 @@
pContext->lastRowid = db->lastRowid;
pContext->nChange = p->nChange;
pContext->sFifo = p->sFifo;
- sqlite3VdbeFifoInit(&p->sFifo);
+ sqlite3VdbeFifoInit(&p->sFifo, db);
break;
}
@@ -4628,7 +4629,7 @@
assert(pVtab && pModule);
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xOpen(pVtab, &pVtabCursor);
- sqlite3_free(p->zErrMsg);
+ sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
@@ -4860,7 +4861,7 @@
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
sqlite3VtabLock(pVtab);
rc = pVtab->pModule->xRename(pVtab, pName->z);
- sqlite3_free(p->zErrMsg);
+ sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
sqlite3VtabUnlock(db, pVtab);
@@ -4915,7 +4916,7 @@
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
sqlite3VtabLock(pVtab);
rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
- sqlite3_free(p->zErrMsg);
+ sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
sqlite3VtabUnlock(db, pVtab);
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index 50c34d1..6ce400e 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -15,7 +15,7 @@
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
**
-** $Id: vdbeInt.h,v 1.150 2008/07/26 18:26:10 danielk1977 Exp $
+** $Id: vdbeInt.h,v 1.151 2008/07/28 19:34:54 drh Exp $
*/
#ifndef _VDBEINT_H_
#define _VDBEINT_H_
@@ -245,6 +245,7 @@
typedef struct Fifo Fifo;
struct Fifo {
int nEntry; /* Total number of entries */
+ sqlite3 *db; /* The associated database connection */
FifoPage *pFirst; /* First page on the list */
FifoPage *pLast; /* Last page on the list */
};
@@ -434,7 +435,7 @@
void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
#endif
int sqlite3VdbeMemHandleBom(Mem *pMem);
-void sqlite3VdbeFifoInit(Fifo*);
+void sqlite3VdbeFifoInit(Fifo*, sqlite3*);
int sqlite3VdbeFifoPush(Fifo*, i64);
int sqlite3VdbeFifoPop(Fifo*, i64*);
void sqlite3VdbeFifoClear(Fifo*);
diff --git a/src/vdbeapi.c b/src/vdbeapi.c
index 1539c5b..2dce141 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -13,7 +13,7 @@
** This file contains code use to implement APIs that are part of the
** VDBE.
**
-** $Id: vdbeapi.c,v 1.135 2008/07/23 21:07:25 drh Exp $
+** $Id: vdbeapi.c,v 1.136 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
@@ -556,7 +556,7 @@
** sqlite3_errmsg() and sqlite3_errcode().
*/
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
- sqlite3_free(v->zErrMsg);
+ sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
} else {
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 9082757..9ab8ebd 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -14,7 +14,7 @@
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
**
-** $Id: vdbeaux.c,v 1.400 2008/07/26 18:26:10 danielk1977 Exp $
+** $Id: vdbeaux.c,v 1.401 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -302,7 +302,7 @@
pOp->p2 = aLabel[-1-pOp->p2];
}
}
- sqlite3_free(p->aLabel);
+ sqlite3DbFree(p->db, p->aLabel);
p->aLabel = 0;
*pMaxFuncArgs = nMaxArgs;
@@ -432,16 +432,16 @@
** If the input FuncDef structure is ephemeral, then free it. If
** the FuncDef is not ephermal, then do nothing.
*/
-static void freeEphemeralFunction(FuncDef *pDef){
+static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
if( pDef && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){
- sqlite3_free(pDef);
+ sqlite3DbFree(db, pDef);
}
}
/*
** Delete a P4 value if necessary.
*/
-static void freeP4(int p4type, void *p4){
+static void freeP4(sqlite3 *db, int p4type, void *p4){
if( p4 ){
switch( p4type ){
case P4_REAL:
@@ -451,18 +451,18 @@
case P4_KEYINFO:
case P4_INTARRAY:
case P4_KEYINFO_HANDOFF: {
- sqlite3_free(p4);
+ sqlite3DbFree(db, p4);
break;
}
case P4_VDBEFUNC: {
VdbeFunc *pVdbeFunc = (VdbeFunc *)p4;
- freeEphemeralFunction(pVdbeFunc->pFunc);
+ freeEphemeralFunction(db, pVdbeFunc->pFunc);
sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
- sqlite3_free(pVdbeFunc);
+ sqlite3DbFree(db, pVdbeFunc);
break;
}
case P4_FUNCDEF: {
- freeEphemeralFunction((FuncDef*)p4);
+ freeEphemeralFunction(db, (FuncDef*)p4);
break;
}
case P4_MEM: {
@@ -480,8 +480,9 @@
void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
if( p && p->aOp ){
VdbeOp *pOp = &p->aOp[addr];
+ sqlite3 *db = p->db;
while( N-- ){
- freeP4(pOp->p4type, pOp->p4.p);
+ freeP4(db, pOp->p4type, pOp->p4.p);
memset(pOp, 0, sizeof(pOp[0]));
pOp->opcode = OP_Noop;
pOp++;
@@ -516,11 +517,13 @@
*/
void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
Op *pOp;
+ sqlite3 *db;
assert( p!=0 );
+ db = p->db;
assert( p->magic==VDBE_MAGIC_INIT );
- if( p->aOp==0 || p->db->mallocFailed ){
+ if( p->aOp==0 || db->mallocFailed ){
if (n != P4_KEYINFO) {
- freeP4(n, (void*)*(char**)&zP4);
+ freeP4(db, n, (void*)*(char**)&zP4);
}
return;
}
@@ -530,7 +533,7 @@
if( addr<0 ) return;
}
pOp = &p->aOp[addr];
- freeP4(pOp->p4type, pOp->p4.p);
+ freeP4(db, pOp->p4type, pOp->p4.p);
pOp->p4.p = 0;
if( n==P4_INT32 ){
/* Note: this cast is safe, because the origin data point was an int
@@ -588,7 +591,7 @@
if( p->nOp ){
char **pz = &p->aOp[p->nOp-1].zComment;
va_start(ap, zFormat);
- sqlite3_free(*pz);
+ sqlite3DbFree(p->db, *pz);
*pz = sqlite3VMPrintf(p->db, zFormat, ap);
va_end(ap);
}
@@ -601,7 +604,7 @@
if( p->nOp ){
char **pz = &p->aOp[p->nOp-1].zComment;
va_start(ap, zFormat);
- sqlite3_free(*pz);
+ sqlite3DbFree(p->db, *pz);
*pz = sqlite3VMPrintf(p->db, zFormat, ap);
va_end(ap);
}
@@ -783,7 +786,7 @@
Mem *pMem = &p->aMem[ii];
if( pMem->z && pMem->flags&MEM_Dyn ){
assert( !pMem->xDel );
- nFree += sqlite3MallocSize(pMem->z);
+ nFree += sqlite3DbMallocSize(pMem->db, pMem->z);
sqlite3VdbeMemRelease(pMem);
}
}
@@ -1102,11 +1105,8 @@
}
#endif
if( !pCx->ephemPseudoTable ){
- sqlite3_free(pCx->pData);
+ sqlite3DbFree(p->db, pCx->pData);
}
- /* memset(pCx, 0, sizeof(Cursor)); */
- /* sqlite3_free(pCx->aType); */
- /* sqlite3_free(pCx); */
}
/*
@@ -1134,6 +1134,7 @@
*/
static void Cleanup(Vdbe *p, int freebuffers){
int i;
+ sqlite3 *db = p->db;
closeAllCursorsExceptActiveVtabs(p);
for(i=1; i<=p->nMem; i++){
MemSetTypeFlag(&p->aMem[i], MEM_Null);
@@ -1144,12 +1145,12 @@
for(i=0; i<p->contextStackTop; i++){
sqlite3VdbeFifoClear(&p->contextStack[i].sFifo);
}
- sqlite3_free(p->contextStack);
+ sqlite3DbFree(db, p->contextStack);
}
p->contextStack = 0;
p->contextStackDepth = 0;
p->contextStackTop = 0;
- sqlite3_free(p->zErrMsg);
+ sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
p->pResultSet = 0;
}
@@ -1163,12 +1164,13 @@
void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
Mem *pColName;
int n;
+ sqlite3 *db = p->db;
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N, 1);
- sqlite3_free(p->aColName);
+ sqlite3DbFree(db, p->aColName);
n = nResColumn*COLNAME_N;
p->nResColumn = nResColumn;
- p->aColName = pColName = (Mem*)sqlite3DbMallocZero(p->db, sizeof(Mem)*n );
+ p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n );
if( p->aColName==0 ) return;
while( n-- > 0 ){
pColName->flags = MEM_Null;
@@ -1185,7 +1187,7 @@
**
** If N==P4_STATIC it means that zName is a pointer to a constant static
** string and we can just copy the pointer. If it is P4_DYNAMIC, then
-** the string is freed using sqlite3_free() when the vdbe is finished with
+** the string is freed using sqlite3DbFree(db, ) when the vdbe is finished with
** it. Otherwise, N bytes of zName are copied.
*/
int sqlite3VdbeSetColName(Vdbe *p, int idx, int var, const char *zName, int N){
@@ -1305,7 +1307,7 @@
/* Select a master journal file name */
do {
u32 random;
- sqlite3_free(zMaster);
+ sqlite3DbFree(db, zMaster);
sqlite3_randomness(sizeof(random), &random);
zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, random&0x7fffffff);
if( !zMaster ){
@@ -1321,7 +1323,7 @@
);
}
if( rc!=SQLITE_OK ){
- sqlite3_free(zMaster);
+ sqlite3DbFree(db, zMaster);
return rc;
}
@@ -1345,7 +1347,7 @@
if( rc!=SQLITE_OK ){
sqlite3OsCloseFree(pMaster);
sqlite3OsDelete(pVfs, zMaster, 0);
- sqlite3_free(zMaster);
+ sqlite3DbFree(db, zMaster);
return rc;
}
}
@@ -1360,7 +1362,7 @@
&& (rc=sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))!=SQLITE_OK) ){
sqlite3OsCloseFree(pMaster);
sqlite3OsDelete(pVfs, zMaster, 0);
- sqlite3_free(zMaster);
+ sqlite3DbFree(db, zMaster);
return rc;
}
@@ -1382,7 +1384,7 @@
}
sqlite3OsCloseFree(pMaster);
if( rc!=SQLITE_OK ){
- sqlite3_free(zMaster);
+ sqlite3DbFree(db, zMaster);
return rc;
}
@@ -1391,7 +1393,7 @@
** transaction files are deleted.
*/
rc = sqlite3OsDelete(pVfs, zMaster, 1);
- sqlite3_free(zMaster);
+ sqlite3DbFree(db, zMaster);
zMaster = 0;
if( rc ){
return rc;
@@ -1633,7 +1635,7 @@
rc = xFunc(pBt);
if( rc && (p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT) ){
p->rc = rc;
- sqlite3_free(p->zErrMsg);
+ sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
}
}
@@ -1713,8 +1715,9 @@
*/
if( p->pc>=0 ){
if( p->zErrMsg ){
- sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,sqlite3_free);
+ sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,SQLITE_TRANSIENT);
db->errCode = p->rc;
+ sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
}else if( p->rc ){
sqlite3Error(db, p->rc, 0);
@@ -1727,7 +1730,8 @@
** called), set the database error in this case as well.
*/
sqlite3Error(db, p->rc, 0);
- sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, sqlite3_free);
+ sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
+ sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
}
@@ -1805,13 +1809,15 @@
*/
void sqlite3VdbeDelete(Vdbe *p){
int i;
+ sqlite3 *db;
+
if( p==0 ) return;
- /* Cleanup(p, 1); */
+ db = p->db;
if( p->pPrev ){
p->pPrev->pNext = p->pNext;
}else{
- assert( p->db->pVdbe==p );
- p->db->pVdbe = p->pNext;
+ assert( db->pVdbe==p );
+ db->pVdbe = p->pNext;
}
if( p->pNext ){
p->pNext->pPrev = p->pPrev;
@@ -1819,23 +1825,23 @@
if( p->aOp ){
Op *pOp = p->aOp;
for(i=0; i<p->nOp; i++, pOp++){
- freeP4(pOp->p4type, pOp->p4.p);
+ freeP4(db, pOp->p4type, pOp->p4.p);
#ifdef SQLITE_DEBUG
- sqlite3_free(pOp->zComment);
+ sqlite3DbFree(db, pOp->zComment);
#endif
}
- sqlite3_free(p->aOp);
+ sqlite3DbFree(db, p->aOp);
}
releaseMemArray(p->aVar, p->nVar, 1);
- sqlite3_free(p->aLabel);
+ sqlite3DbFree(db, p->aLabel);
if( p->aMem ){
- sqlite3_free(&p->aMem[1]);
+ sqlite3DbFree(db, &p->aMem[1]);
}
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N, 1);
- sqlite3_free(p->aColName);
- sqlite3_free(p->zSql);
+ sqlite3DbFree(db, p->aColName);
+ sqlite3DbFree(db, p->zSql);
p->magic = VDBE_MAGIC_DEAD;
- sqlite3_free(p);
+ sqlite3DbFree(db, p);
}
/*
@@ -2259,7 +2265,7 @@
}
}
if( p->needFree ){
- sqlite3_free(p);
+ sqlite3DbFree(p->pKeyInfo->db, p);
}
}
}
diff --git a/src/vdbeblob.c b/src/vdbeblob.c
index e2cfb50..746bfe4 100644
--- a/src/vdbeblob.c
+++ b/src/vdbeblob.c
@@ -12,7 +12,7 @@
**
** This file contains code used to implement incremental BLOB I/O.
**
-** $Id: vdbeblob.c,v 1.24 2008/07/10 00:32:42 drh Exp $
+** $Id: vdbeblob.c,v 1.25 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
@@ -117,7 +117,7 @@
if( sParse.zErrMsg ){
sqlite3_snprintf(sizeof(zErr), zErr, "%s", sParse.zErrMsg);
}
- sqlite3_free(sParse.zErrMsg);
+ sqlite3DbFree(db, sParse.zErrMsg);
rc = SQLITE_ERROR;
(void)sqlite3SafetyOff(db);
sqlite3BtreeLeaveAll(db);
@@ -229,7 +229,7 @@
}
pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
if( db->mallocFailed ){
- sqlite3_free(pBlob);
+ sqlite3DbFree(db, pBlob);
goto blob_open_out;
}
pBlob->flags = flags;
@@ -268,7 +268,7 @@
int rc;
rc = sqlite3_finalize(p->pStmt);
- sqlite3_free(p);
+ sqlite3DbFree(p->db, p);
return rc;
}
diff --git a/src/vdbefifo.c b/src/vdbefifo.c
index 956321c..a5e270d 100644
--- a/src/vdbefifo.c
+++ b/src/vdbefifo.c
@@ -12,7 +12,7 @@
** This file implements a FIFO queue of rowids used for processing
** UPDATE and DELETE statements.
**
-** $Id: vdbefifo.c,v 1.7 2008/06/15 02:51:48 drh Exp $
+** $Id: vdbefifo.c,v 1.8 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
@@ -33,12 +33,12 @@
** Allocate a new FifoPage and return a pointer to it. Return NULL if
** we run out of memory. Leave space on the page for nEntry entries.
*/
-static FifoPage *allocateFifoPage(int nEntry){
+static FifoPage *allocateFifoPage(sqlite3 *db, int nEntry){
FifoPage *pPage;
if( nEntry>FIFOSIZE_MAX ){
nEntry = FIFOSIZE_MAX;
}
- pPage = sqlite3Malloc( sizeof(FifoPage) + sizeof(i64)*(nEntry-1) );
+ pPage = sqlite3DbMallocRaw(db, sizeof(FifoPage) + sizeof(i64)*(nEntry-1) );
if( pPage ){
pPage->nSlot = nEntry;
pPage->iWrite = 0;
@@ -51,8 +51,9 @@
/*
** Initialize a Fifo structure.
*/
-void sqlite3VdbeFifoInit(Fifo *pFifo){
+void sqlite3VdbeFifoInit(Fifo *pFifo, sqlite3 *db){
memset(pFifo, 0, sizeof(*pFifo));
+ pFifo->db = db;
}
/*
@@ -64,12 +65,13 @@
FifoPage *pPage;
pPage = pFifo->pLast;
if( pPage==0 ){
- pPage = pFifo->pLast = pFifo->pFirst = allocateFifoPage(FIFOSIZE_FIRST);
+ pPage = pFifo->pLast = pFifo->pFirst =
+ allocateFifoPage(pFifo->db, FIFOSIZE_FIRST);
if( pPage==0 ){
return SQLITE_NOMEM;
}
}else if( pPage->iWrite>=pPage->nSlot ){
- pPage->pNext = allocateFifoPage(pFifo->nEntry);
+ pPage->pNext = allocateFifoPage(pFifo->db, pFifo->nEntry);
if( pPage->pNext==0 ){
return SQLITE_NOMEM;
}
@@ -101,7 +103,7 @@
pFifo->nEntry--;
if( pPage->iRead>=pPage->iWrite ){
pFifo->pFirst = pPage->pNext;
- sqlite3_free(pPage);
+ sqlite3DbFree(pFifo->db, pPage);
if( pFifo->nEntry==0 ){
assert( pFifo->pLast==pPage );
pFifo->pLast = 0;
@@ -122,7 +124,7 @@
FifoPage *pPage, *pNextPage;
for(pPage=pFifo->pFirst; pPage; pPage=pNextPage){
pNextPage = pPage->pNext;
- sqlite3_free(pPage);
+ sqlite3DbFree(pFifo->db, pPage);
}
- sqlite3VdbeFifoInit(pFifo);
+ sqlite3VdbeFifoInit(pFifo, pFifo->db);
}
diff --git a/src/vdbemem.c b/src/vdbemem.c
index a8a2129..184195c 100644
--- a/src/vdbemem.c
+++ b/src/vdbemem.c
@@ -15,7 +15,7 @@
** only within the VDBE. Interface routines refer to a Mem using the
** name sqlite_value
**
-** $Id: vdbemem.c,v 1.118 2008/07/09 16:51:51 drh Exp $
+** $Id: vdbemem.c,v 1.119 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -83,7 +83,7 @@
);
if( n<32 ) n = 32;
- if( sqlite3MallocSize(pMem->zMalloc)<n ){
+ if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
if( preserve && pMem->z==pMem->zMalloc ){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
if( !pMem->z ){
@@ -91,7 +91,7 @@
}
preserve = 0;
}else{
- sqlite3_free(pMem->zMalloc);
+ sqlite3DbFree(pMem->db, pMem->zMalloc);
pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
}
}
@@ -255,7 +255,7 @@
ctx.isError = 0;
pFunc->xFinalize(&ctx);
assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel );
- sqlite3_free(pMem->zMalloc);
+ sqlite3DbFree(pMem->db, pMem->zMalloc);
*pMem = ctx.s;
rc = (ctx.isError?SQLITE_ERROR:SQLITE_OK);
}
@@ -286,7 +286,7 @@
*/
void sqlite3VdbeMemRelease(Mem *p){
sqlite3VdbeMemReleaseExternal(p);
- sqlite3_free(p->zMalloc);
+ sqlite3DbFree(p->db, p->zMalloc);
p->z = 0;
p->zMalloc = 0;
p->xDel = 0;
@@ -631,11 +631,21 @@
return SQLITE_NOMEM;
}
memcpy(pMem->z, z, nAlloc);
+ }else if( xDel==SQLITE_DYNAMIC ){
+ sqlite3VdbeMemRelease(pMem);
+ pMem->zMalloc = pMem->z = (char *)z;
+ pMem->xDel = 0;
}else{
sqlite3VdbeMemRelease(pMem);
pMem->z = (char *)z;
- pMem->xDel = xDel;
- flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
+ if( xDel==SQLITE_DYNAMIC ){
+ pMem->zMalloc = pMem->z;
+ pMem->xDel = 0;
+ flags |= MEM_Dyn;
+ }else{
+ pMem->xDel = xDel;
+ flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
+ }
}
pMem->n = nByte;
@@ -966,11 +976,11 @@
op = pExpr->op;
if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
- zVal = sqlite3StrNDup((char*)pExpr->token.z, pExpr->token.n);
+ zVal = sqlite3DbStrNDup(db, (char*)pExpr->token.z, pExpr->token.n);
pVal = sqlite3ValueNew(db);
if( !zVal || !pVal ) goto no_mem;
sqlite3Dequote(zVal);
- sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, sqlite3_free);
+ sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, enc);
}else{
@@ -993,7 +1003,7 @@
nVal = pExpr->token.n - 3;
zVal = (char*)pExpr->token.z + 2;
sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
- 0, sqlite3_free);
+ 0, SQLITE_DYNAMIC);
}
#endif
@@ -1002,7 +1012,7 @@
no_mem:
db->mallocFailed = 1;
- sqlite3_free(zVal);
+ sqlite3DbFree(db, zVal);
sqlite3ValueFree(pVal);
*ppVal = 0;
return SQLITE_NOMEM;
@@ -1027,7 +1037,7 @@
void sqlite3ValueFree(sqlite3_value *v){
if( !v ) return;
sqlite3VdbeMemRelease((Mem *)v);
- sqlite3_free(v);
+ sqlite3DbFree(((Mem*)v)->db, v);
}
/*
diff --git a/src/vtab.c b/src/vtab.c
index 2c71215..c9ff4e0 100644
--- a/src/vtab.c
+++ b/src/vtab.c
@@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to help implement virtual tables.
**
-** $Id: vtab.c,v 1.71 2008/07/23 18:17:32 drh Exp $
+** $Id: vtab.c,v 1.72 2008/07/28 19:34:54 drh Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"
@@ -41,7 +41,7 @@
if( pDel && pDel->xDestroy ){
pDel->xDestroy(pDel->pAux);
}
- sqlite3_free(pDel);
+ sqlite3DbFree(db, pDel);
if( pDel==pMod ){
db->mallocFailed = 1;
}
@@ -116,17 +116,18 @@
*/
void sqlite3VtabClear(Table *p){
sqlite3_vtab *pVtab = p->pVtab;
+ sqlite3 *db = p->db;
if( pVtab ){
assert( p->pMod && p->pMod->pModule );
- sqlite3VtabUnlock(p->pSchema->db, pVtab);
+ sqlite3VtabUnlock(db, pVtab);
p->pVtab = 0;
}
if( p->azModuleArg ){
int i;
for(i=0; i<p->nModuleArg; i++){
- sqlite3_free(p->azModuleArg[i]);
+ sqlite3DbFree(db, p->azModuleArg[i]);
}
- sqlite3_free(p->azModuleArg);
+ sqlite3DbFree(db, p->azModuleArg);
}
}
@@ -144,10 +145,10 @@
if( azModuleArg==0 ){
int j;
for(j=0; j<i; j++){
- sqlite3_free(pTable->azModuleArg[j]);
+ sqlite3DbFree(db, pTable->azModuleArg[j]);
}
- sqlite3_free(zArg);
- sqlite3_free(pTable->azModuleArg);
+ sqlite3DbFree(db, zArg);
+ sqlite3DbFree(db, pTable->azModuleArg);
pTable->nModuleArg = 0;
}else{
azModuleArg[i] = zArg;
@@ -278,7 +279,7 @@
zStmt,
pParse->regRowid
);
- sqlite3_free(zStmt);
+ sqlite3DbFree(db, zStmt);
v = sqlite3GetVdbe(pParse);
sqlite3ChangeCookie(pParse, iDb);
@@ -377,7 +378,7 @@
*pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
}else {
*pzErr = sqlite3MPrintf(db, "%s", zErr);
- sqlite3_free(zErr);
+ sqlite3DbFree(db, zErr);
}
}else if( db->pVTab ){
const char *zFormat = "vtable constructor did not declare schema: %s";
@@ -388,7 +389,7 @@
rc = rc2;
}
db->pVTab = 0;
- sqlite3_free(zModuleName);
+ sqlite3DbFree(db, zModuleName);
/* If everything went according to plan, loop through the columns
** of the table to see if any of them contain the token "hidden".
@@ -457,7 +458,7 @@
if( rc!=SQLITE_OK ){
sqlite3ErrorMsg(pParse, "%s", zErr);
}
- sqlite3_free(zErr);
+ sqlite3DbFree(db, zErr);
}
return rc;
@@ -493,7 +494,7 @@
**
** If an error occurs, *pzErr is set to point an an English language
** description of the error and an SQLITE_XXX error code is returned.
-** In this case the caller must call sqlite3_free() on *pzErr.
+** In this case the caller must call sqlite3DbFree(db, ) on *pzErr.
*/
int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
int rc = SQLITE_OK;
@@ -562,7 +563,7 @@
db->pVTab = 0;
} else {
sqlite3Error(db, SQLITE_ERROR, zErr);
- sqlite3_free(zErr);
+ sqlite3DbFree(db, zErr);
rc = SQLITE_ERROR;
}
sParse.declareVtab = 0;
@@ -632,7 +633,7 @@
if( x ) x(pVtab);
sqlite3VtabUnlock(db, pVtab);
}
- sqlite3_free(db->aVTrans);
+ sqlite3DbFree(db, db->aVTrans);
db->nVTrans = 0;
db->aVTrans = 0;
}
@@ -787,7 +788,7 @@
*z = sqlite3UpperToLower[*z];
}
rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg);
- sqlite3_free(zLowerName);
+ sqlite3DbFree(db, zLowerName);
sqlite3VtabTransferError(db, rc, pVtab);
}
if( rc==0 ){
@@ -835,7 +836,7 @@
void sqlite3VtabTransferError(sqlite3 *db, int rc, sqlite3_vtab *pVtab){
if( pVtab->zErrMsg ){
sqlite3Error(db, rc, "%s", pVtab->zErrMsg);
- sqlite3_free(pVtab->zErrMsg);
+ sqlite3DbFree(db, pVtab->zErrMsg);
pVtab->zErrMsg = 0;
}
}
diff --git a/src/where.c b/src/where.c
index 5971028..dac5161 100644
--- a/src/where.c
+++ b/src/where.c
@@ -16,7 +16,7 @@
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
-** $Id: where.c,v 1.317 2008/07/12 14:52:20 drh Exp $
+** $Id: where.c,v 1.318 2008/07/28 19:34:54 drh Exp $
*/
#include "sqliteInt.h"
@@ -92,7 +92,7 @@
/*
** Allowed values of WhereTerm.flags
*/
-#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(pExpr) */
+#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(db, pExpr) */
#define TERM_VIRTUAL 0x02 /* Added by the optimizer. Do not code */
#define TERM_CODED 0x04 /* This term is already coded */
#define TERM_COPIED 0x08 /* Has a child */
@@ -203,13 +203,14 @@
static void whereClauseClear(WhereClause *pWC){
int i;
WhereTerm *a;
+ sqlite3 *db = pWC->pParse->db;
for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
if( a->flags & TERM_DYNAMIC ){
- sqlite3ExprDelete(a->pExpr);
+ sqlite3ExprDelete(db, a->pExpr);
}
}
if( pWC->a!=pWC->aStatic ){
- sqlite3_free(pWC->a);
+ sqlite3DbFree(db, pWC->a);
}
}
@@ -230,18 +231,18 @@
int idx;
if( pWC->nTerm>=pWC->nSlot ){
WhereTerm *pOld = pWC->a;
- pWC->a = sqlite3Malloc( sizeof(pWC->a[0])*pWC->nSlot*2 );
+ sqlite3 *db = pWC->pParse->db;
+ pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
if( pWC->a==0 ){
- pWC->pParse->db->mallocFailed = 1;
if( flags & TERM_DYNAMIC ){
- sqlite3ExprDelete(p);
+ sqlite3ExprDelete(db, p);
}
pWC->a = pOld;
return 0;
}
memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
if( pOld!=pWC->aStatic ){
- sqlite3_free(pOld);
+ sqlite3DbFree(db, pOld);
}
pWC->nSlot *= 2;
}
@@ -773,7 +774,7 @@
int idxNew;
pDup = sqlite3ExprDup(db, pExpr);
if( db->mallocFailed ){
- sqlite3ExprDelete(pDup);
+ sqlite3ExprDelete(db, pDup);
return;
}
idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
@@ -889,7 +890,7 @@
pWC->a[idxNew].iParent = idxTerm;
pTerm->nChild = 1;
}else{
- sqlite3ExprListDelete(pList);
+ sqlite3ExprListDelete(db, pList);
}
}
or_not_possible:
@@ -1908,14 +1909,15 @@
static void whereInfoFree(WhereInfo *pWInfo){
if( pWInfo ){
int i;
+ sqlite3 *db = pWInfo->pParse->db;
for(i=0; i<pWInfo->nLevel; i++){
sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
if( pInfo ){
assert( pInfo->needToFreeIdxStr==0 );
- sqlite3_free(pInfo);
+ sqlite3DbFree(db, pInfo);
}
}
- sqlite3_free(pWInfo);
+ sqlite3DbFree(db, pWInfo);
}
}
@@ -2248,22 +2250,22 @@
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
zMsg = sqlite3MPrintf(db, "TABLE %s", pItem->zName);
if( pItem->zAlias ){
- zMsg = sqlite3MPrintf(db, "%z AS %s", zMsg, pItem->zAlias);
+ zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
}
if( (pIx = pLevel->pIdx)!=0 ){
- zMsg = sqlite3MPrintf(db, "%z WITH INDEX %s", zMsg, pIx->zName);
+ zMsg = sqlite3MAppendf(db, zMsg, "%s WITH INDEX %s", zMsg, pIx->zName);
}else if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
- zMsg = sqlite3MPrintf(db, "%z USING PRIMARY KEY", zMsg);
+ zMsg = sqlite3MAppendf(db, zMsg, "%s USING PRIMARY KEY", zMsg);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( pLevel->pBestIdx ){
sqlite3_index_info *pBestIdx = pLevel->pBestIdx;
- zMsg = sqlite3MPrintf(db, "%z VIRTUAL TABLE INDEX %d:%s", zMsg,
+ zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
pBestIdx->idxNum, pBestIdx->idxStr);
}
#endif
if( pLevel->flags & WHERE_ORDERBY ){
- zMsg = sqlite3MPrintf(db, "%z ORDER BY", zMsg);
+ zMsg = sqlite3MAppendf(db, zMsg, "%s ORDER BY", zMsg);
}
sqlite3VdbeAddOp4(v, OP_Explain, i, pLevel->iFrom, 0, zMsg, P4_DYNAMIC);
}
@@ -2779,14 +2781,16 @@
** sqlite3WhereBegin() for additional information.
*/
void sqlite3WhereEnd(WhereInfo *pWInfo){
- Vdbe *v = pWInfo->pParse->pVdbe;
+ Parse *pParse = pWInfo->pParse;
+ Vdbe *v = pParse->pVdbe;
int i;
WhereLevel *pLevel;
SrcList *pTabList = pWInfo->pTabList;
+ sqlite3 *db = pParse->db;
/* Generate loop termination code.
*/
- sqlite3ExprClearColumnCache(pWInfo->pParse, -1);
+ sqlite3ExprClearColumnCache(pParse, -1);
for(i=pTabList->nSrc-1; i>=0; i--){
pLevel = &pWInfo->a[i];
sqlite3VdbeResolveLabel(v, pLevel->cont);
@@ -2802,7 +2806,7 @@
sqlite3VdbeAddOp2(v, OP_Next, pIn->iCur, pIn->topAddr);
sqlite3VdbeJumpHere(v, pIn->topAddr-1);
}
- sqlite3_free(pLevel->aInLoop);
+ sqlite3DbFree(db, pLevel->aInLoop);
}
sqlite3VdbeResolveLabel(v, pLevel->brk);
if( pLevel->iLeftJoin ){