updated to sqlite-3.5.1 now that it's stable

used new shared cache functionality (yay)

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401651
This commit is contained in:
David Anderson 2007-10-28 05:48:06 +00:00
parent dc746c5806
commit f78ceafdce
66 changed files with 9797 additions and 6449 deletions

View File

@ -67,11 +67,14 @@ SqDriver::SqDriver()
{
m_Handle = BAD_HANDLE;
m_pOpenLock = NULL;
m_bThreadSafe = false;
}
void SqDriver::Initialize()
{
m_pOpenLock = threader->MakeMutex();
InitializeThreadSafety();
}
void SqDriver::Shutdown()
@ -80,6 +83,11 @@ void SqDriver::Shutdown()
{
m_pOpenLock->DestroyThis();
}
if (m_bThreadSafe)
{
sqlite3_enable_shared_cache(0);
}
}
bool SqDriver::IsThreadSafe()
@ -89,10 +97,23 @@ bool SqDriver::IsThreadSafe()
bool SqDriver::InitializeThreadSafety()
{
/* sqlite should be thread safe if the locks are done right.
* we don't enable the "shared cache" because it can corrupt
* open databases!
*/
if (m_bThreadSafe)
{
return true;
}
if (sqlite3_threadsafe() == 0)
{
return false;
}
if (sqlite3_enable_shared_cache(1) != SQLITE_OK)
{
return false;
}
m_bThreadSafe = true;
return true;
}

View File

@ -72,6 +72,7 @@ private:
Handle_t m_Handle;
IMutex *m_pOpenLock;
List<SqDbInfo> m_Cache;
bool m_bThreadSafe;
};
extern SqDriver g_SqDriver;

View File

@ -121,7 +121,7 @@
Name="VCCLCompilerTool"
FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\sourcepawn;$(SOURCEMM)\sourcehook"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD;THREADSAFE;SQLITE_OMIT_LOAD_EXTENSION"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD;SQLITE_THREADSAFE;SQLITE_OMIT_LOAD_EXTENSION;_WIN32_WINNT=0x0400"
RuntimeLibrary="0"
EnableEnhancedInstructionSet="1"
RuntimeTypeInfo="false"
@ -259,6 +259,10 @@
RelativePath="..\sqlite-source\keywordhash.h"
>
</File>
<File
RelativePath="..\sqlite-source\mutex.h"
>
</File>
<File
RelativePath="..\sqlite-source\opcodes.h"
>
@ -355,6 +359,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\sqlite-source\btmutex.c"
>
</File>
<File
RelativePath="..\sqlite-source\btree.c"
>
@ -475,6 +483,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\sqlite-source\journal.c"
>
</File>
<File
RelativePath="..\sqlite-source\legacy.c"
>
@ -511,6 +523,22 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\sqlite-source\mem1.c"
>
</File>
<File
RelativePath="..\sqlite-source\mem2.c"
>
</File>
<File
RelativePath="..\sqlite-source\mutex.c"
>
</File>
<File
RelativePath="..\sqlite-source\mutex_w32.c"
>
</File>
<File
RelativePath="..\sqlite-source\opcodes.c"
>

View File

@ -51,6 +51,8 @@ static void renameTableFunc(
int len = 0;
char *zRet;
sqlite3 *db = sqlite3_user_data(context);
/* The principle used to locate the table name in the CREATE TABLE
** statement is that the table name is the first token that is immediatedly
** followed by a left parenthesis - TK_LP - or "USING" TK_USING.
@ -76,9 +78,9 @@ static void renameTableFunc(
assert( len>0 );
} while( token!=TK_LP && token!=TK_USING );
zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql,
zRet = sqlite3MPrintf(db, "%.*s%Q%s", tname.z - zSql, zSql,
zTableName, tname.z+tname.n);
sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
sqlite3_result_text(context, zRet, -1, sqlite3_free);
}
}
@ -105,6 +107,8 @@ static void renameTriggerFunc(
int len = 0;
char *zRet;
sqlite3 *db = sqlite3_user_data(context);
/* The principle used to locate the table name in the CREATE TRIGGER
** statement is that the table name is the first token that is immediatedly
** preceded by either TK_ON or TK_DOT and immediatedly followed by one
@ -149,9 +153,9 @@ static void renameTriggerFunc(
/* Variable tname now contains the token that is the old table-name
** in the CREATE TRIGGER statement.
*/
zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql,
zRet = sqlite3MPrintf(db, "%.*s%Q%s", tname.z - zSql, zSql,
zTableName, tname.z+tname.n);
sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
sqlite3_result_text(context, zRet, -1, sqlite3_free);
}
}
#endif /* !SQLITE_OMIT_TRIGGER */
@ -174,7 +178,7 @@ void sqlite3AlterFunctions(sqlite3 *db){
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
SQLITE_UTF8, (void *)db, aFuncs[i].xFunc, 0, 0);
}
}
@ -196,14 +200,15 @@ static char *whereTempTriggers(Parse *pParse, Table *pTab){
** expression being built up in zWhere.
*/
if( pTab->pSchema!=pTempSchema ){
sqlite3 *db = pParse->db;
for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){
if( pTrig->pSchema==pTempSchema ){
if( !zWhere ){
zWhere = sqlite3MPrintf("name=%Q", pTrig->name);
zWhere = sqlite3MPrintf(db, "name=%Q", pTrig->name);
}else{
tmp = zWhere;
zWhere = sqlite3MPrintf("%s OR name=%Q", zWhere, pTrig->name);
sqliteFree(tmp);
zWhere = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, pTrig->name);
sqlite3_free(tmp);
}
}
}
@ -229,6 +234,7 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
v = sqlite3GetVdbe(pParse);
if( !v ) return;
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
assert( iDb>=0 );
@ -245,7 +251,7 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
/* Reload the table, index and permanent trigger schemas. */
zWhere = sqlite3MPrintf("tbl_name=%Q", zName);
zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName);
if( !zWhere ) return;
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
@ -281,8 +287,9 @@ void sqlite3AlterRenameTable(
#endif
int isVirtualRename = 0; /* True if this is a v-table with an xRename() */
if( sqlite3MallocFailed() ) goto exit_rename_table;
if( db->mallocFailed ) goto exit_rename_table;
assert( pSrc->nSrc==1 );
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
if( !pTab ) goto exit_rename_table;
@ -290,7 +297,7 @@ void sqlite3AlterRenameTable(
zDb = db->aDb[iDb].zName;
/* Get a NULL terminated version of the new table name. */
zName = sqlite3NameFromToken(pName);
zName = sqlite3NameFromToken(db, pName);
if( !zName ) goto exit_rename_table;
/* Check that a table or index named 'zName' does not already exist
@ -404,7 +411,7 @@ void sqlite3AlterRenameTable(
"sql = sqlite_rename_trigger(sql, %Q), "
"tbl_name = %Q "
"WHERE %s;", zName, zName, zWhere);
sqliteFree(zWhere);
sqlite3_free(zWhere);
}
#endif
@ -413,7 +420,7 @@ void sqlite3AlterRenameTable(
exit_rename_table:
sqlite3SrcListDelete(pSrc);
sqliteFree(zName);
sqlite3_free(zName);
}
@ -434,17 +441,20 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
char *zCol; /* Null-terminated column definition */
Column *pCol; /* The new column */
Expr *pDflt; /* Default value for the new column */
sqlite3 *db; /* The database connection; */
if( pParse->nErr ) return;
pNew = pParse->pNewTable;
assert( pNew );
iDb = sqlite3SchemaToIndex(pParse->db, pNew->pSchema);
zDb = pParse->db->aDb[iDb].zName;
db = pParse->db;
assert( sqlite3BtreeHoldsAllMutexes(db) );
iDb = sqlite3SchemaToIndex(db, pNew->pSchema);
zDb = db->aDb[iDb].zName;
zTab = pNew->zName;
pCol = &pNew->aCol[pNew->nCol-1];
pDflt = pCol->pDflt;
pTab = sqlite3FindTable(pParse->db, zTab, zDb);
pTab = sqlite3FindTable(db, zTab, zDb);
assert( pTab );
#ifndef SQLITE_OMIT_AUTHORIZATION
@ -485,8 +495,8 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
*/
if( pDflt ){
sqlite3_value *pVal;
if( sqlite3ValueFromExpr(pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
/* malloc() has failed */
if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
db->mallocFailed = 1;
return;
}
if( !pVal ){
@ -497,7 +507,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
}
/* Modify the CREATE TABLE statement. */
zCol = sqliteStrNDup((char*)pColDef->z, pColDef->n);
zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
if( zCol ){
char *zEnd = &zCol[pColDef->n-1];
while( (zEnd>zCol && *zEnd==';') || isspace(*(unsigned char *)zEnd) ){
@ -510,7 +520,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
zTab
);
sqliteFree(zCol);
sqlite3_free(zCol);
}
/* If the default value of the new column is NULL, then set the file
@ -545,10 +555,12 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
int iDb;
int i;
int nAlloc;
sqlite3 *db = pParse->db;
/* Look up the table being altered. */
assert( pParse->pNewTable==0 );
if( sqlite3MallocFailed() ) goto exit_begin_add_column;
assert( sqlite3BtreeHoldsAllMutexes(db) );
if( db->mallocFailed ) goto exit_begin_add_column;
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
if( !pTab ) goto exit_begin_add_column;
@ -566,12 +578,12 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
}
assert( pTab->addColOffset>0 );
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
/* Put a copy of the Table struct in Parse.pNewTable for the
** sqlite3AddColumn() function and friends to modify.
*/
pNew = (Table *)sqliteMalloc(sizeof(Table));
pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table));
if( !pNew ) goto exit_begin_add_column;
pParse->pNewTable = pNew;
pNew->nRef = 1;
@ -579,20 +591,21 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
assert( pNew->nCol>0 );
nAlloc = (((pNew->nCol-1)/8)*8)+8;
assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
pNew->aCol = (Column *)sqliteMalloc(sizeof(Column)*nAlloc);
pNew->zName = sqliteStrDup(pTab->zName);
pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc);
pNew->zName = sqlite3DbStrDup(db, pTab->zName);
if( !pNew->aCol || !pNew->zName ){
db->mallocFailed = 1;
goto exit_begin_add_column;
}
memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
for(i=0; i<pNew->nCol; i++){
Column *pCol = &pNew->aCol[i];
pCol->zName = sqliteStrDup(pCol->zName);
pCol->zName = sqlite3DbStrDup(db, pCol->zName);
pCol->zColl = 0;
pCol->zType = 0;
pCol->pDflt = 0;
}
pNew->pSchema = pParse->db->aDb[iDb].pSchema;
pNew->pSchema = db->aDb[iDb].pSchema;
pNew->addColOffset = pTab->addColOffset;
pNew->nRef = 1;
@ -600,7 +613,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
sqlite3BeginWriteOperation(pParse, 0, iDb);
v = sqlite3GetVdbe(pParse);
if( !v ) goto exit_begin_add_column;
sqlite3ChangeCookie(pParse->db, v, iDb);
sqlite3ChangeCookie(db, v, iDb);
exit_begin_add_column:
sqlite3SrcListDelete(pSrc);

View File

@ -37,6 +37,8 @@ static void openStatTable(
Vdbe *v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
assert( sqlite3BtreeHoldsAllMutexes(db) );
assert( sqlite3VdbeDb(v)==db );
pDb = &db->aDb[iDb];
if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){
/* The sqlite_stat1 tables does not exist. Create it.
@ -100,7 +102,7 @@ static void analyzeOneTable(
/* Do no analysis for tables that have no indices */
return;
}
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
assert( iDb>=0 );
#ifndef SQLITE_OMIT_AUTHORIZATION
@ -258,6 +260,7 @@ static void analyzeTable(Parse *pParse, Table *pTab){
int iStatCur;
assert( pTab!=0 );
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
sqlite3BeginWriteOperation(pParse, 0, iDb);
iStatCur = pParse->nTab++;
@ -288,6 +291,7 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
/* Read the database schema. If an error occurs, leave an error message
** and code in pParse and return NULL. */
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
return;
}
@ -304,9 +308,9 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
if( iDb>=0 ){
analyzeDatabase(pParse, iDb);
}else{
z = sqlite3NameFromToken(pName1);
z = sqlite3NameFromToken(db, pName1);
pTab = sqlite3LocateTable(pParse, z, 0);
sqliteFree(z);
sqlite3_free(z);
if( pTab ){
analyzeTable(pParse, pTab);
}
@ -316,10 +320,10 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
if( iDb>=0 ){
zDb = db->aDb[iDb].zName;
z = sqlite3NameFromToken(pTableName);
z = sqlite3NameFromToken(db, pTableName);
if( z ){
pTab = sqlite3LocateTable(pParse, z, zDb);
sqliteFree(z);
sqlite3_free(z);
if( pTab ){
analyzeTable(pParse, pTab);
}
@ -382,6 +386,10 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
char *zSql;
int rc;
assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pBt!=0 );
assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
/* Clear any prior statistics */
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
@ -397,12 +405,12 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
/* Load new statistics out of the sqlite_stat1 table */
zSql = sqlite3MPrintf("SELECT idx, stat FROM %Q.sqlite_stat1",
zSql = sqlite3MPrintf(db, "SELECT idx, stat FROM %Q.sqlite_stat1",
sInfo.zDatabase);
sqlite3SafetyOff(db);
rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
sqlite3SafetyOn(db);
sqliteFree(zSql);
sqlite3_free(zSql);
return rc;
}

View File

@ -73,8 +73,8 @@ static void attachFunc(
const char *zName;
const char *zFile;
Db *aNew;
char zErr[128];
char *zErrDyn = 0;
char zErr[128];
zFile = (const char *)sqlite3_value_text(argv[0]);
zName = (const char *)sqlite3_value_text(argv[1]);
@ -102,7 +102,8 @@ static void attachFunc(
for(i=0; i<db->nDb; i++){
char *z = db->aDb[i].zName;
if( z && zName && sqlite3StrICmp(z, zName)==0 ){
sqlite3_snprintf(sizeof(zErr), zErr, "database %s is already in use", zName);
sqlite3_snprintf(sizeof(zErr), zErr,
"database %s is already in use", zName);
goto attach_error;
}
}
@ -111,14 +112,16 @@ static void attachFunc(
** hash tables.
*/
if( db->aDb==db->aDbStatic ){
aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
aNew = sqlite3_malloc( sizeof(db->aDb[0])*3 );
if( aNew==0 ){
db->mallocFailed = 1;
return;
}
memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
}else{
aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
aNew = sqlite3_realloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
if( aNew==0 ){
db->mallocFailed = 1;
return;
}
}
@ -130,9 +133,11 @@ static void attachFunc(
** it to obtain the database schema. At this point the schema may
** or may not be initialised.
*/
rc = sqlite3BtreeFactory(db, zFile, 0, SQLITE_DEFAULT_CACHE_SIZE, &aNew->pBt);
rc = sqlite3BtreeFactory(db, zFile, 0, SQLITE_DEFAULT_CACHE_SIZE,
db->openFlags | SQLITE_OPEN_MAIN_DB,
&aNew->pBt);
if( rc==SQLITE_OK ){
aNew->pSchema = sqlite3SchemaGet(aNew->pBt);
aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);
if( !aNew->pSchema ){
rc = SQLITE_NOMEM;
}else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
@ -142,7 +147,7 @@ static void attachFunc(
}
sqlite3PagerLockingMode(sqlite3BtreePager(aNew->pBt), db->dfltLockMode);
}
aNew->zName = sqliteStrDup(zName);
aNew->zName = sqlite3DbStrDup(db, zName);
aNew->safety_level = 3;
#if SQLITE_HAS_CODEC
@ -155,7 +160,7 @@ static void attachFunc(
switch( t ){
case SQLITE_INTEGER:
case SQLITE_FLOAT:
zErrDyn = sqliteStrDup("Invalid key value");
zErrDyn = sqlite3DbStrDup(db, "Invalid key value");
rc = SQLITE_ERROR;
break;
@ -195,8 +200,8 @@ static void attachFunc(
}
sqlite3ResetInternalSchema(db, 0);
db->nDb = iDb;
if( rc==SQLITE_NOMEM ){
sqlite3FailedMalloc();
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
db->mallocFailed = 1;
sqlite3_snprintf(sizeof(zErr),zErr, "out of memory");
}else{
sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile);
@ -210,7 +215,7 @@ attach_error:
/* Return an error if we get here */
if( zErrDyn ){
sqlite3_result_error(context, zErrDyn, -1);
sqliteFree(zErrDyn);
sqlite3_free(zErrDyn);
}else{
zErr[sizeof(zErr)-1] = 0;
sqlite3_result_error(context, zErr, -1);
@ -292,14 +297,14 @@ static void codeAttach(
sqlite3* db = pParse->db;
#ifndef SQLITE_OMIT_AUTHORIZATION
assert( sqlite3MallocFailed() || pAuthArg );
assert( db->mallocFailed || pAuthArg );
if( pAuthArg ){
char *zAuthArg = sqlite3NameFromToken(&pAuthArg->span);
char *zAuthArg = sqlite3NameFromToken(db, &pAuthArg->span);
if( !zAuthArg ){
goto attach_end;
}
rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
sqliteFree(zAuthArg);
sqlite3_free(zAuthArg);
if(rc!=SQLITE_OK ){
goto attach_end;
}
@ -323,7 +328,7 @@ static void codeAttach(
sqlite3ExprCode(pParse, pDbname);
sqlite3ExprCode(pParse, pKey);
assert( v || sqlite3MallocFailed() );
assert( v || db->mallocFailed );
if( v ){
sqlite3VdbeAddOp(v, OP_Function, 0, nFunc);
pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0);
@ -424,7 +429,7 @@ int sqlite3FixSrcList(
zDb = pFix->zDb;
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pItem->zDatabase==0 ){
pItem->zDatabase = sqliteStrDup(zDb);
pItem->zDatabase = sqlite3DbStrDup(pFix->pParse->db, zDb);
}else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){
sqlite3ErrorMsg(pFix->pParse,
"%s %T cannot reference objects in database %s",

View File

@ -74,9 +74,11 @@ int sqlite3_set_authorizer(
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
void *pArg
){
sqlite3_mutex_enter(db->mutex);
db->xAuth = xAuth;
db->pAuthArg = pArg;
sqlite3ExpirePreparedStatements(db);
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
@ -103,11 +105,12 @@ static void sqliteAuthBadReturnCode(Parse *pParse, int rc){
void sqlite3AuthRead(
Parse *pParse, /* The parser context */
Expr *pExpr, /* The expression to check authorization on */
Schema *pSchema, /* The schema of the expression */
SrcList *pTabList /* All table that pExpr might refer to */
){
sqlite3 *db = pParse->db;
int rc;
Table *pTab; /* The table being read */
Table *pTab = 0; /* The table being read */
const char *zCol; /* Name of the column of the table */
int iSrc; /* Index in pTabList->a[] of table being read */
const char *zDBase; /* Name of database being accessed */
@ -116,7 +119,7 @@ void sqlite3AuthRead(
if( db->xAuth==0 ) return;
if( pExpr->op!=TK_COLUMN ) return;
iDb = sqlite3SchemaToIndex(pParse->db, pExpr->pSchema);
iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
if( iDb<0 ){
/* An attempt to read a column out of a subquery or other
** temporary table. */
@ -133,8 +136,6 @@ void sqlite3AuthRead(
*/
assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
pTab = pStack->pTab;
}else{
return;
}
if( pTab==0 ) return;
if( pExpr->iColumn>=0 ){

File diff suppressed because it is too large Load Diff

View File

@ -41,13 +41,26 @@
typedef struct Btree Btree;
typedef struct BtCursor BtCursor;
typedef struct BtShared BtShared;
typedef struct BtreeMutexArray BtreeMutexArray;
/*
** This structure records all of the Btrees that need to hold
** a mutex before we enter sqlite3VdbeExec(). The Btrees are
** are placed in aBtree[] in order of aBtree[]->pBt. That way,
** we can always lock and unlock them all quickly.
*/
struct BtreeMutexArray {
int nMutex;
Btree *aBtree[SQLITE_MAX_ATTACHED+1];
};
int sqlite3BtreeOpen(
const char *zFilename, /* Name of database file to open */
sqlite3 *db, /* Associated database connection */
Btree **, /* Return open Btree* here */
int flags /* Flags */
int flags, /* Flags */
int vfsFlags /* Flags passed through to VFS open */
);
/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
@ -59,6 +72,14 @@ int sqlite3BtreeOpen(
#define BTREE_OMIT_JOURNAL 1 /* Do not use journal. No argument */
#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */
#define BTREE_MEMORY 4 /* In-memory DB. No argument */
#define BTREE_READONLY 8 /* Open the database in read-only mode */
#define BTREE_READWRITE 16 /* Open for both reading and writing */
#define BTREE_CREATE 32 /* Create the database if it does not exist */
/* Additional values for the 4th argument of sqlite3BtreeOpen that
** are not associated with PAGER_ values.
*/
#define BTREE_PRIVATE 64 /* Never share with other connections */
int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*);
@ -105,6 +126,7 @@ int sqlite3BtreeDropTable(Btree*, int, int*);
int sqlite3BtreeClearTable(Btree*, int);
int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
void sqlite3BtreeTripAllCursors(Btree*, int);
int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
@ -129,6 +151,7 @@ int sqlite3BtreeFlags(BtCursor*);
int sqlite3BtreePrevious(BtCursor*, int *pRes);
int sqlite3BtreeKeySize(BtCursor*, i64 *pSize);
int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
sqlite3 *sqlite3BtreeCursorDb(const BtCursor*);
const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt);
const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt);
int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
@ -146,4 +169,36 @@ void sqlite3BtreeCursorList(Btree*);
int sqlite3BtreePageDump(Btree*, int, int recursive);
#endif
/*
** If we are not using shared cache, then there is no need to
** use mutexes to access the BtShared structures. So make the
** Enter and Leave procedures no-ops.
*/
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
void sqlite3BtreeEnter(Btree*);
void sqlite3BtreeLeave(Btree*);
int sqlite3BtreeHoldsMutex(Btree*);
void sqlite3BtreeEnterCursor(BtCursor*);
void sqlite3BtreeLeaveCursor(BtCursor*);
void sqlite3BtreeEnterAll(sqlite3*);
void sqlite3BtreeLeaveAll(sqlite3*);
int sqlite3BtreeHoldsAllMutexes(sqlite3*);
void sqlite3BtreeMutexArrayEnter(BtreeMutexArray*);
void sqlite3BtreeMutexArrayLeave(BtreeMutexArray*);
void sqlite3BtreeMutexArrayInsert(BtreeMutexArray*, Btree*);
#else
# define sqlite3BtreeEnter(X)
# define sqlite3BtreeLeave(X)
# define sqlite3BtreeHoldsMutex(X) 1
# define sqlite3BtreeEnterCursor(X)
# define sqlite3BtreeLeaveCursor(X)
# define sqlite3BtreeEnterAll(X)
# define sqlite3BtreeLeaveAll(X)
# define sqlite3BtreeHoldsAllMutexes(X) 1
# define sqlite3BtreeMutexArrayEnter(X)
# define sqlite3BtreeMutexArrayLeave(X)
# define sqlite3BtreeMutexArrayInsert(X,Y)
#endif
#endif /* _BTREE_H_ */

View File

@ -248,7 +248,7 @@ typedef struct BtLock BtLock;
/*
** Page type flags. An ORed combination of these flags appear as the
** first byte of every BTree page.
** first byte of on-disk image of every BTree page.
*/
#define PTF_INTKEY 0x01
#define PTF_ZERODATA 0x02
@ -264,6 +264,9 @@ typedef struct BtLock BtLock;
** walk up the BTree from any leaf to the root. Care must be taken to
** unref() the parent page pointer when this page is no longer referenced.
** The pageDestructor() routine handles that chore.
**
** Access to all fields of this structure is controlled by the mutex
** stored in MemPage.pBt->mutex.
*/
struct MemPage {
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
@ -276,8 +279,8 @@ struct MemPage {
u8 hasData; /* True if this page stores data */
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
u16 maxLocal; /* Copy of Btree.maxLocal or Btree.maxLeaf */
u16 minLocal; /* Copy of Btree.minLocal or Btree.minLeaf */
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
u16 cellOffset; /* Index in aData of first cell pointer */
u16 idxParent; /* Index in parent of this node */
u16 nFree; /* Number of free bytes on the page */
@ -286,8 +289,8 @@ struct MemPage {
u8 *pCell; /* Pointers to the body of the overflow cell */
u16 idx; /* Insert this cell before idx-th non-overflow cell */
} aOvfl[5];
BtShared *pBt; /* Pointer back to BTree structure */
u8 *aData; /* Pointer back to the start of the page */
BtShared *pBt; /* Pointer to BtShared that this page is part of */
u8 *aData; /* Pointer to disk image of the page data */
DbPage *pDbPage; /* Pager page handle */
Pgno pgno; /* Page number for this page */
MemPage *pParent; /* The parent of this page. NULL for root */
@ -300,11 +303,36 @@ struct MemPage {
*/
#define EXTRA_SIZE sizeof(MemPage)
/* Btree handle */
/* A Btree handle
**
** A database connection contains a pointer to an instance of
** this object for every database file that it has open. This structure
** is opaque to the database connection. The database connection cannot
** see the internals of this structure and only deals with pointers to
** this structure.
**
** For some database files, the same underlying database cache might be
** shared between multiple connections. In that case, each contection
** has it own pointer to this object. But each instance of this object
** points to the same BtShared object. The database cache and the
** schema associated with the database file are all contained within
** the BtShared object.
**
** All fields in this structure are accessed under sqlite3.mutex.
** The pBt pointer itself may not be changed while there exists cursors
** in the referenced BtShared that point back to this Btree since those
** cursors have to do go through this Btree to find their BtShared and
** they often do so without holding sqlite3.mutex.
*/
struct Btree {
sqlite3 *pSqlite;
BtShared *pBt;
u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
sqlite3 *pSqlite; /* The database connection holding this btree */
BtShared *pBt; /* Sharable content of this btree */
u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
u8 sharable; /* True if we can share pBt with other pSqlite */
u8 locked; /* True if pSqlite currently has pBt locked */
int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
Btree *pNext; /* List of other sharable Btrees from the same pSqlite */
Btree *pPrev; /* Back pointer of the same list */
};
/*
@ -312,15 +340,28 @@ struct Btree {
**
** If the shared-data extension is enabled, there may be multiple users
** of the Btree structure. At most one of these may open a write transaction,
** but any number may have active read transactions. Variable Btree.pDb
** points to the handle that owns any current write-transaction.
** but any number may have active read transactions.
*/
#define TRANS_NONE 0
#define TRANS_READ 1
#define TRANS_WRITE 2
/*
** Everything we need to know about an open database
** An instance of this object represents a single database file.
**
** A single database file can be in use as the same time by two
** or more database connections. When two or more connections are
** sharing the same database file, each connection has it own
** private Btree object for the file and each of those Btrees points
** to this one BtShared object. BtShared.nRef is the number of
** connections currently sharing this database file.
**
** Fields in this structure are accessed under the BtShared.mutex
** mutex, except for nRef and pNext which are accessed under the
** global SQLITE_MUTEX_STATIC_MASTER mutex. The pPager field
** may not be modified once it is initially set as long as nRef>0.
** The pSchema field may be set once under BtShared.mutex and
** thereafter is unchanged as long as nRef>0.
*/
struct BtShared {
Pager *pPager; /* The page cache */
@ -345,13 +386,14 @@ struct BtShared {
int minLeaf; /* Minimum local payload in a LEAFDATA table */
BusyHandler *pBusyHandler; /* Callback for when there is lock contention */
u8 inTransaction; /* Transaction state */
int nRef; /* Number of references to this structure */
int nTransaction; /* Number of open transactions (read + write) */
void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */
#ifndef SQLITE_OMIT_SHARED_CACHE
int nRef; /* Number of references to this structure */
BtShared *pNext; /* Next on a list of sharable BtShared structs */
BtLock *pLock; /* List of locks held on this shared-btree struct */
BtShared *pNext; /* Next in ThreadData.pBtree linked list */
#endif
};
@ -373,12 +415,22 @@ struct CellInfo {
};
/*
** A cursor is a pointer to a particular entry in the BTree.
** A cursor is a pointer to a particular entry within a particular
** b-tree within a database file.
**
** The entry is identified by its MemPage and the index in
** MemPage.aCell[] of the entry.
**
** When a single database file can shared by two more database connections,
** but cursors cannot be shared. Each cursor is associated with a
** particular database connection identified BtCursor.pBtree.pSqlite.
**
** Fields in this structure are accessed under the BtShared.mutex
** found at self->pBt->mutex.
*/
struct BtCursor {
Btree *pBtree; /* The Btree to which this cursor belongs */
BtShared *pBt; /* The BtShared this cursor points to */
BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */
int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */
void *pArg; /* First arg to xCompare() */
@ -414,10 +466,18 @@ struct BtCursor {
** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
** this state, restoreOrClearCursorPosition() can be called to attempt to
** seek the cursor to the saved position.
**
** CURSOR_FAULT:
** A unrecoverable error (an I/O error or a malloc failure) has occurred
** on a different connection that shares the BtShared cache with this
** cursor. The error has left the cache in an inconsistent state.
** Do nothing else with this cursor. Any attempt to use the cursor
** should return the error code stored in BtCursor.skip
*/
#define CURSOR_INVALID 0
#define CURSOR_VALID 1
#define CURSOR_REQUIRESEEK 2
#define CURSOR_FAULT 3
/*
** The TRACE macro will print high-level status information about the
@ -530,8 +590,6 @@ struct BtLock {
** of handle p (type Btree*) are internally consistent.
*/
#define btreeIntegrity(p) \
assert( p->inTrans!=TRANS_NONE || p->pBt->nTransaction<p->pBt->nRef ); \
assert( p->pBt->nTransaction<=p->pBt->nRef ); \
assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \
assert( p->pBt->inTransaction>=p->inTrans );
@ -580,7 +638,9 @@ int sqlite3BtreeGetPage(BtShared*, Pgno, MemPage**, int);
int sqlite3BtreeInitPage(MemPage *pPage, MemPage *pParent);
void sqlite3BtreeParseCellPtr(MemPage*, u8*, CellInfo*);
void sqlite3BtreeParseCell(MemPage*, int, CellInfo*);
#ifdef SQLITE_TEST
u8 *sqlite3BtreeFindCell(MemPage *pPage, int iCell);
#endif
int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur);
void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur);
void sqlite3BtreeReleaseTempCursor(BtCursor *pCur);

View File

@ -69,7 +69,7 @@ void sqlite3TableLock(
int nBytes;
TableLock *p;
if( 0==sqlite3ThreadDataReadOnly()->useSharedData || iDb<0 ){
if( iDb<0 ){
return;
}
@ -82,13 +82,17 @@ void sqlite3TableLock(
}
nBytes = sizeof(TableLock) * (pParse->nTableLock+1);
pParse->aTableLock = sqliteReallocOrFree(pParse->aTableLock, nBytes);
pParse->aTableLock =
sqlite3DbReallocOrFree(pParse->db, pParse->aTableLock, nBytes);
if( pParse->aTableLock ){
p = &pParse->aTableLock[pParse->nTableLock++];
p->iDb = iDb;
p->iTab = iTab;
p->isWriteLock = isWriteLock;
p->zName = zName;
}else{
pParse->nTableLock = 0;
pParse->db->mallocFailed = 1;
}
}
@ -99,7 +103,6 @@ void sqlite3TableLock(
static void codeTableLocks(Parse *pParse){
int i;
Vdbe *pVdbe;
assert( sqlite3ThreadDataReadOnly()->useSharedData || pParse->nTableLock==0 );
if( 0==(pVdbe = sqlite3GetVdbe(pParse)) ){
return;
@ -132,7 +135,8 @@ void sqlite3FinishCoding(Parse *pParse){
sqlite3 *db;
Vdbe *v;
if( sqlite3MallocFailed() ) return;
db = pParse->db;
if( db->mallocFailed ) return;
if( pParse->nested ) return;
if( !pParse->pVdbe ){
if( pParse->rc==SQLITE_OK && pParse->nErr ){
@ -144,7 +148,6 @@ void sqlite3FinishCoding(Parse *pParse){
/* Begin by generating some termination code at the end of the
** vdbe program
*/
db = pParse->db;
v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
@ -161,6 +164,7 @@ void sqlite3FinishCoding(Parse *pParse){
sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
if( (mask & pParse->cookieMask)==0 ) continue;
sqlite3VdbeUsesBtree(v, iDb);
sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]);
}
@ -193,7 +197,7 @@ void sqlite3FinishCoding(Parse *pParse){
/* Get the VDBE program ready for execution
*/
if( v && pParse->nErr==0 && !sqlite3MallocFailed() ){
if( v && pParse->nErr==0 && !db->mallocFailed ){
#ifdef SQLITE_DEBUG
FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
sqlite3VdbeTrace(v, trace);
@ -234,16 +238,17 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
if( pParse->nErr ) return;
assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
va_start(ap, zFormat);
zSql = sqlite3VMPrintf(zFormat, ap);
zSql = sqlite3VMPrintf(pParse->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, 0);
sqliteFree(zSql);
sqlite3_free(zSql);
memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
pParse->nested--;
}
@ -336,8 +341,8 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
** Reclaim the memory used by an index
*/
static void freeIndex(Index *p){
sqliteFree(p->zColAff);
sqliteFree(p);
sqlite3_free(p->zColAff);
sqlite3_free(p);
}
/*
@ -426,7 +431,7 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
for(i=j=2; i<db->nDb; i++){
struct Db *pDb = &db->aDb[i];
if( pDb->pBt==0 ){
sqliteFree(pDb->zName);
sqlite3_free(pDb->zName);
pDb->zName = 0;
continue;
}
@ -439,7 +444,7 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
db->nDb = j;
if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
sqliteFree(db->aDb);
sqlite3_free(db->aDb);
db->aDb = db->aDbStatic;
}
}
@ -460,12 +465,12 @@ static void sqliteResetColumnNames(Table *pTable){
assert( pTable!=0 );
if( (pCol = pTable->aCol)!=0 ){
for(i=0; i<pTable->nCol; i++, pCol++){
sqliteFree(pCol->zName);
sqlite3_free(pCol->zName);
sqlite3ExprDelete(pCol->pDflt);
sqliteFree(pCol->zType);
sqliteFree(pCol->zColl);
sqlite3_free(pCol->zType);
sqlite3_free(pCol->zColl);
}
sqliteFree(pTable->aCol);
sqlite3_free(pTable->aCol);
}
pTable->aCol = 0;
pTable->nCol = 0;
@ -510,21 +515,21 @@ void sqlite3DeleteTable(Table *pTable){
pNextFKey = pFKey->pNextFrom;
assert( sqlite3HashFind(&pTable->pSchema->aFKey,
pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
sqliteFree(pFKey);
sqlite3_free(pFKey);
}
#endif
/* Delete the Table structure itself.
*/
sqliteResetColumnNames(pTable);
sqliteFree(pTable->zName);
sqliteFree(pTable->zColAff);
sqlite3_free(pTable->zName);
sqlite3_free(pTable->zColAff);
sqlite3SelectDelete(pTable->pSelect);
#ifndef SQLITE_OMIT_CHECK
sqlite3ExprDelete(pTable->pCheck);
#endif
sqlite3VtabClear(pTable);
sqliteFree(pTable);
sqlite3_free(pTable);
}
/*
@ -571,10 +576,10 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
** are not \000 terminated and are not persistent. The returned string
** is \000 terminated and is persistent.
*/
char *sqlite3NameFromToken(Token *pName){
char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
char *zName;
if( pName ){
zName = sqliteStrNDup((char*)pName->z, pName->n);
zName = sqlite3DbStrNDup(db, (char*)pName->z, pName->n);
sqlite3Dequote(zName);
}else{
zName = 0;
@ -606,7 +611,7 @@ int sqlite3FindDb(sqlite3 *db, Token *pName){
Db *pDb; /* A database whose name space is being searched */
char *zName; /* Name we are searching for */
zName = sqlite3NameFromToken(pName);
zName = sqlite3NameFromToken(db, pName);
if( zName ){
n = strlen(zName);
for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
@ -615,7 +620,7 @@ int sqlite3FindDb(sqlite3 *db, Token *pName){
break;
}
}
sqliteFree(zName);
sqlite3_free(zName);
}
return i;
}
@ -738,7 +743,7 @@ void sqlite3StartTable(
if( !OMIT_TEMPDB && isTemp ) iDb = 1;
pParse->sNameToken = *pName;
zName = sqlite3NameFromToken(pName);
zName = sqlite3NameFromToken(db, pName);
if( zName==0 ) return;
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
goto begin_table_error;
@ -795,8 +800,9 @@ void sqlite3StartTable(
}
}
pTable = sqliteMalloc( sizeof(Table) );
pTable = sqlite3DbMallocZero(db, sizeof(Table));
if( pTable==0 ){
db->mallocFailed = 1;
pParse->rc = SQLITE_NOMEM;
pParse->nErr++;
goto begin_table_error;
@ -841,6 +847,7 @@ void sqlite3StartTable(
** set them now.
*/
sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); /* file_format */
sqlite3VdbeUsesBtree(v, iDb);
lbl = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp(v, OP_If, 0, lbl);
fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ?
@ -881,7 +888,7 @@ void sqlite3StartTable(
/* If an error occurs, we jump here */
begin_table_error:
sqliteFree(zName);
sqlite3_free(zName);
return;
}
@ -916,20 +923,20 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){
sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
return;
}
z = sqlite3NameFromToken(pName);
z = sqlite3NameFromToken(pParse->db, pName);
if( z==0 ) return;
for(i=0; i<p->nCol; i++){
if( STRICMP(z, p->aCol[i].zName) ){
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
sqliteFree(z);
sqlite3_free(z);
return;
}
}
if( (p->nCol & 0x7)==0 ){
Column *aNew;
aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0]));
aNew = sqlite3DbRealloc(pParse->db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0]));
if( aNew==0 ){
sqliteFree(z);
sqlite3_free(z);
return;
}
p->aCol = aNew;
@ -1041,8 +1048,8 @@ void sqlite3AddColumnType(Parse *pParse, Token *pType){
i = p->nCol-1;
if( i<0 ) return;
pCol = &p->aCol[i];
sqliteFree(pCol->zType);
pCol->zType = sqlite3NameFromToken(pType);
sqlite3_free(pCol->zType);
pCol->zType = sqlite3NameFromToken(pParse->db, pType);
pCol->affinity = sqlite3AffinityType(pType);
}
@ -1066,10 +1073,11 @@ void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
pCol->zName);
}else{
Expr *pCopy;
sqlite3 *db = pParse->db;
sqlite3ExprDelete(pCol->pDflt);
pCol->pDflt = pCopy = sqlite3ExprDup(pExpr);
pCol->pDflt = pCopy = sqlite3ExprDup(db, pExpr);
if( pCopy ){
sqlite3TokenCopy(&pCopy->span, &pExpr->span);
sqlite3TokenCopy(db, &pCopy->span, &pExpr->span);
}
}
}
@ -1159,11 +1167,13 @@ void sqlite3AddCheckConstraint(
){
#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
** statement */
pTab->pCheck = sqlite3ExprAnd(pTab->pCheck, sqlite3ExprDup(pCheckExpr));
pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck,
sqlite3ExprDup(db, pCheckExpr));
}
#endif
sqlite3ExprDelete(pCheckExpr);
@ -1182,7 +1192,7 @@ void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){
if( sqlite3LocateCollSeq(pParse, zType, nType) ){
Index *pIdx;
p->aCol[i].zColl = sqliteStrNDup(zType, nType);
p->aCol[i].zColl = sqlite3DbStrNDup(pParse->db, zType, nType);
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
** then an index may have been created on this column before the
@ -1326,7 +1336,7 @@ static char *createTableStmt(Table *p, int isTemp){
zEnd = "\n)";
}
n += 35 + 6*p->nCol;
zStmt = sqliteMallocRaw( n );
zStmt = sqlite3_malloc( n );
if( zStmt==0 ) return 0;
sqlite3_snprintf(n, zStmt,
!OMIT_TEMPDB&&isTemp ? "CREATE TEMP TABLE ":"CREATE TABLE ");
@ -1379,7 +1389,7 @@ void sqlite3EndTable(
sqlite3 *db = pParse->db;
int iDb;
if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite3MallocFailed() ) {
if( (pEnd==0 && pSelect==0) || pParse->nErr || db->mallocFailed ) {
return;
}
p = pParse->pNewTable;
@ -1491,10 +1501,12 @@ void sqlite3EndTable(
/* Compute the complete text of the CREATE statement */
if( pSelect ){
zStmt = createTableStmt(p, p->pSchema==pParse->db->aDb[1].pSchema);
zStmt = createTableStmt(p, p->pSchema==db->aDb[1].pSchema);
}else{
n = pEnd->z - pParse->sNameToken.z + 1;
zStmt = sqlite3MPrintf("CREATE %s %.*s", zType2, n, pParse->sNameToken.z);
zStmt = sqlite3MPrintf(db,
"CREATE %s %.*s", zType2, n, pParse->sNameToken.z
);
}
/* A slot for the record has already been allocated in the
@ -1513,7 +1525,7 @@ void sqlite3EndTable(
p->zName,
zStmt
);
sqliteFree(zStmt);
sqlite3_free(zStmt);
sqlite3ChangeCookie(db, v, iDb);
#ifndef SQLITE_OMIT_AUTOINCREMENT
@ -1533,7 +1545,7 @@ void sqlite3EndTable(
/* Reparse everything to update our internal data structures */
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0,
sqlite3MPrintf("tbl_name='%q'",p->zName), P3_DYNAMIC);
sqlite3MPrintf(db, "tbl_name='%q'",p->zName), P3_DYNAMIC);
}
@ -1546,13 +1558,18 @@ void sqlite3EndTable(
pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, strlen(p->zName)+1,p);
if( pOld ){
assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
db->mallocFailed = 1;
return;
}
#ifndef SQLITE_OMIT_FOREIGN_KEY
for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){
void *data;
int nTo = strlen(pFKey->zTo) + 1;
pFKey->pNextTo = sqlite3HashFind(&pSchema->aFKey, pFKey->zTo, nTo);
sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey);
data = sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey);
if( data==(void *)pFKey ){
db->mallocFailed = 1;
}
}
#endif
pParse->pNewTable = 0;
@ -1594,6 +1611,7 @@ void sqlite3CreateView(
DbFixer sFix;
Token *pName;
int iDb;
sqlite3 *db = pParse->db;
if( pParse->nVar>0 ){
sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
@ -1607,7 +1625,7 @@ void sqlite3CreateView(
return;
}
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
iDb = sqlite3SchemaToIndex(db, p->pSchema);
if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName)
&& sqlite3FixSelect(&sFix, pSelect)
){
@ -1620,12 +1638,12 @@ void sqlite3CreateView(
** allocated rather than point to the input string - which means that
** they will persist after the current sqlite3_exec() call returns.
*/
p->pSelect = sqlite3SelectDup(pSelect);
p->pSelect = sqlite3SelectDup(db, pSelect);
sqlite3SelectDelete(pSelect);
if( sqlite3MallocFailed() ){
if( db->mallocFailed ){
return;
}
if( !pParse->db->init.busy ){
if( !db->init.busy ){
sqlite3ViewGetColumnNames(pParse, p);
}
@ -1660,6 +1678,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
Select *pSel; /* Copy of the SELECT that implements the view */
int nErr = 0; /* Number of errors encountered */
int n; /* Temporarily holds the number of cursors assigned */
sqlite3 *db = pParse->db; /* Database connection for malloc errors */
assert( pTable );
@ -1700,7 +1719,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
** statement that defines the view.
*/
assert( pTable->pSelect );
pSel = sqlite3SelectDup(pTable->pSelect);
pSel = sqlite3SelectDup(db, pTable->pSelect);
if( pSel ){
n = pParse->nTab;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
@ -1879,7 +1898,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
sqlite3 *db = pParse->db;
int iDb;
if( pParse->nErr || sqlite3MallocFailed() ){
if( pParse->nErr || db->mallocFailed ){
goto exit_drop_table;
}
assert( pName->nSrc==1 );
@ -2082,8 +2101,10 @@ void sqlite3CreateForeignKey(
nByte += strlen(pToCol->a[i].zName) + 1;
}
}
pFKey = sqliteMalloc( nByte );
if( pFKey==0 ) goto fk_end;
pFKey = sqlite3DbMallocZero(pParse->db, nByte );
if( pFKey==0 ){
goto fk_end;
}
pFKey->pFrom = p;
pFKey->pNextFrom = p->pFKey;
z = (char*)&pFKey[1];
@ -2134,7 +2155,7 @@ void sqlite3CreateForeignKey(
pFKey = 0;
fk_end:
sqliteFree(pFKey);
sqlite3_free(pFKey);
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
sqlite3ExprListDelete(pFromCol);
sqlite3ExprListDelete(pToCol);
@ -2175,11 +2196,12 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
int tnum; /* Root page of index */
Vdbe *v; /* Generate code into this virtual machine */
KeyInfo *pKey; /* KeyInfo for index */
int iDb = sqlite3SchemaToIndex(pParse->db, pIndex->pSchema);
sqlite3 *db = pParse->db; /* The database connection */
int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
#ifndef SQLITE_OMIT_AUTHORIZATION
if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
pParse->db->aDb[iDb].zName ) ){
db->aDb[iDb].zName ) ){
return;
}
#endif
@ -2211,7 +2233,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3VdbeAddOp(v, OP_IsUnique, iIdx, addr2);
sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort,
"indexed columns are not unique", P3_STATIC);
assert( sqlite3MallocFailed() || addr2==sqlite3VdbeCurrentAddr(v) );
assert( db->mallocFailed || addr2==sqlite3VdbeCurrentAddr(v) );
}
sqlite3VdbeAddOp(v, OP_IdxInsert, iIdx, 0);
sqlite3VdbeAddOp(v, OP_Next, iTab, addr1+1);
@ -2261,7 +2283,7 @@ void sqlite3CreateIndex(
int nExtra = 0;
char *zExtra;
if( pParse->nErr || sqlite3MallocFailed() || IN_DECLARE_VTAB ){
if( pParse->nErr || db->mallocFailed || IN_DECLARE_VTAB ){
goto exit_create_index;
}
@ -2339,7 +2361,7 @@ void sqlite3CreateIndex(
** own name.
*/
if( pName ){
zName = sqlite3NameFromToken(pName);
zName = sqlite3NameFromToken(db, pName);
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index;
if( zName==0 ) goto exit_create_index;
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
@ -2366,7 +2388,10 @@ void sqlite3CreateIndex(
sqlite3_snprintf(sizeof(zBuf),zBuf,"_%d",n);
zName = 0;
sqlite3SetString(&zName, "sqlite_autoindex_", pTab->zName, zBuf, (char*)0);
if( zName==0 ) goto exit_create_index;
if( zName==0 ){
db->mallocFailed = 1;
goto exit_create_index;
}
}
/* Check for authorization to create an index.
@ -2392,7 +2417,7 @@ void sqlite3CreateIndex(
if( pList==0 ){
nullId.z = (u8*)pTab->aCol[pTab->nCol-1].zName;
nullId.n = strlen((char*)nullId.z);
pList = sqlite3ExprListAppend(0, 0, &nullId);
pList = sqlite3ExprListAppend(pParse, 0, 0, &nullId);
if( pList==0 ) goto exit_create_index;
pList->a[0].sortOrder = sortOrder;
}
@ -2412,7 +2437,7 @@ void sqlite3CreateIndex(
*/
nName = strlen(zName);
nCol = pList->nExpr;
pIndex = sqliteMalloc(
pIndex = sqlite3DbMallocZero(db,
sizeof(Index) + /* Index structure */
sizeof(int)*nCol + /* Index.aiColumn */
sizeof(int)*(nCol+1) + /* Index.aiRowEst */
@ -2421,7 +2446,9 @@ void sqlite3CreateIndex(
nName + 1 + /* Index.zName */
nExtra /* Collation sequence names */
);
if( sqlite3MallocFailed() ) goto exit_create_index;
if( db->mallocFailed ){
goto exit_create_index;
}
pIndex->azColl = (char**)(&pIndex[1]);
pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]);
pIndex->aiRowEst = (unsigned *)(&pIndex->aiColumn[nCol]);
@ -2548,6 +2575,7 @@ void sqlite3CreateIndex(
pIndex->zName, strlen(pIndex->zName)+1, pIndex);
if( p ){
assert( p==pIndex ); /* Malloc must have failed */
db->mallocFailed = 1;
goto exit_create_index;
}
db->flags |= SQLITE_InternChanges;
@ -2591,7 +2619,7 @@ void sqlite3CreateIndex(
*/
if( pStart && pEnd ){
/* A named index with an explicit CREATE INDEX statement */
zStmt = sqlite3MPrintf("CREATE%s INDEX %.*s",
zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
onError==OE_None ? "" : " UNIQUE",
pEnd->z - pName->z + 1,
pName->z);
@ -2611,7 +2639,7 @@ void sqlite3CreateIndex(
zStmt
);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqliteFree(zStmt);
sqlite3_free(zStmt);
/* Fill the index with data and reparse the schema. Code an OP_Expire
** to invalidate all pre-compiled statements.
@ -2620,7 +2648,7 @@ void sqlite3CreateIndex(
sqlite3RefillIndex(pParse, pIndex, iMem);
sqlite3ChangeCookie(db, v, iDb);
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0,
sqlite3MPrintf("name='%q'", pIndex->zName), P3_DYNAMIC);
sqlite3MPrintf(db, "name='%q'", pIndex->zName), P3_DYNAMIC);
sqlite3VdbeAddOp(v, OP_Expire, 0, 0);
}
}
@ -2653,7 +2681,7 @@ exit_create_index:
}
sqlite3ExprListDelete(pList);
sqlite3SrcListDelete(pTblName);
sqliteFree(zName);
sqlite3_free(zName);
return;
}
@ -2666,6 +2694,7 @@ void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){
v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1);
sqlite3VdbeUsesBtree(v, iDb);
sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0);
sqlite3VdbeAddOp(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3);
sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0);
@ -2718,7 +2747,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
sqlite3 *db = pParse->db;
int iDb;
if( pParse->nErr || sqlite3MallocFailed() ){
if( pParse->nErr || db->mallocFailed ){
goto exit_drop_index;
}
assert( pName->nSrc==1 );
@ -2788,6 +2817,7 @@ exit_drop_index:
** pointer if the array was resized.
*/
void *sqlite3ArrayAllocate(
sqlite3 *db, /* Connection to notify of malloc failures */
void *pArray, /* Array of objects. Might be reallocated */
int szEntry, /* Size of each object in the array */
int initSize, /* Suggested initial allocation, in elements */
@ -2800,7 +2830,7 @@ void *sqlite3ArrayAllocate(
void *pNew;
int newSize;
newSize = (*pnAlloc)*2 + initSize;
pNew = sqliteRealloc(pArray, newSize*szEntry);
pNew = sqlite3DbRealloc(db, pArray, newSize*szEntry);
if( pNew==0 ){
*pIdx = -1;
return pArray;
@ -2821,14 +2851,15 @@ void *sqlite3ArrayAllocate(
**
** A new IdList is returned, or NULL if malloc() fails.
*/
IdList *sqlite3IdListAppend(IdList *pList, Token *pToken){
IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){
int i;
if( pList==0 ){
pList = sqliteMalloc( sizeof(IdList) );
pList = sqlite3DbMallocZero(db, sizeof(IdList) );
if( pList==0 ) return 0;
pList->nAlloc = 0;
}
pList->a = sqlite3ArrayAllocate(
db,
pList->a,
sizeof(pList->a[0]),
5,
@ -2840,7 +2871,7 @@ IdList *sqlite3IdListAppend(IdList *pList, Token *pToken){
sqlite3IdListDelete(pList);
return 0;
}
pList->a[i].zName = sqlite3NameFromToken(pToken);
pList->a[i].zName = sqlite3NameFromToken(db, pToken);
return pList;
}
@ -2851,10 +2882,10 @@ void sqlite3IdListDelete(IdList *pList){
int i;
if( pList==0 ) return;
for(i=0; i<pList->nId; i++){
sqliteFree(pList->a[i].zName);
sqlite3_free(pList->a[i].zName);
}
sqliteFree(pList->a);
sqliteFree(pList);
sqlite3_free(pList->a);
sqlite3_free(pList);
}
/*
@ -2886,26 +2917,31 @@ int sqlite3IdListIndex(IdList *pList, const char *zName){
**
** In other words, if call like this:
**
** sqlite3SrcListAppend(A,B,0);
** sqlite3SrcListAppend(D,A,B,0);
**
** Then B is a table name and the database name is unspecified. If called
** like this:
**
** sqlite3SrcListAppend(A,B,C);
** sqlite3SrcListAppend(D,A,B,C);
**
** Then C is the table name and B is the database name.
*/
SrcList *sqlite3SrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){
SrcList *sqlite3SrcListAppend(
sqlite3 *db, /* Connection to notify of malloc failures */
SrcList *pList, /* Append to this SrcList. NULL creates a new SrcList */
Token *pTable, /* Table to append */
Token *pDatabase /* Database of the table */
){
struct SrcList_item *pItem;
if( pList==0 ){
pList = sqliteMalloc( sizeof(SrcList) );
pList = sqlite3DbMallocZero(db, sizeof(SrcList) );
if( pList==0 ) return 0;
pList->nAlloc = 1;
}
if( pList->nSrc>=pList->nAlloc ){
SrcList *pNew;
pList->nAlloc *= 2;
pNew = sqliteRealloc(pList,
pNew = sqlite3DbRealloc(db, pList,
sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) );
if( pNew==0 ){
sqlite3SrcListDelete(pList);
@ -2923,8 +2959,8 @@ SrcList *sqlite3SrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){
pDatabase = pTable;
pTable = pTemp;
}
pItem->zName = sqlite3NameFromToken(pTable);
pItem->zDatabase = sqlite3NameFromToken(pDatabase);
pItem->zName = sqlite3NameFromToken(db, pTable);
pItem->zDatabase = sqlite3NameFromToken(db, pDatabase);
pItem->iCursor = -1;
pItem->isPopulated = 0;
pList->nSrc++;
@ -2937,7 +2973,7 @@ SrcList *sqlite3SrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){
void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
struct SrcList_item *pItem;
assert(pList || sqlite3MallocFailed() );
assert(pList || pParse->db->mallocFailed );
if( pList ){
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pItem->iCursor>=0 ) break;
@ -2957,15 +2993,15 @@ void sqlite3SrcListDelete(SrcList *pList){
struct SrcList_item *pItem;
if( pList==0 ) return;
for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
sqliteFree(pItem->zDatabase);
sqliteFree(pItem->zName);
sqliteFree(pItem->zAlias);
sqlite3_free(pItem->zDatabase);
sqlite3_free(pItem->zName);
sqlite3_free(pItem->zAlias);
sqlite3DeleteTable(pItem->pTab);
sqlite3SelectDelete(pItem->pSelect);
sqlite3ExprDelete(pItem->pOn);
sqlite3IdListDelete(pItem->pUsing);
}
sqliteFree(pList);
sqlite3_free(pList);
}
/*
@ -2985,6 +3021,7 @@ void sqlite3SrcListDelete(SrcList *pList){
** term added.
*/
SrcList *sqlite3SrcListAppendFromTerm(
Parse *pParse, /* Parsing context */
SrcList *p, /* The left part of the FROM clause already seen */
Token *pTable, /* Name of the table to add to the FROM clause */
Token *pDatabase, /* Name of the database containing pTable */
@ -2994,7 +3031,8 @@ SrcList *sqlite3SrcListAppendFromTerm(
IdList *pUsing /* The USING clause of a join */
){
struct SrcList_item *pItem;
p = sqlite3SrcListAppend(p, pTable, pDatabase);
sqlite3 *db = pParse->db;
p = sqlite3SrcListAppend(db, p, pTable, pDatabase);
if( p==0 || p->nSrc==0 ){
sqlite3ExprDelete(pOn);
sqlite3IdListDelete(pUsing);
@ -3003,7 +3041,7 @@ SrcList *sqlite3SrcListAppendFromTerm(
}
pItem = &p->a[p->nSrc-1];
if( pAlias && pAlias->n ){
pItem->zAlias = sqlite3NameFromToken(pAlias);
pItem->zAlias = sqlite3NameFromToken(db, pAlias);
}
pItem->pSelect = pSubquery;
pItem->pOn = pOn;
@ -3045,7 +3083,7 @@ void sqlite3BeginTransaction(Parse *pParse, int type){
int i;
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
if( pParse->nErr || sqlite3MallocFailed() ) return;
if( pParse->nErr || db->mallocFailed ) return;
if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return;
v = sqlite3GetVdbe(pParse);
@ -3053,6 +3091,7 @@ void sqlite3BeginTransaction(Parse *pParse, int type){
if( type!=TK_DEFERRED ){
for(i=0; i<db->nDb; i++){
sqlite3VdbeAddOp(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
sqlite3VdbeUsesBtree(v, i);
}
}
sqlite3VdbeAddOp(v, OP_AutoCommit, 0, 0);
@ -3066,7 +3105,7 @@ void sqlite3CommitTransaction(Parse *pParse){
Vdbe *v;
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
if( pParse->nErr || sqlite3MallocFailed() ) return;
if( pParse->nErr || db->mallocFailed ) return;
if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return;
v = sqlite3GetVdbe(pParse);
@ -3083,7 +3122,7 @@ void sqlite3RollbackTransaction(Parse *pParse){
Vdbe *v;
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
if( pParse->nErr || sqlite3MallocFailed() ) return;
if( pParse->nErr || db->mallocFailed ) return;
if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return;
v = sqlite3GetVdbe(pParse);
@ -3099,7 +3138,15 @@ void sqlite3RollbackTransaction(Parse *pParse){
int sqlite3OpenTempDatabase(Parse *pParse){
sqlite3 *db = pParse->db;
if( db->aDb[1].pBt==0 && !pParse->explain ){
int rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE,
int rc;
static const int flags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXCLUSIVE |
SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_TEMP_DB;
rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags,
&db->aDb[1].pBt);
if( rc!=SQLITE_OK ){
sqlite3ErrorMsg(pParse, "unable to open a temporary database "
@ -3295,27 +3342,27 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
assert( pName1->z );
pColl = sqlite3FindCollSeq(db, ENC(db), (char*)pName1->z, pName1->n, 0);
if( pColl ){
char *zColl = sqliteStrNDup((const char *)pName1->z, pName1->n);
char *zColl = sqlite3DbStrNDup(db, (const char *)pName1->z, pName1->n);
if( zColl ){
reindexDatabases(pParse, zColl);
sqliteFree(zColl);
sqlite3_free(zColl);
}
return;
}
}
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName);
if( iDb<0 ) return;
z = sqlite3NameFromToken(pObjName);
z = sqlite3NameFromToken(db, pObjName);
if( z==0 ) return;
zDb = db->aDb[iDb].zName;
pTab = sqlite3FindTable(db, z, zDb);
if( pTab ){
reindexTable(pParse, pTab, 0);
sqliteFree(z);
sqlite3_free(z);
return;
}
pIndex = sqlite3FindIndex(db, z, zDb);
sqliteFree(z);
sqlite3_free(z);
if( pIndex ){
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3RefillIndex(pParse, pIndex, -1);
@ -3330,7 +3377,7 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
** 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 sqliteFree() on the returned
** the caller is responsible for calling sqlite3_free() 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.
@ -3339,9 +3386,10 @@ KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
int i;
int nCol = pIdx->nColumn;
int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol;
KeyInfo *pKey = (KeyInfo *)sqliteMalloc(nBytes);
KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(pParse->db, nBytes);
if( pKey ){
pKey->db = pParse->db;
pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]);
assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) );
for(i=0; i<nCol; i++){
@ -3354,7 +3402,7 @@ KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
}
if( pParse->nErr ){
sqliteFree(pKey);
sqlite3_free(pKey);
pKey = 0;
}
return pKey;

View File

@ -27,15 +27,15 @@ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
assert( !db->xCollNeeded || !db->xCollNeeded16 );
if( nName<0 ) nName = strlen(zName);
if( db->xCollNeeded ){
char *zExternal = sqliteStrNDup(zName, nName);
char *zExternal = sqlite3DbStrNDup(db, zName, nName);
if( !zExternal ) return;
db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal);
sqliteFree(zExternal);
sqlite3_free(zExternal);
}
#ifndef SQLITE_OMIT_UTF16
if( db->xCollNeeded16 ){
char const *zExternal;
sqlite3_value *pTmp = sqlite3ValueNew();
sqlite3_value *pTmp = sqlite3ValueNew(db);
sqlite3ValueSetStr(pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC);
zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE);
if( zExternal ){
@ -162,7 +162,7 @@ static CollSeq *findCollSeqEntry(
pColl = sqlite3HashFind(&db->aCollSeq, zName, nName);
if( 0==pColl && create ){
pColl = sqliteMalloc( 3*sizeof(*pColl) + nName + 1 );
pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 );
if( pColl ){
CollSeq *pDel = 0;
pColl[0].zName = (char*)&pColl[3];
@ -179,9 +179,10 @@ static CollSeq *findCollSeqEntry(
** return the pColl pointer to be deleted (because it wasn't added
** to the hash table).
*/
assert( !pDel || (sqlite3MallocFailed() && pDel==pColl) );
if( pDel ){
sqliteFree(pDel);
assert( pDel==0 || pDel==pColl );
if( pDel!=0 ){
db->mallocFailed = 1;
sqlite3_free(pDel);
pColl = 0;
}
}
@ -303,14 +304,15 @@ FuncDef *sqlite3FindFunction(
** new entry to the hash table and return it.
*/
if( createFlag && bestmatch<6 &&
(pBest = sqliteMalloc(sizeof(*pBest)+nName))!=0 ){
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName))!=0 ){
pBest->nArg = nArg;
pBest->pNext = pFirst;
pBest->iPrefEnc = enc;
memcpy(pBest->zName, zName, nName);
pBest->zName[nName] = 0;
if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){
sqliteFree(pBest);
db->mallocFailed = 1;
sqlite3_free(pBest);
return 0;
}
}
@ -323,7 +325,7 @@ FuncDef *sqlite3FindFunction(
/*
** Free all resources held by the schema structure. The void* argument points
** at a Schema struct. This function does not call sqliteFree() on the
** at a Schema struct. This function does not call sqlite3_free() on the
** pointer itself, it just cleans up subsiduary resources (i.e. the contents
** of the schema hash tables).
*/
@ -356,14 +358,16 @@ void sqlite3SchemaFree(void *p){
** Find and return the schema associated with a BTree. Create
** a new one if necessary.
*/
Schema *sqlite3SchemaGet(Btree *pBt){
Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
Schema * p;
if( pBt ){
p = (Schema *)sqlite3BtreeSchema(pBt,sizeof(Schema),sqlite3SchemaFree);
p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaFree);
}else{
p = (Schema *)sqliteMalloc(sizeof(Schema));
p = (Schema *)sqlite3MallocZero(sizeof(Schema));
}
if( p && 0==p->file_format ){
if( !p ){
db->mallocFailed = 1;
}else if ( 0==p->file_format ){
sqlite3HashInit(&p->tblHash, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&p->idxHash, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&p->trigHash, SQLITE_HASH_STRING, 0);

View File

@ -24,8 +24,16 @@
/*
** This is defined in tokenize.c. We just have to import the definition.
*/
extern const char sqlite3IsIdChar[];
#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsIdChar[c-0x20]))
#ifndef SQLITE_AMALGAMATION
#ifdef SQLITE_ASCII
extern const char sqlite3IsAsciiIdChar[];
#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsAsciiIdChar[c-0x20]))
#endif
#ifdef SQLITE_EBCDIC
extern const char sqlite3IsEbcdicIdChar[];
#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
#endif
#endif /* SQLITE_AMALGAMATION */
/*
@ -248,9 +256,9 @@ int sqlite3_complete(const char *zSql){
int sqlite3_complete16(const void *zSql){
sqlite3_value *pVal;
char const *zSql8;
int rc = 0;
int rc = SQLITE_NOMEM;
pVal = sqlite3ValueNew();
pVal = sqlite3ValueNew(0);
sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
if( zSql8 ){

View File

@ -46,7 +46,6 @@
** Richmond, Virginia (USA)
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <stdlib.h>
#include <assert.h>
@ -303,7 +302,11 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){
** as there is a time string. The time string can be omitted as long
** as there is a year and date.
*/
static int parseDateOrTime(const char *zDate, DateTime *p){
static int parseDateOrTime(
sqlite3_context *context,
const char *zDate,
DateTime *p
){
memset(p, 0, sizeof(*p));
if( parseYyyyMmDd(zDate,p)==0 ){
return 0;
@ -311,7 +314,7 @@ static int parseDateOrTime(const char *zDate, DateTime *p){
return 0;
}else if( sqlite3StrICmp(zDate,"now")==0){
double r;
sqlite3OsCurrentTime(&r);
sqlite3OsCurrentTime((sqlite3_vfs *)sqlite3_user_data(context), &r);
p->rJD = r;
p->validJD = 1;
return 0;
@ -423,7 +426,7 @@ static double localtimeOffset(DateTime *p){
#else
{
struct tm *pTm;
sqlite3OsEnterMutex();
sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
pTm = localtime(&t);
y.Y = pTm->tm_year + 1900;
y.M = pTm->tm_mon + 1;
@ -431,7 +434,7 @@ static double localtimeOffset(DateTime *p){
y.h = pTm->tm_hour;
y.m = pTm->tm_min;
y.s = pTm->tm_sec;
sqlite3OsLeaveMutex();
sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
}
#endif
y.validYMD = 1;
@ -651,11 +654,17 @@ static int parseModifier(const char *zMod, DateTime *p){
** the resulting time into the DateTime structure p. Return 0
** on success and 1 if there are any errors.
*/
static int isDate(int argc, sqlite3_value **argv, DateTime *p){
static int isDate(
sqlite3_context *context,
int argc,
sqlite3_value **argv,
DateTime *p
){
int i;
const unsigned char *z;
if( argc==0 ) return 1;
if( (z = sqlite3_value_text(argv[0]))==0 || parseDateOrTime((char*)z, p) ){
z = sqlite3_value_text(argv[0]);
if( !z || parseDateOrTime(context, (char*)z, p) ){
return 1;
}
for(i=1; i<argc; i++){
@ -683,7 +692,7 @@ static void juliandayFunc(
sqlite3_value **argv
){
DateTime x;
if( isDate(argc, argv, &x)==0 ){
if( isDate(context, argc, argv, &x)==0 ){
computeJD(&x);
sqlite3_result_double(context, x.rJD);
}
@ -700,7 +709,7 @@ static void datetimeFunc(
sqlite3_value **argv
){
DateTime x;
if( isDate(argc, argv, &x)==0 ){
if( isDate(context, argc, argv, &x)==0 ){
char zBuf[100];
computeYMD_HMS(&x);
sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
@ -720,7 +729,7 @@ static void timeFunc(
sqlite3_value **argv
){
DateTime x;
if( isDate(argc, argv, &x)==0 ){
if( isDate(context, argc, argv, &x)==0 ){
char zBuf[100];
computeHMS(&x);
sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
@ -739,7 +748,7 @@ static void dateFunc(
sqlite3_value **argv
){
DateTime x;
if( isDate(argc, argv, &x)==0 ){
if( isDate(context, argc, argv, &x)==0 ){
char zBuf[100];
computeYMD(&x);
sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
@ -777,7 +786,7 @@ static void strftimeFunc(
char *z;
const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
char zBuf[100];
if( zFmt==0 || isDate(argc-1, argv+1, &x) ) return;
if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
for(i=0, n=1; zFmt[i]; i++, n++){
if( zFmt[i]=='%' ){
switch( zFmt[i+1] ){
@ -817,7 +826,7 @@ static void strftimeFunc(
sqlite3_result_error_toobig(context);
return;
}else{
z = sqliteMalloc( n );
z = sqlite3_malloc( n );
if( z==0 ) return;
}
computeJD(&x);
@ -880,7 +889,7 @@ static void strftimeFunc(
z[j] = 0;
sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
if( z!=zBuf ){
sqliteFree(z);
sqlite3_free(z);
}
}
@ -894,7 +903,7 @@ static void ctimeFunc(
int argc,
sqlite3_value **argv
){
sqlite3_value *pVal = sqlite3ValueNew();
sqlite3_value *pVal = sqlite3ValueNew(0);
if( pVal ){
sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
timeFunc(context, 1, &pVal);
@ -912,7 +921,7 @@ static void cdateFunc(
int argc,
sqlite3_value **argv
){
sqlite3_value *pVal = sqlite3ValueNew();
sqlite3_value *pVal = sqlite3ValueNew(0);
if( pVal ){
sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
dateFunc(context, 1, &pVal);
@ -930,7 +939,7 @@ static void ctimestampFunc(
int argc,
sqlite3_value **argv
){
sqlite3_value *pVal = sqlite3ValueNew();
sqlite3_value *pVal = sqlite3ValueNew(0);
if( pVal ){
sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
datetimeFunc(context, 1, &pVal);
@ -979,10 +988,10 @@ static void currentTimeFunc(
#else
{
struct tm *pTm;
sqlite3OsEnterMutex();
sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
pTm = gmtime(&t);
strftime(zBuf, 20, zFormat, pTm);
sqlite3OsLeaveMutex();
sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
}
#endif
@ -1015,7 +1024,7 @@ void sqlite3RegisterDateTimeFunctions(sqlite3 *db){
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
SQLITE_UTF8, (void *)(db->pVfs), aFuncs[i].xFunc, 0, 0);
}
#else
static const struct {

View File

@ -115,10 +115,10 @@ void sqlite3DeleteFrom(
#endif
sContext.pParse = 0;
if( pParse->nErr || sqlite3MallocFailed() ){
db = pParse->db;
if( pParse->nErr || db->mallocFailed ){
goto delete_from_cleanup;
}
db = pParse->db;
assert( pTabList->nSrc==1 );
/* Locate the table which we want to delete. This table has to be
@ -196,7 +196,7 @@ void sqlite3DeleteFrom(
** a ephemeral table.
*/
if( isView ){
Select *pView = sqlite3SelectDup(pTab->pSelect);
Select *pView = sqlite3SelectDup(db, pTab->pSelect);
sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}

View File

@ -177,7 +177,7 @@ static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
** Argument pRight (but not pLeft) may be a null pointer. In this case,
** it is not considered.
*/
CollSeq* sqlite3BinaryCompareCollSeq(
CollSeq *sqlite3BinaryCompareCollSeq(
Parse *pParse,
Expr *pLeft,
Expr *pRight
@ -217,12 +217,18 @@ static int codeCompare(
/*
** Construct a new expression node and return a pointer to it. Memory
** for this node is obtained from sqliteMalloc(). The calling function
** for this node is obtained from sqlite3_malloc(). The calling function
** is responsible for making sure the node eventually gets freed.
*/
Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){
Expr *sqlite3Expr(
sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */
int op, /* Expression opcode */
Expr *pLeft, /* Left operand */
Expr *pRight, /* Right operand */
const Token *pToken /* Argument token */
){
Expr *pNew;
pNew = sqliteMalloc( sizeof(Expr) );
pNew = sqlite3DbMallocZero(db, sizeof(Expr));
if( pNew==0 ){
/* When malloc fails, delete pLeft and pRight. Expressions passed to
** this function must always be allocated with sqlite3Expr() for this
@ -258,16 +264,17 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){
}
/*
** Works like sqlite3Expr() but frees its pLeft and pRight arguments
** if it fails due to a malloc problem.
** Works like sqlite3Expr() except that it takes an extra Parse*
** argument and notifies the associated connection object if malloc fails.
*/
Expr *sqlite3ExprOrFree(int op, Expr *pLeft, Expr *pRight, const Token *pToken){
Expr *pNew = sqlite3Expr(op, pLeft, pRight, pToken);
if( pNew==0 ){
sqlite3ExprDelete(pLeft);
sqlite3ExprDelete(pRight);
}
return pNew;
Expr *sqlite3PExpr(
Parse *pParse, /* Parsing context */
int op, /* Expression opcode */
Expr *pLeft, /* Left operand */
Expr *pRight, /* Right operand */
const Token *pToken /* Argument token */
){
return sqlite3Expr(pParse->db, op, pLeft, pRight, pToken);
}
/*
@ -287,10 +294,10 @@ Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){
int depth;
if( pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken);
return sqlite3Expr(TK_NULL, 0, 0, 0);
return sqlite3PExpr(pParse, TK_NULL, 0, 0, 0);
}
if( v==0 ) return 0;
p = sqlite3Expr(TK_REGISTER, 0, 0, pToken);
p = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, pToken);
if( p==0 ){
return 0; /* Malloc failed */
}
@ -305,13 +312,13 @@ Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){
** Join two expressions using an AND operator. If either expression is
** NULL, then just return the other expression.
*/
Expr *sqlite3ExprAnd(Expr *pLeft, Expr *pRight){
Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){
if( pLeft==0 ){
return pRight;
}else if( pRight==0 ){
return pLeft;
}else{
return sqlite3Expr(TK_AND, pLeft, pRight, 0);
return sqlite3Expr(db, TK_AND, pLeft, pRight, 0);
}
}
@ -322,7 +329,7 @@ Expr *sqlite3ExprAnd(Expr *pLeft, Expr *pRight){
void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){
assert( pRight!=0 );
assert( pLeft!=0 );
if( !sqlite3MallocFailed() && pRight->z && pLeft->z ){
if( pExpr && pRight->z && pLeft->z ){
assert( pLeft->dyn==0 || pLeft->z[pLeft->n]==0 );
if( pLeft->dyn==0 && pRight->dyn==0 ){
pExpr->span.z = pLeft->z;
@ -337,10 +344,10 @@ void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){
** Construct a new expression node for a function with multiple
** arguments.
*/
Expr *sqlite3ExprFunction(ExprList *pList, Token *pToken){
Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
Expr *pNew;
assert( pToken );
pNew = sqliteMalloc( sizeof(Expr) );
pNew = sqlite3DbMallocZero(pParse->db, sizeof(Expr) );
if( pNew==0 ){
sqlite3ExprListDelete(pList); /* Avoid leaking memory when malloc fails */
return 0;
@ -373,6 +380,8 @@ Expr *sqlite3ExprFunction(ExprList *pList, Token *pToken){
*/
void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
Token *pToken;
sqlite3 *db = pParse->db;
if( pExpr==0 ) return;
pToken = &pExpr->token;
assert( pToken->n>=1 );
@ -413,10 +422,14 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
pExpr->iTable = ++pParse->nVar;
if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){
pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10;
pParse->apVarExpr = sqliteReallocOrFree(pParse->apVarExpr,
pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) );
pParse->apVarExpr =
sqlite3DbReallocOrFree(
db,
pParse->apVarExpr,
pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0])
);
}
if( !sqlite3MallocFailed() ){
if( !db->mallocFailed ){
assert( pParse->apVarExpr!=0 );
pParse->apVarExpr[pParse->nVarExpr++] = pExpr;
}
@ -432,26 +445,26 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
*/
void sqlite3ExprDelete(Expr *p){
if( p==0 ) return;
if( p->span.dyn ) sqliteFree((char*)p->span.z);
if( p->token.dyn ) sqliteFree((char*)p->token.z);
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);
sqliteFree(p);
sqlite3_free(p);
}
/*
** The Expr.token field might be a string literal that is quoted.
** If so, remove the quotation marks.
*/
void sqlite3DequoteExpr(Expr *p){
void sqlite3DequoteExpr(sqlite3 *db, Expr *p){
if( ExprHasAnyProperty(p, EP_Dequoted) ){
return;
}
ExprSetProperty(p, EP_Dequoted);
if( p->token.dyn==0 ){
sqlite3TokenCopy(&p->token, &p->token);
sqlite3TokenCopy(db, &p->token, &p->token);
}
sqlite3Dequote((char*)p->token.z);
}
@ -469,62 +482,63 @@ void sqlite3DequoteExpr(Expr *p){
**
** Any tables that the SrcList might point to are not duplicated.
*/
Expr *sqlite3ExprDup(Expr *p){
Expr *sqlite3ExprDup(sqlite3 *db, Expr *p){
Expr *pNew;
if( p==0 ) return 0;
pNew = sqliteMallocRaw( sizeof(*p) );
pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
if( pNew==0 ) return 0;
memcpy(pNew, p, sizeof(*pNew));
if( p->token.z!=0 ){
pNew->token.z = (u8*)sqliteStrNDup((char*)p->token.z, p->token.n);
pNew->token.z = (u8*)sqlite3DbStrNDup(db, (char*)p->token.z, p->token.n);
pNew->token.dyn = 1;
}else{
assert( pNew->token.z==0 );
}
pNew->span.z = 0;
pNew->pLeft = sqlite3ExprDup(p->pLeft);
pNew->pRight = sqlite3ExprDup(p->pRight);
pNew->pList = sqlite3ExprListDup(p->pList);
pNew->pSelect = sqlite3SelectDup(p->pSelect);
pNew->pLeft = sqlite3ExprDup(db, p->pLeft);
pNew->pRight = sqlite3ExprDup(db, p->pRight);
pNew->pList = sqlite3ExprListDup(db, p->pList);
pNew->pSelect = sqlite3SelectDup(db, p->pSelect);
return pNew;
}
void sqlite3TokenCopy(Token *pTo, Token *pFrom){
if( pTo->dyn ) sqliteFree((char*)pTo->z);
void sqlite3TokenCopy(sqlite3 *db, Token *pTo, Token *pFrom){
if( pTo->dyn ) sqlite3_free((char*)pTo->z);
if( pFrom->z ){
pTo->n = pFrom->n;
pTo->z = (u8*)sqliteStrNDup((char*)pFrom->z, pFrom->n);
pTo->z = (u8*)sqlite3DbStrNDup(db, (char*)pFrom->z, pFrom->n);
pTo->dyn = 1;
}else{
pTo->z = 0;
}
}
ExprList *sqlite3ExprListDup(ExprList *p){
ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p){
ExprList *pNew;
struct ExprList_item *pItem, *pOldItem;
int i;
if( p==0 ) return 0;
pNew = sqliteMalloc( sizeof(*pNew) );
pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
if( pNew==0 ) return 0;
pNew->iECursor = 0;
pNew->nExpr = pNew->nAlloc = p->nExpr;
pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
pNew->a = pItem = sqlite3DbMallocRaw(db, p->nExpr*sizeof(p->a[0]) );
if( pItem==0 ){
sqliteFree(pNew);
sqlite3_free(pNew);
return 0;
}
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
Expr *pNewExpr, *pOldExpr;
pItem->pExpr = pNewExpr = sqlite3ExprDup(pOldExpr = pOldItem->pExpr);
pItem->pExpr = pNewExpr = sqlite3ExprDup(db, pOldExpr = pOldItem->pExpr);
if( pOldExpr->span.z!=0 && pNewExpr ){
/* Always make a copy of the span for top-level expressions in the
** expression list. The logic in SELECT processing that determines
** the names of columns in the result set needs this information */
sqlite3TokenCopy(&pNewExpr->span, &pOldExpr->span);
sqlite3TokenCopy(db, &pNewExpr->span, &pOldExpr->span);
}
assert( pNewExpr==0 || pNewExpr->span.z!=0
|| pOldExpr->span.z==0
|| sqlite3MallocFailed() );
pItem->zName = sqliteStrDup(pOldItem->zName);
|| db->mallocFailed );
pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pItem->sortOrder = pOldItem->sortOrder;
pItem->isAgg = pOldItem->isAgg;
pItem->done = 0;
@ -540,22 +554,22 @@ ExprList *sqlite3ExprListDup(ExprList *p){
*/
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
|| !defined(SQLITE_OMIT_SUBQUERY)
SrcList *sqlite3SrcListDup(SrcList *p){
SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p){
SrcList *pNew;
int i;
int nByte;
if( p==0 ) return 0;
nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
pNew = sqliteMallocRaw( nByte );
pNew = sqlite3DbMallocRaw(db, nByte );
if( pNew==0 ) return 0;
pNew->nSrc = pNew->nAlloc = p->nSrc;
for(i=0; i<p->nSrc; i++){
struct SrcList_item *pNewItem = &pNew->a[i];
struct SrcList_item *pOldItem = &p->a[i];
Table *pTab;
pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase);
pNewItem->zName = sqliteStrDup(pOldItem->zName);
pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias);
pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
pNewItem->jointype = pOldItem->jointype;
pNewItem->iCursor = pOldItem->iCursor;
pNewItem->isPopulated = pOldItem->isPopulated;
@ -563,49 +577,49 @@ SrcList *sqlite3SrcListDup(SrcList *p){
if( pTab ){
pTab->nRef++;
}
pNewItem->pSelect = sqlite3SelectDup(pOldItem->pSelect);
pNewItem->pOn = sqlite3ExprDup(pOldItem->pOn);
pNewItem->pUsing = sqlite3IdListDup(pOldItem->pUsing);
pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect);
pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn);
pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing);
pNewItem->colUsed = pOldItem->colUsed;
}
return pNew;
}
IdList *sqlite3IdListDup(IdList *p){
IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
IdList *pNew;
int i;
if( p==0 ) return 0;
pNew = sqliteMallocRaw( sizeof(*pNew) );
pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
if( pNew==0 ) return 0;
pNew->nId = pNew->nAlloc = p->nId;
pNew->a = sqliteMallocRaw( p->nId*sizeof(p->a[0]) );
pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) );
if( pNew->a==0 ){
sqliteFree(pNew);
sqlite3_free(pNew);
return 0;
}
for(i=0; i<p->nId; i++){
struct IdList_item *pNewItem = &pNew->a[i];
struct IdList_item *pOldItem = &p->a[i];
pNewItem->zName = sqliteStrDup(pOldItem->zName);
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pNewItem->idx = pOldItem->idx;
}
return pNew;
}
Select *sqlite3SelectDup(Select *p){
Select *sqlite3SelectDup(sqlite3 *db, Select *p){
Select *pNew;
if( p==0 ) return 0;
pNew = sqliteMallocRaw( sizeof(*p) );
pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
if( pNew==0 ) return 0;
pNew->isDistinct = p->isDistinct;
pNew->pEList = sqlite3ExprListDup(p->pEList);
pNew->pSrc = sqlite3SrcListDup(p->pSrc);
pNew->pWhere = sqlite3ExprDup(p->pWhere);
pNew->pGroupBy = sqlite3ExprListDup(p->pGroupBy);
pNew->pHaving = sqlite3ExprDup(p->pHaving);
pNew->pOrderBy = sqlite3ExprListDup(p->pOrderBy);
pNew->pEList = sqlite3ExprListDup(db, p->pEList);
pNew->pSrc = sqlite3SrcListDup(db, p->pSrc);
pNew->pWhere = sqlite3ExprDup(db, p->pWhere);
pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy);
pNew->pHaving = sqlite3ExprDup(db, p->pHaving);
pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy);
pNew->op = p->op;
pNew->pPrior = sqlite3SelectDup(p->pPrior);
pNew->pLimit = sqlite3ExprDup(p->pLimit);
pNew->pOffset = sqlite3ExprDup(p->pOffset);
pNew->pPrior = sqlite3SelectDup(db, p->pPrior);
pNew->pLimit = sqlite3ExprDup(db, p->pLimit);
pNew->pOffset = sqlite3ExprDup(db, p->pOffset);
pNew->iLimit = -1;
pNew->iOffset = -1;
pNew->isResolved = p->isResolved;
@ -619,7 +633,7 @@ Select *sqlite3SelectDup(Select *p){
return pNew;
}
#else
Select *sqlite3SelectDup(Select *p){
Select *sqlite3SelectDup(sqlite3 *db, Select *p){
assert( p==0 );
return 0;
}
@ -630,9 +644,15 @@ Select *sqlite3SelectDup(Select *p){
** Add a new element to the end of an expression list. If pList is
** initially NULL, then create a new expression list.
*/
ExprList *sqlite3ExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
ExprList *sqlite3ExprListAppend(
Parse *pParse, /* Parsing context */
ExprList *pList, /* List to which to append. Might be NULL */
Expr *pExpr, /* Expression to be appended */
Token *pName /* AS keyword for the expression */
){
sqlite3 *db = pParse->db;
if( pList==0 ){
pList = sqliteMalloc( sizeof(ExprList) );
pList = sqlite3DbMallocZero(db, sizeof(ExprList) );
if( pList==0 ){
goto no_mem;
}
@ -641,7 +661,7 @@ ExprList *sqlite3ExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
if( pList->nAlloc<=pList->nExpr ){
struct ExprList_item *a;
int n = pList->nAlloc*2 + 4;
a = sqliteRealloc(pList->a, n*sizeof(pList->a[0]));
a = sqlite3DbRealloc(db, pList->a, n*sizeof(pList->a[0]));
if( a==0 ){
goto no_mem;
}
@ -652,7 +672,7 @@ ExprList *sqlite3ExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
if( pExpr || pName ){
struct ExprList_item *pItem = &pList->a[pList->nExpr++];
memset(pItem, 0, sizeof(*pItem));
pItem->zName = sqlite3NameFromToken(pName);
pItem->zName = sqlite3NameFromToken(db, pName);
pItem->pExpr = pExpr;
}
return pList;
@ -680,7 +700,7 @@ void sqlite3ExprListCheckLength(
}
#if SQLITE_MAX_EXPR_DEPTH>0
#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
/* The following three functions, heightOfExpr(), heightOfExprList()
** and heightOfSelect(), are used to determine the maximum height
** of any expression tree referenced by the structure passed as the
@ -756,10 +776,10 @@ void sqlite3ExprListDelete(ExprList *pList){
assert( pList->nExpr<=pList->nAlloc );
for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
sqlite3ExprDelete(pItem->pExpr);
sqliteFree(pItem->zName);
sqlite3_free(pItem->zName);
}
sqliteFree(pList->a);
sqliteFree(pList);
sqlite3_free(pList->a);
sqlite3_free(pList);
}
/*
@ -994,12 +1014,13 @@ static int lookupName(
struct SrcList_item *pItem; /* Use for looping over pSrcList items */
struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
NameContext *pTopNC = pNC; /* First namecontext in the list */
Schema *pSchema = 0; /* Schema of the expression */
assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
zDb = sqlite3NameFromToken(pDbToken);
zTab = sqlite3NameFromToken(pTableToken);
zCol = sqlite3NameFromToken(pColumnToken);
if( sqlite3MallocFailed() ){
zDb = sqlite3NameFromToken(db, pDbToken);
zTab = sqlite3NameFromToken(db, pTableToken);
zCol = sqlite3NameFromToken(db, pColumnToken);
if( db->mallocFailed ){
goto lookupname_end;
}
@ -1032,7 +1053,7 @@ static int lookupName(
}
if( 0==(cntTab++) ){
pExpr->iTable = pItem->iCursor;
pExpr->pSchema = pTab->pSchema;
pSchema = pTab->pSchema;
pMatch = pItem;
}
for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
@ -1042,7 +1063,7 @@ static int lookupName(
cnt++;
pExpr->iTable = pItem->iCursor;
pMatch = pItem;
pExpr->pSchema = pTab->pSchema;
pSchema = pTab->pSchema;
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
pExpr->iColumn = j==pTab->iPKey ? -1 : j;
pExpr->affinity = pTab->aCol[j].affinity;
@ -1096,7 +1117,7 @@ static int lookupName(
int iCol;
Column *pCol = pTab->aCol;
pExpr->pSchema = pTab->pSchema;
pSchema = pTab->pSchema;
cntTab++;
for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) {
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
@ -1140,19 +1161,25 @@ static int lookupName(
for(j=0; j<pEList->nExpr; j++){
char *zAs = pEList->a[j].zName;
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
Expr *pDup;
Expr *pDup, *pOrig;
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
assert( pExpr->pList==0 );
assert( pExpr->pSelect==0 );
pDup = sqlite3ExprDup(pEList->a[j].pExpr);
pOrig = pEList->a[j].pExpr;
if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
sqlite3_free(zCol);
return 2;
}
pDup = sqlite3ExprDup(db, pOrig);
if( pExpr->flags & EP_ExpCollate ){
pDup->pColl = pExpr->pColl;
pDup->flags |= EP_ExpCollate;
}
if( pExpr->span.dyn ) sqliteFree((char*)pExpr->span.z);
if( pExpr->token.dyn ) sqliteFree((char*)pExpr->token.z);
if( pExpr->span.dyn ) sqlite3_free((char*)pExpr->span.z);
if( pExpr->token.dyn ) sqlite3_free((char*)pExpr->token.z);
memcpy(pExpr, pDup, sizeof(*pExpr));
sqliteFree(pDup);
sqlite3_free(pDup);
cnt = 1;
pMatch = 0;
assert( zTab==0 && zDb==0 );
@ -1180,7 +1207,7 @@ static int lookupName(
** fields are not changed in any context.
*/
if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
sqliteFree(zCol);
sqlite3_free(zCol);
return 0;
}
@ -1197,11 +1224,15 @@ static int lookupName(
}else if( zTab ){
sqlite3SetString(&z, zTab, ".", zCol, (char*)0);
}else{
z = sqliteStrDup(zCol);
z = sqlite3StrDup(zCol);
}
if( z ){
sqlite3ErrorMsg(pParse, zErr, z);
sqlite3_free(z);
pTopNC->nErr++;
}else{
db->mallocFailed = 1;
}
sqlite3ErrorMsg(pParse, zErr, z);
sqliteFree(z);
pTopNC->nErr++;
}
/* If a column from a table in pSrcList is referenced, then record
@ -1222,18 +1253,18 @@ static int lookupName(
lookupname_end:
/* Clean up and return
*/
sqliteFree(zDb);
sqliteFree(zTab);
sqlite3_free(zDb);
sqlite3_free(zTab);
sqlite3ExprDelete(pExpr->pLeft);
pExpr->pLeft = 0;
sqlite3ExprDelete(pExpr->pRight);
pExpr->pRight = 0;
pExpr->op = TK_COLUMN;
lookupname_end_2:
sqliteFree(zCol);
sqlite3_free(zCol);
if( cnt==1 ){
assert( pNC!=0 );
sqlite3AuthRead(pParse, pExpr, pNC->pSrcList);
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
if( pMatch && !pMatch->pSelect ){
pExpr->pTab = pMatch->pTab;
}
@ -1450,7 +1481,7 @@ int sqlite3ExprResolveNames(
){
int savedHasAgg;
if( pExpr==0 ) return 0;
#if SQLITE_MAX_EXPR_DEPTH>0
#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
if( (pExpr->nHeight+pNC->pParse->nHeight)>SQLITE_MAX_EXPR_DEPTH ){
sqlite3ErrorMsg(pNC->pParse,
"Expression tree is too large (maximum depth %d)",
@ -1463,7 +1494,7 @@ int sqlite3ExprResolveNames(
savedHasAgg = pNC->hasAgg;
pNC->hasAgg = 0;
walkExprTree(pExpr, nameResolverStep, pNC);
#if SQLITE_MAX_EXPR_DEPTH>0
#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
pNC->pParse->nHeight -= pExpr->nHeight;
#endif
if( pNC->nErr>0 ){
@ -1521,7 +1552,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
int mem = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0);
testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0);
assert( testAddr>0 || sqlite3MallocFailed() );
assert( testAddr>0 || pParse->db->mallocFailed );
sqlite3VdbeAddOp(v, OP_MemInt, 1, mem);
}
@ -1572,7 +1603,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
}else if( pExpr->pList ){
/* Case 2: expr IN (exprlist)
**
** For each expression, build an index key from the evaluation and
** For each expression, build an index key from the evaluation and
** store it in the temporary table. If <expr> is a column, then use
** that columns affinity when building index keys. If <expr> is not
** a column, use numeric affinity.
@ -1633,7 +1664,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
VdbeComment((v, "# Init EXISTS result"));
}
sqlite3ExprDelete(pSel->pLimit);
pSel->pLimit = sqlite3Expr(TK_INTEGER, 0, 0, &one);
pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one);
if( sqlite3Select(pParse, pSel, sop, iMem, 0, 0, 0, 0) ){
return;
}
@ -1654,7 +1685,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
** text z[0..n-1] on the stack.
*/
static void codeInteger(Vdbe *v, const char *z, int n){
assert( z || sqlite3MallocFailed() );
assert( z || v==0 || sqlite3VdbeDb(v)->mallocFailed );
if( z ){
int i;
if( sqlite3GetInt32(z, &i) ){
@ -1745,7 +1776,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
case TK_STRING: {
assert( TK_FLOAT==OP_Real );
assert( TK_STRING==OP_String8 );
sqlite3DequoteExpr(pExpr);
sqlite3DequoteExpr(pParse->db, pExpr);
sqlite3VdbeOp3(v, op, 0, 0, (char*)pExpr->token.z, pExpr->token.n);
break;
}
@ -1848,13 +1879,13 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
assert( pLeft );
if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){
Token *p = &pLeft->token;
char *z = sqlite3MPrintf("-%.*s", p->n, p->z);
char *z = sqlite3MPrintf(pParse->db, "-%.*s", p->n, p->z);
if( pLeft->op==TK_FLOAT ){
sqlite3VdbeOp3(v, OP_Real, 0, 0, z, p->n+1);
}else{
codeInteger(v, z, p->n+1);
}
sqliteFree(z);
sqlite3_free(z);
break;
}
/* Fall through into TK_NOT */
@ -1900,8 +1931,10 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
const char *zId;
int constMask = 0;
int i;
u8 enc = ENC(pParse->db);
sqlite3 *db = pParse->db;
u8 enc = ENC(db);
CollSeq *pColl = 0;
zId = (char*)pExpr->token.z;
nId = pExpr->token.n;
pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
@ -1921,9 +1954,9 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
** for function overloading. But we use the B term in "glob(B,A)".
*/
if( nExpr>=2 && (pExpr->flags & EP_InfixFunc) ){
pDef = sqlite3VtabOverloadFunction(pDef, nExpr, pList->a[1].pExpr);
pDef = sqlite3VtabOverloadFunction(db, pDef, nExpr, pList->a[1].pExpr);
}else if( nExpr>0 ){
pDef = sqlite3VtabOverloadFunction(pDef, nExpr, pList->a[0].pExpr);
pDef = sqlite3VtabOverloadFunction(db, pDef, nExpr, pList->a[0].pExpr);
}
#endif
for(i=0; i<nExpr && i<32; i++){
@ -2052,13 +2085,13 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
if( !pParse->trigStack ){
sqlite3ErrorMsg(pParse,
"RAISE() may only be used within a trigger-program");
return;
return;
}
if( pExpr->iColumn!=OE_Ignore ){
assert( pExpr->iColumn==OE_Rollback ||
pExpr->iColumn == OE_Abort ||
pExpr->iColumn == OE_Fail );
sqlite3DequoteExpr(pExpr);
sqlite3DequoteExpr(pParse->db, pExpr);
sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn,
(char*)pExpr->token.z, pExpr->token.n);
} else {
@ -2383,9 +2416,10 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
** Add a new element to the pAggInfo->aCol[] array. Return the index of
** the new element. Return a negative number if malloc fails.
*/
static int addAggInfoColumn(AggInfo *pInfo){
static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){
int i;
pInfo->aCol = sqlite3ArrayAllocate(
db,
pInfo->aCol,
sizeof(pInfo->aCol[0]),
3,
@ -2400,9 +2434,10 @@ static int addAggInfoColumn(AggInfo *pInfo){
** Add a new element to the pAggInfo->aFunc[] array. Return the index of
** the new element. Return a negative number if malloc fails.
*/
static int addAggInfoFunc(AggInfo *pInfo){
static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){
int i;
pInfo->aFunc = sqlite3ArrayAllocate(
db,
pInfo->aFunc,
sizeof(pInfo->aFunc[0]),
3,
@ -2426,7 +2461,6 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
Parse *pParse = pNC->pParse;
SrcList *pSrcList = pNC->pSrcList;
AggInfo *pAggInfo = pNC->pAggInfo;
switch( pExpr->op ){
case TK_AGG_COLUMN:
@ -2452,7 +2486,9 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
break;
}
}
if( k>=pAggInfo->nColumn && (k = addAggInfoColumn(pAggInfo))>=0 ){
if( (k>=pAggInfo->nColumn)
&& (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
){
pCol = &pAggInfo->aCol[k];
pCol->pTab = pExpr->pTab;
pCol->iTable = pExpr->iTable;
@ -2509,7 +2545,7 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
/* pExpr is original. Make a new entry in pAggInfo->aFunc[]
*/
u8 enc = ENC(pParse->db);
i = addAggInfoFunc(pAggInfo);
i = addAggInfoFunc(pParse->db, pAggInfo);
if( i>=0 ){
pItem = &pAggInfo->aFunc[i];
pItem->pExpr = pExpr;

View File

@ -20,11 +20,10 @@
*/
#include "sqliteInt.h"
#include <ctype.h>
/* #include <math.h> */
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"
#include "os.h"
/*
** Return the collating function associated with a function.
@ -235,6 +234,19 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3_result_double(context, r);
}
/*
** Allocate nByte bytes of space using sqlite3_malloc(). If the
** allocation fails, call sqlite3_result_error_nomem() to notify
** the database handle that malloc() has failed.
*/
static void *contextMalloc(sqlite3_context *context, int nByte){
char *z = sqlite3_malloc(nByte);
if( !z && nByte>0 ){
sqlite3_result_error_nomem(context);
}
return z;
}
/*
** Implementation of the upper() and lower() SQL functions.
*/
@ -248,7 +260,7 @@ static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
/* Verify that the call to _bytes() does not invalidate the _text() pointer */
assert( z2==(char*)sqlite3_value_text(argv[0]) );
if( z2 ){
z1 = sqlite3_malloc(n+1);
z1 = contextMalloc(context, n+1);
if( z1 ){
memcpy(z1, z2, n+1);
for(i=0; z1[i]; i++){
@ -268,7 +280,7 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
/* Verify that the call to _bytes() does not invalidate the _text() pointer */
assert( z2==(char*)sqlite3_value_text(argv[0]) );
if( z2 ){
z1 = sqlite3_malloc(n+1);
z1 = contextMalloc(context, n+1);
if( z1 ){
memcpy(z1, z2, n+1);
for(i=0; z1[i]; i++){
@ -333,10 +345,10 @@ static void randomBlob(
sqlite3_result_error_toobig(context);
return;
}
p = sqliteMalloc(n);
p = contextMalloc(context, n);
if( p ){
sqlite3Randomness(n, p);
sqlite3_result_blob(context, (char*)p, n, sqlite3FreeX);
sqlite3_result_blob(context, (char*)p, n, sqlite3_free);
}
}
@ -397,15 +409,6 @@ static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 };
** is case sensitive causing 'a' LIKE 'A' to be false */
static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
/*
** Read a single UTF-8 character and return its value.
*/
u32 sqlite3ReadUtf8(const unsigned char *z){
u32 c;
SQLITE_READ_UTF8(z, c);
return c;
}
/*
** Compare two UTF-8 strings for equality where the first string can
** potentially be a "glob" expression. Return true (1) if they
@ -440,97 +443,102 @@ static int patternCompare(
const struct compareInfo *pInfo, /* Information about how to do the compare */
const int esc /* The escape character */
){
register int c;
int c, c2;
int invert;
int seen;
int c2;
u8 matchOne = pInfo->matchOne;
u8 matchAll = pInfo->matchAll;
u8 matchSet = pInfo->matchSet;
u8 noCase = pInfo->noCase;
int prevEscape = 0; /* True if the previous character was 'escape' */
while( (c = *zPattern)!=0 ){
while( (c = sqlite3Utf8Read(zPattern,0,&zPattern))!=0 ){
if( !prevEscape && c==matchAll ){
while( (c=zPattern[1]) == matchAll || c == matchOne ){
if( c==matchOne ){
if( *zString==0 ) return 0;
SQLITE_SKIP_UTF8(zString);
while( (c=sqlite3Utf8Read(zPattern,0,&zPattern)) == matchAll
|| c == matchOne ){
if( c==matchOne && sqlite3Utf8Read(zString, 0, &zString)==0 ){
return 0;
}
zPattern++;
}
if( c && esc && sqlite3ReadUtf8(&zPattern[1])==esc ){
u8 const *zTemp = &zPattern[1];
SQLITE_SKIP_UTF8(zTemp);
c = *zTemp;
}
if( c==0 ) return 1;
if( c==matchSet ){
assert( esc==0 ); /* This is GLOB, not LIKE */
while( *zString && patternCompare(&zPattern[1],zString,pInfo,esc)==0 ){
if( c==0 ){
return 1;
}else if( c==esc ){
c = sqlite3Utf8Read(zPattern, 0, &zPattern);
if( c==0 ){
return 0;
}
}else if( c==matchSet ){
assert( esc==0 ); /* This is GLOB, not LIKE */
assert( matchSet<0x80 ); /* '[' is a single-byte character */
while( *zString && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){
SQLITE_SKIP_UTF8(zString);
}
return *zString!=0;
}else{
while( (c2 = *zString)!=0 ){
if( noCase ){
c2 = sqlite3UpperToLower[c2];
c = sqlite3UpperToLower[c];
while( c2 != 0 && c2 != c ){ c2 = sqlite3UpperToLower[*++zString]; }
}else{
while( c2 != 0 && c2 != c ){ c2 = *++zString; }
}
while( (c2 = sqlite3Utf8Read(zString,0,&zString))!=0 ){
if( noCase ){
c2 = c2<0x80 ? sqlite3UpperToLower[c2] : c2;
c = c<0x80 ? sqlite3UpperToLower[c] : c;
while( c2 != 0 && c2 != c ){
c2 = sqlite3Utf8Read(zString, 0, &zString);
if( c2<0x80 ) c2 = sqlite3UpperToLower[c2];
}
}else{
while( c2 != 0 && c2 != c ){
c2 = sqlite3Utf8Read(zString, 0, &zString);
}
if( c2==0 ) return 0;
if( patternCompare(&zPattern[1],zString,pInfo,esc) ) return 1;
SQLITE_SKIP_UTF8(zString);
}
if( c2==0 ) return 0;
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
}
return 0;
}else if( !prevEscape && c==matchOne ){
if( sqlite3Utf8Read(zString, 0, &zString)==0 ){
return 0;
}
}else if( !prevEscape && c==matchOne ){
if( *zString==0 ) return 0;
SQLITE_SKIP_UTF8(zString);
zPattern++;
}else if( c==matchSet ){
int prior_c = 0;
assert( esc==0 ); /* This only occurs for GLOB, not LIKE */
seen = 0;
invert = 0;
c = sqlite3ReadUtf8(zString);
c = sqlite3Utf8Read(zString, 0, &zString);
if( c==0 ) return 0;
c2 = *++zPattern;
if( c2=='^' ){ invert = 1; c2 = *++zPattern; }
c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
if( c2=='^' ){
invert = 1;
c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
}
if( c2==']' ){
if( c==']' ) seen = 1;
c2 = *++zPattern;
c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
}
while( (c2 = sqlite3ReadUtf8(zPattern))!=0 && c2!=']' ){
if( c2=='-' && zPattern[1]!=']' && zPattern[1]!=0 && prior_c>0 ){
zPattern++;
c2 = sqlite3ReadUtf8(zPattern);
while( c2 && c2!=']' ){
if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){
c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
if( c>=prior_c && c<=c2 ) seen = 1;
prior_c = 0;
}else if( c==c2 ){
seen = 1;
prior_c = c2;
}else{
if( c==c2 ){
seen = 1;
}
prior_c = c2;
}
SQLITE_SKIP_UTF8(zPattern);
c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
}
if( c2==0 || (seen ^ invert)==0 ) return 0;
SQLITE_SKIP_UTF8(zString);
zPattern++;
}else if( esc && !prevEscape && sqlite3ReadUtf8(zPattern)==esc){
if( c2==0 || (seen ^ invert)==0 ){
return 0;
}
}else if( esc==c && !prevEscape ){
prevEscape = 1;
SQLITE_SKIP_UTF8(zPattern);
}else{
c2 = sqlite3Utf8Read(zString, 0, &zString);
if( noCase ){
if( sqlite3UpperToLower[c] != sqlite3UpperToLower[*zString] ) return 0;
}else{
if( c != *zString ) return 0;
c = c<0x80 ? sqlite3UpperToLower[c] : c;
c2 = c2<0x80 ? sqlite3UpperToLower[c2] : c2;
}
if( c!=c2 ){
return 0;
}
zPattern++;
zString++;
prevEscape = 0;
}
}
@ -590,7 +598,7 @@ static void likeFunc(
"ESCAPE expression must be a single character", -1);
return;
}
escape = sqlite3ReadUtf8(zEsc);
escape = sqlite3Utf8Read(zEsc, 0, &zEsc);
}
if( zA && zB ){
struct compareInfo *pInfo = sqlite3_user_data(context);
@ -670,10 +678,8 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3_result_error_toobig(context);
return;
}
zText = (char *)sqliteMalloc((2*nBlob)+4);
if( !zText ){
sqlite3_result_error(context, "out of memory", -1);
}else{
zText = (char *)contextMalloc(context, (2*nBlob)+4);
if( zText ){
int i;
for(i=0; i<nBlob; i++){
zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
@ -684,7 +690,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
zText[0] = 'X';
zText[1] = '\'';
sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
sqliteFree(zText);
sqlite3_free(zText);
}
break;
}
@ -700,19 +706,19 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3_result_error_toobig(context);
return;
}
z = sqliteMalloc( i+n+3 );
if( z==0 ) return;
z[0] = '\'';
for(i=0, j=1; zArg[i]; i++){
z[j++] = zArg[i];
if( zArg[i]=='\'' ){
z[j++] = '\'';
z = contextMalloc(context, i+n+3);
if( z ){
z[0] = '\'';
for(i=0, j=1; zArg[i]; i++){
z[j++] = zArg[i];
if( zArg[i]=='\'' ){
z[j++] = '\'';
}
}
z[j++] = '\'';
z[j] = 0;
sqlite3_result_text(context, z, j, sqlite3_free);
}
z[j++] = '\'';
z[j] = 0;
sqlite3_result_text(context, z, j, SQLITE_TRANSIENT);
sqliteFree(z);
}
}
}
@ -737,15 +743,16 @@ static void hexFunc(
return;
}
assert( pBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
z = zHex = sqlite3_malloc(n*2 + 1);
if( zHex==0 ) return;
for(i=0; i<n; i++, pBlob++){
unsigned char c = *pBlob;
*(z++) = hexdigits[(c>>4)&0xf];
*(z++) = hexdigits[c&0xf];
z = zHex = contextMalloc(context, n*2 + 1);
if( zHex ){
for(i=0; i<n; i++, pBlob++){
unsigned char c = *pBlob;
*(z++) = hexdigits[(c>>4)&0xf];
*(z++) = hexdigits[c&0xf];
}
*z = 0;
sqlite3_result_text(context, zHex, n*2, sqlite3_free);
}
*z = 0;
sqlite3_result_text(context, zHex, n*2, sqlite3_free);
}
/*
@ -803,7 +810,7 @@ static void replaceFunc(
assert( zRep==sqlite3_value_text(argv[2]) );
nOut = nStr + 1;
assert( nOut<SQLITE_MAX_LENGTH );
zOut = sqlite3_malloc((int)nOut);
zOut = contextMalloc(context, (int)nOut);
if( zOut==0 ){
return;
}
@ -812,14 +819,18 @@ static void replaceFunc(
if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){
zOut[j++] = zStr[i];
}else{
u8 *zOld;
nOut += nRep - nPattern;
if( nOut>=SQLITE_MAX_LENGTH ){
sqlite3_result_error_toobig(context);
sqlite3_free(zOut);
return;
}
zOld = zOut;
zOut = sqlite3_realloc(zOut, (int)nOut);
if( zOut==0 ){
sqlite3_result_error_nomem(context);
sqlite3_free(zOld);
return;
}
memcpy(&zOut[j], zRep, nRep);
@ -875,7 +886,7 @@ static void trimFunc(
SQLITE_SKIP_UTF8(z);
}
if( nChar>0 ){
azChar = sqlite3_malloc( nChar*(sizeof(char*)+1) );
azChar = contextMalloc(context, nChar*(sizeof(char*)+1));
if( azChar==0 ){
return;
}
@ -1005,20 +1016,18 @@ static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){
".-!,:*^+=_|?/<> ";
int iMin, iMax, n, r, i;
unsigned char zBuf[1000];
if( argc>=1 ){
iMin = sqlite3_value_int(argv[0]);
if( iMin<0 ) iMin = 0;
if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1;
}else{
iMin = 1;
}
if( argc>=2 ){
iMax = sqlite3_value_int(argv[1]);
if( iMax<iMin ) iMax = iMin;
if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1;
}else{
iMax = 50;
}
/* It used to be possible to call randstr() with any number of arguments,
** but now it is registered with SQLite as requiring exactly 2.
*/
assert(argc==2);
iMin = sqlite3_value_int(argv[0]);
if( iMin<0 ) iMin = 0;
if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1;
iMax = sqlite3_value_int(argv[1]);
if( iMax<iMin ) iMax = iMin;
if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1;
n = iMin;
if( iMax>iMin ){
sqlite3Randomness(sizeof(r), &r);
@ -1052,7 +1061,7 @@ static void destructor(void *p){
char *zVal = (char *)p;
assert(zVal);
zVal--;
sqliteFree(zVal);
sqlite3_free(zVal);
test_destructor_count_var--;
}
static void test_destructor(
@ -1068,10 +1077,12 @@ static void test_destructor(
assert( nArg==1 );
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
len = sqlite3ValueBytes(argv[0], ENC(db));
zVal = sqliteMalloc(len+3);
zVal[len] = 0;
zVal[len-1] = 0;
assert( zVal );
zVal = contextMalloc(pCtx, len+3);
if( !zVal ){
return;
}
zVal[len+1] = 0;
zVal[len+2] = 0;
zVal++;
memcpy(zVal, sqlite3ValueText(argv[0], ENC(db)), len);
if( ENC(db)==SQLITE_UTF8 ){
@ -1105,15 +1116,16 @@ static void test_destructor_count(
** registration, the result for that argument is 1. The overall result
** is the individual argument results separated by spaces.
*/
static void free_test_auxdata(void *p) {sqliteFree(p);}
static void free_test_auxdata(void *p) {sqlite3_free(p);}
static void test_auxdata(
sqlite3_context *pCtx,
int nArg,
sqlite3_value **argv
){
int i;
char *zRet = sqliteMalloc(nArg*2);
char *zRet = contextMalloc(pCtx, nArg*2);
if( !zRet ) return;
memset(zRet, 0, nArg*2);
for(i=0; i<nArg; i++){
char const *z = (char*)sqlite3_value_text(argv[i]);
if( z ){
@ -1124,9 +1136,13 @@ static void test_auxdata(
sqlite3_result_error(pCtx, "Auxilary data corruption", -1);
return;
}
}else{
}else {
zRet[i*2] = '0';
zAux = sqliteStrDup(z);
}
zAux = contextMalloc(pCtx, strlen(z)+1);
if( zAux ){
strcpy(zAux, z);
sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata);
}
zRet[i*2+1] = ' ';
@ -1410,11 +1426,11 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
}
}
sqlite3RegisterDateTimeFunctions(db);
if( !sqlite3MallocFailed() ){
if( !db->mallocFailed ){
int rc = sqlite3_overload_function(db, "MATCH", 2);
assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
if( rc==SQLITE_NOMEM ){
sqlite3FailedMalloc();
db->mallocFailed = 1;
}
}
#ifdef SQLITE_SSE

View File

@ -41,8 +41,6 @@ void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){
pNew->count = 0;
pNew->htsize = 0;
pNew->ht = 0;
pNew->xMalloc = sqlite3MallocX;
pNew->xFree = sqlite3FreeX;
}
/* Remove all entries from a hash table. Reclaim all memory.
@ -55,15 +53,15 @@ void sqlite3HashClear(Hash *pH){
assert( pH!=0 );
elem = pH->first;
pH->first = 0;
if( pH->ht ) pH->xFree(pH->ht);
if( pH->ht ) sqlite3_free(pH->ht);
pH->ht = 0;
pH->htsize = 0;
while( elem ){
HashElem *next_elem = elem->next;
if( pH->copyKey && elem->pKey ){
pH->xFree(elem->pKey);
sqlite3_free(elem->pKey);
}
pH->xFree(elem);
sqlite3_free(elem);
elem = next_elem;
}
pH->count = 0;
@ -216,7 +214,7 @@ static void insertElement(
/* Resize the hash table so that it cantains "new_size" buckets.
** "new_size" must be a power of 2. The hash table might fail
** to resize if sqliteMalloc() fails.
** to resize if sqlite3_malloc() fails.
*/
static void rehash(Hash *pH, int new_size){
struct _ht *new_ht; /* The new hash table */
@ -224,9 +222,17 @@ static void rehash(Hash *pH, int new_size){
int (*xHash)(const void*,int); /* The hash function */
assert( (new_size & (new_size-1))==0 );
new_ht = (struct _ht *)pH->xMalloc( new_size*sizeof(struct _ht) );
/* There is a call to sqlite3_malloc() inside rehash(). If there is
** already an allocation at pH->ht, then if this malloc() fails it
** is benign (since failing to resize a hash table is a performance
** hit only, not a fatal error).
*/
sqlite3MallocBenignFailure(pH->htsize>0);
new_ht = (struct _ht *)sqlite3MallocZero( new_size*sizeof(struct _ht) );
if( new_ht==0 ) return;
if( pH->ht ) pH->xFree(pH->ht);
if( pH->ht ) sqlite3_free(pH->ht);
pH->ht = new_ht;
pH->htsize = new_size;
xHash = hashFunction(pH->keyClass);
@ -292,9 +298,9 @@ static void removeElementGivenHash(
pEntry->chain = 0;
}
if( pH->copyKey ){
pH->xFree(elem->pKey);
sqlite3_free(elem->pKey);
}
pH->xFree( elem );
sqlite3_free( elem );
pH->count--;
if( pH->count<=0 ){
assert( pH->first==0 );
@ -304,10 +310,11 @@ static void removeElementGivenHash(
}
/* Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey. Return the data for this element if it is
** found, or NULL if there is no match.
** that matches pKey,nKey. Return a pointer to the corresponding
** HashElem structure for this element if it is found, or NULL
** otherwise.
*/
void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){
HashElem *sqlite3HashFindElem(const Hash *pH, const void *pKey, int nKey){
int h; /* A hash on key */
HashElem *elem; /* The element that matches key */
int (*xHash)(const void*,int); /* The hash function */
@ -318,6 +325,16 @@ void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){
h = (*xHash)(pKey,nKey);
assert( (pH->htsize & (pH->htsize-1))==0 );
elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
return elem;
}
/* Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey. Return the data for this element if it is
** found, or NULL if there is no match.
*/
void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){
HashElem *elem; /* The element that matches key */
elem = sqlite3HashFindElem(pH, pKey, nKey);
return elem ? elem->data : 0;
}
@ -356,16 +373,20 @@ void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
removeElementGivenHash(pH,elem,h);
}else{
elem->data = data;
if( !pH->copyKey ){
elem->pKey = (void *)pKey;
}
assert(nKey==elem->nKey);
}
return old_data;
}
if( data==0 ) return 0;
new_elem = (HashElem*)pH->xMalloc( sizeof(HashElem) );
new_elem = (HashElem*)sqlite3_malloc( sizeof(HashElem) );
if( new_elem==0 ) return data;
if( pH->copyKey && pKey!=0 ){
new_elem->pKey = pH->xMalloc( nKey );
new_elem->pKey = sqlite3_malloc( nKey );
if( new_elem->pKey==0 ){
pH->xFree(new_elem);
sqlite3_free(new_elem);
return data;
}
memcpy((void*)new_elem->pKey, pKey, nKey);
@ -379,9 +400,9 @@ void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
if( pH->htsize==0 ){
pH->count = 0;
if( pH->copyKey ){
pH->xFree(new_elem->pKey);
sqlite3_free(new_elem->pKey);
}
pH->xFree(new_elem);
sqlite3_free(new_elem);
return data;
}
}

View File

@ -33,10 +33,8 @@ struct Hash {
char keyClass; /* SQLITE_HASH_INT, _POINTER, _STRING, _BINARY */
char copyKey; /* True if copy of key made on insert */
int count; /* Number of entries in this table */
HashElem *first; /* The first element of the array */
void *(*xMalloc)(int); /* malloc() function to use */
void (*xFree)(void *); /* free() function to use */
int htsize; /* Number of buckets in the hash table */
HashElem *first; /* The first element of the array */
struct _ht { /* the hash table */
int count; /* Number of entries with this hash */
HashElem *chain; /* Pointer to first entry with this hash */
@ -83,6 +81,7 @@ struct HashElem {
void sqlite3HashInit(Hash*, int keytype, int copyKey);
void *sqlite3HashInsert(Hash*, const void *pKey, int nKey, void *pData);
void *sqlite3HashFind(const Hash*, const void *pKey, int nKey);
HashElem *sqlite3HashFindElem(const Hash*, const void *pKey, int nKey);
void sqlite3HashClear(Hash*);
/*

View File

@ -41,7 +41,8 @@ void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
*/
int n;
Table *pTab = pIdx->pTable;
pIdx->zColAff = (char *)sqliteMalloc(pIdx->nColumn+1);
sqlite3 *db = sqlite3VdbeDb(v);
pIdx->zColAff = (char *)sqlite3DbMallocZero(db, pIdx->nColumn+1);
if( !pIdx->zColAff ){
return;
}
@ -79,8 +80,9 @@ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
if( !pTab->zColAff ){
char *zColAff;
int i;
sqlite3 *db = sqlite3VdbeDb(v);
zColAff = (char *)sqliteMalloc(pTab->nCol+1);
zColAff = (char *)sqlite3DbMallocZero(db, pTab->nCol+1);
if( !zColAff ){
return;
}
@ -356,10 +358,10 @@ void sqlite3Insert(
int triggers_exist = 0; /* True if there are FOR EACH ROW triggers */
#endif
if( pParse->nErr || sqlite3MallocFailed() ){
db = pParse->db;
if( pParse->nErr || db->mallocFailed ){
goto insert_cleanup;
}
db = pParse->db;
/* Locate the table into which we will be inserting new information.
*/
@ -462,7 +464,7 @@ void sqlite3Insert(
/* Resolve the expressions in the SELECT statement and execute it. */
rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock,0,0,0,0);
if( rc || pParse->nErr || sqlite3MallocFailed() ){
if( rc || pParse->nErr || db->mallocFailed ){
goto insert_cleanup;
}
@ -1027,7 +1029,7 @@ void sqlite3GenerateConstraintChecks(
assert( pParse->ckOffset==nCol );
pParse->ckOffset = 0;
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
if( onError==OE_Ignore || onError==OE_Replace ){
if( onError==OE_Ignore ){
sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0);
sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
}else{
@ -1416,9 +1418,7 @@ static int xferOptimization(
if( onError!=OE_Abort && onError!=OE_Rollback ){
return 0; /* Cannot do OR REPLACE or OR IGNORE or OR FAIL */
}
if( pSelect->pSrc==0 ){
return 0; /* SELECT must have a FROM clause */
}
assert(pSelect->pSrc); /* allocated even if there is no FROM clause */
if( pSelect->pSrc->nSrc!=1 ){
return 0; /* FROM clause must have exactly one term */
}
@ -1523,6 +1523,7 @@ static int xferOptimization(
#endif
iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema);
v = sqlite3GetVdbe(pParse);
sqlite3CodeVerifySchema(pParse, iDbSrc);
iSrc = pParse->nTab++;
iDest = pParse->nTab++;
counterMem = autoIncBegin(pParse, iDbDest, pDest);

View File

@ -0,0 +1,238 @@
/*
** 2007 August 22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** @(#) $Id$
*/
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
/*
** This file implements a special kind of sqlite3_file object used
** by SQLite to create journal files if the atomic-write optimization
** is enabled.
**
** The distinctive characteristic of this sqlite3_file is that the
** actual on disk file is created lazily. When the file is created,
** the caller specifies a buffer size for an in-memory buffer to
** be used to service read() and write() requests. The actual file
** on disk is not created or populated until either:
**
** 1) The in-memory representation grows too large for the allocated
** buffer, or
** 2) The xSync() method is called.
*/
#include "sqliteInt.h"
/*
** A JournalFile object is a subclass of sqlite3_file used by
** as an open file handle for journal files.
*/
struct JournalFile {
sqlite3_io_methods *pMethod; /* I/O methods on journal files */
int nBuf; /* Size of zBuf[] in bytes */
char *zBuf; /* Space to buffer journal writes */
int iSize; /* Amount of zBuf[] currently used */
int flags; /* xOpen flags */
sqlite3_vfs *pVfs; /* The "real" underlying VFS */
sqlite3_file *pReal; /* The "real" underlying file descriptor */
const char *zJournal; /* Name of the journal file */
};
typedef struct JournalFile JournalFile;
/*
** If it does not already exists, create and populate the on-disk file
** for JournalFile p.
*/
static int createFile(JournalFile *p){
int rc = SQLITE_OK;
if( !p->pReal ){
sqlite3_file *pReal = (sqlite3_file *)&p[1];
rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0);
if( rc==SQLITE_OK ){
p->pReal = pReal;
if( p->iSize>0 ){
assert(p->iSize<=p->nBuf);
rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
}
}
}
return rc;
}
/*
** Close the file.
*/
static int jrnlClose(sqlite3_file *pJfd){
JournalFile *p = (JournalFile *)pJfd;
if( p->pReal ){
sqlite3OsClose(p->pReal);
}
sqlite3_free(p->zBuf);
return SQLITE_OK;
}
/*
** Read data from the file.
*/
static int jrnlRead(
sqlite3_file *pJfd, /* The journal file from which to read */
void *zBuf, /* Put the results here */
int iAmt, /* Number of bytes to read */
sqlite_int64 iOfst /* Begin reading at this offset */
){
int rc = SQLITE_OK;
JournalFile *p = (JournalFile *)pJfd;
if( p->pReal ){
rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
}else{
assert( iAmt+iOfst<=p->iSize );
memcpy(zBuf, &p->zBuf[iOfst], iAmt);
}
return rc;
}
/*
** Write data to the file.
*/
static int jrnlWrite(
sqlite3_file *pJfd, /* The journal file into which to write */
const void *zBuf, /* Take data to be written from here */
int iAmt, /* Number of bytes to write */
sqlite_int64 iOfst /* Begin writing at this offset into the file */
){
int rc = SQLITE_OK;
JournalFile *p = (JournalFile *)pJfd;
if( !p->pReal && (iOfst+iAmt)>p->nBuf ){
rc = createFile(p);
}
if( rc==SQLITE_OK ){
if( p->pReal ){
rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
}else{
memcpy(&p->zBuf[iOfst], zBuf, iAmt);
if( p->iSize<(iOfst+iAmt) ){
p->iSize = (iOfst+iAmt);
}
}
}
return rc;
}
/*
** Truncate the file.
*/
static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
int rc = SQLITE_OK;
JournalFile *p = (JournalFile *)pJfd;
if( p->pReal ){
rc = sqlite3OsTruncate(p->pReal, size);
}else if( size<p->iSize ){
p->iSize = size;
}
return rc;
}
/*
** Sync the file.
*/
static int jrnlSync(sqlite3_file *pJfd, int flags){
int rc;
JournalFile *p = (JournalFile *)pJfd;
rc = createFile(p);
if( rc==SQLITE_OK ){
rc = sqlite3OsSync(p->pReal, flags);
}
return rc;
}
/*
** Query the size of the file in bytes.
*/
static int jrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){
int rc = SQLITE_OK;
JournalFile *p = (JournalFile *)pJfd;
if( p->pReal ){
rc = sqlite3OsFileSize(p->pReal, pSize);
}else{
*pSize = (sqlite_int64) p->iSize;
}
return rc;
}
/*
** Table of methods for JournalFile sqlite3_file object.
*/
static struct sqlite3_io_methods JournalFileMethods = {
1, /* iVersion */
jrnlClose, /* xClose */
jrnlRead, /* xRead */
jrnlWrite, /* xWrite */
jrnlTruncate, /* xTruncate */
jrnlSync, /* xSync */
jrnlFileSize, /* xFileSize */
0, /* xLock */
0, /* xUnlock */
0, /* xCheckReservedLock */
0, /* xFileControl */
0, /* xSectorSize */
0 /* xDeviceCharacteristics */
};
/*
** Open a journal file.
*/
int sqlite3JournalOpen(
sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */
const char *zName, /* Name of the journal file */
sqlite3_file *pJfd, /* Preallocated, blank file handle */
int flags, /* Opening flags */
int nBuf /* Bytes buffered before opening the file */
){
JournalFile *p = (JournalFile *)pJfd;
memset(p, 0, sqlite3JournalSize(pVfs));
if( nBuf>0 ){
p->zBuf = sqlite3MallocZero(nBuf);
if( !p->zBuf ){
return SQLITE_NOMEM;
}
}else{
return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0);
}
p->pMethod = &JournalFileMethods;
p->nBuf = nBuf;
p->flags = flags;
p->zJournal = zName;
p->pVfs = pVfs;
return SQLITE_OK;
}
/*
** If the argument p points to a JournalFile structure, and the underlying
** file has not yet been created, create it now.
*/
int sqlite3JournalCreate(sqlite3_file *p){
if( p->pMethods!=&JournalFileMethods ){
return SQLITE_OK;
}
return createFile((JournalFile *)p);
}
/*
** Return the number of bytes required to store a JournalFile that uses vfs
** pVfs to create the underlying on-disk files.
*/
int sqlite3JournalSize(sqlite3_vfs *pVfs){
return (pVfs->szOsFile+sizeof(JournalFile));
}
#endif

View File

@ -2,7 +2,7 @@
**
** The code in this file has been automatically generated by
**
** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.30 2007/05/04 18:30:41 drh Exp $
** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.31 2007/07/30 18:26:20 rse Exp $
**
** The code in this file implements a function that determines whether
** or not a given identifier is really an SQL keyword. The same thing

View File

@ -18,7 +18,6 @@
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
/*
@ -47,6 +46,8 @@ int sqlite3_exec(
int nCallback;
if( zSql==0 ) return SQLITE_OK;
sqlite3_mutex_enter(db->mutex);
while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
int nCol;
char **azVals = 0;
@ -66,7 +67,7 @@ int sqlite3_exec(
nCallback = 0;
nCol = sqlite3_column_count(pStmt);
azCols = sqliteMalloc(2*nCol*sizeof(const char *) + 1);
azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char *) + 1);
if( azCols==0 ){
goto exec_out;
}
@ -108,15 +109,15 @@ int sqlite3_exec(
}
}
sqliteFree(azCols);
sqlite3_free(azCols);
azCols = 0;
}
exec_out:
if( pStmt ) sqlite3_finalize(pStmt);
if( azCols ) sqliteFree(azCols);
if( azCols ) sqlite3_free(azCols);
rc = sqlite3ApiExit(0, rc);
rc = sqlite3ApiExit(db, rc);
if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){
int nErrMsg = 1 + strlen(sqlite3_errmsg(db));
*pzErrMsg = sqlite3_malloc(nErrMsg);
@ -128,5 +129,6 @@ exec_out:
}
assert( (rc&db->errMask)==rc );
sqlite3_mutex_leave(db->mutex);
return rc;
}

View File

@ -17,7 +17,6 @@
** $Id$
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
/*
@ -26,6 +25,7 @@
const char sqlite3_version[] = SQLITE_VERSION;
const char *sqlite3_libversion(void){ return sqlite3_version; }
int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }
int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }
/*
** If the following function pointer is not NULL and if
@ -119,6 +119,7 @@ int sqlite3_close(sqlite3 *db){
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
sqlite3_mutex_enter(db->mutex);
#ifdef SQLITE_SSE
{
@ -142,6 +143,7 @@ int sqlite3_close(sqlite3 *db){
if( db->pVdbe ){
sqlite3Error(db, SQLITE_BUSY,
"Unable to close due to unfinalised statements");
sqlite3_mutex_leave(db->mutex);
return SQLITE_BUSY;
}
assert( !sqlite3SafetyCheck(db) );
@ -156,6 +158,7 @@ int sqlite3_close(sqlite3 *db){
*/
if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){
/* printf("DID NOT CLOSE\n"); fflush(stdout); */
sqlite3_mutex_leave(db->mutex);
return SQLITE_ERROR;
}
@ -176,7 +179,7 @@ int sqlite3_close(sqlite3 *db){
FuncDef *pFunc, *pNext;
for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
pNext = pFunc->pNext;
sqliteFree(pFunc);
sqlite3_free(pFunc);
}
}
@ -188,7 +191,7 @@ int sqlite3_close(sqlite3 *db){
pColl[j].xDel(pColl[j].pUser);
}
}
sqliteFree(pColl);
sqlite3_free(pColl);
}
sqlite3HashClear(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
@ -197,7 +200,7 @@ int sqlite3_close(sqlite3 *db){
if( pMod->xDestroy ){
pMod->xDestroy(pMod->pAux);
}
sqliteFree(pMod);
sqlite3_free(pMod);
}
sqlite3HashClear(&db->aModule);
#endif
@ -217,9 +220,10 @@ int sqlite3_close(sqlite3 *db){
** the same sqliteMalloc() as the one that allocates the database
** structure?
*/
sqliteFree(db->aDb[1].pSchema);
sqliteFree(db);
sqlite3ReleaseThreadData();
sqlite3_free(db->aDb[1].pSchema);
sqlite3_mutex_leave(db->mutex);
sqlite3_mutex_free(db->mutex);
sqlite3_free(db);
return SQLITE_OK;
}
@ -229,6 +233,8 @@ int sqlite3_close(sqlite3 *db){
void sqlite3RollbackAll(sqlite3 *db){
int i;
int inTrans = 0;
assert( sqlite3_mutex_held(db->mutex) );
sqlite3MallocEnterBenignBlock(1); /* Enter benign region */
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pBt ){
if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){
@ -239,7 +245,10 @@ void sqlite3RollbackAll(sqlite3 *db){
}
}
sqlite3VtabRollback(db);
sqlite3MallocLeaveBenignBlock(); /* Leave benign region */
if( db->flags&SQLITE_InternChanges ){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetInternalSchema(db, 0);
}
@ -303,7 +312,8 @@ static int sqliteDefaultBusyCallback(
static const u8 totals[] =
{ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 };
# define NDELAY (sizeof(delays)/sizeof(delays[0]))
int timeout = ((sqlite3 *)ptr)->busyTimeout;
sqlite3 *db = (sqlite3 *)ptr;
int timeout = db->busyTimeout;
int delay, prior;
assert( count>=0 );
@ -318,14 +328,15 @@ static int sqliteDefaultBusyCallback(
delay = timeout - prior;
if( delay<=0 ) return 0;
}
sqlite3OsSleep(delay);
sqlite3OsSleep(db->pVfs, delay*1000);
return 1;
#else
sqlite3 *db = (sqlite3 *)ptr;
int timeout = ((sqlite3 *)ptr)->busyTimeout;
if( (count+1)*1000 > timeout ){
return 0;
}
sqlite3OsSleep(1000);
sqlite3OsSleep(db->pVfs, 1000000);
return 1;
#endif
}
@ -361,9 +372,11 @@ int sqlite3_busy_handler(
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
sqlite3_mutex_enter(db->mutex);
db->busyHandler.xFunc = xBusy;
db->busyHandler.pArg = pArg;
db->busyHandler.nBusy = 0;
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
@ -380,6 +393,7 @@ void sqlite3_progress_handler(
void *pArg
){
if( !sqlite3SafetyCheck(db) ){
sqlite3_mutex_enter(db->mutex);
if( nOps>0 ){
db->xProgress = xProgress;
db->nProgressOps = nOps;
@ -389,6 +403,7 @@ void sqlite3_progress_handler(
db->nProgressOps = 0;
db->pProgressArg = 0;
}
sqlite3_mutex_leave(db->mutex);
}
}
#endif
@ -420,30 +435,6 @@ void sqlite3_interrupt(sqlite3 *db){
}
}
/*
** Memory allocation routines that use SQLites internal memory
** memory allocator. Depending on how SQLite is compiled, the
** internal memory allocator might be just an alias for the
** system default malloc/realloc/free. Or the built-in allocator
** might do extra stuff like put sentinals around buffers to
** check for overruns or look for memory leaks.
**
** Use sqlite3_free() to free memory returned by sqlite3_mprintf().
*/
void sqlite3_free(void *p){ if( p ) sqlite3OsFree(p); }
void *sqlite3_malloc(int nByte){ return nByte>0 ? sqlite3OsMalloc(nByte) : 0; }
void *sqlite3_realloc(void *pOld, int nByte){
if( pOld ){
if( nByte>0 ){
return sqlite3OsRealloc(pOld, nByte);
}else{
sqlite3OsFree(pOld);
return 0;
}
}else{
return sqlite3_malloc(nByte);
}
}
/*
** This function is exactly the same as sqlite3_create_function(), except
@ -464,6 +455,7 @@ int sqlite3CreateFunc(
FuncDef *p;
int nName;
assert( sqlite3_mutex_held(db->mutex) );
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
@ -491,10 +483,13 @@ int sqlite3CreateFunc(
int rc;
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8,
pUserData, xFunc, xStep, xFinal);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE,
pUserData, xFunc, xStep, xFinal);
if( rc!=SQLITE_OK ) return rc;
if( rc==SQLITE_OK ){
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE,
pUserData, xFunc, xStep, xFinal);
}
if( rc!=SQLITE_OK ){
return rc;
}
enc = SQLITE_UTF16BE;
}
#else
@ -511,7 +506,7 @@ int sqlite3CreateFunc(
if( db->activeVdbeCnt ){
sqlite3Error(db, SQLITE_BUSY,
"Unable to delete/modify user-function due to active statements");
assert( !sqlite3MallocFailed() );
assert( !db->mallocFailed );
return SQLITE_BUSY;
}else{
sqlite3ExpirePreparedStatements(db);
@ -519,14 +514,16 @@ int sqlite3CreateFunc(
}
p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1);
if( p ){
p->flags = 0;
p->xFunc = xFunc;
p->xStep = xStep;
p->xFinalize = xFinal;
p->pUserData = pUserData;
p->nArg = nArg;
assert(p || db->mallocFailed);
if( !p ){
return SQLITE_NOMEM;
}
p->flags = 0;
p->xFunc = xFunc;
p->xStep = xStep;
p->xFinalize = xFinal;
p->pUserData = pUserData;
p->nArg = nArg;
return SQLITE_OK;
}
@ -544,10 +541,12 @@ int sqlite3_create_function(
void (*xFinal)(sqlite3_context*)
){
int rc;
assert( !sqlite3MallocFailed() );
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
rc = sqlite3CreateFunc(db, zFunctionName, nArg, enc, p, xFunc, xStep, xFinal);
return sqlite3ApiExit(db, rc);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
#ifndef SQLITE_OMIT_UTF16
@ -563,13 +562,14 @@ int sqlite3_create_function16(
){
int rc;
char *zFunc8;
assert( !sqlite3MallocFailed() );
zFunc8 = sqlite3Utf16to8(zFunctionName, -1);
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1);
rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal);
sqliteFree(zFunc8);
return sqlite3ApiExit(db, rc);
sqlite3_free(zFunc8);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
#endif
@ -592,11 +592,15 @@ int sqlite3_overload_function(
int nArg
){
int nName = strlen(zName);
int rc;
sqlite3_mutex_enter(db->mutex);
if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){
sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8,
0, sqlite3InvalidFunction, 0, 0);
}
return sqlite3ApiExit(db, SQLITE_OK);
rc = sqlite3ApiExit(db, SQLITE_OK);
sqlite3_mutex_leave(db->mutex);
return rc;
}
#ifndef SQLITE_OMIT_TRACE
@ -609,9 +613,12 @@ int sqlite3_overload_function(
** SQL statement.
*/
void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){
void *pOld = db->pTraceArg;
void *pOld;
sqlite3_mutex_enter(db->mutex);
pOld = db->pTraceArg;
db->xTrace = xTrace;
db->pTraceArg = pArg;
sqlite3_mutex_leave(db->mutex);
return pOld;
}
/*
@ -627,9 +634,12 @@ void *sqlite3_profile(
void (*xProfile)(void*,const char*,sqlite_uint64),
void *pArg
){
void *pOld = db->pProfileArg;
void *pOld;
sqlite3_mutex_enter(db->mutex);
pOld = db->pProfileArg;
db->xProfile = xProfile;
db->pProfileArg = pArg;
sqlite3_mutex_leave(db->mutex);
return pOld;
}
#endif /* SQLITE_OMIT_TRACE */
@ -645,9 +655,12 @@ void *sqlite3_commit_hook(
int (*xCallback)(void*), /* Function to invoke on each commit */
void *pArg /* Argument to the function */
){
void *pOld = db->pCommitArg;
void *pOld;
sqlite3_mutex_enter(db->mutex);
pOld = db->pCommitArg;
db->xCommitCallback = xCallback;
db->pCommitArg = pArg;
sqlite3_mutex_leave(db->mutex);
return pOld;
}
@ -660,9 +673,12 @@ void *sqlite3_update_hook(
void (*xCallback)(void*,int,char const *,char const *,sqlite_int64),
void *pArg /* Argument to the function */
){
void *pRet = db->pUpdateArg;
void *pRet;
sqlite3_mutex_enter(db->mutex);
pRet = db->pUpdateArg;
db->xUpdateCallback = xCallback;
db->pUpdateArg = pArg;
sqlite3_mutex_leave(db->mutex);
return pRet;
}
@ -675,9 +691,12 @@ void *sqlite3_rollback_hook(
void (*xCallback)(void*), /* Callback function */
void *pArg /* Argument to the function */
){
void *pRet = db->pRollbackArg;
void *pRet;
sqlite3_mutex_enter(db->mutex);
pRet = db->pRollbackArg;
db->xRollbackCallback = xCallback;
db->pRollbackArg = pArg;
sqlite3_mutex_leave(db->mutex);
return pRet;
}
@ -711,17 +730,19 @@ int sqlite3BtreeFactory(
const char *zFilename, /* Name of the file containing the BTree database */
int omitJournal, /* if TRUE then do not journal this file */
int nCache, /* How many pages in the page cache */
int vfsFlags, /* Flags passed through to vfsOpen */
Btree **ppBtree /* Pointer to new Btree object written here */
){
int btree_flags = 0;
int btFlags = 0;
int rc;
assert( sqlite3_mutex_held(db->mutex) );
assert( ppBtree != 0);
if( omitJournal ){
btree_flags |= BTREE_OMIT_JOURNAL;
btFlags |= BTREE_OMIT_JOURNAL;
}
if( db->flags & SQLITE_NoReadlock ){
btree_flags |= BTREE_NO_READLOCK;
btFlags |= BTREE_NO_READLOCK;
}
if( zFilename==0 ){
#if TEMP_STORE==0
@ -740,7 +761,10 @@ int sqlite3BtreeFactory(
#endif /* SQLITE_OMIT_MEMORYDB */
}
rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btree_flags);
if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (zFilename==0 || *zFilename==0) ){
vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
}
rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btFlags, vfsFlags);
if( rc==SQLITE_OK ){
sqlite3BtreeSetBusyHandler(*ppBtree, (void*)&db->busyHandler);
sqlite3BtreeSetCacheSize(*ppBtree, nCache);
@ -754,17 +778,19 @@ int sqlite3BtreeFactory(
*/
const char *sqlite3_errmsg(sqlite3 *db){
const char *z;
assert( !sqlite3MallocFailed() );
if( !db ){
return sqlite3ErrStr(SQLITE_NOMEM);
}
if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){
return sqlite3ErrStr(SQLITE_MISUSE);
}
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
z = (char*)sqlite3_value_text(db->pErr);
if( z==0 ){
z = sqlite3ErrStr(db->errCode);
}
sqlite3_mutex_leave(db->mutex);
return z;
}
@ -794,13 +820,14 @@ const void *sqlite3_errmsg16(sqlite3 *db){
};
const void *z;
assert( !sqlite3MallocFailed() );
if( !db ){
return (void *)(&outOfMemBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]);
}
if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){
return (void *)(&misuseBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]);
}
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
z = sqlite3_value_text16(db->pErr);
if( z==0 ){
sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode),
@ -808,6 +835,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){
z = sqlite3_value_text16(db->pErr);
}
sqlite3ApiExit(0, 0);
sqlite3_mutex_leave(db->mutex);
return z;
}
#endif /* SQLITE_OMIT_UTF16 */
@ -817,7 +845,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){
** passed to this function, we assume a malloc() failed during sqlite3_open().
*/
int sqlite3_errcode(sqlite3 *db){
if( !db || sqlite3MallocFailed() ){
if( !db || db->mallocFailed ){
return SQLITE_NOMEM;
}
if( sqlite3SafetyCheck(db) ){
@ -844,6 +872,7 @@ static int createCollation(
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
assert( sqlite3_mutex_held(db->mutex) );
/* If SQLITE_UTF16 is specified as the encoding type, transform this
** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
@ -912,21 +941,28 @@ static int createCollation(
*/
static int openDatabase(
const char *zFilename, /* Database filename UTF-8 encoded */
sqlite3 **ppDb /* OUT: Returned database handle */
sqlite3 **ppDb, /* OUT: Returned database handle */
unsigned flags, /* Operational flags */
const char *zVfs /* Name of the VFS to use */
){
sqlite3 *db;
int rc;
CollSeq *pColl;
assert( !sqlite3MallocFailed() );
/* Allocate the sqlite data structure */
db = sqliteMalloc( sizeof(sqlite3) );
db = sqlite3MallocZero( sizeof(sqlite3) );
if( db==0 ) goto opendb_out;
db->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE);
if( db->mutex==0 ){
sqlite3_free(db);
db = 0;
goto opendb_out;
}
sqlite3_mutex_enter(db->mutex);
db->errMask = 0xff;
db->priorNewRowid = 0;
db->magic = SQLITE_MAGIC_BUSY;
db->nDb = 2;
db->magic = SQLITE_MAGIC_BUSY;
db->aDb = db->aDbStatic;
db->autoCommit = 1;
db->flags |= SQLITE_ShortColNames
@ -943,6 +979,14 @@ static int openDatabase(
sqlite3HashInit(&db->aModule, SQLITE_HASH_STRING, 0);
#endif
db->pVfs = sqlite3_vfs_find(zVfs);
if( !db->pVfs ){
rc = SQLITE_ERROR;
db->magic = SQLITE_MAGIC_CLOSED;
sqlite3Error(db, rc, "no such vfs: %s", (zVfs?zVfs:"(null)"));
goto opendb_out;
}
/* Add the default collation sequence BINARY. BINARY works for both UTF-8
** and UTF-16, so add a version for each to avoid any unnecessary
** conversions. The only error that can occur here is a malloc() failure.
@ -952,7 +996,7 @@ static int openDatabase(
createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0) ||
(db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0))==0
){
assert( sqlite3MallocFailed() );
assert( db->mallocFailed );
db->magic = SQLITE_MAGIC_CLOSED;
goto opendb_out;
}
@ -968,15 +1012,17 @@ static int openDatabase(
}
/* Open the backend database driver */
rc = sqlite3BtreeFactory(db, zFilename, 0, SQLITE_DEFAULT_CACHE_SIZE,
db->openFlags = flags;
rc = sqlite3BtreeFactory(db, zFilename, 0, SQLITE_DEFAULT_CACHE_SIZE,
flags | SQLITE_OPEN_MAIN_DB,
&db->aDb[0].pBt);
if( rc!=SQLITE_OK ){
sqlite3Error(db, rc, 0);
db->magic = SQLITE_MAGIC_CLOSED;
goto opendb_out;
}
db->aDb[0].pSchema = sqlite3SchemaGet(db->aDb[0].pBt);
db->aDb[1].pSchema = sqlite3SchemaGet(0);
db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
/* The default safety_level for the main database is 'full'; for the temp
@ -990,7 +1036,7 @@ static int openDatabase(
#endif
db->magic = SQLITE_MAGIC_OPEN;
if( sqlite3MallocFailed() ){
if( db->mallocFailed ){
goto opendb_out;
}
@ -1010,21 +1056,28 @@ static int openDatabase(
}
#ifdef SQLITE_ENABLE_FTS1
if( !sqlite3MallocFailed() ){
if( !db->mallocFailed ){
extern int sqlite3Fts1Init(sqlite3*);
rc = sqlite3Fts1Init(db);
}
#endif
#ifdef SQLITE_ENABLE_FTS2
if( !sqlite3MallocFailed() && rc==SQLITE_OK ){
if( !db->mallocFailed && rc==SQLITE_OK ){
extern int sqlite3Fts2Init(sqlite3*);
rc = sqlite3Fts2Init(db);
}
#endif
#ifdef SQLITE_ENABLE_FTS3
if( !db->mallocFailed && rc==SQLITE_OK ){
extern int sqlite3Fts3Init(sqlite3*);
rc = sqlite3Fts3Init(db);
}
#endif
#ifdef SQLITE_ENABLE_ICU
if( !sqlite3MallocFailed() && rc==SQLITE_OK ){
if( !db->mallocFailed && rc==SQLITE_OK ){
extern int sqlite3IcuInit(sqlite3*);
rc = sqlite3IcuInit(db);
}
@ -1042,6 +1095,9 @@ static int openDatabase(
#endif
opendb_out:
if( db && db->mutex ){
sqlite3_mutex_leave(db->mutex);
}
if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){
sqlite3_close(db);
db = 0;
@ -1057,7 +1113,16 @@ int sqlite3_open(
const char *zFilename,
sqlite3 **ppDb
){
return openDatabase(zFilename, ppDb);
return openDatabase(zFilename, ppDb,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
}
int sqlite3_open_v2(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb, /* OUT: SQLite db handle */
int flags, /* Flags */
const char *zVfs /* Name of VFS module to use */
){
return openDatabase(filename, ppDb, flags, zVfs);
}
#ifndef SQLITE_OMIT_UTF16
@ -1069,17 +1134,18 @@ int sqlite3_open16(
sqlite3 **ppDb
){
char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */
int rc = SQLITE_OK;
sqlite3_value *pVal;
int rc = SQLITE_NOMEM;
assert( zFilename );
assert( ppDb );
*ppDb = 0;
pVal = sqlite3ValueNew();
pVal = sqlite3ValueNew(0);
sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC);
zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8);
if( zFilename8 ){
rc = openDatabase(zFilename8, ppDb);
rc = openDatabase(zFilename8, ppDb,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
if( rc==SQLITE_OK && *ppDb ){
rc = sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0);
if( rc!=SQLITE_OK ){
@ -1094,45 +1160,6 @@ int sqlite3_open16(
}
#endif /* SQLITE_OMIT_UTF16 */
/*
** The following routine destroys a virtual machine that is created by
** the sqlite3_compile() routine. The integer returned is an SQLITE_
** success/failure code that describes the result of executing the virtual
** machine.
**
** This routine sets the error code and string returned by
** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
*/
int sqlite3_finalize(sqlite3_stmt *pStmt){
int rc;
if( pStmt==0 ){
rc = SQLITE_OK;
}else{
rc = sqlite3VdbeFinalize((Vdbe*)pStmt);
}
return rc;
}
/*
** Terminate the current execution of an SQL statement and reset it
** back to its starting state so that it can be reused. A success code from
** the prior execution is returned.
**
** This routine sets the error code and string returned by
** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
*/
int sqlite3_reset(sqlite3_stmt *pStmt){
int rc;
if( pStmt==0 ){
rc = SQLITE_OK;
}else{
rc = sqlite3VdbeReset((Vdbe*)pStmt);
sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0);
assert( (rc & (sqlite3_db_handle(pStmt)->errMask))==rc );
}
return rc;
}
/*
** Register a new collation sequence with the database handle db.
*/
@ -1144,9 +1171,12 @@ int sqlite3_create_collation(
int(*xCompare)(void*,int,const void*,int,const void*)
){
int rc;
assert( !sqlite3MallocFailed() );
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
rc = createCollation(db, zName, enc, pCtx, xCompare, 0);
return sqlite3ApiExit(db, rc);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*
@ -1161,9 +1191,12 @@ int sqlite3_create_collation_v2(
void(*xDel)(void*)
){
int rc;
assert( !sqlite3MallocFailed() );
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
rc = createCollation(db, zName, enc, pCtx, xCompare, xDel);
return sqlite3ApiExit(db, rc);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
#ifndef SQLITE_OMIT_UTF16
@ -1179,13 +1212,16 @@ int sqlite3_create_collation16(
){
int rc = SQLITE_OK;
char *zName8;
assert( !sqlite3MallocFailed() );
zName8 = sqlite3Utf16to8(zName, -1);
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
zName8 = sqlite3Utf16to8(db, zName, -1);
if( zName8 ){
rc = createCollation(db, zName8, enc, pCtx, xCompare, 0);
sqliteFree(zName8);
sqlite3_free(zName8);
}
return sqlite3ApiExit(db, rc);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
#endif /* SQLITE_OMIT_UTF16 */
@ -1201,9 +1237,11 @@ int sqlite3_collation_needed(
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
sqlite3_mutex_enter(db->mutex);
db->xCollNeeded = xCollNeeded;
db->xCollNeeded16 = 0;
db->pCollNeededArg = pCollNeededArg;
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
@ -1220,9 +1258,11 @@ int sqlite3_collation_needed16(
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
sqlite3_mutex_enter(db->mutex);
db->xCollNeeded = 0;
db->xCollNeeded16 = xCollNeeded16;
db->pCollNeededArg = pCollNeededArg;
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
#endif /* SQLITE_OMIT_UTF16 */
@ -1260,45 +1300,14 @@ int sqlite3Corrupt(void){
}
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
/*
** Enable or disable the shared pager and schema features for the
** current thread.
**
** This routine should only be called when there are no open
** database connections.
*/
int sqlite3_enable_shared_cache(int enable){
ThreadData *pTd = sqlite3ThreadData();
if( pTd ){
/* It is only legal to call sqlite3_enable_shared_cache() when there
** are no currently open b-trees that were opened by the calling thread.
** This condition is only easy to detect if the shared-cache were
** previously enabled (and is being disabled).
*/
if( pTd->pBtree && !enable ){
assert( pTd->useSharedData );
return SQLITE_MISUSE;
}
pTd->useSharedData = enable;
sqlite3ReleaseThreadData();
}
return sqlite3ApiExit(0, SQLITE_OK);
}
#endif
/*
** This is a convenience routine that makes sure that all thread-specific
** data for this thread has been deallocated.
**
** SQLite no longer uses thread-specific data so this routine is now a
** no-op. It is retained for historical compatibility.
*/
void sqlite3_thread_cleanup(void){
ThreadData *pTd = sqlite3OsThreadSpecificData(0);
if( pTd ){
memset(pTd, 0, sizeof(*pTd));
sqlite3OsThreadSpecificData(-1);
}
}
/*
@ -1333,6 +1342,7 @@ int sqlite3_table_column_metadata(
if( sqlite3SafetyOn(db) ){
return SQLITE_MISUSE;
}
sqlite3_mutex_enter(db->mutex);
rc = sqlite3Init(db, &zErrMsg);
if( SQLITE_OK!=rc ){
goto error_out;
@ -1409,34 +1419,67 @@ error_out:
rc = SQLITE_ERROR;
}
sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg);
sqliteFree(zErrMsg);
return sqlite3ApiExit(db, rc);
}
#endif
/*
** Set all the parameters in the compiled SQL statement to NULL.
*/
int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
int i;
int rc = SQLITE_OK;
for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){
rc = sqlite3_bind_null(pStmt, i);
}
sqlite3_free(zErrMsg);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
#endif
/*
** Sleep for a little while. Return the amount of time slept.
*/
int sqlite3_sleep(int ms){
return sqlite3OsSleep(ms);
sqlite3_vfs *pVfs;
int rc;
pVfs = sqlite3_vfs_find(0);
/* This function works in milliseconds, but the underlying OsSleep()
** API uses microseconds. Hence the 1000's.
*/
rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000);
return rc;
}
/*
** Enable or disable the extended result codes.
*/
int sqlite3_extended_result_codes(sqlite3 *db, int onoff){
sqlite3_mutex_enter(db->mutex);
db->errMask = onoff ? 0xffffffff : 0xff;
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
/*
** Invoke the xFileControl method on a particular database.
*/
int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
int rc = SQLITE_ERROR;
int iDb;
sqlite3_mutex_enter(db->mutex);
if( zDbName==0 ){
iDb = 0;
}else{
for(iDb=0; iDb<db->nDb; iDb++){
if( strcmp(db->aDb[iDb].zName, zDbName)==0 ) break;
}
}
if( iDb<db->nDb ){
Btree *pBtree = db->aDb[iDb].pBt;
if( pBtree ){
Pager *pPager;
sqlite3BtreeEnter(pBtree);
pPager = sqlite3BtreePager(pBtree);
if( pPager ){
sqlite3_file *fd = sqlite3PagerFile(pPager);
if( fd ){
rc = sqlite3OsFileControl(fd, op, pArg);
}
}
sqlite3BtreeLeave(pBtree);
}
}
sqlite3_mutex_leave(db->mutex);
return rc;
}

View File

@ -15,705 +15,122 @@
** $Id$
*/
#include "sqliteInt.h"
#include "os.h"
#include <stdarg.h>
#include <ctype.h>
/*
** MALLOC WRAPPER ARCHITECTURE
**
** The sqlite code accesses dynamic memory allocation/deallocation by invoking
** the following six APIs (which may be implemented as macros).
**
** sqlite3Malloc()
** sqlite3MallocRaw()
** sqlite3Realloc()
** sqlite3ReallocOrFree()
** sqlite3Free()
** sqlite3AllocSize()
**
** The function sqlite3FreeX performs the same task as sqlite3Free and is
** guaranteed to be a real function. The same holds for sqlite3MallocX
**
** The above APIs are implemented in terms of the functions provided in the
** operating-system interface. The OS interface is never accessed directly
** by code outside of this file.
**
** sqlite3OsMalloc()
** sqlite3OsRealloc()
** sqlite3OsFree()
** sqlite3OsAllocationSize()
**
** Functions sqlite3MallocRaw() and sqlite3Realloc() may invoke
** sqlite3_release_memory() if a call to sqlite3OsMalloc() or
** sqlite3OsRealloc() fails (or if the soft-heap-limit for the thread is
** exceeded). Function sqlite3Malloc() usually invokes
** sqlite3MallocRaw().
**
** MALLOC TEST WRAPPER ARCHITECTURE
**
** The test wrapper provides extra test facilities to ensure the library
** does not leak memory and handles the failure of the underlying OS level
** allocation system correctly. It is only present if the library is
** compiled with the SQLITE_MEMDEBUG macro set.
**
** * Guardposts to detect overwrites.
** * Ability to cause a specific Malloc() or Realloc() to fail.
** * Audit outstanding memory allocations (i.e check for leaks).
** This routine runs when the memory allocator sees that the
** total memory allocation is about to exceed the soft heap
** limit.
*/
static void softHeapLimitEnforcer(
void *NotUsed,
sqlite3_int64 inUse,
int allocSize
){
sqlite3_release_memory(allocSize);
}
#define MAX(x,y) ((x)>(y)?(x):(y))
#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
/*
** Set the soft heap-size limit for the current thread. Passing a negative
** value indicates no limit.
** Set the soft heap-size limit for the current thread. Passing a
** zero or negative value indicates no limit.
*/
void sqlite3_soft_heap_limit(int n){
ThreadData *pTd = sqlite3ThreadData();
if( pTd ){
pTd->nSoftHeapLimit = n;
sqlite3_uint64 iLimit;
int overage;
if( n<0 ){
iLimit = 0;
}else{
iLimit = n;
}
if( iLimit>0 ){
sqlite3_memory_alarm(softHeapLimitEnforcer, 0, iLimit);
}else{
sqlite3_memory_alarm(0, 0, 0);
}
overage = sqlite3_memory_used() - n;
if( overage>0 ){
sqlite3_release_memory(overage);
}
sqlite3ReleaseThreadData();
}
/*
** Release memory held by SQLite instances created by the current thread.
*/
int sqlite3_release_memory(int n){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
return sqlite3PagerReleaseMemory(n);
#else
return SQLITE_OK;
#endif
}
#else
/* If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, then define a version
** of sqlite3_release_memory() to be used by other code in this file.
** This is done for no better reason than to reduce the number of
** pre-processor #ifndef statements.
*/
#define sqlite3_release_memory(x) 0 /* 0 == no memory freed */
#endif
#ifdef SQLITE_MEMDEBUG
/*--------------------------------------------------------------------------
** Begin code for memory allocation system test layer.
**
** Memory debugging is turned on by defining the SQLITE_MEMDEBUG macro.
**
** SQLITE_MEMDEBUG==1 -> Fence-posting only (thread safe)
** SQLITE_MEMDEBUG==2 -> Fence-posting + linked list of allocations (not ts)
** SQLITE_MEMDEBUG==3 -> Above + backtraces (not thread safe, req. glibc)
*/
/* Figure out whether or not to store backtrace() information for each malloc.
** The backtrace() function is only used if SQLITE_MEMDEBUG is set to 2 or
** greater and glibc is in use. If we don't want to use backtrace(), then just
** define it as an empty macro and set the amount of space reserved to 0.
*/
#if defined(__GLIBC__) && SQLITE_MEMDEBUG>2
extern int backtrace(void **, int);
#define TESTALLOC_STACKSIZE 128
#define TESTALLOC_STACKFRAMES ((TESTALLOC_STACKSIZE-8)/sizeof(void*))
#else
#define backtrace(x, y)
#define TESTALLOC_STACKSIZE 0
#define TESTALLOC_STACKFRAMES 0
#endif
/*
** Number of 32-bit guard words. This should probably be a multiple of
** 2 since on 64-bit machines we want the value returned by sqliteMalloc()
** to be 8-byte aligned.
*/
#ifndef TESTALLOC_NGUARD
# define TESTALLOC_NGUARD 2
#endif
/*
** Size reserved for storing file-name along with each malloc()ed blob.
*/
#define TESTALLOC_FILESIZE 64
/*
** Size reserved for storing the user string. Each time a Malloc() or Realloc()
** call succeeds, up to TESTALLOC_USERSIZE bytes of the string pointed to by
** sqlite3_malloc_id are stored along with the other test system metadata.
*/
#define TESTALLOC_USERSIZE 64
const char *sqlite3_malloc_id = 0;
/*
** Blocks used by the test layer have the following format:
**
** <sizeof(void *) pNext pointer>
** <sizeof(void *) pPrev pointer>
** <TESTALLOC_NGUARD 32-bit guard words>
** <The application level allocation>
** <TESTALLOC_NGUARD 32-bit guard words>
** <32-bit line number>
** <TESTALLOC_FILESIZE bytes containing null-terminated file name>
** <TESTALLOC_STACKSIZE bytes of backtrace() output>
** Allocate and zero memory.
*/
#define TESTALLOC_OFFSET_GUARD1(p) (sizeof(void *) * 2)
#define TESTALLOC_OFFSET_DATA(p) ( \
TESTALLOC_OFFSET_GUARD1(p) + sizeof(u32) * TESTALLOC_NGUARD \
)
#define TESTALLOC_OFFSET_GUARD2(p) ( \
TESTALLOC_OFFSET_DATA(p) + sqlite3OsAllocationSize(p) - TESTALLOC_OVERHEAD \
)
#define TESTALLOC_OFFSET_LINENUMBER(p) ( \
TESTALLOC_OFFSET_GUARD2(p) + sizeof(u32) * TESTALLOC_NGUARD \
)
#define TESTALLOC_OFFSET_FILENAME(p) ( \
TESTALLOC_OFFSET_LINENUMBER(p) + sizeof(u32) \
)
#define TESTALLOC_OFFSET_USER(p) ( \
TESTALLOC_OFFSET_FILENAME(p) + TESTALLOC_FILESIZE \
)
#define TESTALLOC_OFFSET_STACK(p) ( \
TESTALLOC_OFFSET_USER(p) + TESTALLOC_USERSIZE + 8 - \
(TESTALLOC_OFFSET_USER(p) % 8) \
)
#define TESTALLOC_OVERHEAD ( \
sizeof(void *)*2 + /* pPrev and pNext pointers */ \
TESTALLOC_NGUARD*sizeof(u32)*2 + /* Guard words */ \
sizeof(u32) + TESTALLOC_FILESIZE + /* File and line number */ \
TESTALLOC_USERSIZE + /* User string */ \
TESTALLOC_STACKSIZE /* backtrace() stack */ \
)
/*
** For keeping track of the number of mallocs and frees. This
** is used to check for memory leaks. The iMallocFail and iMallocReset
** values are used to simulate malloc() failures during testing in
** order to verify that the library correctly handles an out-of-memory
** condition.
*/
int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */
int sqlite3_nFree; /* Number of sqliteFree() calls */
int sqlite3_memUsed; /* TODO Total memory obtained from malloc */
int sqlite3_memMax; /* TODO Mem usage high-water mark */
int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */
int sqlite3_iMallocReset = -1; /* When iMallocFail reaches 0, set to this */
void *sqlite3_pFirst = 0; /* Pointer to linked list of allocations */
int sqlite3_nMaxAlloc = 0; /* High water mark of ThreadData.nAlloc */
int sqlite3_mallocDisallowed = 0; /* assert() in sqlite3Malloc() if set */
int sqlite3_isFail = 0; /* True if all malloc calls should fail */
const char *sqlite3_zFile = 0; /* Filename to associate debug info with */
int sqlite3_iLine = 0; /* Line number for debug info */
int sqlite3_mallocfail_trace = 0; /* Print a msg on malloc fail if true */
/*
** Check for a simulated memory allocation failure. Return true if
** the failure should be simulated. Return false to proceed as normal.
*/
int sqlite3TestMallocFail(){
if( sqlite3_isFail ){
return 1;
}
if( sqlite3_iMallocFail>=0 ){
sqlite3_iMallocFail--;
if( sqlite3_iMallocFail==0 ){
sqlite3_iMallocFail = sqlite3_iMallocReset;
sqlite3_isFail = 1;
if( sqlite3_mallocfail_trace ){
sqlite3DebugPrintf("###_malloc_fails_###\n");
}
return 1;
}
}
return 0;
}
/*
** The argument is a pointer returned by sqlite3OsMalloc() or xRealloc().
** assert() that the first and last (TESTALLOC_NGUARD*4) bytes are set to the
** values set by the applyGuards() function.
*/
static void checkGuards(u32 *p)
{
int i;
char *zAlloc = (char *)p;
char *z;
/* First set of guard words */
z = &zAlloc[TESTALLOC_OFFSET_GUARD1(p)];
for(i=0; i<TESTALLOC_NGUARD; i++){
assert(((u32 *)z)[i]==0xdead1122);
}
/* Second set of guard words */
z = &zAlloc[TESTALLOC_OFFSET_GUARD2(p)];
for(i=0; i<TESTALLOC_NGUARD; i++){
u32 guard = 0;
memcpy(&guard, &z[i*sizeof(u32)], sizeof(u32));
assert(guard==0xdead3344);
}
}
/*
** The argument is a pointer returned by sqlite3OsMalloc() or Realloc(). The
** first and last (TESTALLOC_NGUARD*4) bytes are set to known values for use as
** guard-posts.
*/
static void applyGuards(u32 *p)
{
int i;
char *z;
char *zAlloc = (char *)p;
/* First set of guard words */
z = &zAlloc[TESTALLOC_OFFSET_GUARD1(p)];
for(i=0; i<TESTALLOC_NGUARD; i++){
((u32 *)z)[i] = 0xdead1122;
}
/* Second set of guard words */
z = &zAlloc[TESTALLOC_OFFSET_GUARD2(p)];
for(i=0; i<TESTALLOC_NGUARD; i++){
static const int guard = 0xdead3344;
memcpy(&z[i*sizeof(u32)], &guard, sizeof(u32));
}
/* Line number */
z = &((char *)z)[TESTALLOC_NGUARD*sizeof(u32)]; /* Guard words */
z = &zAlloc[TESTALLOC_OFFSET_LINENUMBER(p)];
memcpy(z, &sqlite3_iLine, sizeof(u32));
/* File name */
z = &zAlloc[TESTALLOC_OFFSET_FILENAME(p)];
strncpy(z, sqlite3_zFile, TESTALLOC_FILESIZE);
z[TESTALLOC_FILESIZE - 1] = '\0';
/* User string */
z = &zAlloc[TESTALLOC_OFFSET_USER(p)];
z[0] = 0;
if( sqlite3_malloc_id ){
strncpy(z, sqlite3_malloc_id, TESTALLOC_USERSIZE);
z[TESTALLOC_USERSIZE-1] = 0;
}
/* backtrace() stack */
z = &zAlloc[TESTALLOC_OFFSET_STACK(p)];
backtrace((void **)z, TESTALLOC_STACKFRAMES);
/* Sanity check to make sure checkGuards() is working */
checkGuards(p);
}
/*
** The argument is a malloc()ed pointer as returned by the test-wrapper.
** Return a pointer to the Os level allocation.
*/
static void *getOsPointer(void *p)
{
char *z = (char *)p;
return (void *)(&z[-1 * TESTALLOC_OFFSET_DATA(p)]);
}
#if SQLITE_MEMDEBUG>1
/*
** The argument points to an Os level allocation. Link it into the threads list
** of allocations.
*/
static void linkAlloc(void *p){
void **pp = (void **)p;
pp[0] = 0;
pp[1] = sqlite3_pFirst;
if( sqlite3_pFirst ){
((void **)sqlite3_pFirst)[0] = p;
}
sqlite3_pFirst = p;
}
/*
** The argument points to an Os level allocation. Unlinke it from the threads
** list of allocations.
*/
static void unlinkAlloc(void *p)
{
void **pp = (void **)p;
if( p==sqlite3_pFirst ){
assert(!pp[0]);
assert(!pp[1] || ((void **)(pp[1]))[0]==p);
sqlite3_pFirst = pp[1];
if( sqlite3_pFirst ){
((void **)sqlite3_pFirst)[0] = 0;
}
}else{
void **pprev = pp[0];
void **pnext = pp[1];
assert(pprev);
assert(pprev[1]==p);
pprev[1] = (void *)pnext;
if( pnext ){
assert(pnext[0]==p);
pnext[0] = (void *)pprev;
}
}
}
/*
** Pointer p is a pointer to an OS level allocation that has just been
** realloc()ed. Set the list pointers that point to this entry to it's new
** location.
*/
static void relinkAlloc(void *p)
{
void **pp = (void **)p;
if( pp[0] ){
((void **)(pp[0]))[1] = p;
}else{
sqlite3_pFirst = p;
}
if( pp[1] ){
((void **)(pp[1]))[0] = p;
}
}
#else
#define linkAlloc(x)
#define relinkAlloc(x)
#define unlinkAlloc(x)
#endif
/*
** This function sets the result of the Tcl interpreter passed as an argument
** to a list containing an entry for each currently outstanding call made to
** sqliteMalloc and friends by the current thread. Each list entry is itself a
** list, consisting of the following (in order):
**
** * The number of bytes allocated
** * The __FILE__ macro at the time of the sqliteMalloc() call.
** * The __LINE__ macro ...
** * The value of the sqlite3_malloc_id variable ...
** * The output of backtrace() (if available) ...
**
** Todo: We could have a version of this function that outputs to stdout,
** to debug memory leaks when Tcl is not available.
*/
#if defined(TCLSH) && defined(SQLITE_DEBUG) && SQLITE_MEMDEBUG>1
#include <tcl.h>
int sqlite3OutstandingMallocs(Tcl_Interp *interp){
void *p;
Tcl_Obj *pRes = Tcl_NewObj();
Tcl_IncrRefCount(pRes);
for(p=sqlite3_pFirst; p; p=((void **)p)[1]){
Tcl_Obj *pEntry = Tcl_NewObj();
Tcl_Obj *pStack = Tcl_NewObj();
char *z;
u32 iLine;
int nBytes = sqlite3OsAllocationSize(p) - TESTALLOC_OVERHEAD;
char *zAlloc = (char *)p;
int i;
Tcl_ListObjAppendElement(0, pEntry, Tcl_NewIntObj(nBytes));
z = &zAlloc[TESTALLOC_OFFSET_FILENAME(p)];
Tcl_ListObjAppendElement(0, pEntry, Tcl_NewStringObj(z, -1));
z = &zAlloc[TESTALLOC_OFFSET_LINENUMBER(p)];
memcpy(&iLine, z, sizeof(u32));
Tcl_ListObjAppendElement(0, pEntry, Tcl_NewIntObj(iLine));
z = &zAlloc[TESTALLOC_OFFSET_USER(p)];
Tcl_ListObjAppendElement(0, pEntry, Tcl_NewStringObj(z, -1));
z = &zAlloc[TESTALLOC_OFFSET_STACK(p)];
for(i=0; i<TESTALLOC_STACKFRAMES; i++){
char zHex[128];
sqlite3_snprintf(sizeof(zHex), zHex, "%p", ((void **)z)[i]);
Tcl_ListObjAppendElement(0, pStack, Tcl_NewStringObj(zHex, -1));
}
Tcl_ListObjAppendElement(0, pEntry, pStack);
Tcl_ListObjAppendElement(0, pRes, pEntry);
}
Tcl_ResetResult(interp);
Tcl_SetObjResult(interp, pRes);
Tcl_DecrRefCount(pRes);
return TCL_OK;
}
#endif
/*
** This is the test layer's wrapper around sqlite3OsMalloc().
*/
static void * OSMALLOC(int n){
sqlite3OsEnterMutex();
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
sqlite3_nMaxAlloc =
MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc);
#endif
assert( !sqlite3_mallocDisallowed );
if( !sqlite3TestMallocFail() ){
u32 *p;
p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD);
assert(p);
sqlite3_nMalloc++;
applyGuards(p);
linkAlloc(p);
sqlite3OsLeaveMutex();
return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
}
sqlite3OsLeaveMutex();
return 0;
}
static int OSSIZEOF(void *p){
if( p ){
u32 *pOs = (u32 *)getOsPointer(p);
return sqlite3OsAllocationSize(pOs) - TESTALLOC_OVERHEAD;
}
return 0;
}
/*
** This is the test layer's wrapper around sqlite3OsFree(). The argument is a
** pointer to the space allocated for the application to use.
*/
static void OSFREE(void *pFree){
u32 *p; /* Pointer to the OS-layer allocation */
sqlite3OsEnterMutex();
p = (u32 *)getOsPointer(pFree);
checkGuards(p);
unlinkAlloc(p);
memset(pFree, 0x55, OSSIZEOF(pFree));
sqlite3OsFree(p);
sqlite3_nFree++;
sqlite3OsLeaveMutex();
}
/*
** This is the test layer's wrapper around sqlite3OsRealloc().
*/
static void * OSREALLOC(void *pRealloc, int n){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
sqlite3_nMaxAlloc =
MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc);
#endif
assert( !sqlite3_mallocDisallowed );
if( !sqlite3TestMallocFail() ){
u32 *p = (u32 *)getOsPointer(pRealloc);
checkGuards(p);
p = sqlite3OsRealloc(p, n + TESTALLOC_OVERHEAD);
applyGuards(p);
relinkAlloc(p);
return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
}
return 0;
}
static void OSMALLOC_FAILED(){
sqlite3_isFail = 0;
}
#else
/* Define macros to call the sqlite3OsXXX interface directly if
** the SQLITE_MEMDEBUG macro is not defined.
*/
#define OSMALLOC(x) sqlite3OsMalloc(x)
#define OSREALLOC(x,y) sqlite3OsRealloc(x,y)
#define OSFREE(x) sqlite3OsFree(x)
#define OSSIZEOF(x) sqlite3OsAllocationSize(x)
#define OSMALLOC_FAILED()
#endif /* SQLITE_MEMDEBUG */
/*
** End code for memory allocation system test layer.
**--------------------------------------------------------------------------*/
/*
** This routine is called when we are about to allocate n additional bytes
** of memory. If the new allocation will put is over the soft allocation
** limit, then invoke sqlite3_release_memory() to try to release some
** memory before continuing with the allocation.
**
** This routine also makes sure that the thread-specific-data (TSD) has
** be allocated. If it has not and can not be allocated, then return
** false. The updateMemoryUsedCount() routine below will deallocate
** the TSD if it ought to be.
**
** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is
** a no-op
*/
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
static int enforceSoftLimit(int n){
ThreadData *pTsd = sqlite3ThreadData();
if( pTsd==0 ){
return 0;
}
assert( pTsd->nAlloc>=0 );
if( n>0 && pTsd->nSoftHeapLimit>0 ){
while( pTsd->nAlloc+n>pTsd->nSoftHeapLimit && sqlite3_release_memory(n) ){}
}
return 1;
}
#else
# define enforceSoftLimit(X) 1
#endif
/*
** Update the count of total outstanding memory that is held in
** thread-specific-data (TSD). If after this update the TSD is
** no longer being used, then deallocate it.
**
** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is
** a no-op
*/
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
static void updateMemoryUsedCount(int n){
ThreadData *pTsd = sqlite3ThreadData();
if( pTsd ){
pTsd->nAlloc += n;
assert( pTsd->nAlloc>=0 );
if( pTsd->nAlloc==0 && pTsd->nSoftHeapLimit==0 ){
sqlite3ReleaseThreadData();
}
}
}
#else
#define updateMemoryUsedCount(x) /* no-op */
#endif
/*
** Allocate and return N bytes of uninitialised memory by calling
** sqlite3OsMalloc(). If the Malloc() call fails, attempt to free memory
** by calling sqlite3_release_memory().
*/
void *sqlite3MallocRaw(int n, int doMemManage){
void *p = 0;
if( n>0 && !sqlite3MallocFailed() && (!doMemManage || enforceSoftLimit(n)) ){
while( (p = OSMALLOC(n))==0 && sqlite3_release_memory(n) ){}
if( !p ){
sqlite3FailedMalloc();
OSMALLOC_FAILED();
}else if( doMemManage ){
updateMemoryUsedCount(OSSIZEOF(p));
}
}
return p;
}
/*
** Resize the allocation at p to n bytes by calling sqlite3OsRealloc(). The
** pointer to the new allocation is returned. If the Realloc() call fails,
** attempt to free memory by calling sqlite3_release_memory().
*/
void *sqlite3Realloc(void *p, int n){
if( sqlite3MallocFailed() ){
return 0;
}
if( !p ){
return sqlite3Malloc(n, 1);
}else{
void *np = 0;
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
int origSize = OSSIZEOF(p);
#endif
if( enforceSoftLimit(n - origSize) ){
while( (np = OSREALLOC(p, n))==0 && sqlite3_release_memory(n) ){}
if( !np ){
sqlite3FailedMalloc();
OSMALLOC_FAILED();
}else{
updateMemoryUsedCount(OSSIZEOF(np) - origSize);
}
}
return np;
}
}
/*
** Free the memory pointed to by p. p must be either a NULL pointer or a
** value returned by a previous call to sqlite3Malloc() or sqlite3Realloc().
*/
void sqlite3FreeX(void *p){
if( p ){
updateMemoryUsedCount(0 - OSSIZEOF(p));
OSFREE(p);
}
}
/*
** A version of sqliteMalloc() that is always a function, not a macro.
** Currently, this is used only to alloc to allocate the parser engine.
*/
void *sqlite3MallocX(int n){
return sqliteMalloc(n);
}
/*
** sqlite3Malloc
** sqlite3ReallocOrFree
**
** These two are implemented as wrappers around sqlite3MallocRaw(),
** sqlite3Realloc() and sqlite3Free().
*/
void *sqlite3Malloc(int n, int doMemManage){
void *p = sqlite3MallocRaw(n, doMemManage);
void *sqlite3MallocZero(unsigned n){
void *p = sqlite3_malloc(n);
if( p ){
memset(p, 0, n);
}
return p;
}
void *sqlite3ReallocOrFree(void *p, int n){
void *pNew;
pNew = sqlite3Realloc(p, n);
if( !pNew ){
sqlite3FreeX(p);
/*
** Allocate and zero memory. If the allocation fails, make
** the mallocFailed flag in the connection pointer.
*/
void *sqlite3DbMallocZero(sqlite3 *db, unsigned n){
void *p = sqlite3DbMallocRaw(db, n);
if( p ){
memset(p, 0, n);
}
return p;
}
/*
** Allocate and zero memory. If the allocation fails, make
** the mallocFailed flag in the connection pointer.
*/
void *sqlite3DbMallocRaw(sqlite3 *db, unsigned n){
void *p = 0;
if( !db || db->mallocFailed==0 ){
p = sqlite3_malloc(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.
*/
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;
}
}
return pNew;
}
/*
** sqlite3ThreadSafeMalloc() and sqlite3ThreadSafeFree() are used in those
** rare scenarios where sqlite may allocate memory in one thread and free
** it in another. They are exactly the same as sqlite3Malloc() and
** sqlite3Free() except that:
**
** * The allocated memory is not included in any calculations with
** respect to the soft-heap-limit, and
**
** * sqlite3ThreadSafeMalloc() must be matched with ThreadSafeFree(),
** not sqlite3Free(). Calling sqlite3Free() on memory obtained from
** ThreadSafeMalloc() will cause an error somewhere down the line.
** Attempt to reallocate p. If the reallocation fails, then free p
** and set the mallocFailed flag in the database connection.
*/
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
void *sqlite3ThreadSafeMalloc(int n){
(void)ENTER_MALLOC;
return sqlite3Malloc(n, 0);
}
void sqlite3ThreadSafeFree(void *p){
(void)ENTER_MALLOC;
if( p ){
OSFREE(p);
void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){
void *pNew;
pNew = sqlite3DbRealloc(db, p, n);
if( !pNew ){
sqlite3_free(p);
}
return pNew;
}
#endif
/*
** Return the number of bytes allocated at location p. p must be either
** a NULL pointer (in which case 0 is returned) or a pointer returned by
** sqlite3Malloc(), sqlite3Realloc() or sqlite3ReallocOrFree().
**
** The number of bytes allocated does not include any overhead inserted by
** any malloc() wrapper functions that may be called. So the value returned
** is the number of bytes that were available to SQLite using pointer p,
** regardless of how much memory was actually allocated.
*/
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
int sqlite3AllocSize(void *p){
return OSSIZEOF(p);
}
#endif
/*
** Make a copy of a string in memory obtained from sqliteMalloc(). These
@ -727,14 +144,14 @@ char *sqlite3StrDup(const char *z){
int n;
if( z==0 ) return 0;
n = strlen(z)+1;
zNew = sqlite3MallocRaw(n, 1);
zNew = sqlite3_malloc(n);
if( zNew ) memcpy(zNew, z, n);
return zNew;
}
char *sqlite3StrNDup(const char *z, int n){
char *zNew;
if( z==0 ) return 0;
zNew = sqlite3MallocRaw(n+1, 1);
zNew = sqlite3_malloc(n+1);
if( zNew ){
memcpy(zNew, z, n);
zNew[n] = 0;
@ -742,6 +159,21 @@ char *sqlite3StrNDup(const char *z, int n){
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;
}
return zNew;
}
/*
** Create a string from the 2nd and subsequent arguments (up to the
** first NULL argument), store the string in memory obtained from
@ -762,8 +194,8 @@ void sqlite3SetString(char **pz, ...){
nByte += strlen(z);
}
va_end(ap);
sqliteFree(*pz);
*pz = zResult = sqliteMallocRaw( nByte );
sqlite3_free(*pz);
*pz = zResult = sqlite3_malloc(nByte);
if( zResult==0 ){
return;
}
@ -781,8 +213,8 @@ void sqlite3SetString(char **pz, ...){
/*
** This function must be called before exiting any API function (i.e.
** returning control to the user) that has called sqlite3Malloc or
** sqlite3Realloc.
** returning control to the user) that has called sqlite3_malloc or
** sqlite3_realloc.
**
** The returned value is normally a copy of the second argument to this
** function. However, if a malloc() failure has occured since the previous
@ -792,44 +224,17 @@ void sqlite3SetString(char **pz, ...){
** then the connection error-code (the value returned by sqlite3_errcode())
** is set to SQLITE_NOMEM.
*/
int sqlite3_mallocHasFailed = 0;
int sqlite3ApiExit(sqlite3* db, int rc){
if( sqlite3MallocFailed() ){
sqlite3_mallocHasFailed = 0;
sqlite3OsLeaveMutex();
/* If the db handle is not NULL, then we must hold the connection handle
** mutex here. Otherwise the read (and possible write) of db->mallocFailed
** is unsafe, as is the call to sqlite3Error().
*/
assert( !db || sqlite3_mutex_held(db->mutex) );
if( db && db->mallocFailed ){
sqlite3Error(db, SQLITE_NOMEM, 0);
db->mallocFailed = 0;
rc = SQLITE_NOMEM;
}
return rc & (db ? db->errMask : 0xff);
}
/*
** Set the "malloc has failed" condition to true for this thread.
*/
void sqlite3FailedMalloc(){
if( !sqlite3MallocFailed() ){
sqlite3OsEnterMutex();
assert( sqlite3_mallocHasFailed==0 );
sqlite3_mallocHasFailed = 1;
}
}
#ifdef SQLITE_MEMDEBUG
/*
** This function sets a flag in the thread-specific-data structure that will
** cause an assert to fail if sqliteMalloc() or sqliteRealloc() is called.
*/
void sqlite3MallocDisallow(){
assert( sqlite3_mallocDisallowed>=0 );
sqlite3_mallocDisallowed++;
}
/*
** This function clears the flag set in the thread-specific-data structure set
** by sqlite3MallocDisallow().
*/
void sqlite3MallocAllow(){
assert( sqlite3_mallocDisallowed>0 );
sqlite3_mallocDisallowed--;
}
#endif

View File

@ -0,0 +1,229 @@
/*
** 2007 August 14
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite.
**
** $Id$
*/
/*
** This version of the memory allocator is the default. It is
** used when no other memory allocator is specified using compile-time
** macros.
*/
#if !defined(SQLITE_MEMDEBUG) && !defined(SQLITE_OMIT_MEMORY_ALLOCATION)
/*
** We will eventually construct multiple memory allocation subsystems
** suitable for use in various contexts:
**
** * Normal multi-threaded builds
** * Normal single-threaded builds
** * Debugging builds
**
** This initial version is suitable for use in normal multi-threaded
** builds. We envision that alternative versions will be stored in
** separate source files. #ifdefs will be used to select the code from
** one of the various memN.c source files for use in any given build.
*/
#include "sqliteInt.h"
/*
** All of the static variables used by this module are collected
** into a single structure named "mem". This is to keep the
** static variables organized and to reduce namespace pollution
** when this module is combined with other in the amalgamation.
*/
static struct {
/*
** The alarm callback and its arguments. The mem.mutex lock will
** be held while the callback is running. Recursive calls into
** the memory subsystem are allowed, but no new callbacks will be
** issued. The alarmBusy variable is set to prevent recursive
** callbacks.
*/
sqlite3_int64 alarmThreshold;
void (*alarmCallback)(void*, sqlite3_int64,int);
void *alarmArg;
int alarmBusy;
/*
** Mutex to control access to the memory allocation subsystem.
*/
sqlite3_mutex *mutex;
/*
** Current allocation and high-water mark.
*/
sqlite3_int64 nowUsed;
sqlite3_int64 mxUsed;
} mem;
/*
** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
*/
static void enterMem(void){
if( mem.mutex==0 ){
mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
}
sqlite3_mutex_enter(mem.mutex);
}
/*
** Return the amount of memory currently checked out.
*/
sqlite3_int64 sqlite3_memory_used(void){
sqlite3_int64 n;
enterMem();
n = mem.nowUsed;
sqlite3_mutex_leave(mem.mutex);
return n;
}
/*
** Return the maximum amount of memory that has ever been
** checked out since either the beginning of this process
** or since the most recent reset.
*/
sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
sqlite3_int64 n;
enterMem();
n = mem.mxUsed;
if( resetFlag ){
mem.mxUsed = mem.nowUsed;
}
sqlite3_mutex_leave(mem.mutex);
return n;
}
/*
** Change the alarm callback
*/
int sqlite3_memory_alarm(
void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
void *pArg,
sqlite3_int64 iThreshold
){
enterMem();
mem.alarmCallback = xCallback;
mem.alarmArg = pArg;
mem.alarmThreshold = iThreshold;
sqlite3_mutex_leave(mem.mutex);
return SQLITE_OK;
}
/*
** Trigger the alarm
*/
static void sqlite3MemsysAlarm(int nByte){
void (*xCallback)(void*,sqlite3_int64,int);
sqlite3_int64 nowUsed;
void *pArg;
if( mem.alarmCallback==0 || mem.alarmBusy ) return;
mem.alarmBusy = 1;
xCallback = mem.alarmCallback;
nowUsed = mem.nowUsed;
pArg = mem.alarmArg;
sqlite3_mutex_leave(mem.mutex);
xCallback(pArg, nowUsed, nByte);
sqlite3_mutex_enter(mem.mutex);
mem.alarmBusy = 0;
}
/*
** Allocate nBytes of memory
*/
void *sqlite3_malloc(int nBytes){
sqlite3_int64 *p = 0;
if( nBytes>0 ){
enterMem();
if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){
sqlite3MemsysAlarm(nBytes);
}
p = malloc(nBytes+8);
if( p==0 ){
sqlite3MemsysAlarm(nBytes);
p = malloc(nBytes+8);
}
if( p ){
p[0] = nBytes;
p++;
mem.nowUsed += nBytes;
if( mem.nowUsed>mem.mxUsed ){
mem.mxUsed = mem.nowUsed;
}
}
sqlite3_mutex_leave(mem.mutex);
}
return (void*)p;
}
/*
** Free memory.
*/
void sqlite3_free(void *pPrior){
sqlite3_int64 *p;
int nByte;
if( pPrior==0 ){
return;
}
assert( mem.mutex!=0 );
p = pPrior;
p--;
nByte = (int)*p;
sqlite3_mutex_enter(mem.mutex);
mem.nowUsed -= nByte;
free(p);
sqlite3_mutex_leave(mem.mutex);
}
/*
** Change the size of an existing memory allocation
*/
void *sqlite3_realloc(void *pPrior, int nBytes){
int nOld;
sqlite3_int64 *p;
if( pPrior==0 ){
return sqlite3_malloc(nBytes);
}
if( nBytes<=0 ){
sqlite3_free(pPrior);
return 0;
}
p = pPrior;
p--;
nOld = (int)p[0];
assert( mem.mutex!=0 );
sqlite3_mutex_enter(mem.mutex);
if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){
sqlite3MemsysAlarm(nBytes-nOld);
}
p = realloc(p, nBytes+8);
if( p==0 ){
sqlite3MemsysAlarm(nBytes);
p = realloc(p, nBytes+8);
}
if( p ){
p[0] = nBytes;
p++;
mem.nowUsed += nBytes-nOld;
if( mem.nowUsed>mem.mxUsed ){
mem.mxUsed = mem.nowUsed;
}
}
sqlite3_mutex_leave(mem.mutex);
return (void*)p;
}
#endif /* !SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */

View File

@ -0,0 +1,546 @@
/*
** 2007 August 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite.
**
** $Id$
*/
/*
** This version of the memory allocator is used only if the
** SQLITE_MEMDEBUG macro is defined and SQLITE_OMIT_MEMORY_ALLOCATION
** is not defined.
*/
#if defined(SQLITE_MEMDEBUG) && !defined(SQLITE_OMIT_MEMORY_ALLOCATION)
/*
** We will eventually construct multiple memory allocation subsystems
** suitable for use in various contexts:
**
** * Normal multi-threaded builds
** * Normal single-threaded builds
** * Debugging builds
**
** This version is suitable for use in debugging builds.
**
** Features:
**
** * Every allocate has guards at both ends.
** * New allocations are initialized with randomness
** * Allocations are overwritten with randomness when freed
** * Optional logs of malloc activity generated
** * Summary of outstanding allocations with backtraces to the
** point of allocation.
** * The ability to simulate memory allocation failure
*/
#include "sqliteInt.h"
#include <stdio.h>
/*
** The backtrace functionality is only available with GLIBC
*/
#ifdef __GLIBC__
extern int backtrace(void**,int);
extern void backtrace_symbols_fd(void*const*,int,int);
#else
# define backtrace(A,B) 0
# define backtrace_symbols_fd(A,B,C)
#endif
/*
** Each memory allocation looks like this:
**
** ------------------------------------------------------------------------
** | Title | backtrace pointers | MemBlockHdr | allocation | EndGuard |
** ------------------------------------------------------------------------
**
** The application code sees only a pointer to the allocation. We have
** to back up from the allocation pointer to find the MemBlockHdr. The
** MemBlockHdr tells us the size of the allocation and the number of
** backtrace pointers. There is also a guard word at the end of the
** MemBlockHdr.
*/
struct MemBlockHdr {
struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */
int iSize; /* Size of this allocation */
char nBacktrace; /* Number of backtraces on this alloc */
char nBacktraceSlots; /* Available backtrace slots */
short nTitle; /* Bytes of title; includes '\0' */
int iForeGuard; /* Guard word for sanity */
};
/*
** Guard words
*/
#define FOREGUARD 0x80F5E153
#define REARGUARD 0xE4676B53
/*
** All of the static variables used by this module are collected
** into a single structure named "mem". This is to keep the
** static variables organized and to reduce namespace pollution
** when this module is combined with other in the amalgamation.
*/
static struct {
/*
** The alarm callback and its arguments. The mem.mutex lock will
** be held while the callback is running. Recursive calls into
** the memory subsystem are allowed, but no new callbacks will be
** issued. The alarmBusy variable is set to prevent recursive
** callbacks.
*/
sqlite3_int64 alarmThreshold;
void (*alarmCallback)(void*, sqlite3_int64, int);
void *alarmArg;
int alarmBusy;
/*
** Mutex to control access to the memory allocation subsystem.
*/
sqlite3_mutex *mutex;
/*
** Current allocation and high-water mark.
*/
sqlite3_int64 nowUsed;
sqlite3_int64 mxUsed;
/*
** Head and tail of a linked list of all outstanding allocations
*/
struct MemBlockHdr *pFirst;
struct MemBlockHdr *pLast;
/*
** The number of levels of backtrace to save in new allocations.
*/
int nBacktrace;
/*
** Title text to insert in front of each block
*/
int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */
char zTitle[100]; /* The title text */
/*
** These values are used to simulate malloc failures. When
** iFail is 1, simulate a malloc failures and reset the value
** to iReset.
*/
int iFail; /* Decrement and fail malloc when this is 1 */
int iReset; /* When malloc fails set iiFail to this value */
int iFailCnt; /* Number of failures */
int iBenignFailCnt; /* Number of benign failures */
int iNextIsBenign; /* True if the next call to malloc may fail benignly */
int iIsBenign; /* All malloc calls may fail benignly */
/*
** sqlite3MallocDisallow() increments the following counter.
** sqlite3MallocAllow() decrements it.
*/
int disallow; /* Do not allow memory allocation */
} mem;
/*
** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
*/
static void enterMem(void){
if( mem.mutex==0 ){
mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
}
sqlite3_mutex_enter(mem.mutex);
}
/*
** Return the amount of memory currently checked out.
*/
sqlite3_int64 sqlite3_memory_used(void){
sqlite3_int64 n;
enterMem();
n = mem.nowUsed;
sqlite3_mutex_leave(mem.mutex);
return n;
}
/*
** Return the maximum amount of memory that has ever been
** checked out since either the beginning of this process
** or since the most recent reset.
*/
sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
sqlite3_int64 n;
enterMem();
n = mem.mxUsed;
if( resetFlag ){
mem.mxUsed = mem.nowUsed;
}
sqlite3_mutex_leave(mem.mutex);
return n;
}
/*
** Change the alarm callback
*/
int sqlite3_memory_alarm(
void(*xCallback)(void *pArg, sqlite3_int64 used, int N),
void *pArg,
sqlite3_int64 iThreshold
){
enterMem();
mem.alarmCallback = xCallback;
mem.alarmArg = pArg;
mem.alarmThreshold = iThreshold;
sqlite3_mutex_leave(mem.mutex);
return SQLITE_OK;
}
/*
** Trigger the alarm
*/
static void sqlite3MemsysAlarm(int nByte){
void (*xCallback)(void*,sqlite3_int64,int);
sqlite3_int64 nowUsed;
void *pArg;
if( mem.alarmCallback==0 || mem.alarmBusy ) return;
mem.alarmBusy = 1;
xCallback = mem.alarmCallback;
nowUsed = mem.nowUsed;
pArg = mem.alarmArg;
sqlite3_mutex_leave(mem.mutex);
xCallback(pArg, nowUsed, nByte);
sqlite3_mutex_enter(mem.mutex);
mem.alarmBusy = 0;
}
/*
** Given an allocation, find the MemBlockHdr for that allocation.
**
** This routine checks the guards at either end of the allocation and
** if they are incorrect it asserts.
*/
static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
struct MemBlockHdr *p;
int *pInt;
p = (struct MemBlockHdr*)pAllocation;
p--;
assert( p->iForeGuard==FOREGUARD );
assert( (p->iSize & 3)==0 );
pInt = (int*)pAllocation;
assert( pInt[p->iSize/sizeof(int)]==REARGUARD );
return p;
}
/*
** This routine is called once the first time a simulated memory
** failure occurs. The sole purpose of this routine is to provide
** a convenient place to set a debugger breakpoint when debugging
** errors related to malloc() failures.
*/
static void sqlite3MemsysFailed(void){
mem.iFailCnt = 0;
mem.iBenignFailCnt = 0;
}
/*
** Allocate nByte bytes of memory.
*/
void *sqlite3_malloc(int nByte){
struct MemBlockHdr *pHdr;
void **pBt;
char *z;
int *pInt;
void *p = 0;
int totalSize;
if( nByte>0 ){
enterMem();
assert( mem.disallow==0 );
if( mem.alarmCallback!=0 && mem.nowUsed+nByte>=mem.alarmThreshold ){
sqlite3MemsysAlarm(nByte);
}
nByte = (nByte+3)&~3;
totalSize = nByte + sizeof(*pHdr) + sizeof(int) +
mem.nBacktrace*sizeof(void*) + mem.nTitle;
if( mem.iFail>0 ){
if( mem.iFail==1 ){
p = 0;
mem.iFail = mem.iReset;
if( mem.iFailCnt==0 ){
sqlite3MemsysFailed(); /* A place to set a breakpoint */
}
mem.iFailCnt++;
if( mem.iNextIsBenign || mem.iIsBenign ){
mem.iBenignFailCnt++;
}
}else{
p = malloc(totalSize);
mem.iFail--;
}
}else{
p = malloc(totalSize);
if( p==0 ){
sqlite3MemsysAlarm(nByte);
p = malloc(totalSize);
}
}
if( p ){
z = p;
pBt = (void**)&z[mem.nTitle];
pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace];
pHdr->pNext = 0;
pHdr->pPrev = mem.pLast;
if( mem.pLast ){
mem.pLast->pNext = pHdr;
}else{
mem.pFirst = pHdr;
}
mem.pLast = pHdr;
pHdr->iForeGuard = FOREGUARD;
pHdr->nBacktraceSlots = mem.nBacktrace;
pHdr->nTitle = mem.nTitle;
if( mem.nBacktrace ){
void *aAddr[40];
pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
}else{
pHdr->nBacktrace = 0;
}
if( mem.nTitle ){
memcpy(z, mem.zTitle, mem.nTitle);
}
pHdr->iSize = nByte;
pInt = (int*)&pHdr[1];
pInt[nByte/sizeof(int)] = REARGUARD;
memset(pInt, 0x65, nByte);
mem.nowUsed += nByte;
if( mem.nowUsed>mem.mxUsed ){
mem.mxUsed = mem.nowUsed;
}
p = (void*)pInt;
}
sqlite3_mutex_leave(mem.mutex);
}
mem.iNextIsBenign = 0;
return p;
}
/*
** Free memory.
*/
void sqlite3_free(void *pPrior){
struct MemBlockHdr *pHdr;
void **pBt;
char *z;
if( pPrior==0 ){
return;
}
assert( mem.mutex!=0 );
pHdr = sqlite3MemsysGetHeader(pPrior);
pBt = (void**)pHdr;
pBt -= pHdr->nBacktraceSlots;
sqlite3_mutex_enter(mem.mutex);
mem.nowUsed -= pHdr->iSize;
if( pHdr->pPrev ){
assert( pHdr->pPrev->pNext==pHdr );
pHdr->pPrev->pNext = pHdr->pNext;
}else{
assert( mem.pFirst==pHdr );
mem.pFirst = pHdr->pNext;
}
if( pHdr->pNext ){
assert( pHdr->pNext->pPrev==pHdr );
pHdr->pNext->pPrev = pHdr->pPrev;
}else{
assert( mem.pLast==pHdr );
mem.pLast = pHdr->pPrev;
}
z = (char*)pBt;
z -= pHdr->nTitle;
memset(z, 0x2b, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
pHdr->iSize + sizeof(int) + pHdr->nTitle);
free(z);
sqlite3_mutex_leave(mem.mutex);
}
/*
** Change the size of an existing memory allocation.
**
** For this debugging implementation, we *always* make a copy of the
** allocation into a new place in memory. In this way, if the
** higher level code is using pointer to the old allocation, it is
** much more likely to break and we are much more liking to find
** the error.
*/
void *sqlite3_realloc(void *pPrior, int nByte){
struct MemBlockHdr *pOldHdr;
void *pNew;
if( pPrior==0 ){
return sqlite3_malloc(nByte);
}
if( nByte<=0 ){
sqlite3_free(pPrior);
return 0;
}
assert( mem.disallow==0 );
pOldHdr = sqlite3MemsysGetHeader(pPrior);
pNew = sqlite3_malloc(nByte);
if( pNew ){
memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
if( nByte>pOldHdr->iSize ){
memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize);
}
sqlite3_free(pPrior);
}
return pNew;
}
/*
** Set the number of backtrace levels kept for each allocation.
** A value of zero turns of backtracing. The number is always rounded
** up to a multiple of 2.
*/
void sqlite3_memdebug_backtrace(int depth){
if( depth<0 ){ depth = 0; }
if( depth>20 ){ depth = 20; }
depth = (depth+1)&0xfe;
mem.nBacktrace = depth;
}
/*
** Set the title string for subsequent allocations.
*/
void sqlite3_memdebug_settitle(const char *zTitle){
int n = strlen(zTitle) + 1;
enterMem();
if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1;
memcpy(mem.zTitle, zTitle, n);
mem.zTitle[n] = 0;
mem.nTitle = (n+3)&~3;
sqlite3_mutex_leave(mem.mutex);
}
/*
** Open the file indicated and write a log of all unfreed memory
** allocations into that log.
*/
void sqlite3_memdebug_dump(const char *zFilename){
FILE *out;
struct MemBlockHdr *pHdr;
void **pBt;
out = fopen(zFilename, "w");
if( out==0 ){
fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
zFilename);
return;
}
for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
char *z = (char*)pHdr;
z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle;
fprintf(out, "**** %d bytes at %p from %s ****\n",
pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???");
if( pHdr->nBacktrace ){
fflush(out);
pBt = (void**)pHdr;
pBt -= pHdr->nBacktraceSlots;
backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out));
fprintf(out, "\n");
}
}
fclose(out);
}
/*
** This routine is used to simulate malloc failures.
**
** After calling this routine, there will be iFail successful
** memory allocations and then a failure. If iRepeat is 1
** all subsequent memory allocations will fail. If iRepeat is
** 0, only a single allocation will fail. If iRepeat is negative
** then the previous setting for iRepeat is unchanged.
**
** Each call to this routine overrides the previous. To disable
** the simulated allocation failure mechanism, set iFail to -1.
**
** This routine returns the number of simulated failures that have
** occurred since the previous call.
*/
int sqlite3_memdebug_fail(int iFail, int iRepeat, int *piBenign){
int n = mem.iFailCnt;
if( piBenign ){
*piBenign = mem.iBenignFailCnt;
}
mem.iFail = iFail+1;
if( iRepeat>=0 ){
mem.iReset = iRepeat;
}
mem.iFailCnt = 0;
mem.iBenignFailCnt = 0;
return n;
}
int sqlite3_memdebug_pending(){
return (mem.iFail-1);
}
/*
** The following three functions are used to indicate to the test
** infrastructure which malloc() calls may fail benignly without
** affecting functionality. This can happen when resizing hash tables
** (failing to resize a hash-table is a performance hit, but not an
** error) or sometimes during a rollback operation.
**
** If the argument is true, sqlite3MallocBenignFailure() indicates that the
** next call to allocate memory may fail benignly.
**
** If sqlite3MallocEnterBenignBlock() is called with a non-zero argument,
** then all memory allocations requested before the next call to
** sqlite3MallocLeaveBenignBlock() may fail benignly.
*/
void sqlite3MallocBenignFailure(int isBenign){
if( isBenign ){
mem.iNextIsBenign = 1;
}
}
void sqlite3MallocEnterBenignBlock(int isBenign){
if( isBenign ){
mem.iIsBenign = 1;
}
}
void sqlite3MallocLeaveBenignBlock(){
mem.iIsBenign = 0;
}
/*
** The following two routines are used to assert that no memory
** allocations occur between one call and the next. The use of
** these routines does not change the computed results in any way.
** These routines are like asserts.
*/
void sqlite3MallocDisallow(void){
assert( mem.mutex!=0 );
sqlite3_mutex_enter(mem.mutex);
mem.disallow++;
sqlite3_mutex_leave(mem.mutex);
}
void sqlite3MallocAllow(void){
assert( mem.mutex );
sqlite3_mutex_enter(mem.mutex);
assert( mem.disallow>0 );
mem.disallow--;
sqlite3_mutex_leave(mem.mutex);
}
#endif /* SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */

View File

@ -0,0 +1,126 @@
/*
** 2007 August 14
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement mutexes.
**
** The implementation in this file does not provide any mutual
** exclusion and is thus suitable for use only in applications
** that use SQLite in a single thread. But this implementation
** does do a lot of error checking on mutexes to make sure they
** are called correctly and at appropriate times. Hence, this
** implementation is suitable for testing.
** debugging purposes
**
** $Id$
*/
#include "sqliteInt.h"
#ifdef SQLITE_MUTEX_NOOP_DEBUG
/*
** In this implementation, mutexes do not provide any mutual exclusion.
** But the error checking is provided. This implementation is useful
** for test purposes.
*/
/*
** The mutex object
*/
struct sqlite3_mutex {
int id; /* The mutex type */
int cnt; /* Number of entries without a matching leave */
};
/*
** The sqlite3_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it. If it returns NULL
** that means that a mutex could not be allocated.
*/
sqlite3_mutex *sqlite3_mutex_alloc(int id){
static sqlite3_mutex aStatic[5];
sqlite3_mutex *pNew = 0;
switch( id ){
case SQLITE_MUTEX_FAST:
case SQLITE_MUTEX_RECURSIVE: {
pNew = sqlite3_malloc(sizeof(*pNew));
if( pNew ){
pNew->id = id;
pNew->cnt = 0;
}
break;
}
default: {
assert( id-2 >= 0 );
assert( id-2 < sizeof(aStatic)/sizeof(aStatic[0]) );
pNew = &aStatic[id-2];
pNew->id = id;
break;
}
}
return pNew;
}
/*
** This routine deallocates a previously allocated mutex.
*/
void sqlite3_mutex_free(sqlite3_mutex *p){
assert( p );
assert( p->cnt==0 );
assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
sqlite3_free(p);
}
/*
** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
** to enter a mutex. If another thread is already within the mutex,
** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
** be entered multiple times by the same thread. In such cases the,
** mutex must be exited an equal number of times before another thread
** can enter. If the same thread tries to enter any other kind of mutex
** more than once, the behavior is undefined.
*/
void sqlite3_mutex_enter(sqlite3_mutex *p){
assert( p );
assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
p->cnt++;
}
int sqlite3_mutex_try(sqlite3_mutex *p){
assert( p );
assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
p->cnt++;
return SQLITE_OK;
}
/*
** The sqlite3_mutex_leave() routine exits a mutex that was
** previously entered by the same thread. The behavior
** is undefined if the mutex is not currently entered or
** is not currently allocated. SQLite will never do either.
*/
void sqlite3_mutex_leave(sqlite3_mutex *p){
assert( p );
assert( sqlite3_mutex_held(p) );
p->cnt--;
assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
}
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use inside assert() statements.
*/
int sqlite3_mutex_held(sqlite3_mutex *p){
return p==0 || p->cnt>0;
}
int sqlite3_mutex_notheld(sqlite3_mutex *p){
return p==0 || p->cnt==0;
}
#endif /* SQLITE_MUTEX_NOOP_DEBUG */

View File

@ -0,0 +1,82 @@
/*
** 2007 August 28
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains the common header for all mutex implementations.
** The sqliteInt.h header #includes this file so that it is available
** to all source files. We break it out in an effort to keep the code
** better organized.
**
** NOTE: source files should *not* #include this header file directly.
** Source files should #include the sqliteInt.h file and let that file
** include this one indirectly.
**
** $Id$
*/
#ifdef SQLITE_MUTEX_APPDEF
/*
** If SQLITE_MUTEX_APPDEF is defined, then this whole module is
** omitted and equivalent functionality must be provided by the
** application that links against the SQLite library.
*/
#else
/*
** Figure out what version of the code to use. The choices are
**
** SQLITE_MUTEX_NOOP For single-threaded applications that
** do not desire error checking.
**
** SQLITE_MUTEX_NOOP_DEBUG For single-threaded applications with
** error checking to help verify that mutexes
** are being used correctly even though they
** are not needed. Used when SQLITE_DEBUG is
** defined on single-threaded builds.
**
** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix.
**
** SQLITE_MUTEX_W32 For multi-threaded applications on Win32.
**
** SQLITE_MUTEX_OS2 For multi-threaded applications on OS/2.
*/
#define SQLITE_MUTEX_NOOP 1 /* The default */
#if defined(SQLITE_DEBUG) && !SQLITE_THREADSAFE
# undef SQLITE_MUTEX_NOOP
# define SQLITE_MUTEX_NOOP_DEBUG
#endif
#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && OS_UNIX
# undef SQLITE_MUTEX_NOOP
# define SQLITE_MUTEX_PTHREADS
#endif
#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && OS_WIN
# undef SQLITE_MUTEX_NOOP
# define SQLITE_MUTEX_W32
#endif
#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && OS_OS2
# undef SQLITE_MUTEX_NOOP
# define SQLITE_MUTEX_OS2
#endif
#ifdef SQLITE_MUTEX_NOOP
/*
** If this is a no-op implementation, implement everything as macros.
*/
#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
#define sqlite3_mutex_free(X)
#define sqlite3_mutex_enter(X)
#define sqlite3_mutex_try(X) SQLITE_OK
#define sqlite3_mutex_leave(X)
#define sqlite3_mutex_held(X) 1
#define sqlite3_mutex_notheld(X) 1
#endif
#endif /* SQLITE_MUTEX_APPDEF */

View File

@ -0,0 +1,223 @@
/*
** 2007 August 28
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement mutexes for pthreads
**
** $Id$
*/
#include "sqliteInt.h"
/*
** The code in this file is only used if we are compiling threadsafe
** under unix with pthreads.
**
** Note that this implementation requires a version of pthreads that
** supports recursive mutexes.
*/
#ifdef SQLITE_MUTEX_PTHREADS
#include <pthread.h>
/*
** Each recursive mutex is an instance of the following structure.
*/
struct sqlite3_mutex {
pthread_mutex_t mutex; /* Mutex controlling the lock */
int id; /* Mutex type */
int nRef; /* Number of entrances */
pthread_t owner; /* Thread that is within this mutex */
#ifdef SQLITE_DEBUG
int trace; /* True to trace changes */
#endif
};
/*
** The sqlite3_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it. If it returns NULL
** that means that a mutex could not be allocated. SQLite
** will unwind its stack and return an error. The argument
** to sqlite3_mutex_alloc() is one of these integer constants:
**
** <ul>
** <li> SQLITE_MUTEX_FAST
** <li> SQLITE_MUTEX_RECURSIVE
** <li> SQLITE_MUTEX_STATIC_MASTER
** <li> SQLITE_MUTEX_STATIC_MEM
** <li> SQLITE_MUTEX_STATIC_MEM2
** <li> SQLITE_MUTEX_STATIC_PRNG
** <li> SQLITE_MUTEX_STATIC_LRU
** </ul>
**
** The first two constants cause sqlite3_mutex_alloc() to create
** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
** The mutex implementation does not need to make a distinction
** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
** not want to. But SQLite will only request a recursive mutex in
** cases where it really needs one. If a faster non-recursive mutex
** implementation is available on the host platform, the mutex subsystem
** might return such a mutex in response to SQLITE_MUTEX_FAST.
**
** The other allowed parameters to sqlite3_mutex_alloc() each return
** a pointer to a static preexisting mutex. Three static mutexes are
** used by the current version of SQLite. Future versions of SQLite
** may add additional static mutexes. Static mutexes are for internal
** use by SQLite only. Applications that use SQLite mutexes should
** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
** SQLITE_MUTEX_RECURSIVE.
**
** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
** returns a different mutex on every call. But for the static
** mutex types, the same mutex is returned on every call that has
** the same type number.
*/
sqlite3_mutex *sqlite3_mutex_alloc(int iType){
static sqlite3_mutex staticMutexes[] = {
{ PTHREAD_MUTEX_INITIALIZER, },
{ PTHREAD_MUTEX_INITIALIZER, },
{ PTHREAD_MUTEX_INITIALIZER, },
{ PTHREAD_MUTEX_INITIALIZER, },
{ PTHREAD_MUTEX_INITIALIZER, },
};
sqlite3_mutex *p;
switch( iType ){
case SQLITE_MUTEX_RECURSIVE: {
p = sqlite3MallocZero( sizeof(*p) );
if( p ){
pthread_mutexattr_t recursiveAttr;
pthread_mutexattr_init(&recursiveAttr);
pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&p->mutex, &recursiveAttr);
pthread_mutexattr_destroy(&recursiveAttr);
p->id = iType;
}
break;
}
case SQLITE_MUTEX_FAST: {
p = sqlite3MallocZero( sizeof(*p) );
if( p ){
p->id = iType;
pthread_mutex_init(&p->mutex, 0);
}
break;
}
default: {
assert( iType-2 >= 0 );
assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
p = &staticMutexes[iType-2];
p->id = iType;
break;
}
}
return p;
}
/*
** This routine deallocates a previously
** allocated mutex. SQLite is careful to deallocate every
** mutex that it allocates.
*/
void sqlite3_mutex_free(sqlite3_mutex *p){
assert( p );
assert( p->nRef==0 );
assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
pthread_mutex_destroy(&p->mutex);
sqlite3_free(p);
}
/*
** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
** to enter a mutex. If another thread is already within the mutex,
** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
** be entered multiple times by the same thread. In such cases the,
** mutex must be exited an equal number of times before another thread
** can enter. If the same thread tries to enter any other kind of mutex
** more than once, the behavior is undefined.
*/
void sqlite3_mutex_enter(sqlite3_mutex *p){
assert( p );
assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
pthread_mutex_lock(&p->mutex);
p->owner = pthread_self();
p->nRef++;
#ifdef SQLITE_DEBUG
if( p->trace ){
printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
}
#endif
}
int sqlite3_mutex_try(sqlite3_mutex *p){
int rc;
assert( p );
assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
if( pthread_mutex_trylock(&p->mutex)==0 ){
p->owner = pthread_self();
p->nRef++;
rc = SQLITE_OK;
#ifdef SQLITE_DEBUG
if( p->trace ){
printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
}
#endif
}else{
rc = SQLITE_BUSY;
}
return rc;
}
/*
** The sqlite3_mutex_leave() routine exits a mutex that was
** previously entered by the same thread. The behavior
** is undefined if the mutex is not currently entered or
** is not currently allocated. SQLite will never do either.
*/
void sqlite3_mutex_leave(sqlite3_mutex *p){
assert( p );
assert( sqlite3_mutex_held(p) );
p->nRef--;
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
#ifdef SQLITE_DEBUG
if( p->trace ){
printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
}
#endif
pthread_mutex_unlock(&p->mutex);
}
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use only inside assert() statements. On some platforms,
** there might be race conditions that can cause these routines to
** deliver incorrect results. In particular, if pthread_equal() is
** not an atomic operation, then these routines might delivery
** incorrect results. On most platforms, pthread_equal() is a
** comparison of two integers and is therefore atomic. But we are
** told that HPUX is not such a platform. If so, then these routines
** will not always work correctly on HPUX.
**
** On those platforms where pthread_equal() is not atomic, SQLite
** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to
** make sure no assert() statements are evaluated and hence these
** routines are never called.
*/
#ifndef NDEBUG
int sqlite3_mutex_held(sqlite3_mutex *p){
return p==0 || (p->nRef!=0 && pthread_equal(p->owner, pthread_self()));
}
int sqlite3_mutex_notheld(sqlite3_mutex *p){
return p==0 || p->nRef==0 || pthread_equal(p->owner, pthread_self())==0;
}
#endif
#endif /* SQLITE_MUTEX_PTHREAD */

View File

@ -0,0 +1,208 @@
/*
** 2007 August 14
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement mutexes for win32
**
** $Id$
*/
#include "sqliteInt.h"
/*
** The code in this file is only used if we are compiling multithreaded
** on a win32 system.
*/
#ifdef SQLITE_MUTEX_W32
/*
** Each recursive mutex is an instance of the following structure.
*/
struct sqlite3_mutex {
CRITICAL_SECTION mutex; /* Mutex controlling the lock */
int id; /* Mutex type */
int nRef; /* Number of enterances */
DWORD owner; /* Thread holding this mutex */
};
/*
** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
** or WinCE. Return false (zero) for Win95, Win98, or WinME.
**
** Here is an interesting observation: Win95, Win98, and WinME lack
** the LockFileEx() API. But we can still statically link against that
** API as long as we don't call it win running Win95/98/ME. A call to
** this routine is used to determine if the host is Win95/98/ME or
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
*/
#if OS_WINCE
# define mutexIsNT() (1)
#else
static int mutexIsNT(void){
static int osType = 0;
if( osType==0 ){
OSVERSIONINFO sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
GetVersionEx(&sInfo);
osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
}
return osType==2;
}
#endif /* OS_WINCE */
/*
** The sqlite3_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it. If it returns NULL
** that means that a mutex could not be allocated. SQLite
** will unwind its stack and return an error. The argument
** to sqlite3_mutex_alloc() is one of these integer constants:
**
** <ul>
** <li> SQLITE_MUTEX_FAST 0
** <li> SQLITE_MUTEX_RECURSIVE 1
** <li> SQLITE_MUTEX_STATIC_MASTER 2
** <li> SQLITE_MUTEX_STATIC_MEM 3
** <li> SQLITE_MUTEX_STATIC_PRNG 4
** </ul>
**
** The first two constants cause sqlite3_mutex_alloc() to create
** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
** The mutex implementation does not need to make a distinction
** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
** not want to. But SQLite will only request a recursive mutex in
** cases where it really needs one. If a faster non-recursive mutex
** implementation is available on the host platform, the mutex subsystem
** might return such a mutex in response to SQLITE_MUTEX_FAST.
**
** The other allowed parameters to sqlite3_mutex_alloc() each return
** a pointer to a static preexisting mutex. Three static mutexes are
** used by the current version of SQLite. Future versions of SQLite
** may add additional static mutexes. Static mutexes are for internal
** use by SQLite only. Applications that use SQLite mutexes should
** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
** SQLITE_MUTEX_RECURSIVE.
**
** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
** returns a different mutex on every call. But for the static
** mutex types, the same mutex is returned on every call that has
** the same type number.
*/
sqlite3_mutex *sqlite3_mutex_alloc(int iType){
sqlite3_mutex *p;
switch( iType ){
case SQLITE_MUTEX_FAST:
case SQLITE_MUTEX_RECURSIVE: {
p = sqlite3MallocZero( sizeof(*p) );
if( p ){
p->id = iType;
InitializeCriticalSection(&p->mutex);
}
break;
}
default: {
static sqlite3_mutex staticMutexes[5];
static int isInit = 0;
while( !isInit ){
static long lock = 0;
if( InterlockedIncrement(&lock)==1 ){
int i;
for(i=0; i<sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++){
InitializeCriticalSection(&staticMutexes[i].mutex);
}
isInit = 1;
}else{
Sleep(1);
}
}
assert( iType-2 >= 0 );
assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
p = &staticMutexes[iType-2];
p->id = iType;
break;
}
}
return p;
}
/*
** This routine deallocates a previously
** allocated mutex. SQLite is careful to deallocate every
** mutex that it allocates.
*/
void sqlite3_mutex_free(sqlite3_mutex *p){
assert( p );
assert( p->nRef==0 );
assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
DeleteCriticalSection(&p->mutex);
sqlite3_free(p);
}
/*
** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
** to enter a mutex. If another thread is already within the mutex,
** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
** be entered multiple times by the same thread. In such cases the,
** mutex must be exited an equal number of times before another thread
** can enter. If the same thread tries to enter any other kind of mutex
** more than once, the behavior is undefined.
*/
void sqlite3_mutex_enter(sqlite3_mutex *p){
assert( p );
assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
EnterCriticalSection(&p->mutex);
p->owner = GetCurrentThreadId();
p->nRef++;
}
int sqlite3_mutex_try(sqlite3_mutex *p){
int rc;
assert( p );
assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
p->owner = GetCurrentThreadId();
p->nRef++;
rc = SQLITE_OK;
}else{
rc = SQLITE_BUSY;
}
return rc;
}
/*
** The sqlite3_mutex_leave() routine exits a mutex that was
** previously entered by the same thread. The behavior
** is undefined if the mutex is not currently entered or
** is not currently allocated. SQLite will never do either.
*/
void sqlite3_mutex_leave(sqlite3_mutex *p){
assert( p->nRef>0 );
assert( p->owner==GetCurrentThreadId() );
p->nRef--;
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
LeaveCriticalSection(&p->mutex);
}
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use only inside assert() statements.
*/
int sqlite3_mutex_held(sqlite3_mutex *p){
return p==0 || (p->nRef!=0 && p->owner==GetCurrentThreadId());
}
int sqlite3_mutex_notheld(sqlite3_mutex *p){
return p==0 || p->nRef==0 || p->owner!=GetCurrentThreadId();
}
#endif /* SQLITE_MUTEX_W32 */

View File

@ -1,148 +1,151 @@
/* Automatically generated. Do not edit */
/* See the mkopcodec.awk script for details. */
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
const char *const sqlite3OpcodeNames[] = { "?",
/* 1 */ "MemLoad",
/* 2 */ "VNext",
/* 3 */ "Column",
/* 4 */ "SetCookie",
/* 5 */ "IfMemPos",
/* 6 */ "Sequence",
/* 7 */ "MoveGt",
/* 8 */ "RowKey",
/* 9 */ "OpenWrite",
/* 10 */ "If",
/* 11 */ "Pop",
/* 12 */ "VRowid",
/* 13 */ "CollSeq",
/* 14 */ "OpenRead",
/* 15 */ "Expire",
/* 16 */ "Not",
/* 17 */ "AutoCommit",
/* 18 */ "IntegrityCk",
/* 19 */ "Sort",
/* 20 */ "Function",
/* 21 */ "Noop",
/* 22 */ "Return",
/* 23 */ "NewRowid",
/* 24 */ "IfMemNeg",
/* 25 */ "Variable",
/* 26 */ "String",
/* 27 */ "RealAffinity",
/* 28 */ "VRename",
/* 29 */ "ParseSchema",
/* 30 */ "VOpen",
/* 31 */ "Close",
/* 32 */ "CreateIndex",
/* 33 */ "IsUnique",
/* 34 */ "NotFound",
/* 35 */ "Int64",
/* 36 */ "MustBeInt",
/* 37 */ "Halt",
/* 38 */ "Rowid",
/* 39 */ "IdxLT",
/* 40 */ "AddImm",
/* 41 */ "Statement",
/* 42 */ "RowData",
/* 43 */ "MemMax",
/* 44 */ "Push",
/* 45 */ "NotExists",
/* 46 */ "MemIncr",
/* 47 */ "Gosub",
/* 48 */ "Integer",
/* 49 */ "MemInt",
/* 50 */ "Prev",
/* 51 */ "VColumn",
/* 52 */ "CreateTable",
/* 53 */ "Last",
/* 54 */ "IncrVacuum",
/* 55 */ "IdxRowid",
/* 56 */ "MakeIdxRec",
/* 57 */ "ResetCount",
/* 58 */ "FifoWrite",
/* 59 */ "Callback",
/* 60 */ "Or",
/* 61 */ "And",
/* 62 */ "ContextPush",
/* 63 */ "DropTrigger",
/* 64 */ "DropIndex",
/* 65 */ "IsNull",
/* 66 */ "NotNull",
/* 67 */ "Ne",
/* 68 */ "Eq",
/* 69 */ "Gt",
/* 70 */ "Le",
/* 71 */ "Lt",
/* 72 */ "Ge",
/* 73 */ "IdxGE",
/* 74 */ "BitAnd",
/* 75 */ "BitOr",
/* 76 */ "ShiftLeft",
/* 77 */ "ShiftRight",
/* 78 */ "Add",
/* 79 */ "Subtract",
/* 80 */ "Multiply",
/* 81 */ "Divide",
/* 82 */ "Remainder",
/* 83 */ "Concat",
/* 84 */ "IdxDelete",
/* 85 */ "Negative",
/* 86 */ "Vacuum",
/* 87 */ "BitNot",
/* 88 */ "String8",
/* 89 */ "MoveLe",
/* 90 */ "IfNot",
/* 91 */ "DropTable",
/* 92 */ "MakeRecord",
/* 93 */ "Delete",
/* 94 */ "AggFinal",
/* 95 */ "Dup",
/* 96 */ "Goto",
/* 97 */ "TableLock",
/* 98 */ "FifoRead",
/* 99 */ "Clear",
/* 100 */ "IdxGT",
/* 101 */ "MoveLt",
/* 102 */ "VerifyCookie",
/* 103 */ "AggStep",
/* 104 */ "Pull",
/* 105 */ "SetNumColumns",
/* 106 */ "AbsValue",
/* 107 */ "Transaction",
/* 108 */ "VFilter",
/* 109 */ "VDestroy",
/* 110 */ "ContextPop",
/* 111 */ "Next",
/* 112 */ "IdxInsert",
/* 113 */ "Distinct",
/* 114 */ "Insert",
/* 115 */ "Destroy",
/* 116 */ "ReadCookie",
/* 117 */ "ForceInt",
/* 118 */ "LoadAnalysis",
/* 119 */ "Explain",
/* 120 */ "IfMemZero",
/* 121 */ "OpenPseudo",
/* 122 */ "OpenEphemeral",
/* 123 */ "Null",
/* 124 */ "Blob",
/* 125 */ "Real",
/* 126 */ "HexBlob",
/* 127 */ "MemStore",
/* 128 */ "Rewind",
/* 129 */ "MoveGe",
/* 130 */ "VBegin",
/* 131 */ "VUpdate",
/* 132 */ "VCreate",
/* 133 */ "MemMove",
/* 134 */ "MemNull",
/* 135 */ "Found",
/* 136 */ "NullRow",
/* 137 */ "NotUsed_137",
/* 138 */ "ToText",
/* 139 */ "ToBlob",
/* 140 */ "ToNumeric",
/* 141 */ "ToInt",
/* 142 */ "ToReal",
};
const char *sqlite3OpcodeName(int i){
static const char *const azName[] = { "?",
/* 1 */ "MemLoad",
/* 2 */ "VNext",
/* 3 */ "Column",
/* 4 */ "SetCookie",
/* 5 */ "IfMemPos",
/* 6 */ "Sequence",
/* 7 */ "MoveGt",
/* 8 */ "RowKey",
/* 9 */ "OpenWrite",
/* 10 */ "If",
/* 11 */ "Pop",
/* 12 */ "VRowid",
/* 13 */ "CollSeq",
/* 14 */ "OpenRead",
/* 15 */ "Expire",
/* 16 */ "Not",
/* 17 */ "AutoCommit",
/* 18 */ "IntegrityCk",
/* 19 */ "Sort",
/* 20 */ "Function",
/* 21 */ "Noop",
/* 22 */ "Return",
/* 23 */ "NewRowid",
/* 24 */ "IfMemNeg",
/* 25 */ "Variable",
/* 26 */ "String",
/* 27 */ "RealAffinity",
/* 28 */ "VRename",
/* 29 */ "ParseSchema",
/* 30 */ "VOpen",
/* 31 */ "Close",
/* 32 */ "CreateIndex",
/* 33 */ "IsUnique",
/* 34 */ "NotFound",
/* 35 */ "Int64",
/* 36 */ "MustBeInt",
/* 37 */ "Halt",
/* 38 */ "Rowid",
/* 39 */ "IdxLT",
/* 40 */ "AddImm",
/* 41 */ "Statement",
/* 42 */ "RowData",
/* 43 */ "MemMax",
/* 44 */ "Push",
/* 45 */ "NotExists",
/* 46 */ "MemIncr",
/* 47 */ "Gosub",
/* 48 */ "Integer",
/* 49 */ "MemInt",
/* 50 */ "Prev",
/* 51 */ "VColumn",
/* 52 */ "CreateTable",
/* 53 */ "Last",
/* 54 */ "IncrVacuum",
/* 55 */ "IdxRowid",
/* 56 */ "MakeIdxRec",
/* 57 */ "ResetCount",
/* 58 */ "FifoWrite",
/* 59 */ "Callback",
/* 60 */ "Or",
/* 61 */ "And",
/* 62 */ "ContextPush",
/* 63 */ "DropTrigger",
/* 64 */ "DropIndex",
/* 65 */ "IsNull",
/* 66 */ "NotNull",
/* 67 */ "Ne",
/* 68 */ "Eq",
/* 69 */ "Gt",
/* 70 */ "Le",
/* 71 */ "Lt",
/* 72 */ "Ge",
/* 73 */ "IdxGE",
/* 74 */ "BitAnd",
/* 75 */ "BitOr",
/* 76 */ "ShiftLeft",
/* 77 */ "ShiftRight",
/* 78 */ "Add",
/* 79 */ "Subtract",
/* 80 */ "Multiply",
/* 81 */ "Divide",
/* 82 */ "Remainder",
/* 83 */ "Concat",
/* 84 */ "IdxDelete",
/* 85 */ "Negative",
/* 86 */ "Vacuum",
/* 87 */ "BitNot",
/* 88 */ "String8",
/* 89 */ "MoveLe",
/* 90 */ "IfNot",
/* 91 */ "DropTable",
/* 92 */ "MakeRecord",
/* 93 */ "Delete",
/* 94 */ "AggFinal",
/* 95 */ "Dup",
/* 96 */ "Goto",
/* 97 */ "TableLock",
/* 98 */ "FifoRead",
/* 99 */ "Clear",
/* 100 */ "IdxGT",
/* 101 */ "MoveLt",
/* 102 */ "VerifyCookie",
/* 103 */ "AggStep",
/* 104 */ "Pull",
/* 105 */ "SetNumColumns",
/* 106 */ "AbsValue",
/* 107 */ "Transaction",
/* 108 */ "VFilter",
/* 109 */ "VDestroy",
/* 110 */ "ContextPop",
/* 111 */ "Next",
/* 112 */ "IdxInsert",
/* 113 */ "Distinct",
/* 114 */ "Insert",
/* 115 */ "Destroy",
/* 116 */ "ReadCookie",
/* 117 */ "ForceInt",
/* 118 */ "LoadAnalysis",
/* 119 */ "Explain",
/* 120 */ "IfMemZero",
/* 121 */ "OpenPseudo",
/* 122 */ "OpenEphemeral",
/* 123 */ "Null",
/* 124 */ "Blob",
/* 125 */ "Real",
/* 126 */ "HexBlob",
/* 127 */ "MemStore",
/* 128 */ "Rewind",
/* 129 */ "MoveGe",
/* 130 */ "VBegin",
/* 131 */ "VUpdate",
/* 132 */ "VCreate",
/* 133 */ "MemMove",
/* 134 */ "MemNull",
/* 135 */ "Found",
/* 136 */ "NullRow",
/* 137 */ "NotUsed_137",
/* 138 */ "ToText",
/* 139 */ "ToBlob",
/* 140 */ "ToNumeric",
/* 141 */ "ToInt",
/* 142 */ "ToReal",
};
return azName[i];
}
#endif

View File

@ -1,4 +1,4 @@
/*
/*
** 2005 November 29
**
** The author disclaims copyright to this source code. In place of
@ -15,82 +15,268 @@
*/
#define _SQLITE_OS_C_ 1
#include "sqliteInt.h"
#include "os.h"
#undef _SQLITE_OS_C_
/*
** The default SQLite sqlite3_vfs implementations do not allocate
** memory (actually, os_unix.c allocates a small amount of memory
** from within OsOpen()), but some third-party implementations may.
** So we test the effects of a malloc() failing and the sqlite3OsXXX()
** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
**
** The following functions are instrumented for malloc() failure
** testing:
**
** sqlite3OsOpen()
** sqlite3OsRead()
** sqlite3OsWrite()
** sqlite3OsSync()
** sqlite3OsLock()
**
*/
#ifdef SQLITE_TEST
#define DO_OS_MALLOC_TEST if (1) { \
void *pTstAlloc = sqlite3_malloc(10); \
if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \
sqlite3_free(pTstAlloc); \
}
#else
#define DO_OS_MALLOC_TEST
#endif
/*
** The following routines are convenience wrappers around methods
** of the OsFile object. This is mostly just syntactic sugar. All
** of the sqlite3_file object. This is mostly just syntactic sugar. All
** of this would be completely automatic if SQLite were coded using
** C++ instead of plain old C.
*/
int sqlite3OsClose(OsFile **pId){
OsFile *id;
if( pId!=0 && (id = *pId)!=0 ){
return id->pMethod->xClose(pId);
}else{
return SQLITE_OK;
int sqlite3OsClose(sqlite3_file *pId){
int rc = SQLITE_OK;
if( pId->pMethods ){
rc = pId->pMethods->xClose(pId);
pId->pMethods = 0;
}
return rc;
}
int sqlite3OsOpenDirectory(OsFile *id, const char *zName){
return id->pMethod->xOpenDirectory(id, zName);
int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
DO_OS_MALLOC_TEST;
return id->pMethods->xRead(id, pBuf, amt, offset);
}
int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
return id->pMethod->xRead(id, pBuf, amt);
int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){
DO_OS_MALLOC_TEST;
return id->pMethods->xWrite(id, pBuf, amt, offset);
}
int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
return id->pMethod->xWrite(id, pBuf, amt);
int sqlite3OsTruncate(sqlite3_file *id, i64 size){
return id->pMethods->xTruncate(id, size);
}
int sqlite3OsSeek(OsFile *id, i64 offset){
return id->pMethod->xSeek(id, offset);
int sqlite3OsSync(sqlite3_file *id, int flags){
DO_OS_MALLOC_TEST;
return id->pMethods->xSync(id, flags);
}
int sqlite3OsTruncate(OsFile *id, i64 size){
return id->pMethod->xTruncate(id, size);
int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
return id->pMethods->xFileSize(id, pSize);
}
int sqlite3OsSync(OsFile *id, int fullsync){
return id->pMethod->xSync(id, fullsync);
int sqlite3OsLock(sqlite3_file *id, int lockType){
DO_OS_MALLOC_TEST;
return id->pMethods->xLock(id, lockType);
}
void sqlite3OsSetFullSync(OsFile *id, int value){
id->pMethod->xSetFullSync(id, value);
int sqlite3OsUnlock(sqlite3_file *id, int lockType){
return id->pMethods->xUnlock(id, lockType);
}
int sqlite3OsFileSize(OsFile *id, i64 *pSize){
return id->pMethod->xFileSize(id, pSize);
int sqlite3OsCheckReservedLock(sqlite3_file *id){
return id->pMethods->xCheckReservedLock(id);
}
int sqlite3OsLock(OsFile *id, int lockType){
return id->pMethod->xLock(id, lockType);
}
int sqlite3OsUnlock(OsFile *id, int lockType){
return id->pMethod->xUnlock(id, lockType);
}
int sqlite3OsCheckReservedLock(OsFile *id){
return id->pMethod->xCheckReservedLock(id);
}
int sqlite3OsSectorSize(OsFile *id){
int (*xSectorSize)(OsFile*) = id->pMethod->xSectorSize;
return xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE;
int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
return id->pMethods->xFileControl(id,op,pArg);
}
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
/* These methods are currently only used for testing and debugging. */
int sqlite3OsFileHandle(OsFile *id){
return id->pMethod->xFileHandle(id);
#ifdef SQLITE_TEST
/* The following two variables are used to override the values returned
** by the xSectorSize() and xDeviceCharacteristics() vfs methods for
** testing purposes. They are usually set by a test command implemented
** in test6.c.
*/
int sqlite3_test_sector_size = 0;
int sqlite3_test_device_characteristics = 0;
int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
int dc = id->pMethods->xDeviceCharacteristics(id);
return dc | sqlite3_test_device_characteristics;
}
int sqlite3OsLockState(OsFile *id){
return id->pMethod->xLockState(id);
int sqlite3OsSectorSize(sqlite3_file *id){
if( sqlite3_test_sector_size==0 ){
int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
}
return sqlite3_test_sector_size;
}
#else
int sqlite3OsSectorSize(sqlite3_file *id){
int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
}
int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
return id->pMethods->xDeviceCharacteristics(id);
}
#endif
#ifdef SQLITE_ENABLE_REDEF_IO
/*
** A function to return a pointer to the virtual function table.
** This routine really does not accomplish very much since the
** virtual function table is a global variable and anybody who
** can call this function can just as easily access the variable
** for themselves. Nevertheless, we include this routine for
** backwards compatibility with an earlier redefinable I/O
** interface design.
** The next group of routines are convenience wrappers around the
** VFS methods.
*/
struct sqlite3OsVtbl *sqlite3_os_switch(void){
return &sqlite3Os;
int sqlite3OsOpen(
sqlite3_vfs *pVfs,
const char *zPath,
sqlite3_file *pFile,
int flags,
int *pFlagsOut
){
DO_OS_MALLOC_TEST;
return pVfs->xOpen(pVfs, zPath, pFile, flags, pFlagsOut);
}
int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
return pVfs->xDelete(pVfs, zPath, dirSync);
}
int sqlite3OsAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){
return pVfs->xAccess(pVfs, zPath, flags);
}
int sqlite3OsGetTempname(sqlite3_vfs *pVfs, int nBufOut, char *zBufOut){
return pVfs->xGetTempname(pVfs, nBufOut, zBufOut);
}
int sqlite3OsFullPathname(
sqlite3_vfs *pVfs,
const char *zPath,
int nPathOut,
char *zPathOut
){
return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
}
void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
return pVfs->xDlOpen(pVfs, zPath);
}
void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
pVfs->xDlError(pVfs, nByte, zBufOut);
}
void *sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
return pVfs->xDlSym(pVfs, pHandle, zSymbol);
}
void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
pVfs->xDlClose(pVfs, pHandle);
}
int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
return pVfs->xRandomness(pVfs, nByte, zBufOut);
}
int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
return pVfs->xSleep(pVfs, nMicro);
}
int sqlite3OsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
return pVfs->xCurrentTime(pVfs, pTimeOut);
}
int sqlite3OsOpenMalloc(
sqlite3_vfs *pVfs,
const char *zFile,
sqlite3_file **ppFile,
int flags,
int *pOutFlags
){
int rc = SQLITE_NOMEM;
sqlite3_file *pFile;
pFile = (sqlite3_file *)sqlite3_malloc(pVfs->szOsFile);
if( pFile ){
rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
if( rc!=SQLITE_OK ){
sqlite3_free(pFile);
}else{
*ppFile = pFile;
}
}
return rc;
}
int sqlite3OsCloseFree(sqlite3_file *pFile){
int rc = SQLITE_OK;
if( pFile ){
rc = sqlite3OsClose(pFile);
sqlite3_free(pFile);
}
return rc;
}
/*
** The list of all registered VFS implementations. This list is
** initialized to the single VFS returned by sqlite3OsDefaultVfs()
** upon the first call to sqlite3_vfs_find().
*/
static sqlite3_vfs *vfsList = 0;
/*
** Locate a VFS by name. If no name is given, simply return the
** first VFS on the list.
*/
sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_vfs *pVfs;
static int isInit = 0;
sqlite3_mutex_enter(mutex);
if( !isInit ){
vfsList = sqlite3OsDefaultVfs();
isInit = 1;
}
for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
if( zVfs==0 ) break;
if( strcmp(zVfs, pVfs->zName)==0 ) break;
}
sqlite3_mutex_leave(mutex);
return pVfs;
}
/*
** Unlink a VFS from the linked list
*/
static void vfsUnlink(sqlite3_vfs *pVfs){
assert( sqlite3_mutex_held(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)) );
if( vfsList==pVfs ){
vfsList = pVfs->pNext;
}else{
sqlite3_vfs *p = vfsList;
while( p->pNext && p->pNext!=pVfs ){
p = p->pNext;
}
if( p->pNext==pVfs ){
p->pNext = pVfs->pNext;
}
}
}
/*
** Register a VFS with the system. It is harmless to register the same
** VFS multiple times. The new VFS becomes the default if makeDflt is
** true.
*/
int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_vfs_find(0); /* Make sure we are initialized */
sqlite3_mutex_enter(mutex);
vfsUnlink(pVfs);
if( makeDflt || vfsList==0 ){
pVfs->pNext = vfsList;
vfsList = pVfs;
}else{
pVfs->pNext = vfsList->pNext;
vfsList->pNext = pVfs;
}
assert(vfsList);
sqlite3_mutex_leave(mutex);
return SQLITE_OK;
}
/*
** Unregister a VFS so that it is no longer accessible.
*/
int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(mutex);
vfsUnlink(pVfs);
assert(vfsList);
sqlite3_mutex_leave(mutex);
return SQLITE_OK;
}
#endif

View File

@ -13,13 +13,18 @@
** This header file (together with is companion C source-code file
** "os.c") attempt to abstract the underlying operating system so that
** the SQLite library will work on both POSIX and windows systems.
**
** This header file is #include-ed by sqliteInt.h and thus ends up
** being included by every source file.
*/
#ifndef _SQLITE_OS_H_
#define _SQLITE_OS_H_
/*
** Figure out if we are dealing with Unix, Windows, or some other
** operating system.
** operating system. After the following block of preprocess macros,
** all of OS_UNIX, OS_WIN, OS_OS2, and OS_OTHER will defined to either
** 1 or 0. One of the four will be 1. The other three will be 0.
*/
#if defined(OS_OTHER)
# if OS_OTHER==1
@ -60,6 +65,7 @@
#endif
/*
** Define the maximum size of a temporary filename
*/
@ -103,7 +109,7 @@
** If sqlite is being embedded in another program, you may wish to change the
** prefix to reflect your program's name, so that if your program exits
** prematurely, old temporary files can be easily identified. This can be done
** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line.
** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line.
**
** 2006-10-31: The default prefix used to be "sqlite_". But then
** Mcafee started using SQLite in their anti-virus product and it
@ -117,92 +123,10 @@
** enough to know that calling the developer will not help get rid
** of the file.
*/
#ifndef TEMP_FILE_PREFIX
# define TEMP_FILE_PREFIX "etilqs_"
#ifndef SQLITE_TEMP_FILE_PREFIX
# define SQLITE_TEMP_FILE_PREFIX "etilqs_"
#endif
/*
** Define the interfaces for Unix, Windows, and OS/2.
*/
#if OS_UNIX
#define sqlite3OsOpenReadWrite sqlite3UnixOpenReadWrite
#define sqlite3OsOpenExclusive sqlite3UnixOpenExclusive
#define sqlite3OsOpenReadOnly sqlite3UnixOpenReadOnly
#define sqlite3OsDelete sqlite3UnixDelete
#define sqlite3OsFileExists sqlite3UnixFileExists
#define sqlite3OsFullPathname sqlite3UnixFullPathname
#define sqlite3OsIsDirWritable sqlite3UnixIsDirWritable
#define sqlite3OsSyncDirectory sqlite3UnixSyncDirectory
#define sqlite3OsTempFileName sqlite3UnixTempFileName
#define sqlite3OsRandomSeed sqlite3UnixRandomSeed
#define sqlite3OsSleep sqlite3UnixSleep
#define sqlite3OsCurrentTime sqlite3UnixCurrentTime
#define sqlite3OsEnterMutex sqlite3UnixEnterMutex
#define sqlite3OsLeaveMutex sqlite3UnixLeaveMutex
#define sqlite3OsInMutex sqlite3UnixInMutex
#define sqlite3OsThreadSpecificData sqlite3UnixThreadSpecificData
#define sqlite3OsMalloc sqlite3GenericMalloc
#define sqlite3OsRealloc sqlite3GenericRealloc
#define sqlite3OsFree sqlite3GenericFree
#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
#define sqlite3OsDlopen sqlite3UnixDlopen
#define sqlite3OsDlsym sqlite3UnixDlsym
#define sqlite3OsDlclose sqlite3UnixDlclose
#endif
#if OS_WIN
#define sqlite3OsOpenReadWrite sqlite3WinOpenReadWrite
#define sqlite3OsOpenExclusive sqlite3WinOpenExclusive
#define sqlite3OsOpenReadOnly sqlite3WinOpenReadOnly
#define sqlite3OsDelete sqlite3WinDelete
#define sqlite3OsFileExists sqlite3WinFileExists
#define sqlite3OsFullPathname sqlite3WinFullPathname
#define sqlite3OsIsDirWritable sqlite3WinIsDirWritable
#define sqlite3OsSyncDirectory sqlite3WinSyncDirectory
#define sqlite3OsTempFileName sqlite3WinTempFileName
#define sqlite3OsRandomSeed sqlite3WinRandomSeed
#define sqlite3OsSleep sqlite3WinSleep
#define sqlite3OsCurrentTime sqlite3WinCurrentTime
#define sqlite3OsEnterMutex sqlite3WinEnterMutex
#define sqlite3OsLeaveMutex sqlite3WinLeaveMutex
#define sqlite3OsInMutex sqlite3WinInMutex
#define sqlite3OsThreadSpecificData sqlite3WinThreadSpecificData
#define sqlite3OsMalloc sqlite3GenericMalloc
#define sqlite3OsRealloc sqlite3GenericRealloc
#define sqlite3OsFree sqlite3GenericFree
#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
#define sqlite3OsDlopen sqlite3WinDlopen
#define sqlite3OsDlsym sqlite3WinDlsym
#define sqlite3OsDlclose sqlite3WinDlclose
#endif
#if OS_OS2
#define sqlite3OsOpenReadWrite sqlite3Os2OpenReadWrite
#define sqlite3OsOpenExclusive sqlite3Os2OpenExclusive
#define sqlite3OsOpenReadOnly sqlite3Os2OpenReadOnly
#define sqlite3OsDelete sqlite3Os2Delete
#define sqlite3OsFileExists sqlite3Os2FileExists
#define sqlite3OsFullPathname sqlite3Os2FullPathname
#define sqlite3OsIsDirWritable sqlite3Os2IsDirWritable
#define sqlite3OsSyncDirectory sqlite3Os2SyncDirectory
#define sqlite3OsTempFileName sqlite3Os2TempFileName
#define sqlite3OsRandomSeed sqlite3Os2RandomSeed
#define sqlite3OsSleep sqlite3Os2Sleep
#define sqlite3OsCurrentTime sqlite3Os2CurrentTime
#define sqlite3OsEnterMutex sqlite3Os2EnterMutex
#define sqlite3OsLeaveMutex sqlite3Os2LeaveMutex
#define sqlite3OsInMutex sqlite3Os2InMutex
#define sqlite3OsThreadSpecificData sqlite3Os2ThreadSpecificData
#define sqlite3OsMalloc sqlite3GenericMalloc
#define sqlite3OsRealloc sqlite3GenericRealloc
#define sqlite3OsFree sqlite3GenericFree
#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
#define sqlite3OsDlopen sqlite3Os2Dlopen
#define sqlite3OsDlsym sqlite3Os2Dlsym
#define sqlite3OsDlclose sqlite3Os2Dlclose
#endif
/*
** If using an alternative OS interface, then we must have an "os_other.h"
** header file available for that interface. Presumably the "os_other.h"
@ -213,47 +137,6 @@
#endif
/*
** Forward declarations
*/
typedef struct OsFile OsFile;
typedef struct IoMethod IoMethod;
/*
** An instance of the following structure contains pointers to all
** methods on an OsFile object.
*/
struct IoMethod {
int (*xClose)(OsFile**);
int (*xOpenDirectory)(OsFile*, const char*);
int (*xRead)(OsFile*, void*, int amt);
int (*xWrite)(OsFile*, const void*, int amt);
int (*xSeek)(OsFile*, i64 offset);
int (*xTruncate)(OsFile*, i64 size);
int (*xSync)(OsFile*, int);
void (*xSetFullSync)(OsFile *id, int setting);
int (*xFileHandle)(OsFile *id);
int (*xFileSize)(OsFile*, i64 *pSize);
int (*xLock)(OsFile*, int);
int (*xUnlock)(OsFile*, int);
int (*xLockState)(OsFile *id);
int (*xCheckReservedLock)(OsFile *id);
int (*xSectorSize)(OsFile *id);
};
/*
** The OsFile object describes an open disk file in an OS-dependent way.
** The version of OsFile defined here is a generic version. Each OS
** implementation defines its own subclass of this structure that contains
** additional information needed to handle file I/O. But the pMethod
** entry (pointing to the virtual function table) always occurs first
** so that we can always find the appropriate methods.
*/
struct OsFile {
IoMethod const *pMethod;
};
/*
** The following values may be passed as the second argument to
** sqlite3OsLock(). The various locks exhibit the following semantics:
@ -345,204 +228,57 @@ extern unsigned int sqlite3_pending_byte;
#define SHARED_FIRST (PENDING_BYTE+2)
#define SHARED_SIZE 510
/*
** Prototypes for operating system interface routines.
/*
** Functions for accessing sqlite3_file methods
*/
int sqlite3OsClose(OsFile**);
int sqlite3OsOpenDirectory(OsFile*, const char*);
int sqlite3OsRead(OsFile*, void*, int amt);
int sqlite3OsWrite(OsFile*, const void*, int amt);
int sqlite3OsSeek(OsFile*, i64 offset);
int sqlite3OsTruncate(OsFile*, i64 size);
int sqlite3OsSync(OsFile*, int);
void sqlite3OsSetFullSync(OsFile *id, int setting);
int sqlite3OsFileSize(OsFile*, i64 *pSize);
int sqlite3OsLock(OsFile*, int);
int sqlite3OsUnlock(OsFile*, int);
int sqlite3OsCheckReservedLock(OsFile *id);
int sqlite3OsOpenReadWrite(const char*, OsFile**, int*);
int sqlite3OsOpenExclusive(const char*, OsFile**, int);
int sqlite3OsOpenReadOnly(const char*, OsFile**);
int sqlite3OsDelete(const char*);
int sqlite3OsFileExists(const char*);
char *sqlite3OsFullPathname(const char*);
int sqlite3OsIsDirWritable(char*);
int sqlite3OsSyncDirectory(const char*);
int sqlite3OsSectorSize(OsFile *id);
int sqlite3OsTempFileName(char*);
int sqlite3OsRandomSeed(char*);
int sqlite3OsSleep(int ms);
int sqlite3OsCurrentTime(double*);
void sqlite3OsEnterMutex(void);
void sqlite3OsLeaveMutex(void);
int sqlite3OsInMutex(int);
ThreadData *sqlite3OsThreadSpecificData(int);
void *sqlite3OsMalloc(int);
void *sqlite3OsRealloc(void *, int);
void sqlite3OsFree(void *);
int sqlite3OsAllocationSize(void *);
void *sqlite3OsDlopen(const char*);
void *sqlite3OsDlsym(void*, const char*);
int sqlite3OsDlclose(void*);
int sqlite3OsClose(sqlite3_file*);
int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
int sqlite3OsTruncate(sqlite3_file*, i64 size);
int sqlite3OsSync(sqlite3_file*, int);
int sqlite3OsFileSize(sqlite3_file*, i64 *pSize);
int sqlite3OsLock(sqlite3_file*, int);
int sqlite3OsUnlock(sqlite3_file*, int);
int sqlite3OsCheckReservedLock(sqlite3_file *id);
int sqlite3OsFileControl(sqlite3_file*,int,void*);
int sqlite3OsSectorSize(sqlite3_file *id);
int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
int sqlite3OsFileHandle(OsFile *id);
int sqlite3OsLockState(OsFile *id);
#endif
/*
** Functions for accessing sqlite3_vfs methods
*/
int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
int sqlite3OsAccess(sqlite3_vfs *, const char *, int);
int sqlite3OsGetTempname(sqlite3_vfs *, int, char *);
int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *);
void *sqlite3OsDlOpen(sqlite3_vfs *, const char *);
void sqlite3OsDlError(sqlite3_vfs *, int, char *);
void *sqlite3OsDlSym(sqlite3_vfs *, void *, const char *);
void sqlite3OsDlClose(sqlite3_vfs *, void *);
int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
int sqlite3OsSleep(sqlite3_vfs *, int);
int sqlite3OsCurrentTime(sqlite3_vfs *, double*);
/*
** If the SQLITE_ENABLE_REDEF_IO macro is defined, then the OS-layer
** interface routines are not called directly but are invoked using
** pointers to functions. This allows the implementation of various
** OS-layer interface routines to be modified at run-time. There are
** obscure but legitimate reasons for wanting to do this. But for
** most users, a direct call to the underlying interface is preferable
** so the the redefinable I/O interface is turned off by default.
** Convenience functions for opening and closing files using
** sqlite3_malloc() to obtain space for the file-handle structure.
*/
#ifdef SQLITE_ENABLE_REDEF_IO
int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
int sqlite3OsCloseFree(sqlite3_file *);
/*
** When redefinable I/O is enabled, a single global instance of the
** following structure holds pointers to the routines that SQLite
** uses to talk with the underlying operating system. Modify this
** structure (before using any SQLite API!) to accomodate perculiar
** operating system interfaces or behaviors.
** Each OS-specific backend defines an instance of the following
** structure for returning a pointer to its sqlite3_vfs. If OS_OTHER
** is defined (meaning that the application-defined OS interface layer
** is used) then there is no default VFS. The application must
** register one or more VFS structures using sqlite3_vfs_register()
** before attempting to use SQLite.
*/
struct sqlite3OsVtbl {
int (*xOpenReadWrite)(const char*, OsFile**, int*);
int (*xOpenExclusive)(const char*, OsFile**, int);
int (*xOpenReadOnly)(const char*, OsFile**);
int (*xDelete)(const char*);
int (*xFileExists)(const char*);
char *(*xFullPathname)(const char*);
int (*xIsDirWritable)(char*);
int (*xSyncDirectory)(const char*);
int (*xTempFileName)(char*);
int (*xRandomSeed)(char*);
int (*xSleep)(int ms);
int (*xCurrentTime)(double*);
void (*xEnterMutex)(void);
void (*xLeaveMutex)(void);
int (*xInMutex)(int);
ThreadData *(*xThreadSpecificData)(int);
void *(*xMalloc)(int);
void *(*xRealloc)(void *, int);
void (*xFree)(void *);
int (*xAllocationSize)(void *);
void *(*xDlopen)(const char*);
void *(*xDlsym)(void*, const char*);
int (*xDlclose)(void*);
};
/* Macro used to comment out routines that do not exists when there is
** no disk I/O or extension loading
*/
#ifdef SQLITE_OMIT_DISKIO
# define IF_DISKIO(X) 0
#if OS_UNIX || OS_WIN || OS_OS2
sqlite3_vfs *sqlite3OsDefaultVfs(void);
#else
# define IF_DISKIO(X) X
# define sqlite3OsDefaultVfs(X) 0
#endif
#ifdef SQLITE_OMIT_LOAD_EXTENSION
# define IF_DLOPEN(X) 0
#else
# define IF_DLOPEN(X) X
#endif
#if defined(_SQLITE_OS_C_) || defined(SQLITE_AMALGAMATION)
/*
** The os.c file implements the global virtual function table.
** We have to put this file here because the initializers
** (ex: sqlite3OsRandomSeed) are macros that are about to be
** redefined.
*/
struct sqlite3OsVtbl sqlite3Os = {
IF_DISKIO( sqlite3OsOpenReadWrite ),
IF_DISKIO( sqlite3OsOpenExclusive ),
IF_DISKIO( sqlite3OsOpenReadOnly ),
IF_DISKIO( sqlite3OsDelete ),
IF_DISKIO( sqlite3OsFileExists ),
IF_DISKIO( sqlite3OsFullPathname ),
IF_DISKIO( sqlite3OsIsDirWritable ),
IF_DISKIO( sqlite3OsSyncDirectory ),
IF_DISKIO( sqlite3OsTempFileName ),
sqlite3OsRandomSeed,
sqlite3OsSleep,
sqlite3OsCurrentTime,
sqlite3OsEnterMutex,
sqlite3OsLeaveMutex,
sqlite3OsInMutex,
sqlite3OsThreadSpecificData,
sqlite3OsMalloc,
sqlite3OsRealloc,
sqlite3OsFree,
sqlite3OsAllocationSize,
IF_DLOPEN( sqlite3OsDlopen ),
IF_DLOPEN( sqlite3OsDlsym ),
IF_DLOPEN( sqlite3OsDlclose ),
};
#else
/*
** Files other than os.c just reference the global virtual function table.
*/
extern struct sqlite3OsVtbl sqlite3Os;
#endif /* _SQLITE_OS_C_ */
/* This additional API routine is available with redefinable I/O */
struct sqlite3OsVtbl *sqlite3_os_switch(void);
/*
** Redefine the OS interface to go through the virtual function table
** rather than calling routines directly.
*/
#undef sqlite3OsOpenReadWrite
#undef sqlite3OsOpenExclusive
#undef sqlite3OsOpenReadOnly
#undef sqlite3OsDelete
#undef sqlite3OsFileExists
#undef sqlite3OsFullPathname
#undef sqlite3OsIsDirWritable
#undef sqlite3OsSyncDirectory
#undef sqlite3OsTempFileName
#undef sqlite3OsRandomSeed
#undef sqlite3OsSleep
#undef sqlite3OsCurrentTime
#undef sqlite3OsEnterMutex
#undef sqlite3OsLeaveMutex
#undef sqlite3OsInMutex
#undef sqlite3OsThreadSpecificData
#undef sqlite3OsMalloc
#undef sqlite3OsRealloc
#undef sqlite3OsFree
#undef sqlite3OsAllocationSize
#define sqlite3OsOpenReadWrite sqlite3Os.xOpenReadWrite
#define sqlite3OsOpenExclusive sqlite3Os.xOpenExclusive
#define sqlite3OsOpenReadOnly sqlite3Os.xOpenReadOnly
#define sqlite3OsDelete sqlite3Os.xDelete
#define sqlite3OsFileExists sqlite3Os.xFileExists
#define sqlite3OsFullPathname sqlite3Os.xFullPathname
#define sqlite3OsIsDirWritable sqlite3Os.xIsDirWritable
#define sqlite3OsSyncDirectory sqlite3Os.xSyncDirectory
#define sqlite3OsTempFileName sqlite3Os.xTempFileName
#define sqlite3OsRandomSeed sqlite3Os.xRandomSeed
#define sqlite3OsSleep sqlite3Os.xSleep
#define sqlite3OsCurrentTime sqlite3Os.xCurrentTime
#define sqlite3OsEnterMutex sqlite3Os.xEnterMutex
#define sqlite3OsLeaveMutex sqlite3Os.xLeaveMutex
#define sqlite3OsInMutex sqlite3Os.xInMutex
#define sqlite3OsThreadSpecificData sqlite3Os.xThreadSpecificData
#define sqlite3OsMalloc sqlite3Os.xMalloc
#define sqlite3OsRealloc sqlite3Os.xRealloc
#define sqlite3OsFree sqlite3Os.xFree
#define sqlite3OsAllocationSize sqlite3Os.xAllocationSize
#endif /* SQLITE_ENABLE_REDEF_IO */
#endif /* _SQLITE_OS_H_ */

View File

@ -36,8 +36,8 @@
unsigned int sqlite3_pending_byte = 0x40000000;
#endif
int sqlite3_os_trace = 0;
#ifdef SQLITE_DEBUG
int sqlite3_os_trace = 0;
#define OSTRACE1(X) if( sqlite3_os_trace ) sqlite3DebugPrintf(X)
#define OSTRACE2(X,Y) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y)
#define OSTRACE3(X,Y,Z) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z)
@ -125,74 +125,3 @@ int sqlite3_open_file_count = 0;
#else
#define OpenCounter(X)
#endif
/*
** sqlite3GenericMalloc
** sqlite3GenericRealloc
** sqlite3GenericOsFree
** sqlite3GenericAllocationSize
**
** Implementation of the os level dynamic memory allocation interface in terms
** of the standard malloc(), realloc() and free() found in many operating
** systems. No rocket science here.
**
** There are two versions of these four functions here. The version
** implemented here is only used if memory-management or memory-debugging is
** enabled. This version allocates an extra 8-bytes at the beginning of each
** block and stores the size of the allocation there.
**
** If neither memory-management or debugging is enabled, the second
** set of implementations is used instead.
*/
#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || defined (SQLITE_MEMDEBUG)
void *sqlite3GenericMalloc(int n){
char *p = (char *)malloc(n+8);
assert(n>0);
assert(sizeof(int)<=8);
if( p ){
*(int *)p = n;
p += 8;
}
return (void *)p;
}
void *sqlite3GenericRealloc(void *p, int n){
char *p2 = ((char *)p - 8);
assert(n>0);
p2 = (char*)realloc(p2, n+8);
if( p2 ){
*(int *)p2 = n;
p2 += 8;
}
return (void *)p2;
}
void sqlite3GenericFree(void *p){
assert(p);
free((void *)((char *)p - 8));
}
int sqlite3GenericAllocationSize(void *p){
return p ? *(int *)((char *)p - 8) : 0;
}
#else
void *sqlite3GenericMalloc(int n){
char *p = (char *)malloc(n);
return (void *)p;
}
void *sqlite3GenericRealloc(void *p, int n){
assert(n>0);
p = realloc(p, n);
return p;
}
void sqlite3GenericFree(void *p){
assert(p);
free(p);
}
/* Never actually used, but needed for the linker */
int sqlite3GenericAllocationSize(void *p){ return 0; }
#endif
/*
** The default size of a disk sector
*/
#ifndef PAGER_SECTOR_SIZE
# define PAGER_SECTOR_SIZE 512
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -54,12 +54,11 @@ typedef struct PgHdr DbPage;
** See source code comments for a detailed description of the following
** routines:
*/
int sqlite3PagerOpen(Pager **ppPager, const char *zFilename,
int nExtra, int flags);
int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int);
void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler);
void sqlite3PagerSetDestructor(Pager*, void(*)(DbPage*,int));
void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int));
int sqlite3PagerSetPagesize(Pager*, int);
int sqlite3PagerSetPagesize(Pager*, u16*);
int sqlite3PagerMaxPageCount(Pager*, int);
int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
void sqlite3PagerSetCachesize(Pager*, int);
@ -86,6 +85,8 @@ void sqlite3PagerDontWrite(DbPage*);
int sqlite3PagerRefcount(Pager*);
void sqlite3PagerSetSafetyLevel(Pager*,int,int);
const char *sqlite3PagerFilename(Pager*);
const sqlite3_vfs *sqlite3PagerVfs(Pager*);
sqlite3_file *sqlite3PagerFile(Pager*);
const char *sqlite3PagerDirname(Pager*);
const char *sqlite3PagerJournalname(Pager*);
int sqlite3PagerNosync(Pager*);
@ -107,10 +108,6 @@ int sqlite3PagerLockingMode(Pager *, int);
int sqlite3PagerIswriteable(DbPage*);
#endif
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
int sqlite3PagerLockstate(Pager*);
#endif
#ifdef SQLITE_TEST
int *sqlite3PagerStats(Pager*);
void sqlite3PagerRefdump(Pager*);

File diff suppressed because it is too large Load Diff

View File

@ -14,18 +14,12 @@
** $Id$
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
/* Ignore this whole file if pragmas are disabled
*/
#if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER)
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
# include "pager.h"
# include "btree.h"
#endif
/*
** Interpret the given string as a safety level. Return 0 for OFF,
** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
@ -264,12 +258,12 @@ void sqlite3Pragma(
return;
}
zLeft = sqlite3NameFromToken(pId);
zLeft = sqlite3NameFromToken(db, pId);
if( !zLeft ) return;
if( minusFlag ){
zRight = sqlite3MPrintf("-%T", pValue);
zRight = sqlite3MPrintf(db, "-%T", pValue);
}else{
zRight = sqlite3NameFromToken(pValue);
zRight = sqlite3NameFromToken(db, pValue);
}
zDb = ((iDb>0)?pDb->zName:0);
@ -306,6 +300,7 @@ void sqlite3Pragma(
};
int addr;
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3VdbeUsesBtree(v, iDb);
if( !zRight ){
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P3_STATIC);
@ -342,7 +337,12 @@ void sqlite3Pragma(
int size = pBt ? sqlite3BtreeGetPageSize(pBt) : 0;
returnSingleInt(pParse, "page_size", size);
}else{
sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1);
/* Malloc may fail when setting the page-size, as there is an internal
** buffer that the pager module resizes using sqlite3_realloc().
*/
if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1) ){
db->mallocFailed = 1;
}
}
}else
@ -461,6 +461,7 @@ void sqlite3Pragma(
sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
sqlite3VdbeChangeP1(v, iAddr+5, iDb);
sqlite3VdbeUsesBtree(v, iDb);
}
}
}
@ -557,7 +558,9 @@ void sqlite3Pragma(
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
}
}else{
if( zRight[0] && !sqlite3OsIsDirWritable(zRight) ){
if( zRight[0]
&& !sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE)
){
sqlite3ErrorMsg(pParse, "not a writable directory");
goto pragma_out;
}
@ -567,7 +570,7 @@ void sqlite3Pragma(
){
invalidateTempStorage(pParse);
}
sqliteFree(sqlite3_temp_directory);
sqlite3_free(sqlite3_temp_directory);
if( zRight[0] ){
sqlite3_temp_directory = zRight;
zRight = 0;
@ -864,7 +867,7 @@ void sqlite3Pragma(
sqlite3VdbeAddOp(v, OP_IntegrityCk, 0, i);
addr = sqlite3VdbeAddOp(v, OP_IsNull, -1, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0,
sqlite3MPrintf("*** in database %s ***\n", db->aDb[i].zName),
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
P3_DYNAMIC);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
sqlite3VdbeAddOp(v, OP_Concat, 0, 0);
@ -1047,6 +1050,7 @@ void sqlite3Pragma(
){
int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */
sqlite3VdbeUsesBtree(v, iDb);
switch( zLeft[0] ){
case 's': case 'S':
iCookie = 0;
@ -1104,16 +1108,18 @@ void sqlite3Pragma(
for(i=0; i<db->nDb; i++){
Btree *pBt;
Pager *pPager;
const char *zState = "unknown";
int j;
if( db->aDb[i].zName==0 ) continue;
sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, P3_STATIC);
pBt = db->aDb[i].pBt;
if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){
sqlite3VdbeOp3(v, OP_String8, 0, 0, "closed", P3_STATIC);
}else{
int j = sqlite3PagerLockstate(pPager);
sqlite3VdbeOp3(v, OP_String8, 0, 0,
(j>=0 && j<=4) ? azLockName[j] : "unknown", P3_STATIC);
zState = "closed";
}else if( sqlite3_file_control(db, db->aDb[i].zName,
SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
zState = azLockName[j];
}
sqlite3VdbeOp3(v, OP_String8, 0, 0, zState, P3_STATIC);
sqlite3VdbeAddOp(v, OP_Callback, 2, 0);
}
}else
@ -1173,8 +1179,8 @@ void sqlite3Pragma(
#endif
}
pragma_out:
sqliteFree(zLeft);
sqliteFree(zRight);
sqlite3_free(zLeft);
sqlite3_free(zRight);
}
#endif /* SQLITE_OMIT_PRAGMA || SQLITE_OMIT_PARSER */

View File

@ -16,7 +16,6 @@
** $Id$
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
/*
@ -24,7 +23,7 @@
** that the database is corrupt.
*/
static void corruptSchema(InitData *pData, const char *zExtra){
if( !sqlite3MallocFailed() ){
if( !pData->db->mallocFailed ){
sqlite3SetString(pData->pzErrMsg, "malformed database schema",
zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
}
@ -48,9 +47,10 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){
sqlite3 *db = pData->db;
int iDb = pData->iDb;
assert( sqlite3_mutex_held(db->mutex) );
pData->rc = SQLITE_OK;
DbClearProperty(db, iDb, DB_Empty);
if( sqlite3MallocFailed() ){
if( db->mallocFailed ){
corruptSchema(pData, 0);
return SQLITE_NOMEM;
}
@ -79,7 +79,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){
if( SQLITE_OK!=rc ){
pData->rc = rc;
if( rc==SQLITE_NOMEM ){
sqlite3FailedMalloc();
db->mallocFailed = 1;
}else if( rc!=SQLITE_INTERRUPT ){
corruptSchema(pData, zErr);
}
@ -157,6 +157,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pSchema );
assert( sqlite3_mutex_held(db->mutex) );
/* zMasterSchema and zInitScript are set to point at the master schema
** and initialisation script appropriate for the database being
@ -181,7 +182,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
rc = sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
if( rc ){
sqlite3SafetyOn(db);
return initData.rc;
rc = initData.rc;
goto error_out;
}
pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
if( pTab ){
@ -198,10 +200,12 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
}
return SQLITE_OK;
}
sqlite3BtreeEnter(pDb->pBt);
rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, 0, &curMain);
if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){
sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
return rc;
sqlite3BtreeLeave(pDb->pBt);
goto error_out;
}
/* Get the database meta information.
@ -229,7 +233,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
if( rc ){
sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
sqlite3BtreeCloseCursor(curMain);
return rc;
sqlite3BtreeLeave(pDb->pBt);
goto error_out;
}
}else{
memset(meta, 0, sizeof(meta));
@ -252,6 +257,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "attached databases must use the same"
" text encoding as main database", (char*)0);
sqlite3BtreeLeave(pDb->pBt);
return SQLITE_ERROR;
}
}
@ -278,6 +284,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){
sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
sqlite3BtreeLeave(pDb->pBt);
return SQLITE_ERROR;
}
@ -290,14 +297,14 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
rc = SQLITE_OK;
}else{
char *zSql;
zSql = sqlite3MPrintf(
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s",
db->aDb[iDb].zName, zMasterName);
sqlite3SafetyOff(db);
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
if( rc==SQLITE_ABORT ) rc = initData.rc;
sqlite3SafetyOn(db);
sqliteFree(zSql);
sqlite3_free(zSql);
#ifndef SQLITE_OMIT_ANALYZE
if( rc==SQLITE_OK ){
sqlite3AnalysisLoad(db, iDb);
@ -305,7 +312,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
#endif
sqlite3BtreeCloseCursor(curMain);
}
if( sqlite3MallocFailed() ){
if( db->mallocFailed ){
/* sqlite3SetString(pzErrMsg, "out of memory", (char*)0); */
rc = SQLITE_NOMEM;
sqlite3ResetInternalSchema(db, 0);
@ -322,6 +329,12 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
DbSetProperty(db, iDb, DB_SchemaLoaded);
rc = SQLITE_OK;
}
sqlite3BtreeLeave(pDb->pBt);
error_out:
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
db->mallocFailed = 1;
}
return rc;
}
@ -337,8 +350,9 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
*/
int sqlite3Init(sqlite3 *db, char **pzErrMsg){
int i, rc;
int called_initone = 0;
int commit_internal = !(db->flags&SQLITE_InternChanges);
assert( sqlite3_mutex_held(db->mutex) );
if( db->init.busy ) return SQLITE_OK;
rc = SQLITE_OK;
db->init.busy = 1;
@ -348,7 +362,6 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
if( rc ){
sqlite3ResetInternalSchema(db, i);
}
called_initone = 1;
}
/* Once all the other databases have been initialised, load the schema
@ -361,12 +374,11 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
if( rc ){
sqlite3ResetInternalSchema(db, 1);
}
called_initone = 1;
}
#endif
db->init.busy = 0;
if( rc==SQLITE_OK && called_initone ){
if( rc==SQLITE_OK && commit_internal ){
sqlite3CommitInternalChanges(db);
}
@ -380,6 +392,7 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
int sqlite3ReadSchema(Parse *pParse){
int rc = SQLITE_OK;
sqlite3 *db = pParse->db;
assert( sqlite3_mutex_held(db->mutex) );
if( !db->init.busy ){
rc = sqlite3Init(db, &pParse->zErrMsg);
}
@ -402,6 +415,7 @@ static int schemaIsValid(sqlite3 *db){
int cookie;
int allOk = 1;
assert( sqlite3_mutex_held(db->mutex) );
for(iDb=0; allOk && iDb<db->nDb; iDb++){
Btree *pBt;
pBt = db->aDb[iDb].pBt;
@ -414,6 +428,9 @@ static int schemaIsValid(sqlite3 *db){
}
sqlite3BtreeCloseCursor(curTemp);
}
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
db->mallocFailed = 1;
}
}
return allOk;
}
@ -438,6 +455,7 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
** more likely to cause a segfault than -1 (of course there are assert()
** statements too, but it never hurts to play the odds).
*/
assert( sqlite3_mutex_held(db->mutex) );
if( pSchema ){
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pSchema==pSchema ){
@ -465,25 +483,28 @@ int sqlite3Prepare(
int rc = SQLITE_OK;
int i;
/* Assert that malloc() has not failed */
assert( !sqlite3MallocFailed() );
assert( ppStmt );
*ppStmt = 0;
if( sqlite3SafetyOn(db) ){
return SQLITE_MISUSE;
}
assert( !db->mallocFailed );
assert( sqlite3_mutex_held(db->mutex) );
/* If any attached database schemas are locked, do not proceed with
** compilation. Instead return SQLITE_LOCKED immediately.
*/
for(i=0; i<db->nDb; i++) {
Btree *pBt = db->aDb[i].pBt;
if( pBt && sqlite3BtreeSchemaLocked(pBt) ){
const char *zDb = db->aDb[i].zName;
sqlite3Error(db, SQLITE_LOCKED, "database schema is locked: %s", zDb);
sqlite3SafetyOff(db);
return SQLITE_LOCKED;
if( pBt ){
int rc;
rc = sqlite3BtreeSchemaLocked(pBt);
if( rc ){
const char *zDb = db->aDb[i].zName;
sqlite3Error(db, SQLITE_LOCKED, "database schema is locked: %s", zDb);
sqlite3SafetyOff(db);
return SQLITE_LOCKED;
}
}
}
@ -494,17 +515,17 @@ int sqlite3Prepare(
if( nBytes>SQLITE_MAX_SQL_LENGTH ){
return SQLITE_TOOBIG;
}
zSqlCopy = sqlite3StrNDup(zSql, nBytes);
zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
if( zSqlCopy ){
sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
sqliteFree(zSqlCopy);
sqlite3_free(zSqlCopy);
}
sParse.zTail = &zSql[nBytes];
}else{
sqlite3RunParser(&sParse, zSql, &zErrMsg);
}
if( sqlite3MallocFailed() ){
if( db->mallocFailed ){
sParse.rc = SQLITE_NOMEM;
}
if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
@ -514,7 +535,7 @@ int sqlite3Prepare(
if( sParse.rc==SQLITE_SCHEMA ){
sqlite3ResetInternalSchema(db, 0);
}
if( sqlite3MallocFailed() ){
if( db->mallocFailed ){
sParse.rc = SQLITE_NOMEM;
}
if( pzTail ){
@ -547,7 +568,7 @@ int sqlite3Prepare(
if( saveSqlFlag ){
sqlite3VdbeSetSql(sParse.pVdbe, zSql, sParse.zTail - zSql);
}
if( rc!=SQLITE_OK || sqlite3MallocFailed() ){
if( rc!=SQLITE_OK || db->mallocFailed ){
sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
assert(!(*ppStmt));
}else{
@ -556,16 +577,35 @@ int sqlite3Prepare(
if( zErrMsg ){
sqlite3Error(db, rc, "%s", zErrMsg);
sqliteFree(zErrMsg);
sqlite3_free(zErrMsg);
}else{
sqlite3Error(db, rc, 0);
}
rc = sqlite3ApiExit(db, rc);
sqlite3ReleaseThreadData();
/* sqlite3ReleaseThreadData(); */
assert( (rc&db->errMask)==rc );
return rc;
}
static int sqlite3LockAndPrepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
){
int rc;
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail);
sqlite3BtreeLeaveAll(db);
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*
** Rerun the compilation of a statement after a schema change.
@ -577,13 +617,15 @@ int sqlite3Reprepare(Vdbe *p){
sqlite3_stmt *pNew;
const char *zSql;
sqlite3 *db;
assert( sqlite3_mutex_held(sqlite3VdbeDb(p)->mutex) );
zSql = sqlite3VdbeGetSql(p);
if( zSql==0 ){
return 0;
}
db = sqlite3VdbeDb(p);
rc = sqlite3Prepare(db, zSql, -1, 0, &pNew, 0);
assert( sqlite3_mutex_held(db->mutex) );
rc = sqlite3LockAndPrepare(db, zSql, -1, 0, &pNew, 0);
if( rc ){
assert( pNew==0 );
return 0;
@ -613,7 +655,7 @@ int sqlite3_prepare(
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
){
return sqlite3Prepare(db,zSql,nBytes,0,ppStmt,pzTail);
return sqlite3LockAndPrepare(db,zSql,nBytes,0,ppStmt,pzTail);
}
int sqlite3_prepare_v2(
sqlite3 *db, /* Database handle. */
@ -622,7 +664,7 @@ int sqlite3_prepare_v2(
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
){
return sqlite3Prepare(db,zSql,nBytes,1,ppStmt,pzTail);
return sqlite3LockAndPrepare(db,zSql,nBytes,1,ppStmt,pzTail);
}
@ -649,9 +691,10 @@ static int sqlite3Prepare16(
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
zSql8 = sqlite3Utf16to8(zSql, nBytes);
sqlite3_mutex_enter(db->mutex);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes);
if( zSql8 ){
rc = sqlite3Prepare(db, zSql8, -1, saveSqlFlag, ppStmt, &zTail8);
rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, ppStmt, &zTail8);
}
if( zTail8 && pzTail ){
@ -663,8 +706,10 @@ static int sqlite3Prepare16(
int chars_parsed = sqlite3Utf8CharLen(zSql8, zTail8-zSql8);
*pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
}
sqliteFree(zSql8);
return sqlite3ApiExit(db, rc);
sqlite3_free(zSql8);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*

View File

@ -113,7 +113,7 @@ static const et_info fmtinfo[] = {
{ 'd', 10, 1, etRADIX, 0, 0 },
{ 's', 0, 4, etSTRING, 0, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 },
{ 'z', 0, 6, etDYNSTRING, 0, 0 },
{ 'z', 0, 4, etDYNSTRING, 0, 0 },
{ 'q', 0, 4, etSQLESCAPE, 0, 0 },
{ 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
{ 'w', 0, 4, etSQLESCAPE3, 0, 0 },
@ -627,7 +627,7 @@ static int vxprintf(
needQuote = !isnull && xtype==etSQLESCAPE2;
n += i + 1 + needQuote*2;
if( n>etBUFSIZE ){
bufpt = zExtra = sqliteMalloc( n );
bufpt = zExtra = sqlite3_malloc( n );
if( bufpt==0 ) return -1;
}else{
bufpt = buf;
@ -701,7 +701,7 @@ static int vxprintf(
}
}
if( zExtra ){
sqliteFree(zExtra);
sqlite3_free(zExtra);
}
}/* End for loop over the format string */
return errorflag ? -1 : count;
@ -718,6 +718,7 @@ struct sgMprintf {
int nTotal; /* Output size if unconstrained */
int nAlloc; /* Amount of space allocated in zText */
void *(*xRealloc)(void*,int); /* Function used to realloc memory */
int iMallocFailed; /* True if xRealloc() has failed */
};
/*
@ -728,30 +729,39 @@ struct sgMprintf {
*/
static void mout(void *arg, const char *zNewText, int nNewChar){
struct sgMprintf *pM = (struct sgMprintf*)arg;
if( pM->iMallocFailed ) return;
pM->nTotal += nNewChar;
if( pM->nChar + nNewChar + 1 > pM->nAlloc ){
if( pM->xRealloc==0 ){
nNewChar = pM->nAlloc - pM->nChar - 1;
}else{
int nAlloc = pM->nChar + nNewChar*2 + 1;
if( pM->zText==pM->zBase ){
pM->zText = pM->xRealloc(0, nAlloc);
if( pM->zText && pM->nChar ){
memcpy(pM->zText, pM->zBase, pM->nChar);
}
}else{
char *zNew;
zNew = pM->xRealloc(pM->zText, nAlloc);
if( zNew ){
pM->zText = zNew;
}else{
return;
}
}
pM->nAlloc = nAlloc;
}
}
if( pM->zText ){
if( pM->nChar + nNewChar + 1 > pM->nAlloc ){
if( pM->xRealloc==0 ){
nNewChar = pM->nAlloc - pM->nChar - 1;
}else{
int nAlloc = pM->nChar + nNewChar*2 + 1;
if( pM->zText==pM->zBase ){
pM->zText = pM->xRealloc(0, nAlloc);
if( pM->zText==0 ){
pM->nAlloc = 0;
pM->iMallocFailed = 1;
return;
}else if( pM->nChar ){
memcpy(pM->zText, pM->zBase, pM->nChar);
}
}else{
char *zNew;
zNew = pM->xRealloc(pM->zText, nAlloc);
if( zNew ){
pM->zText = zNew;
}else{
pM->iMallocFailed = 1;
pM->xRealloc(pM->zText, 0);
pM->zText = 0;
pM->nAlloc = 0;
return;
}
}
pM->nAlloc = nAlloc;
}
}
if( nNewChar>0 ){
memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
pM->nChar += nNewChar;
@ -765,7 +775,7 @@ static void mout(void *arg, const char *zNewText, int nNewChar){
** the consumer.
*/
static char *base_vprintf(
void *(*xRealloc)(void*,int), /* Routine to realloc memory. May be NULL */
void *(*xRealloc)(void*, int), /* realloc() function. May be NULL */
int useInternal, /* Use internal %-conversions if true */
char *zInitBuf, /* Initially write here, before mallocing */
int nInitBuf, /* Size of zInitBuf[] */
@ -777,15 +787,19 @@ static char *base_vprintf(
sM.nChar = sM.nTotal = 0;
sM.nAlloc = nInitBuf;
sM.xRealloc = xRealloc;
sM.iMallocFailed = 0;
vxprintf(mout, &sM, useInternal, zFormat, ap);
if( xRealloc ){
assert(sM.iMallocFailed==0 || sM.zText==0);
if( xRealloc && !sM.iMallocFailed ){
if( sM.zText==sM.zBase ){
sM.zText = xRealloc(0, sM.nChar+1);
if( sM.zText ){
memcpy(sM.zText, sM.zBase, sM.nChar+1);
}
}else if( sM.nAlloc>sM.nChar+10 ){
char *zNew = xRealloc(sM.zText, sM.nChar+1);
char *zNew;
sqlite3MallocBenignFailure(1);
zNew = xRealloc(sM.zText, sM.nChar+1);
if( zNew ){
sM.zText = zNew;
}
@ -798,29 +812,37 @@ static char *base_vprintf(
** Realloc that is a real function, not a macro.
*/
static void *printf_realloc(void *old, int size){
return sqliteRealloc(old,size);
return sqlite3_realloc(old, size);
}
/*
** Print into memory obtained from sqliteMalloc(). Use the internal
** %-conversion extensions.
*/
char *sqlite3VMPrintf(const char *zFormat, va_list ap){
char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
char *z;
char zBase[SQLITE_PRINT_BUF_SIZE];
return base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
if( z==0 && db!=0 ){
db->mallocFailed = 1;
}
return z;
}
/*
** Print into memory obtained from sqliteMalloc(). Use the internal
** %-conversion extensions.
*/
char *sqlite3MPrintf(const char *zFormat, ...){
char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){
va_list ap;
char *z;
char zBase[SQLITE_PRINT_BUF_SIZE];
va_start(ap, zFormat);
z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
va_end(ap);
if( z==0 && db!=0 ){
db->mallocFailed = 1;
}
return z;
}

View File

@ -18,7 +18,6 @@
** $Id$
*/
#include "sqliteInt.h"
#include "os.h"
/*
@ -63,7 +62,7 @@ static int randomByte(void){
char k[256];
prng.j = 0;
prng.i = 0;
sqlite3OsRandomSeed(k);
sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
for(i=0; i<256; i++){
prng.s[i] = i;
}
@ -92,9 +91,13 @@ static int randomByte(void){
*/
void sqlite3Randomness(int N, void *pBuf){
unsigned char *zBuf = pBuf;
sqlite3OsEnterMutex();
static sqlite3_mutex *mutex = 0;
if( mutex==0 ){
mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG);
}
sqlite3_mutex_enter(mutex);
while( N-- ){
*(zBuf++) = randomByte();
}
sqlite3OsLeaveMutex();
sqlite3_mutex_leave(mutex);
}

View File

@ -39,6 +39,7 @@ static void clearSelect(Select *p){
** structure.
*/
Select *sqlite3SelectNew(
Parse *pParse, /* Parsing context */
ExprList *pEList, /* which columns to include in the result */
SrcList *pSrc, /* the FROM clause -- which tables to scan */
Expr *pWhere, /* the WHERE clause */
@ -51,14 +52,15 @@ Select *sqlite3SelectNew(
){
Select *pNew;
Select standin;
pNew = sqliteMalloc( sizeof(*pNew) );
sqlite3 *db = pParse->db;
pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
assert( !pOffset || pLimit ); /* Can't have OFFSET without LIMIT. */
if( pNew==0 ){
pNew = &standin;
memset(pNew, 0, sizeof(*pNew));
}
if( pEList==0 ){
pEList = sqlite3ExprListAppend(0, sqlite3Expr(TK_ALL,0,0,0), 0);
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0,0,0), 0);
}
pNew->pEList = pEList;
pNew->pSrc = pSrc;
@ -89,7 +91,7 @@ Select *sqlite3SelectNew(
void sqlite3SelectDelete(Select *p){
if( p ){
clearSelect(p);
sqliteFree(p);
sqlite3_free(p);
}
}
@ -191,21 +193,23 @@ static void setToken(Token *p, const char *z){
**
** {a"bc} -> {"a""bc"}
*/
static void setQuotedToken(Token *p, const char *z){
p->z = (u8 *)sqlite3MPrintf("\"%w\"", z);
static void setQuotedToken(Parse *pParse, Token *p, const char *z){
p->z = (u8 *)sqlite3MPrintf(0, "\"%w\"", z);
p->dyn = 1;
if( p->z ){
p->n = strlen((char *)p->z);
}else{
pParse->db->mallocFailed = 1;
}
}
/*
** Create an expression node for an identifier with the name of zName
*/
Expr *sqlite3CreateIdExpr(const char *zName){
Expr *sqlite3CreateIdExpr(Parse *pParse, const char *zName){
Token dummy;
setToken(&dummy, zName);
return sqlite3Expr(TK_ID, 0, 0, &dummy);
return sqlite3PExpr(pParse, TK_ID, 0, 0, &dummy);
}
@ -214,6 +218,7 @@ Expr *sqlite3CreateIdExpr(const char *zName){
** zCol column to be equal in the two tables pTab1 and pTab2.
*/
static void addWhereTerm(
Parse *pParse, /* Parsing context */
const char *zCol, /* Name of the column */
const Table *pTab1, /* First table */
const char *zAlias1, /* Alias for first table. May be NULL */
@ -226,24 +231,24 @@ static void addWhereTerm(
Expr *pE2a, *pE2b, *pE2c;
Expr *pE;
pE1a = sqlite3CreateIdExpr(zCol);
pE2a = sqlite3CreateIdExpr(zCol);
pE1a = sqlite3CreateIdExpr(pParse, zCol);
pE2a = sqlite3CreateIdExpr(pParse, zCol);
if( zAlias1==0 ){
zAlias1 = pTab1->zName;
}
pE1b = sqlite3CreateIdExpr(zAlias1);
pE1b = sqlite3CreateIdExpr(pParse, zAlias1);
if( zAlias2==0 ){
zAlias2 = pTab2->zName;
}
pE2b = sqlite3CreateIdExpr(zAlias2);
pE1c = sqlite3ExprOrFree(TK_DOT, pE1b, pE1a, 0);
pE2c = sqlite3ExprOrFree(TK_DOT, pE2b, pE2a, 0);
pE = sqlite3ExprOrFree(TK_EQ, pE1c, pE2c, 0);
pE2b = sqlite3CreateIdExpr(pParse, zAlias2);
pE1c = sqlite3PExpr(pParse, TK_DOT, pE1b, pE1a, 0);
pE2c = sqlite3PExpr(pParse, TK_DOT, pE2b, pE2a, 0);
pE = sqlite3PExpr(pParse, TK_EQ, pE1c, pE2c, 0);
if( pE ){
ExprSetProperty(pE, EP_FromJoin);
pE->iRightJoinTable = iRightJoinTable;
}
pE = sqlite3ExprAnd(*ppExpr, pE);
pE = sqlite3ExprAnd(pParse->db,*ppExpr, pE);
if( pE ){
*ppExpr = pE;
}
@ -325,7 +330,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
for(j=0; j<pLeftTab->nCol; j++){
char *zName = pLeftTab->aCol[j].zName;
if( columnIndex(pRightTab, zName)>=0 ){
addWhereTerm(zName, pLeftTab, pLeft->zAlias,
addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias,
pRightTab, pRight->zAlias,
pRight->iCursor, &p->pWhere);
@ -346,7 +351,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
*/
if( pRight->pOn ){
setJoinExpr(pRight->pOn, pRight->iCursor);
p->pWhere = sqlite3ExprAnd(p->pWhere, pRight->pOn);
p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn);
pRight->pOn = 0;
}
@ -366,7 +371,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
"not present in both tables", zName);
return 1;
}
addWhereTerm(zName, pLeftTab, pLeft->zAlias,
addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias,
pRightTab, pRight->zAlias,
pRight->iCursor, &p->pWhere);
}
@ -689,7 +694,7 @@ static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){
int i;
nExpr = pList->nExpr;
pInfo = sqliteMalloc( sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) );
pInfo = sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) );
if( pInfo ){
pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr];
pInfo->nField = nExpr;
@ -992,7 +997,7 @@ static void generateColumnNames(
#endif
assert( v!=0 );
if( pParse->colNamesSet || v==0 || sqlite3MallocFailed() ) return;
if( pParse->colNamesSet || v==0 || db->mallocFailed ) return;
pParse->colNamesSet = 1;
fullNames = (db->flags & SQLITE_FullColNames)!=0;
shortNames = (db->flags & SQLITE_ShortColNames)!=0;
@ -1076,6 +1081,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
int i, j;
ExprList *pEList;
Column *aCol, *pCol;
sqlite3 *db = pParse->db;
while( pSelect->pPrior ) pSelect = pSelect->pPrior;
if( prepSelectStmt(pParse, pSelect) ){
@ -1084,16 +1090,16 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
if( sqlite3SelectResolve(pParse, pSelect, 0) ){
return 0;
}
pTab = sqliteMalloc( sizeof(Table) );
pTab = sqlite3DbMallocZero(db, sizeof(Table) );
if( pTab==0 ){
return 0;
}
pTab->nRef = 1;
pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0;
pTab->zName = zTabName ? sqlite3DbStrDup(db, zTabName) : 0;
pEList = pSelect->pEList;
pTab->nCol = pEList->nExpr;
assert( pTab->nCol>0 );
pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
pTab->aCol = aCol = sqlite3DbMallocZero(db, sizeof(pTab->aCol[0])*pTab->nCol);
for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){
Expr *p, *pR;
char *zType;
@ -1109,24 +1115,25 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 );
if( (zName = pEList->a[i].zName)!=0 ){
/* If the column contains an "AS <name>" phrase, use <name> as the name */
zName = sqliteStrDup(zName);
zName = sqlite3DbStrDup(db, zName);
}else if( p->op==TK_DOT
&& (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
/* For columns of the from A.B use B as the name */
zName = sqlite3MPrintf("%T", &pR->token);
zName = sqlite3MPrintf(db, "%T", &pR->token);
}else if( p->span.z && p->span.z[0] ){
/* Use the original text of the column expression as its name */
zName = sqlite3MPrintf("%T", &p->span);
zName = sqlite3MPrintf(db, "%T", &p->span);
}else{
/* If all else fails, make up a name */
zName = sqlite3MPrintf("column%d", i+1);
zName = sqlite3MPrintf(db, "column%d", i+1);
}
sqlite3Dequote(zName);
if( sqlite3MallocFailed() ){
sqliteFree(zName);
if( !zName || db->mallocFailed ){
db->mallocFailed = 1;
sqlite3_free(zName);
sqlite3DeleteTable(pTab);
return 0;
}
sqlite3Dequote(zName);
/* Make sure the column name is unique. If the name is not unique,
** append a integer to the name so that it becomes unique.
@ -1135,7 +1142,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
for(j=cnt=0; j<i; j++){
if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
zName[nName] = 0;
zName = sqlite3MPrintf("%z:%d", zName, ++cnt);
zName = sqlite3MPrintf(db, "%z:%d", zName, ++cnt);
j = -1;
if( zName==0 ) break;
}
@ -1147,12 +1154,12 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
*/
memset(&sNC, 0, sizeof(sNC));
sNC.pSrcList = pSelect->pSrc;
zType = sqliteStrDup(columnType(&sNC, p, 0, 0, 0));
zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
pCol->zType = zType;
pCol->affinity = sqlite3ExprAffinity(p);
pColl = sqlite3ExprCollSeq(pParse, p);
if( pColl ){
pCol->zColl = sqliteStrDup(pColl->zName);
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
}
}
pTab->iPKey = -1;
@ -1190,8 +1197,9 @@ static int prepSelectStmt(Parse *pParse, Select *p){
SrcList *pTabList;
ExprList *pEList;
struct SrcList_item *pFrom;
sqlite3 *db = pParse->db;
if( p==0 || p->pSrc==0 || sqlite3MallocFailed() ){
if( p==0 || p->pSrc==0 || db->mallocFailed ){
return 1;
}
pTabList = p->pSrc;
@ -1220,7 +1228,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){
assert( pFrom->pSelect!=0 );
if( pFrom->zAlias==0 ){
pFrom->zAlias =
sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect);
sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pFrom->pSelect);
}
assert( pFrom->pTab==0 );
pFrom->pTab = pTab =
@ -1255,7 +1263,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){
** in the inner view.
*/
if( pFrom->pSelect==0 ){
pFrom->pSelect = sqlite3SelectDup(pTab->pSelect);
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect);
}
}
#endif
@ -1301,7 +1309,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){
(pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
/* This particular expression does not need to be expanded.
*/
pNew = sqlite3ExprListAppend(pNew, a[k].pExpr, 0);
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0);
if( pNew ){
pNew->a[pNew->nExpr-1].zName = a[k].zName;
}else{
@ -1315,7 +1323,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){
int tableSeen = 0; /* Set to 1 when TABLE matches */
char *zTName; /* text of name of TABLE */
if( pE->op==TK_DOT && pE->pLeft ){
zTName = sqlite3NameFromToken(&pE->pLeft->token);
zTName = sqlite3NameFromToken(db, &pE->pLeft->token);
}else{
zTName = 0;
}
@ -1357,15 +1365,16 @@ static int prepSelectStmt(Parse *pParse, Select *p){
continue;
}
}
pRight = sqlite3Expr(TK_ID, 0, 0, 0);
pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
if( pRight==0 ) break;
setQuotedToken(&pRight->token, zName);
setQuotedToken(pParse, &pRight->token, zName);
if( zTabName && (longNames || pTabList->nSrc>1) ){
Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, 0);
pExpr = sqlite3Expr(TK_DOT, pLeft, pRight, 0);
Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
if( pExpr==0 ) break;
setQuotedToken(&pLeft->token, zTabName);
setToken(&pExpr->span, sqlite3MPrintf("%s.%s", zTabName, zName));
setQuotedToken(pParse, &pLeft->token, zTabName);
setToken(&pExpr->span,
sqlite3MPrintf(db, "%s.%s", zTabName, zName));
pExpr->span.dyn = 1;
pExpr->token.z = 0;
pExpr->token.n = 0;
@ -1376,9 +1385,9 @@ static int prepSelectStmt(Parse *pParse, Select *p){
pExpr->span.dyn = 0;
}
if( longNames ){
pNew = sqlite3ExprListAppend(pNew, pExpr, &pExpr->span);
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span);
}else{
pNew = sqlite3ExprListAppend(pNew, pExpr, &pRight->token);
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token);
}
}
}
@ -1390,7 +1399,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){
}
rc = 1;
}
sqliteFree(zTName);
sqlite3_free(zTName);
}
}
sqlite3ExprListDelete(pEList);
@ -1400,7 +1409,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){
sqlite3ErrorMsg(pParse, "too many columns in result set");
rc = SQLITE_ERROR;
}
if( sqlite3MallocFailed() ){
if( db->mallocFailed ){
rc = SQLITE_NOMEM;
}
return rc;
@ -1430,6 +1439,7 @@ static int matchOrderbyToColumn(
int nErr = 0;
int i, j;
ExprList *pEList;
sqlite3 *db = pParse->db;
if( pSelect==0 || pOrderBy==0 ) return 1;
if( mustComplete ){
@ -1462,23 +1472,23 @@ static int matchOrderbyToColumn(
if( !mustComplete ) continue;
iCol--;
}
if( iCol<0 && (zLabel = sqlite3NameFromToken(&pE->token))!=0 ){
if( iCol<0 && (zLabel = sqlite3NameFromToken(db, &pE->token))!=0 ){
for(j=0, pItem=pEList->a; j<pEList->nExpr; j++, pItem++){
char *zName;
int isMatch;
if( pItem->zName ){
zName = sqlite3StrDup(pItem->zName);
zName = sqlite3DbStrDup(db, pItem->zName);
}else{
zName = sqlite3NameFromToken(&pItem->pExpr->token);
zName = sqlite3NameFromToken(db, &pItem->pExpr->token);
}
isMatch = zName && sqlite3StrICmp(zName, zLabel)==0;
sqliteFree(zName);
sqlite3_free(zName);
if( isMatch ){
iCol = j;
break;
}
}
sqliteFree(zLabel);
sqlite3_free(zLabel);
}
if( iCol>=0 ){
pE->op = TK_COLUMN;
@ -1962,7 +1972,8 @@ static int multiSelect(
assert( p->pRightmost==p );
nKeyCol = nCol + (pOrderBy ? pOrderBy->nExpr : 0);
pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nKeyCol*(sizeof(CollSeq*) + 1));
pKeyInfo = sqlite3DbMallocZero(pParse->db,
sizeof(*pKeyInfo)+nKeyCol*(sizeof(CollSeq*) + 1));
if( !pKeyInfo ){
rc = SQLITE_NOMEM;
goto multi_select_end;
@ -2037,7 +2048,7 @@ static int multiSelect(
generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm);
}
sqliteFree(pKeyInfo);
sqlite3_free(pKeyInfo);
}
multi_select_end:
@ -2046,6 +2057,10 @@ multi_select_end:
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
#ifndef SQLITE_OMIT_VIEW
/* Forward Declarations */
static void substExprList(sqlite3*, ExprList*, int, ExprList*);
static void substSelect(sqlite3*, Select *, int, ExprList *);
/*
** Scan through the expression pExpr. Replace every reference to
** a column in table number iTable with a copy of the iColumn-th
@ -2059,9 +2074,12 @@ multi_select_end:
** changes to pExpr so that it refers directly to the source table
** of the subquery rather the result set of the subquery.
*/
static void substExprList(ExprList*,int,ExprList*); /* Forward Decl */
static void substSelect(Select *, int, ExprList *); /* Forward Decl */
static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
static void substExpr(
sqlite3 *db, /* Report malloc errors to this connection */
Expr *pExpr, /* Expr in which substitution occurs */
int iTable, /* Table to be substituted */
ExprList *pEList /* Substitute expressions */
){
if( pExpr==0 ) return;
if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
if( pExpr->iColumn<0 ){
@ -2074,42 +2092,52 @@ static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
assert( pNew!=0 );
pExpr->op = pNew->op;
assert( pExpr->pLeft==0 );
pExpr->pLeft = sqlite3ExprDup(pNew->pLeft);
pExpr->pLeft = sqlite3ExprDup(db, pNew->pLeft);
assert( pExpr->pRight==0 );
pExpr->pRight = sqlite3ExprDup(pNew->pRight);
pExpr->pRight = sqlite3ExprDup(db, pNew->pRight);
assert( pExpr->pList==0 );
pExpr->pList = sqlite3ExprListDup(pNew->pList);
pExpr->pList = sqlite3ExprListDup(db, pNew->pList);
pExpr->iTable = pNew->iTable;
pExpr->pTab = pNew->pTab;
pExpr->iColumn = pNew->iColumn;
pExpr->iAgg = pNew->iAgg;
sqlite3TokenCopy(&pExpr->token, &pNew->token);
sqlite3TokenCopy(&pExpr->span, &pNew->span);
pExpr->pSelect = sqlite3SelectDup(pNew->pSelect);
sqlite3TokenCopy(db, &pExpr->token, &pNew->token);
sqlite3TokenCopy(db, &pExpr->span, &pNew->span);
pExpr->pSelect = sqlite3SelectDup(db, pNew->pSelect);
pExpr->flags = pNew->flags;
}
}else{
substExpr(pExpr->pLeft, iTable, pEList);
substExpr(pExpr->pRight, iTable, pEList);
substSelect(pExpr->pSelect, iTable, pEList);
substExprList(pExpr->pList, iTable, pEList);
substExpr(db, pExpr->pLeft, iTable, pEList);
substExpr(db, pExpr->pRight, iTable, pEList);
substSelect(db, pExpr->pSelect, iTable, pEList);
substExprList(db, pExpr->pList, iTable, pEList);
}
}
static void substExprList(ExprList *pList, int iTable, ExprList *pEList){
static void substExprList(
sqlite3 *db, /* Report malloc errors here */
ExprList *pList, /* List to scan and in which to make substitutes */
int iTable, /* Table to be substituted */
ExprList *pEList /* Substitute values */
){
int i;
if( pList==0 ) return;
for(i=0; i<pList->nExpr; i++){
substExpr(pList->a[i].pExpr, iTable, pEList);
substExpr(db, pList->a[i].pExpr, iTable, pEList);
}
}
static void substSelect(Select *p, int iTable, ExprList *pEList){
static void substSelect(
sqlite3 *db, /* Report malloc errors here */
Select *p, /* SELECT statement in which to make substitutions */
int iTable, /* Table to be replaced */
ExprList *pEList /* Substitute values */
){
if( !p ) return;
substExprList(p->pEList, iTable, pEList);
substExprList(p->pGroupBy, iTable, pEList);
substExprList(p->pOrderBy, iTable, pEList);
substExpr(p->pHaving, iTable, pEList);
substExpr(p->pWhere, iTable, pEList);
substSelect(p->pPrior, iTable, pEList);
substExprList(db, p->pEList, iTable, pEList);
substExprList(db, p->pGroupBy, iTable, pEList);
substExprList(db, p->pOrderBy, iTable, pEList);
substExpr(db, p->pHaving, iTable, pEList);
substExpr(db, p->pWhere, iTable, pEList);
substSelect(db, p->pPrior, iTable, pEList);
}
#endif /* !defined(SQLITE_OMIT_VIEW) */
@ -2192,6 +2220,7 @@ static void substSelect(Select *p, int iTable, ExprList *pEList){
** the subquery before this routine runs.
*/
static int flattenSubquery(
sqlite3 *db, /* Database connection */
Select *p, /* The parent or outer SELECT statement */
int iFrom, /* Index in p->pSrc->a[] of the inner subquery */
int isAgg, /* True if outer SELECT uses aggregate functions */
@ -2289,13 +2318,13 @@ static int flattenSubquery(
int jointype = pSubitem->jointype;
sqlite3DeleteTable(pSubitem->pTab);
sqliteFree(pSubitem->zDatabase);
sqliteFree(pSubitem->zName);
sqliteFree(pSubitem->zAlias);
sqlite3_free(pSubitem->zDatabase);
sqlite3_free(pSubitem->zName);
sqlite3_free(pSubitem->zAlias);
if( nSubSrc>1 ){
int extra = nSubSrc - 1;
for(i=1; i<nSubSrc; i++){
pSrc = sqlite3SrcListAppend(pSrc, 0, 0);
pSrc = sqlite3SrcListAppend(db, pSrc, 0, 0);
}
p->pSrc = pSrc;
for(i=pSrc->nSrc-1; i-extra>=iFrom; i--){
@ -2325,23 +2354,24 @@ static int flattenSubquery(
for(i=0; i<pList->nExpr; i++){
Expr *pExpr;
if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){
pList->a[i].zName = sqliteStrNDup((char*)pExpr->span.z, pExpr->span.n);
pList->a[i].zName =
sqlite3DbStrNDup(db, (char*)pExpr->span.z, pExpr->span.n);
}
}
substExprList(p->pEList, iParent, pSub->pEList);
substExprList(db, p->pEList, iParent, pSub->pEList);
if( isAgg ){
substExprList(p->pGroupBy, iParent, pSub->pEList);
substExpr(p->pHaving, iParent, pSub->pEList);
substExprList(db, p->pGroupBy, iParent, pSub->pEList);
substExpr(db, p->pHaving, iParent, pSub->pEList);
}
if( pSub->pOrderBy ){
assert( p->pOrderBy==0 );
p->pOrderBy = pSub->pOrderBy;
pSub->pOrderBy = 0;
}else if( p->pOrderBy ){
substExprList(p->pOrderBy, iParent, pSub->pEList);
substExprList(db, p->pOrderBy, iParent, pSub->pEList);
}
if( pSub->pWhere ){
pWhere = sqlite3ExprDup(pSub->pWhere);
pWhere = sqlite3ExprDup(db, pSub->pWhere);
}else{
pWhere = 0;
}
@ -2349,13 +2379,14 @@ static int flattenSubquery(
assert( p->pHaving==0 );
p->pHaving = p->pWhere;
p->pWhere = pWhere;
substExpr(p->pHaving, iParent, pSub->pEList);
p->pHaving = sqlite3ExprAnd(p->pHaving, sqlite3ExprDup(pSub->pHaving));
substExpr(db, p->pHaving, iParent, pSub->pEList);
p->pHaving = sqlite3ExprAnd(db, p->pHaving,
sqlite3ExprDup(db, pSub->pHaving));
assert( p->pGroupBy==0 );
p->pGroupBy = sqlite3ExprListDup(pSub->pGroupBy);
p->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy);
}else{
substExpr(p->pWhere, iParent, pSub->pEList);
p->pWhere = sqlite3ExprAnd(p->pWhere, pWhere);
substExpr(db, p->pWhere, iParent, pSub->pEList);
p->pWhere = sqlite3ExprAnd(db, p->pWhere, pWhere);
}
/* The flattened query is distinct if either the inner or the
@ -2571,7 +2602,8 @@ static int processOrderGroupBy(
CollSeq *pColl = pE->pColl;
int flags = pE->flags & EP_ExpCollate;
sqlite3ExprDelete(pE);
pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr);
pE = sqlite3ExprDup(pParse->db, pEList->a[iCol-1].pExpr);
pOrderBy->a[i].pExpr = pE;
if( pColl && flags ){
pE->pColl = pColl;
pE->flags |= flags;
@ -2690,7 +2722,7 @@ int sqlite3SelectResolve(
}
}
if( sqlite3MallocFailed() ){
if( pParse->db->mallocFailed ){
return SQLITE_NOMEM;
}
@ -2897,8 +2929,10 @@ int sqlite3Select(
int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
AggInfo sAggInfo; /* Information used by aggregate queries */
int iEnd; /* Address of the end of the query */
sqlite3 *db; /* The database connection */
if( p==0 || sqlite3MallocFailed() || pParse->nErr ){
db = pParse->db;
if( p==0 || db->mallocFailed || pParse->nErr ){
return 1;
}
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
@ -2985,7 +3019,7 @@ int sqlite3Select(
}else{
needRestoreContext = 0;
}
#if SQLITE_MAX_EXPR_DEPTH>0
#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
/* Increment Parse.nHeight by the height of the largest expression
** tree refered to by this, the parent select. The child select
** may contain expression trees of at most
@ -2997,7 +3031,7 @@ int sqlite3Select(
#endif
sqlite3Select(pParse, pItem->pSelect, SRT_EphemTab,
pItem->iCursor, p, i, &isAgg, 0);
#if SQLITE_MAX_EXPR_DEPTH>0
#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
pParse->nHeight -= sqlite3SelectExprHeight(p);
#endif
if( needRestoreContext ){
@ -3027,7 +3061,7 @@ int sqlite3Select(
*/
#ifndef SQLITE_OMIT_VIEW
if( pParent && pParentAgg &&
flattenSubquery(pParent, parentTab, *pParentAgg, isAgg) ){
flattenSubquery(db, pParent, parentTab, *pParentAgg, isAgg) ){
if( isAgg ) *pParentAgg = 1;
goto select_end;
}
@ -3154,7 +3188,7 @@ int sqlite3Select(
goto select_end;
}
}
if( sqlite3MallocFailed() ) goto select_end;
if( db->mallocFailed ) goto select_end;
/* Processing for aggregates with GROUP BY is very different and
** much more complex tha aggregates without a GROUP BY.
@ -3403,8 +3437,8 @@ select_end:
generateColumnNames(pParse, pTabList, pEList);
}
sqliteFree(sAggInfo.aCol);
sqliteFree(sAggInfo.aFunc);
sqlite3_free(sAggInfo.aCol);
sqlite3_free(sAggInfo.aFunc);
return rc;
}

File diff suppressed because it is too large Load Diff

View File

@ -149,11 +149,39 @@ struct sqlite3_api_routines {
const void * (*value_text16le)(sqlite3_value*);
int (*value_type)(sqlite3_value*);
char *(*vmprintf)(const char*,va_list);
/* Added ??? */
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
/* Added by 3.3.13 */
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
int (*clear_bindings)(sqlite3_stmt*);
/* Added by 3.4.1 */
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,void (*xDestroy)(void *));
/* Added by 3.5.0 */
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
int (*blob_bytes)(sqlite3_blob*);
int (*blob_close)(sqlite3_blob*);
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,int,sqlite3_blob**);
int (*blob_read)(sqlite3_blob*,void*,int,int);
int (*blob_write)(sqlite3_blob*,const void*,int,int);
int (*create_collation_v2)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*),void(*)(void*));
int (*file_control)(sqlite3*,const char*,int,void*);
sqlite3_int64 (*memory_highwater)(int);
sqlite3_int64 (*memory_used)(void);
sqlite3_mutex *(*mutex_alloc)(int);
void (*mutex_enter)(sqlite3_mutex*);
void (*mutex_free)(sqlite3_mutex*);
void (*mutex_leave)(sqlite3_mutex*);
int (*mutex_try)(sqlite3_mutex*);
int (*open_v2)(const char*,sqlite3**,int,const char*);
int (*release_memory)(int);
void (*result_error_nomem)(sqlite3_context*);
void (*result_error_toobig)(sqlite3_context*);
int (*sleep)(int);
void (*soft_heap_limit)(int);
sqlite3_vfs *(*vfs_find)(const char*);
int (*vfs_register)(sqlite3_vfs*,int);
int (*vfs_unregister)(sqlite3_vfs*);
};
/*
@ -290,6 +318,30 @@ struct sqlite3_api_routines {
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
#define sqlite3_blob_bytes sqlite3_api->blob_bytes
#define sqlite3_blob_close sqlite3_api->blob_close
#define sqlite3_blob_open sqlite3_api->blob_open
#define sqlite3_blob_read sqlite3_api->blob_read
#define sqlite3_blob_write sqlite3_api->blob_write
#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
#define sqlite3_file_control sqlite3_api->file_control
#define sqlite3_memory_highwater sqlite3_api->memory_highwater
#define sqlite3_memory_used sqlite3_api->memory_used
#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
#define sqlite3_mutex_enter sqlite3_api->mutex_enter
#define sqlite3_mutex_free sqlite3_api->mutex_free
#define sqlite3_mutex_leave sqlite3_api->mutex_leave
#define sqlite3_mutex_try sqlite3_api->mutex_try
#define sqlite3_open_v2 sqlite3_api->open_v2
#define sqlite3_release_memory sqlite3_api->release_memory
#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
#define sqlite3_sleep sqlite3_api->sleep
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
#define sqlite3_vfs_find sqlite3_api->vfs_find
#define sqlite3_vfs_register sqlite3_api->vfs_register
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
#endif /* SQLITE_CORE */
#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api;

View File

@ -17,6 +17,76 @@
#define _SQLITEINT_H_
#include "sqliteLimit.h"
/*
** For testing purposes, the various size limit constants are really
** variables that we can modify in the testfixture.
*/
#ifdef SQLITE_TEST
#undef SQLITE_MAX_LENGTH
#undef SQLITE_MAX_COLUMN
#undef SQLITE_MAX_SQL_LENGTH
#undef SQLITE_MAX_EXPR_DEPTH
#undef SQLITE_MAX_COMPOUND_SELECT
#undef SQLITE_MAX_VDBE_OP
#undef SQLITE_MAX_FUNCTION_ARG
#undef SQLITE_MAX_VARIABLE_NUMBER
#undef SQLITE_MAX_PAGE_SIZE
#undef SQLITE_MAX_PAGE_COUNT
#undef SQLITE_MAX_LIKE_PATTERN_LENGTH
#define SQLITE_MAX_LENGTH sqlite3MAX_LENGTH
#define SQLITE_MAX_COLUMN sqlite3MAX_COLUMN
#define SQLITE_MAX_SQL_LENGTH sqlite3MAX_SQL_LENGTH
#define SQLITE_MAX_EXPR_DEPTH sqlite3MAX_EXPR_DEPTH
#define SQLITE_MAX_COMPOUND_SELECT sqlite3MAX_COMPOUND_SELECT
#define SQLITE_MAX_VDBE_OP sqlite3MAX_VDBE_OP
#define SQLITE_MAX_FUNCTION_ARG sqlite3MAX_FUNCTION_ARG
#define SQLITE_MAX_VARIABLE_NUMBER sqlite3MAX_VARIABLE_NUMBER
#define SQLITE_MAX_PAGE_SIZE sqlite3MAX_PAGE_SIZE
#define SQLITE_MAX_PAGE_COUNT sqlite3MAX_PAGE_COUNT
#define SQLITE_MAX_LIKE_PATTERN_LENGTH sqlite3MAX_LIKE_PATTERN_LENGTH
extern int sqlite3MAX_LENGTH;
extern int sqlite3MAX_COLUMN;
extern int sqlite3MAX_SQL_LENGTH;
extern int sqlite3MAX_EXPR_DEPTH;
extern int sqlite3MAX_COMPOUND_SELECT;
extern int sqlite3MAX_VDBE_OP;
extern int sqlite3MAX_FUNCTION_ARG;
extern int sqlite3MAX_VARIABLE_NUMBER;
extern int sqlite3MAX_PAGE_SIZE;
extern int sqlite3MAX_PAGE_COUNT;
extern int sqlite3MAX_LIKE_PATTERN_LENGTH;
#endif
/*
** The SQLITE_THREADSAFE macro must be defined as either 0 or 1.
** Older versions of SQLite used an optional THREADSAFE macro.
** We support that for legacy
*/
#if !defined(SQLITE_THREADSAFE)
#if defined(THREADSAFE)
# define SQLITE_THREADSAFE THREADSAFE
#else
# define SQLITE_THREADSAFE 1
#endif
#endif
/*
** We need to define _XOPEN_SOURCE as follows in order to enable
** recursive mutexes on most unix systems. But Mac OS X is different.
** The _XOPEN_SOURCE define causes problems for Mac OS X we are told,
** so it is omitted there. See ticket #2673.
**
** Later we learn that _XOPEN_SOURCE is poorly or incorrectly
** implemented on some systems. So we avoid defining it at all
** if it is already defined or if it is unneeded because we are
** not doing a threadsafe build. Ticket #2681.
*/
#if !defined(_XOPEN_SOURCE) && !defined(__MACOS__) && SQLITE_THREADSAFE
# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */
#endif
#if defined(SQLITE_TCL) || defined(TCLSH)
# include <tcl.h>
@ -184,7 +254,11 @@ typedef UINT8_TYPE i8; /* 1-byte signed integer */
** Macros to determine whether the machine is big or little endian,
** evaluated at runtime.
*/
#ifdef SQLITE_AMALGAMATION
const int sqlite3One;
#else
extern const int sqlite3one;
#endif
#if defined(i386) || defined(__i386__) || defined(_M_IX86)
# define SQLITE_BIGENDIAN 0
# define SQLITE_LITTLEENDIAN 1
@ -215,78 +289,10 @@ struct BusyHandler {
** Defer sourcing vdbe.h and btree.h until after the "u8" and
** "BusyHandler typedefs.
*/
#include "vdbe.h"
#include "btree.h"
#include "vdbe.h"
#include "pager.h"
#ifdef SQLITE_MEMDEBUG
/*
** The following global variables are used for testing and debugging
** only. They only work if SQLITE_MEMDEBUG is defined.
*/
extern int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */
extern int sqlite3_nFree; /* Number of sqliteFree() calls */
extern int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */
extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */
extern void *sqlite3_pFirst; /* Pointer to linked list of allocations */
extern int sqlite3_nMaxAlloc; /* High water mark of ThreadData.nAlloc */
extern int sqlite3_mallocDisallowed; /* assert() in sqlite3Malloc() if set */
extern int sqlite3_isFail; /* True if all malloc calls should fail */
extern const char *sqlite3_zFile; /* Filename to associate debug info with */
extern int sqlite3_iLine; /* Line number for debug info */
#define ENTER_MALLOC (sqlite3_zFile = __FILE__, sqlite3_iLine = __LINE__)
#define sqliteMalloc(x) (ENTER_MALLOC, sqlite3Malloc(x,1))
#define sqliteMallocRaw(x) (ENTER_MALLOC, sqlite3MallocRaw(x,1))
#define sqliteRealloc(x,y) (ENTER_MALLOC, sqlite3Realloc(x,y))
#define sqliteStrDup(x) (ENTER_MALLOC, sqlite3StrDup(x))
#define sqliteStrNDup(x,y) (ENTER_MALLOC, sqlite3StrNDup(x,y))
#define sqliteReallocOrFree(x,y) (ENTER_MALLOC, sqlite3ReallocOrFree(x,y))
#else
#define ENTER_MALLOC 0
#define sqliteMalloc(x) sqlite3Malloc(x,1)
#define sqliteMallocRaw(x) sqlite3MallocRaw(x,1)
#define sqliteRealloc(x,y) sqlite3Realloc(x,y)
#define sqliteStrDup(x) sqlite3StrDup(x)
#define sqliteStrNDup(x,y) sqlite3StrNDup(x,y)
#define sqliteReallocOrFree(x,y) sqlite3ReallocOrFree(x,y)
#endif
/* Variable sqlite3_mallocHasFailed is set to true after a malloc()
** failure occurs.
**
** The sqlite3MallocFailed() macro returns true if a malloc has failed
** in this thread since the last call to sqlite3ApiExit(), or false
** otherwise.
*/
extern int sqlite3_mallocHasFailed;
#define sqlite3MallocFailed() (sqlite3_mallocHasFailed && sqlite3OsInMutex(1))
#define sqliteFree(x) sqlite3FreeX(x)
#define sqliteAllocSize(x) sqlite3AllocSize(x)
/*
** An instance of this structure might be allocated to store information
** specific to a single thread.
*/
struct ThreadData {
int dummy; /* So that this structure is never empty */
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
int nSoftHeapLimit; /* Suggested max mem allocation. No limit if <0 */
int nAlloc; /* Number of bytes currently allocated */
Pager *pPager; /* Linked list of all pagers in this thread */
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
u8 useSharedData; /* True if shared pagers and schemas are enabled */
BtShared *pBtree; /* Linked list of all currently open BTrees */
#endif
};
/*
** Name of the master database table. The master database table
@ -334,7 +340,6 @@ typedef struct NameContext NameContext;
typedef struct Parse Parse;
typedef struct Select Select;
typedef struct SrcList SrcList;
typedef struct ThreadData ThreadData;
typedef struct Table Table;
typedef struct TableLock TableLock;
typedef struct Token Token;
@ -345,6 +350,7 @@ typedef struct WhereInfo WhereInfo;
typedef struct WhereLevel WhereLevel;
#include "os.h"
#include "mutex.h"
/*
** Each database file to be accessed by the system is an instance
@ -441,13 +447,16 @@ struct Schema {
** consistently.
*/
struct sqlite3 {
sqlite3_vfs *pVfs; /* OS Interface */
int nDb; /* Number of backends currently in use */
Db *aDb; /* All backends */
int flags; /* Miscellanous flags. See below */
int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
int errCode; /* Most recent error code (SQLITE_*) */
int errMask; /* & result codes with this before returning */
u8 autoCommit; /* The auto-commit flag. */
u8 temp_store; /* 1: file 2: memory 0: default */
u8 mallocFailed; /* True if we have seen a malloc failure */
int nTable; /* Number of tables in the database */
CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
i64 lastRowid; /* ROWID of most recent insert (see above) */
@ -455,6 +464,7 @@ struct sqlite3 {
int magic; /* Magic number for detect library misuse */
int nChange; /* Value returned by sqlite3_changes() */
int nTotalChange; /* Value returned by sqlite3_total_changes() */
sqlite3_mutex *mutex; /* Connection mutex */
struct sqlite3InitInfo { /* Information used during initialization */
int iDb; /* When back is being initialized */
int newTnum; /* Rootpage of table being initialized */
@ -545,6 +555,8 @@ struct sqlite3 {
#define SQLITE_LoadExtension 0x00020000 /* Enable load_extension */
#define SQLITE_RecoveryMode 0x00040000 /* Ignore schema errors */
#define SQLITE_SharedCache 0x00080000 /* Cache sharing is enabled */
#define SQLITE_Vtab 0x00100000 /* There exists a virtual table */
/*
** Possible values for the sqlite.magic field.
@ -738,7 +750,7 @@ struct Table {
int nModuleArg; /* Number of arguments to the module */
char **azModuleArg; /* Text of all module args. [0] is module name */
#endif
Schema *pSchema;
Schema *pSchema; /* Schema that contains this table */
};
/*
@ -796,7 +808,7 @@ struct FKey {
};
/*
** SQLite supports many different ways to resolve a contraint
** SQLite supports many different ways to resolve a constraint
** error. ROLLBACK processing means that a constraint violation
** causes the operation in process to fail and for the current transaction
** to be rolled back. ABORT processing means the operation in process
@ -845,6 +857,7 @@ struct FKey {
** were larger.
*/
struct KeyInfo {
sqlite3 *db; /* The database connection */
u8 enc; /* Text encoding - one of the TEXT_Utf* values */
u8 incrKey; /* Increase 2nd key by epsilon before comparison */
int nField; /* Number of entries in aColl[] */
@ -1016,8 +1029,8 @@ struct Expr {
Select *pSelect; /* When the expression is a sub-select. Also the
** right side of "<expr> IN (<select>)" */
Table *pTab; /* Table for OP_Column expressions. */
Schema *pSchema;
#if SQLITE_MAX_EXPR_DEPTH>0
/* Schema *pSchema; */
#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
int nHeight; /* Height of the tree headed by this node */
#endif
};
@ -1365,7 +1378,7 @@ struct Parse {
u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
Table *pVirtualLock; /* Require virtual table lock on this table */
#endif
#if SQLITE_MAX_EXPR_DEPTH>0
#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
int nHeight; /* Expression tree height of current sub-select */
#endif
};
@ -1477,11 +1490,11 @@ struct TriggerStep {
Trigger *pTrig; /* The trigger that this step is a part of */
Select *pSelect; /* Valid for SELECT and sometimes
INSERT steps (when pExprList == 0) */
INSERT steps (when pExprList == 0) */
Token target; /* Valid for DELETE, UPDATE, INSERT steps */
Expr *pWhere; /* Valid for DELETE, UPDATE steps */
ExprList *pExprList; /* Valid for UPDATE statements and sometimes
INSERT steps (when pSelect == 0) */
INSERT steps (when pSelect == 0) */
IdList *pIdList; /* Valid for INSERT statements only */
TriggerStep *pNext; /* Next in the link-list */
TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */
@ -1549,69 +1562,15 @@ typedef struct {
} InitData;
/*
* This global flag is set for performance testing of triggers. When it is set
* SQLite will perform the overhead of building new and old trigger references
* even when no triggers exist
*/
extern int sqlite3_always_code_trigger_setup;
/*
** A lookup table used by the SQLITE_READ_UTF8 macro. The definition
** is in utf.c.
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
*/
extern const unsigned char sqlite3UtfTrans1[];
/*
** Macros for reading UTF8 characters.
**
** SQLITE_READ_UTF8(x,c) reads a single UTF8 value out of x and writes
** that value into c. The type of x must be unsigned char*. The type
** of c must be unsigned int.
**
** SQLITE_SKIP_UTF8(x) advances x forward by one character. The type of
** x must be unsigned char*.
**
** Notes On Invalid UTF-8:
**
** * These macros never allow a 7-bit character (0x00 through 0x7f) to
** be encoded as a multi-byte character. Any multi-byte character that
** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd.
**
** * These macros never allow a UTF16 surrogate value to be encoded.
** If a multi-byte character attempts to encode a value between
** 0xd800 and 0xe000 then it is rendered as 0xfffd.
**
** * Bytes in the range of 0x80 through 0xbf which occur as the first
** byte of a character are interpreted as single-byte characters
** and rendered as themselves even though they are technically
** invalid characters.
**
** * These routines accept an infinite number of different UTF8 encodings
** for unicode values 0x80 and greater. They do not change over-length
** encodings to 0xfffd as some systems recommend.
**
*/
#define SQLITE_READ_UTF8(zIn, c) { \
c = *(zIn++); \
if( c>=0xc0 ){ \
c = sqlite3UtfTrans1[c-0xc0]; \
while( (*zIn & 0xc0)==0x80 ){ \
c = (c<<6) + (0x3f & *(zIn++)); \
} \
if( c<0x80 \
|| (c&0xFFFFF800)==0xD800 \
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
} \
}
#define SQLITE_SKIP_UTF8(zIn) { \
if( (*(zIn++))>=0xc0 ){ \
while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
} \
}
/*
** The SQLITE_CORRUPT_BKPT macro can be either a constant (for production
** builds) or a function call (for debugging). If it is a function call,
@ -1632,21 +1591,18 @@ int sqlite3StrICmp(const char *, const char *);
int sqlite3StrNICmp(const char *, const char *, int);
int sqlite3IsNumber(const char*, int*, u8);
void *sqlite3Malloc(int,int);
void *sqlite3MallocRaw(int,int);
void *sqlite3Realloc(void*,int);
void *sqlite3MallocZero(unsigned);
void *sqlite3DbMallocZero(sqlite3*, unsigned);
void *sqlite3DbMallocRaw(sqlite3*, unsigned);
char *sqlite3StrDup(const char*);
char *sqlite3StrNDup(const char*, int);
# define sqlite3CheckMemory(a,b)
void *sqlite3ReallocOrFree(void*,int);
void sqlite3FreeX(void*);
void *sqlite3MallocX(int);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
int sqlite3AllocSize(void *);
#endif
char *sqlite3DbStrDup(sqlite3*,const char*);
char *sqlite3DbStrNDup(sqlite3*,const char*, int);
void *sqlite3DbReallocOrFree(sqlite3 *, void *, int);
void *sqlite3DbRealloc(sqlite3 *, void *, int);
char *sqlite3MPrintf(const char*, ...);
char *sqlite3VMPrintf(const char*, va_list);
char *sqlite3MPrintf(sqlite3*,const char*, ...);
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
void sqlite3DebugPrintf(const char*, ...);
void *sqlite3TextToPtr(const char*);
@ -1655,19 +1611,19 @@ void sqlite3SetString(char **, ...);
void sqlite3ErrorMsg(Parse*, const char*, ...);
void sqlite3ErrorClear(Parse*);
void sqlite3Dequote(char*);
void sqlite3DequoteExpr(Expr*);
void sqlite3DequoteExpr(sqlite3*, Expr*);
int sqlite3KeywordCode(const unsigned char*, int);
int sqlite3RunParser(Parse*, const char*, char **);
void sqlite3FinishCoding(Parse*);
Expr *sqlite3Expr(int, Expr*, Expr*, const Token*);
Expr *sqlite3ExprOrFree(int, Expr*, Expr*, const Token*);
Expr *sqlite3Expr(sqlite3*, int, Expr*, Expr*, const Token*);
Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
Expr *sqlite3RegisterExpr(Parse*,Token*);
Expr *sqlite3ExprAnd(Expr*, Expr*);
Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
void sqlite3ExprSpan(Expr*,Token*,Token*);
Expr *sqlite3ExprFunction(ExprList*, Token*);
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*);
void sqlite3ExprDelete(Expr*);
ExprList *sqlite3ExprListAppend(ExprList*,Expr*,Token*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*,Token*);
void sqlite3ExprListDelete(ExprList*);
int sqlite3Init(sqlite3*, char**);
int sqlite3InitCallback(void*, int, char**, char**);
@ -1698,11 +1654,11 @@ void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
void sqlite3DropTable(Parse*, SrcList*, int, int);
void sqlite3DeleteTable(Table*);
void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
void *sqlite3ArrayAllocate(void*,int,int,int*,int*,int*);
IdList *sqlite3IdListAppend(IdList*, Token*);
void *sqlite3ArrayAllocate(sqlite3*,void*,int,int,int*,int*,int*);
IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*);
SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*);
SrcList *sqlite3SrcListAppendFromTerm(SrcList*, Token*, Token*, Token*,
SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, Token*,
Select*, Expr*, IdList*);
void sqlite3SrcListShiftJoinType(SrcList*);
void sqlite3SrcListAssignCursors(Parse*, SrcList*);
@ -1712,8 +1668,8 @@ void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Token*, int, int);
void sqlite3DropIndex(Parse*, SrcList*, int);
int sqlite3Select(Parse*, Select*, int, int, Select*, int, int*, char *aff);
Select *sqlite3SelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*,
int,Expr*,Expr*);
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,int,Expr*,Expr*);
void sqlite3SelectDelete(Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
@ -1735,14 +1691,13 @@ void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
void sqlite3Vacuum(Parse*);
int sqlite3RunVacuum(char**, sqlite3*);
char *sqlite3NameFromToken(Token*);
char *sqlite3NameFromToken(sqlite3*, Token*);
int sqlite3ExprCompare(Expr*, Expr*);
int sqliteFuncId(Token*);
int sqlite3ExprResolveNames(NameContext *, Expr *);
int sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
int sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
Vdbe *sqlite3GetVdbe(Parse*);
Expr *sqlite3CreateIdExpr(const char*);
Expr *sqlite3CreateIdExpr(Parse *, const char*);
void sqlite3Randomness(int, void*);
void sqlite3RollbackAll(sqlite3*);
void sqlite3CodeVerifySchema(Parse*, int);
@ -1761,12 +1716,12 @@ void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int, int);
void sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
void sqlite3BeginWriteOperation(Parse*, int, int);
Expr *sqlite3ExprDup(Expr*);
void sqlite3TokenCopy(Token*, Token*);
ExprList *sqlite3ExprListDup(ExprList*);
SrcList *sqlite3SrcListDup(SrcList*);
IdList *sqlite3IdListDup(IdList*);
Select *sqlite3SelectDup(Select*);
Expr *sqlite3ExprDup(sqlite3*,Expr*);
void sqlite3TokenCopy(sqlite3*,Token*, Token*);
ExprList *sqlite3ExprListDup(sqlite3*,ExprList*);
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*);
IdList *sqlite3IdListDup(sqlite3*,IdList*);
Select *sqlite3SelectDup(sqlite3*,Select*);
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int);
void sqlite3RegisterBuiltinFunctions(sqlite3*);
void sqlite3RegisterDateTimeFunctions(sqlite3*);
@ -1786,10 +1741,11 @@ void sqlite3ChangeCookie(sqlite3*, Vdbe*, int);
int, int);
void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
void sqlite3DeleteTriggerStep(TriggerStep*);
TriggerStep *sqlite3TriggerSelectStep(Select*);
TriggerStep *sqlite3TriggerInsertStep(Token*, IdList*, ExprList*,Select*,int);
TriggerStep *sqlite3TriggerUpdateStep(Token*, ExprList*, Expr*, int);
TriggerStep *sqlite3TriggerDeleteStep(Token*, Expr*);
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 sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
#else
@ -1804,7 +1760,7 @@ int sqlite3JoinType(Parse*, Token*, Token*, Token*);
void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
void sqlite3DeferForeignKey(Parse*, int);
#ifndef SQLITE_OMIT_AUTHORIZATION
void sqlite3AuthRead(Parse*,Expr*,SrcList*);
void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*);
int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*);
void sqlite3AuthContextPush(Parse*, AuthContext*, const char*);
void sqlite3AuthContextPop(AuthContext*);
@ -1817,7 +1773,7 @@ void sqlite3DeferForeignKey(Parse*, int);
void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
void sqlite3Detach(Parse*, Expr*);
int sqlite3BtreeFactory(const sqlite3 *db, const char *zFilename,
int omitJournal, int nCache, Btree **ppBtree);
int omitJournal, int nCache, int flags, Btree **ppBtree);
int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
int sqlite3FixSrcList(DbFixer*, SrcList*);
int sqlite3FixSelect(DbFixer*, Select*);
@ -1830,7 +1786,7 @@ int sqlite3GetInt32(const char *, int*);
int sqlite3FitsIn64Bits(const char *);
int sqlite3Utf16ByteLen(const void *pData, int nChar);
int sqlite3Utf8CharLen(const char *pData, int nByte);
u32 sqlite3ReadUtf8(const unsigned char *);
int sqlite3Utf8Read(const u8*, const u8*, const u8**);
int sqlite3PutVarint(unsigned char *, u64);
int sqlite3GetVarint(const unsigned char *, u64 *);
int sqlite3GetVarint32(const unsigned char *, u32 *);
@ -1842,7 +1798,7 @@ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
char sqlite3ExprAffinity(Expr *pExpr);
int sqlite3Atoi64(const char*, i64*);
void sqlite3Error(sqlite3*, int, const char*,...);
void *sqlite3HexToBlob(const char *z);
void *sqlite3HexToBlob(sqlite3*, const char *z);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
const char *sqlite3ErrStr(int);
int sqlite3ReadSchema(Parse *pParse);
@ -1853,17 +1809,19 @@ Expr *sqlite3ExprSetColl(Parse *pParse, Expr *, Token *);
int sqlite3CheckCollSeq(Parse *, CollSeq *);
int sqlite3CheckObjectName(Parse *, const char *);
void sqlite3VdbeSetChanges(sqlite3 *, int);
void sqlite3Utf16Substr(sqlite3_context *,int,sqlite3_value **);
const void *sqlite3ValueText(sqlite3_value*, u8);
int sqlite3ValueBytes(sqlite3_value*, u8);
void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*));
void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
void(*)(void*));
void sqlite3ValueFree(sqlite3_value*);
sqlite3_value *sqlite3ValueNew(void);
char *sqlite3Utf16to8(const void*, int);
int sqlite3ValueFromExpr(Expr *, u8, u8, sqlite3_value **);
sqlite3_value *sqlite3ValueNew(sqlite3 *);
char *sqlite3Utf16to8(sqlite3 *, const void*, int);
int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
extern const unsigned char sqlite3UpperToLower[];
#endif
void sqlite3RootPageMoved(Db*, int, int);
void sqlite3Reindex(Parse*, Token*, Token*);
void sqlite3AlterFunctions(sqlite3*);
@ -1885,23 +1843,27 @@ int sqlite3AnalysisLoad(sqlite3*,int iDB);
void sqlite3DefaultRowEst(Index*);
void sqlite3RegisterLikeFunctions(sqlite3*, int);
int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
ThreadData *sqlite3ThreadData(void);
const ThreadData *sqlite3ThreadDataReadOnly(void);
void sqlite3ReleaseThreadData(void);
void sqlite3AttachFunctions(sqlite3 *);
void sqlite3MinimumFileFormat(Parse*, int, int);
void sqlite3SchemaFree(void *);
Schema *sqlite3SchemaGet(Btree *);
Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *);
int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
void (*)(sqlite3_context*,int,sqlite3_value **),
void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*));
int sqlite3ApiExit(sqlite3 *db, int);
void sqlite3FailedMalloc(void);
void sqlite3AbortOtherActiveVdbes(sqlite3 *, Vdbe *);
int sqlite3OpenTempDatabase(Parse *);
/*
** The interface to the LEMON-generated parser
*/
void *sqlite3ParserAlloc(void*(*)(size_t));
void sqlite3ParserFree(void*, void(*)(void*));
void sqlite3Parser(void*, int, Token, Parse*);
#ifndef SQLITE_OMIT_LOAD_EXTENSION
void sqlite3CloseExtensions(sqlite3*);
int sqlite3AutoLoadExtensions(sqlite3*);
@ -1920,23 +1882,25 @@ int sqlite3OpenTempDatabase(Parse *);
int sqlite3Utf8To8(unsigned char*);
#endif
/*
** The MallocDisallow() and MallocAllow() routines are like asserts.
** Call them around a section of code that you do not expect to do
** any memory allocation.
*/
#ifdef SQLITE_MEMDEBUG
void sqlite3MallocDisallow(void);
void sqlite3MallocAllow(void);
int sqlite3TestMallocFail(void);
void sqlite3MallocBenignFailure(int);
void sqlite3MallocEnterBenignBlock(int isBenign);
void sqlite3MallocLeaveBenignBlock();
#else
#define sqlite3TestMallocFail() 0
#define sqlite3MallocDisallow()
#define sqlite3MallocAllow()
# define sqlite3MallocDisallow()
# define sqlite3MallocAllow()
# define sqlite3MallocBenignFailure(x)
# define sqlite3MallocEnterBenignBlock(x);
# define sqlite3MallocLeaveBenignBlock();
#endif
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
void *sqlite3ThreadSafeMalloc(int);
void sqlite3ThreadSafeFree(void *);
#else
#define sqlite3ThreadSafeMalloc sqlite3MallocX
#define sqlite3ThreadSafeFree sqlite3FreeX
#endif
#ifdef SQLITE_OMIT_VIRTUALTABLE
# define sqlite3VtabClear(X)
@ -1959,22 +1923,28 @@ int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
int sqlite3VtabCallConnect(Parse*, Table*);
int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *);
FuncDef *sqlite3VtabOverloadFunction(FuncDef*, int nArg, Expr*);
FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, int, const char*);
CollSeq* sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
#if SQLITE_MAX_EXPR_DEPTH>0
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
int sqlite3JournalSize(sqlite3_vfs *);
int sqlite3JournalCreate(sqlite3_file *);
#else
#define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile)
#endif
#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
void sqlite3ExprSetHeight(Expr *);
int sqlite3SelectExprHeight(Select *);
#else
#define sqlite3ExprSetHeight(x)
#endif
u32 sqlite3Get2byte(const u8*);
u32 sqlite3Get4byte(const u8*);
void sqlite3Put2byte(u8*, u32);
void sqlite3Put4byte(u8*, u32);
#ifdef SQLITE_SSE
@ -1997,6 +1967,6 @@ void sqlite3Put4byte(u8*, u32);
# define IOTRACE(A)
# define sqlite3VdbeIOTraceSql(X)
#endif
extern void (*sqlite3_io_trace)(const char*,...);
SQLITE_EXTERN void (*sqlite3_io_trace)(const char*,...);
#endif

View File

@ -130,6 +130,17 @@
# define SQLITE_DEFAULT_PAGE_SIZE 1024
#endif
/*
** Ordinarily, if no value is explicitly provided, SQLite creates databases
** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain
** device characteristics (sector-size and atomic write() support),
** SQLite may choose a larger value. This constant is the maximum value
** SQLite will choose on it's own.
*/
#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE
# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192
#endif
/* Maximum page size. The upper bound on this value is 32768. This a limit
** imposed by the necessity of storing the value in a 2-byte unsigned integer
** and the fact that the page size must be a power of 2.

View File

@ -143,6 +143,11 @@ int sqlite3_get_table(
if( res.azResult==0 ) return SQLITE_NOMEM;
res.azResult[0] = 0;
rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg);
#ifndef NDEBUG
sqlite3_mutex_enter(db->mutex);
assert((rc&db->errMask)==rc && (res.rc&db->errMask)==res.rc);
sqlite3_mutex_leave(db->mutex);
#endif
if( res.azResult ){
assert( sizeof(res.azResult[0])>= sizeof(res.nData) );
res.azResult[0] = (char*)res.nData;
@ -154,15 +159,17 @@ int sqlite3_get_table(
sqlite3_free(*pzErrMsg);
*pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg);
}
sqliteFree(res.zErrMsg);
sqlite3_free(res.zErrMsg);
}
sqlite3_mutex_enter(db->mutex);
db->errCode = res.rc;
return res.rc & db->errMask;
sqlite3_mutex_leave(db->mutex);
return res.rc;
}
sqliteFree(res.zErrMsg);
sqlite3_free(res.zErrMsg);
if( rc!=SQLITE_OK ){
sqlite3_free_table(&res.azResult[1]);
return rc & db->errMask;
return rc;
}
if( res.nAlloc>res.nData ){
char **azNew;
@ -177,7 +184,7 @@ int sqlite3_get_table(
*pazResult = &res.azResult[1];
if( pnColumn ) *pnColumn = res.nColumn;
if( pnRow ) *pnRow = res.nRow;
return rc & db->errMask;
return rc;
}
/*

View File

@ -18,7 +18,6 @@
** $Id$
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <stdlib.h>
@ -86,7 +85,7 @@ const unsigned char ebcdicToAscii[] = {
** But the feature is undocumented.
*/
#ifdef SQLITE_ASCII
const char sqlite3IsIdChar[] = {
const char sqlite3IsAsciiIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
@ -95,10 +94,10 @@ const char sqlite3IsIdChar[] = {
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
};
#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsIdChar[c-0x20]))
#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsAsciiIdChar[c-0x20]))
#endif
#ifdef SQLITE_EBCDIC
const char sqlite3IsIdChar[] = {
const char sqlite3IsEbcdicIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 4x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, /* 5x */
@ -113,7 +112,7 @@ const char sqlite3IsIdChar[] = {
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Ex */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* Fx */
};
#define IdChar(C) (((c=C)>=0x42 && sqlite3IsIdChar[c-0x40]))
#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
#endif
@ -380,18 +379,11 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
return getToken(z, tokenType);
}
/*
** The interface to the LEMON-generated parser
*/
void *sqlite3ParserAlloc(void*(*)(size_t));
void sqlite3ParserFree(void*, void(*)(void*));
void sqlite3Parser(void*, int, Token, Parse*);
/*
** Run the parser on the given SQL string. The parser structure is
** passed in. An SQLITE_ status code is returned. If an error occurs
** and pzErrMsg!=NULL then an error message might be written into
** memory obtained from malloc() and *pzErrMsg made to point to that
** memory obtained from sqlite3_malloc() and *pzErrMsg made to point to that
** error message. Or maybe not.
*/
int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
@ -407,8 +399,9 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
}
pParse->rc = SQLITE_OK;
i = 0;
pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3MallocX);
pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3_malloc);
if( pEngine==0 ){
db->mallocFailed = 1;
return SQLITE_NOMEM;
}
assert( pParse->sLastToken.dyn==0 );
@ -419,7 +412,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
assert( pParse->nVarExprAlloc==0 );
assert( pParse->apVarExpr==0 );
pParse->zTail = pParse->zSql = zSql;
while( !sqlite3MallocFailed() && zSql[i]!=0 ){
while( !db->mallocFailed && zSql[i]!=0 ){
assert( i>=0 );
pParse->sLastToken.z = (u8*)&zSql[i];
assert( pParse->sLastToken.dyn==0 );
@ -441,8 +434,8 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
}
case TK_ILLEGAL: {
if( pzErrMsg ){
sqliteFree(*pzErrMsg);
*pzErrMsg = sqlite3MPrintf("unrecognized token: \"%T\"",
sqlite3_free(*pzErrMsg);
*pzErrMsg = sqlite3MPrintf(db, "unrecognized token: \"%T\"",
&pParse->sLastToken);
}
nErr++;
@ -470,8 +463,8 @@ abort_parse:
}
sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
}
sqlite3ParserFree(pEngine, sqlite3FreeX);
if( sqlite3MallocFailed() ){
sqlite3ParserFree(pEngine, sqlite3_free);
if( db->mallocFailed ){
pParse->rc = SQLITE_NOMEM;
}
if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
@ -481,7 +474,7 @@ abort_parse:
if( pzErrMsg && *pzErrMsg==0 ){
*pzErrMsg = pParse->zErrMsg;
}else{
sqliteFree(pParse->zErrMsg);
sqlite3_free(pParse->zErrMsg);
}
pParse->zErrMsg = 0;
if( !nErr ) nErr++;
@ -492,7 +485,7 @@ abort_parse:
}
#ifndef SQLITE_OMIT_SHARED_CACHE
if( pParse->nested==0 ){
sqliteFree(pParse->aTableLock);
sqlite3_free(pParse->aTableLock);
pParse->aTableLock = 0;
pParse->nTableLock = 0;
}
@ -507,7 +500,7 @@ abort_parse:
}
sqlite3DeleteTrigger(pParse->pNewTrigger);
sqliteFree(pParse->apVarExpr);
sqlite3_free(pParse->apVarExpr);
if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
pParse->rc = SQLITE_ERROR;
}

View File

@ -21,13 +21,13 @@ void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){
TriggerStep * pTmp = pTriggerStep;
pTriggerStep = pTriggerStep->pNext;
if( pTmp->target.dyn ) sqliteFree((char*)pTmp->target.z);
if( pTmp->target.dyn ) sqlite3_free((char*)pTmp->target.z);
sqlite3ExprDelete(pTmp->pWhere);
sqlite3ExprListDelete(pTmp->pExprList);
sqlite3SelectDelete(pTmp->pSelect);
sqlite3IdListDelete(pTmp->pIdList);
sqliteFree(pTmp);
sqlite3_free(pTmp);
}
}
@ -83,7 +83,7 @@ void sqlite3BeginTrigger(
** If sqlite3SrcListLookup() returns 0, indicating the table does not
** exist, the error is caught by the block below.
*/
if( !pTableName || sqlite3MallocFailed() ){
if( !pTableName || db->mallocFailed ){
goto trigger_cleanup;
}
pTab = sqlite3SrcListLookup(pParse, pTableName);
@ -92,7 +92,7 @@ void sqlite3BeginTrigger(
}
/* Ensure the table name matches database name and that the table exists */
if( sqlite3MallocFailed() ) goto trigger_cleanup;
if( db->mallocFailed ) goto trigger_cleanup;
assert( pTableName->nSrc==1 );
if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
sqlite3FixSrcList(&sFix, pTableName) ){
@ -110,7 +110,7 @@ void sqlite3BeginTrigger(
/* Check that the trigger name is not reserved and that no trigger of the
** specified name exists */
zName = sqlite3NameFromToken(pName);
zName = sqlite3NameFromToken(db, pName);
if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
goto trigger_cleanup;
}
@ -168,23 +168,23 @@ void sqlite3BeginTrigger(
}
/* Build the Trigger object */
pTrigger = (Trigger*)sqliteMalloc(sizeof(Trigger));
pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger));
if( pTrigger==0 ) goto trigger_cleanup;
pTrigger->name = zName;
zName = 0;
pTrigger->table = sqliteStrDup(pTableName->a[0].zName);
pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName);
pTrigger->pSchema = db->aDb[iDb].pSchema;
pTrigger->pTabSchema = pTab->pSchema;
pTrigger->op = op;
pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
pTrigger->pWhen = sqlite3ExprDup(pWhen);
pTrigger->pColumns = sqlite3IdListDup(pColumns);
sqlite3TokenCopy(&pTrigger->nameToken,pName);
pTrigger->pWhen = sqlite3ExprDup(db, pWhen);
pTrigger->pColumns = sqlite3IdListDup(db, pColumns);
sqlite3TokenCopy(db, &pTrigger->nameToken,pName);
assert( pParse->pNewTrigger==0 );
pParse->pNewTrigger = pTrigger;
trigger_cleanup:
sqliteFree(zName);
sqlite3_free(zName);
sqlite3SrcListDelete(pTableName);
sqlite3IdListDelete(pColumns);
sqlite3ExprDelete(pWhen);
@ -253,8 +253,9 @@ void sqlite3FinishTrigger(
sqlite3VdbeChangeP3(v, addr+6, (char*)pAll->z, pAll->n);
sqlite3ChangeCookie(db, v, iDb);
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0,
sqlite3MPrintf("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC);
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, sqlite3MPrintf(
db, "type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC
);
}
if( db->init.busy ){
@ -264,7 +265,8 @@ void sqlite3FinishTrigger(
pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash,
pTrig->name, strlen(pTrig->name), pTrig);
if( pDel ){
assert( sqlite3MallocFailed() && pDel==pTrig );
assert( pDel==pTrig );
db->mallocFailed = 1;
goto triggerfinish_cleanup;
}
n = strlen(pTrig->table) + 1;
@ -284,35 +286,35 @@ triggerfinish_cleanup:
/*
** Make a copy of all components of the given trigger step. This has
** the effect of copying all Expr.token.z values into memory obtained
** from sqliteMalloc(). As initially created, the Expr.token.z values
** from sqlite3_malloc(). As initially created, the Expr.token.z values
** all point to the input string that was fed to the parser. But that
** string is ephemeral - it will go away as soon as the sqlite3_exec()
** call that started the parser exits. This routine makes a persistent
** copy of all the Expr.token.z strings so that the TriggerStep structure
** will be valid even after the sqlite3_exec() call returns.
*/
static void sqlitePersistTriggerStep(TriggerStep *p){
static void sqlitePersistTriggerStep(sqlite3 *db, TriggerStep *p){
if( p->target.z ){
p->target.z = (u8*)sqliteStrNDup((char*)p->target.z, p->target.n);
p->target.z = (u8*)sqlite3DbStrNDup(db, (char*)p->target.z, p->target.n);
p->target.dyn = 1;
}
if( p->pSelect ){
Select *pNew = sqlite3SelectDup(p->pSelect);
Select *pNew = sqlite3SelectDup(db, p->pSelect);
sqlite3SelectDelete(p->pSelect);
p->pSelect = pNew;
}
if( p->pWhere ){
Expr *pNew = sqlite3ExprDup(p->pWhere);
Expr *pNew = sqlite3ExprDup(db, p->pWhere);
sqlite3ExprDelete(p->pWhere);
p->pWhere = pNew;
}
if( p->pExprList ){
ExprList *pNew = sqlite3ExprListDup(p->pExprList);
ExprList *pNew = sqlite3ExprListDup(db, p->pExprList);
sqlite3ExprListDelete(p->pExprList);
p->pExprList = pNew;
}
if( p->pIdList ){
IdList *pNew = sqlite3IdListDup(p->pIdList);
IdList *pNew = sqlite3IdListDup(db, p->pIdList);
sqlite3IdListDelete(p->pIdList);
p->pIdList = pNew;
}
@ -325,8 +327,8 @@ static void sqlitePersistTriggerStep(TriggerStep *p){
** The parser calls this routine when it finds a SELECT statement in
** body of a TRIGGER.
*/
TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
if( pTriggerStep==0 ) {
sqlite3SelectDelete(pSelect);
return 0;
@ -335,7 +337,7 @@ TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){
pTriggerStep->op = TK_SELECT;
pTriggerStep->pSelect = pSelect;
pTriggerStep->orconf = OE_Default;
sqlitePersistTriggerStep(pTriggerStep);
sqlitePersistTriggerStep(db, pTriggerStep);
return pTriggerStep;
}
@ -348,17 +350,19 @@ TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){
** body of a trigger.
*/
TriggerStep *sqlite3TriggerInsertStep(
sqlite3 *db, /* The database connection */
Token *pTableName, /* Name of the table into which we insert */
IdList *pColumn, /* List of columns in pTableName to insert into */
ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
Select *pSelect, /* A SELECT statement that supplies values */
int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
TriggerStep *pTriggerStep;
assert(pEList == 0 || pSelect == 0);
assert(pEList != 0 || pSelect != 0);
assert(pEList != 0 || pSelect != 0 || db->mallocFailed);
pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
if( pTriggerStep ){
pTriggerStep->op = TK_INSERT;
pTriggerStep->pSelect = pSelect;
@ -366,11 +370,11 @@ TriggerStep *sqlite3TriggerInsertStep(
pTriggerStep->pIdList = pColumn;
pTriggerStep->pExprList = pEList;
pTriggerStep->orconf = orconf;
sqlitePersistTriggerStep(pTriggerStep);
sqlitePersistTriggerStep(db, pTriggerStep);
}else{
sqlite3IdListDelete(pColumn);
sqlite3ExprListDelete(pEList);
sqlite3SelectDup(pSelect);
sqlite3SelectDelete(pSelect);
}
return pTriggerStep;
@ -382,12 +386,13 @@ TriggerStep *sqlite3TriggerInsertStep(
** sees an UPDATE statement inside the body of a CREATE TRIGGER.
*/
TriggerStep *sqlite3TriggerUpdateStep(
sqlite3 *db, /* The database connection */
Token *pTableName, /* Name of the table to be updated */
ExprList *pEList, /* The SET clause: list of column and new values */
Expr *pWhere, /* The WHERE clause */
int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
if( pTriggerStep==0 ){
sqlite3ExprListDelete(pEList);
sqlite3ExprDelete(pWhere);
@ -399,7 +404,7 @@ TriggerStep *sqlite3TriggerUpdateStep(
pTriggerStep->pExprList = pEList;
pTriggerStep->pWhere = pWhere;
pTriggerStep->orconf = orconf;
sqlitePersistTriggerStep(pTriggerStep);
sqlitePersistTriggerStep(db, pTriggerStep);
return pTriggerStep;
}
@ -409,8 +414,12 @@ TriggerStep *sqlite3TriggerUpdateStep(
** a pointer to that trigger step. The parser calls this routine when it
** sees a DELETE statement inside the body of a CREATE TRIGGER.
*/
TriggerStep *sqlite3TriggerDeleteStep(Token *pTableName, Expr *pWhere){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
TriggerStep *sqlite3TriggerDeleteStep(
sqlite3 *db, /* Database connection */
Token *pTableName, /* The table from which rows are deleted */
Expr *pWhere /* The WHERE clause */
){
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
if( pTriggerStep==0 ){
sqlite3ExprDelete(pWhere);
return 0;
@ -420,7 +429,7 @@ TriggerStep *sqlite3TriggerDeleteStep(Token *pTableName, Expr *pWhere){
pTriggerStep->target = *pTableName;
pTriggerStep->pWhere = pWhere;
pTriggerStep->orconf = OE_Default;
sqlitePersistTriggerStep(pTriggerStep);
sqlitePersistTriggerStep(db, pTriggerStep);
return pTriggerStep;
}
@ -431,12 +440,12 @@ TriggerStep *sqlite3TriggerDeleteStep(Token *pTableName, Expr *pWhere){
void sqlite3DeleteTrigger(Trigger *pTrigger){
if( pTrigger==0 ) return;
sqlite3DeleteTriggerStep(pTrigger->step_list);
sqliteFree(pTrigger->name);
sqliteFree(pTrigger->table);
sqlite3_free(pTrigger->name);
sqlite3_free(pTrigger->table);
sqlite3ExprDelete(pTrigger->pWhen);
sqlite3IdListDelete(pTrigger->pColumns);
if( pTrigger->nameToken.dyn ) sqliteFree((char*)pTrigger->nameToken.z);
sqliteFree(pTrigger);
if( pTrigger->nameToken.dyn ) sqlite3_free((char*)pTrigger->nameToken.z);
sqlite3_free(pTrigger);
}
/*
@ -455,7 +464,7 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
int nName;
sqlite3 *db = pParse->db;
if( sqlite3MallocFailed() ) goto drop_trigger_cleanup;
if( db->mallocFailed ) goto drop_trigger_cleanup;
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto drop_trigger_cleanup;
}
@ -644,9 +653,9 @@ static SrcList *targetSrcList(
assert( iDb<pParse->db->nDb );
sDb.z = (u8*)pParse->db->aDb[iDb].zName;
sDb.n = strlen((char*)sDb.z);
pSrc = sqlite3SrcListAppend(0, &sDb, &pStep->target);
pSrc = sqlite3SrcListAppend(pParse->db, 0, &sDb, &pStep->target);
} else {
pSrc = sqlite3SrcListAppend(0, &pStep->target, 0);
pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0);
}
return pSrc;
}
@ -663,6 +672,7 @@ static int codeTriggerProgram(
TriggerStep * pTriggerStep = pStepList;
int orconf;
Vdbe *v = pParse->pVdbe;
sqlite3 *db = pParse->db;
assert( pTriggerStep!=0 );
assert( v!=0 );
@ -673,21 +683,21 @@ static int codeTriggerProgram(
pParse->trigStack->orconf = orconf;
switch( pTriggerStep->op ){
case TK_SELECT: {
Select *ss = sqlite3SelectDup(pTriggerStep->pSelect);
Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect);
if( ss ){
sqlite3SelectResolve(pParse, ss, 0);
sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0);
sqlite3SelectDelete(ss);
}
break;
break;
}
case TK_UPDATE: {
SrcList *pSrc;
pSrc = targetSrcList(pParse, pTriggerStep);
sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0);
sqlite3Update(pParse, pSrc,
sqlite3ExprListDup(pTriggerStep->pExprList),
sqlite3ExprDup(pTriggerStep->pWhere), orconf);
sqlite3ExprListDup(db, pTriggerStep->pExprList),
sqlite3ExprDup(db, pTriggerStep->pWhere), orconf);
sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0);
break;
}
@ -696,9 +706,9 @@ static int codeTriggerProgram(
pSrc = targetSrcList(pParse, pTriggerStep);
sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0);
sqlite3Insert(pParse, pSrc,
sqlite3ExprListDup(pTriggerStep->pExprList),
sqlite3SelectDup(pTriggerStep->pSelect),
sqlite3IdListDup(pTriggerStep->pIdList), orconf);
sqlite3ExprListDup(db, pTriggerStep->pExprList),
sqlite3SelectDup(db, pTriggerStep->pSelect),
sqlite3IdListDup(db, pTriggerStep->pIdList), orconf);
sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0);
break;
}
@ -706,7 +716,8 @@ static int codeTriggerProgram(
SrcList *pSrc;
sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0);
pSrc = targetSrcList(pParse, pTriggerStep);
sqlite3DeleteFrom(pParse, pSrc, sqlite3ExprDup(pTriggerStep->pWhere));
sqlite3DeleteFrom(pParse, pSrc,
sqlite3ExprDup(db, pTriggerStep->pWhere));
sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0);
break;
}
@ -805,7 +816,7 @@ int sqlite3CodeRowTrigger(
/* code the WHEN clause */
endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
whenExpr = sqlite3ExprDup(p->pWhen);
whenExpr = sqlite3ExprDup(pParse->db, p->pWhen);
if( sqlite3ExprResolveNames(&sNC, whenExpr) ){
pParse->trigStack = trigStackEntry.pNext;
sqlite3ExprDelete(whenExpr);

View File

@ -60,7 +60,7 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
u8 enc = ENC(sqlite3VdbeDb(v));
Column *pCol = &pTab->aCol[i];
assert( i<pTab->nCol );
sqlite3ValueFromExpr(pCol->pDflt, enc, pCol->affinity, &pValue);
sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, pCol->affinity, &pValue);
if( pValue ){
sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM);
}else{
@ -115,10 +115,10 @@ void sqlite3Update(
int oldIdx = -1; /* index of trigger "old" temp table */
sContext.pParse = 0;
if( pParse->nErr || sqlite3MallocFailed() ){
db = pParse->db;
if( pParse->nErr || db->mallocFailed ){
goto update_cleanup;
}
db = pParse->db;
assert( pTabList->nSrc==1 );
/* Locate the table which we want to update.
@ -148,7 +148,7 @@ void sqlite3Update(
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
goto update_cleanup;
}
aXRef = sqliteMallocRaw( sizeof(int) * pTab->nCol );
aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol );
if( aXRef==0 ) goto update_cleanup;
for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
@ -235,7 +235,7 @@ void sqlite3Update(
if( i<pIdx->nColumn ) nIdx++;
}
if( nIdxTotal>0 ){
apIdx = sqliteMallocRaw( sizeof(Index*) * nIdx + nIdxTotal );
apIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx + nIdxTotal );
if( apIdx==0 ) goto update_cleanup;
aIdxUsed = (char*)&apIdx[nIdx];
}
@ -291,7 +291,7 @@ void sqlite3Update(
*/
if( isView ){
Select *pView;
pView = sqlite3SelectDup(pTab->pSelect);
pView = sqlite3SelectDup(db, pTab->pSelect);
sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}
@ -525,8 +525,8 @@ void sqlite3Update(
update_cleanup:
sqlite3AuthContextPop(&sContext);
sqliteFree(apIdx);
sqliteFree(aXRef);
sqlite3_free(apIdx);
sqlite3_free(aXRef);
sqlite3SrcListDelete(pTabList);
sqlite3ExprListDelete(pChanges);
sqlite3ExprDelete(pWhere);
@ -569,24 +569,27 @@ static void updateVirtualTable(
int ephemTab; /* Table holding the result of the SELECT */
int i; /* Loop counter */
int addr; /* Address of top of loop */
sqlite3 *db = pParse->db; /* Database connection */
/* Construct the SELECT statement that will find the new values for
** all updated rows.
*/
pEList = sqlite3ExprListAppend(0, sqlite3CreateIdExpr("_rowid_"), 0);
pEList = sqlite3ExprListAppend(pParse, 0,
sqlite3CreateIdExpr(pParse, "_rowid_"), 0);
if( pRowid ){
pEList = sqlite3ExprListAppend(pEList, sqlite3ExprDup(pRowid), 0);
pEList = sqlite3ExprListAppend(pParse, pEList,
sqlite3ExprDup(db, pRowid), 0);
}
assert( pTab->iPKey<0 );
for(i=0; i<pTab->nCol; i++){
if( aXRef[i]>=0 ){
pExpr = sqlite3ExprDup(pChanges->a[aXRef[i]].pExpr);
pExpr = sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr);
}else{
pExpr = sqlite3CreateIdExpr(pTab->aCol[i].zName);
pExpr = sqlite3CreateIdExpr(pParse, pTab->aCol[i].zName);
}
pEList = sqlite3ExprListAppend(pEList, pExpr, 0);
pEList = sqlite3ExprListAppend(pParse, pEList, pExpr, 0);
}
pSelect = sqlite3SelectNew(pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
/* Create the ephemeral table into which the update results will
** be stored.

View File

@ -49,7 +49,7 @@ const int sqlite3one = 1;
** This lookup table is used to help decode the first byte of
** a multi-byte UTF8 character.
*/
const unsigned char sqlite3UtfTrans1[] = {
static const unsigned char sqlite3UtfTrans1[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
@ -60,6 +60,7 @@ const unsigned char sqlite3UtfTrans1[] = {
0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
};
#define WRITE_UTF8(zOut, c) { \
if( c<0x00080 ){ \
*zOut++ = (c&0xFF); \
@ -126,6 +127,54 @@ const unsigned char sqlite3UtfTrans1[] = {
} \
}
/*
** Translate a single UTF-8 character. Return the unicode value.
**
** During translation, assume that the byte that zTerm points
** is a 0x00.
**
** Write a pointer to the next unread byte back into *pzNext.
**
** Notes On Invalid UTF-8:
**
** * This routine never allows a 7-bit character (0x00 through 0x7f) to
** be encoded as a multi-byte character. Any multi-byte character that
** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd.
**
** * This routine never allows a UTF16 surrogate value to be encoded.
** If a multi-byte character attempts to encode a value between
** 0xd800 and 0xe000 then it is rendered as 0xfffd.
**
** * Bytes in the range of 0x80 through 0xbf which occur as the first
** byte of a character are interpreted as single-byte characters
** and rendered as themselves even though they are technically
** invalid characters.
**
** * This routine accepts an infinite number of different UTF8 encodings
** for unicode values 0x80 and greater. It do not change over-length
** encodings to 0xfffd as some systems recommend.
*/
int sqlite3Utf8Read(
const unsigned char *z, /* First byte of UTF-8 character */
const unsigned char *zTerm, /* Pretend this byte is 0x00 */
const unsigned char **pzNext /* Write first byte past UTF-8 char here */
){
int c = *(z++);
if( c>=0xc0 ){
c = sqlite3UtfTrans1[c-0xc0];
while( z!=zTerm && (*z & 0xc0)==0x80 ){
c = (c<<6) + (0x3f & *(z++));
}
if( c<0x80
|| (c&0xFFFFF800)==0xD800
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; }
}
*pzNext = z;
return c;
}
/*
** If the TRANSLATE_TRACE macro is defined, the value of each Mem is
** printed on stderr on the way into and out of sqlite3VdbeMemTranslate().
@ -147,6 +196,7 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
unsigned char *z; /* Output iterator */
unsigned int c;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( pMem->flags&MEM_Str );
assert( pMem->enc!=desiredEnc );
assert( pMem->enc!=0 );
@ -205,95 +255,35 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
** byte past the end.
**
** Variable zOut is set to point at the output buffer. This may be space
** obtained from malloc(), or Mem.zShort, if it large enough and not in
** use, or the zShort array on the stack (see above).
** obtained from sqlite3_malloc(), or Mem.zShort, if it large enough and
** not in use, or the zShort array on the stack (see above).
*/
zIn = (u8*)pMem->z;
zTerm = &zIn[pMem->n];
if( len>NBFS ){
zOut = sqliteMallocRaw(len);
if( !zOut ) return SQLITE_NOMEM;
zOut = sqlite3DbMallocRaw(pMem->db, len);
if( !zOut ){
return SQLITE_NOMEM;
}
}else{
zOut = zShort;
}
z = zOut;
if( pMem->enc==SQLITE_UTF8 ){
unsigned int iExtra = 0xD800;
if( 0==(pMem->flags&MEM_Term) && zTerm>zIn && (zTerm[-1]&0x80) ){
/* This UTF8 string is not nul-terminated, and the last byte is
** not a character in the ascii range (codpoints 0..127). This
** means the SQLITE_READ_UTF8() macro might read past the end
** of the allocated buffer.
**
** There are four possibilities:
**
** 1. The last byte is the first byte of a non-ASCII character,
**
** 2. The final N bytes of the input string are continuation bytes
** and immediately preceding them is the first byte of a
** non-ASCII character.
**
** 3. The final N bytes of the input string are continuation bytes
** and immediately preceding them is a byte that encodes a
** character in the ASCII range.
**
** 4. The entire string consists of continuation characters.
**
** Cases (3) and (4) require no special handling. The SQLITE_READ_UTF8()
** macro will not overread the buffer in these cases.
*/
unsigned char *zExtra = &zTerm[-1];
while( zExtra>zIn && (zExtra[0]&0xC0)==0x80 ){
zExtra--;
}
if( (zExtra[0]&0xC0)==0xC0 ){
/* Make a copy of the last character encoding in the input string.
** Then make sure it is nul-terminated and use SQLITE_READ_UTF8()
** to decode the codepoint. Store the codepoint in variable iExtra,
** it will be appended to the output string later.
*/
unsigned char *zFree = 0;
unsigned char zBuf[16];
int nExtra = (pMem->n+zIn-zExtra);
zTerm = zExtra;
if( nExtra>15 ){
zExtra = sqliteMallocRaw(nExtra+1);
if( !zExtra ){
return SQLITE_NOMEM;
}
zFree = zExtra;
}else{
zExtra = zBuf;
}
memcpy(zExtra, zTerm, nExtra);
zExtra[nExtra] = '\0';
SQLITE_READ_UTF8(zExtra, iExtra);
sqliteFree(zFree);
}
}
if( desiredEnc==SQLITE_UTF16LE ){
/* UTF-8 -> UTF-16 Little-endian */
while( zIn<zTerm ){
SQLITE_READ_UTF8(zIn, c);
c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn);
WRITE_UTF16LE(z, c);
}
if( iExtra!=0xD800 ){
WRITE_UTF16LE(z, iExtra);
}
}else{
assert( desiredEnc==SQLITE_UTF16BE );
/* UTF-8 -> UTF-16 Big-endian */
while( zIn<zTerm ){
SQLITE_READ_UTF8(zIn, c);
c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn);
WRITE_UTF16BE(z, c);
}
if( iExtra!=0xD800 ){
WRITE_UTF16BE(z, iExtra);
}
}
pMem->n = z - zOut;
*z++ = 0;
@ -377,7 +367,8 @@ int sqlite3VdbeMemHandleBom(Mem *pMem){
char *z = pMem->z;
pMem->z = 0;
pMem->xDel = 0;
rc = sqlite3VdbeMemSetStr(pMem, &z[2], pMem->n-2, bom, SQLITE_TRANSIENT);
rc = sqlite3VdbeMemSetStr(pMem, &z[2], pMem->n-2, bom,
SQLITE_TRANSIENT);
xDel(z);
}else{
rc = sqlite3VdbeMemSetStr(pMem, &pMem->z[2], pMem->n-2, bom,
@ -412,22 +403,57 @@ int sqlite3Utf8CharLen(const char *zIn, int nByte){
return r;
}
/* This test function is not currently used by the automated test-suite.
** Hence it is only available in debug builds.
*/
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
/*
** Translate UTF-8 to UTF-8.
**
** This has the effect of making sure that the string is well-formed
** UTF-8. Miscoded characters are removed.
**
** The translation is done in-place (since it is impossible for the
** correct UTF-8 encoding to be longer than a malformed encoding).
*/
int sqlite3Utf8To8(unsigned char *zIn){
unsigned char *zOut = zIn;
unsigned char *zStart = zIn;
unsigned char *zTerm;
u32 c;
while( zIn[0] ){
c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn);
if( c!=0xfffd ){
WRITE_UTF8(zOut, c);
}
}
*zOut = 0;
return zOut - zStart;
}
#endif
#ifndef SQLITE_OMIT_UTF16
/*
** Convert a UTF-16 string in the native encoding into a UTF-8 string.
** Memory to hold the UTF-8 string is obtained from malloc and must be
** freed by the calling function.
** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must
** be freed by the calling function.
**
** NULL is returned if there is an allocation error.
*/
char *sqlite3Utf16to8(const void *z, int nByte){
char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte){
Mem m;
memset(&m, 0, sizeof(m));
m.db = db;
sqlite3VdbeMemSetStr(&m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC);
sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
assert( (m.flags & MEM_Term)!=0 || sqlite3MallocFailed() );
assert( (m.flags & MEM_Str)!=0 || sqlite3MallocFailed() );
return (m.flags & MEM_Dyn)!=0 ? m.z : sqliteStrDup(m.z);
if( db->mallocFailed ){
sqlite3VdbeMemRelease(&m);
m.z = 0;
}
assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
return (m.flags & MEM_Dyn)!=0 ? m.z : sqlite3DbStrDup(db, m.z);
}
/*
@ -464,33 +490,6 @@ int sqlite3Utf16ByteLen(const void *zIn, int nChar){
return (z-(char const *)zIn)-((c==0)?2:0);
}
#if defined(SQLITE_TEST)
/*
** Translate UTF-8 to UTF-8.
**
** This has the effect of making sure that the string is well-formed
** UTF-8. Miscoded characters are removed.
**
** The translation is done in-place (since it is impossible for the
** correct UTF-8 encoding to be longer than a malformed encoding).
*/
int sqlite3Utf8To8(unsigned char *zIn){
unsigned char *zOut = zIn;
unsigned char *zStart = zIn;
int c;
while(1){
SQLITE_READ_UTF8(zIn, c);
if( c==0 ) break;
if( c!=0xfffd ){
WRITE_UTF8(zOut, c);
}
}
*zOut = 0;
return zOut - zStart;
}
#endif
#if defined(SQLITE_TEST)
/*
** This routine is called from the TCL test function "translate_selftest".
@ -501,6 +500,7 @@ void sqlite3UtfSelfTest(){
unsigned int i, t;
unsigned char zBuf[20];
unsigned char *z;
unsigned char *zTerm;
int n;
unsigned int c;
@ -509,8 +509,9 @@ void sqlite3UtfSelfTest(){
WRITE_UTF8(z, i);
n = z-zBuf;
z[0] = 0;
zTerm = z;
z = zBuf;
SQLITE_READ_UTF8(z, c);
c = sqlite3Utf8Read(z, zTerm, (const u8**)&z);
t = i;
if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;

View File

@ -17,7 +17,6 @@
** $Id$
*/
#include "sqliteInt.h"
#include "os.h"
#include <stdarg.h>
#include <ctype.h>
@ -44,15 +43,15 @@
** to NULL.
*/
void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
if( db && (db->pErr || (db->pErr = sqlite3ValueNew())!=0) ){
if( db && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
db->errCode = err_code;
if( zFormat ){
char *z;
va_list ap;
va_start(ap, zFormat);
z = sqlite3VMPrintf(zFormat, ap);
z = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, sqlite3FreeX);
sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, sqlite3_free);
}else{
sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
}
@ -79,9 +78,9 @@ void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
va_list ap;
pParse->nErr++;
sqliteFree(pParse->zErrMsg);
sqlite3_free(pParse->zErrMsg);
va_start(ap, zFormat);
pParse->zErrMsg = sqlite3VMPrintf(zFormat, ap);
pParse->zErrMsg = sqlite3VMPrintf(pParse->db, zFormat, ap);
va_end(ap);
if( pParse->rc==SQLITE_OK ){
pParse->rc = SQLITE_ERROR;
@ -92,7 +91,7 @@ void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
** Clear the error message in pParse, if any
*/
void sqlite3ErrorClear(Parse *pParse){
sqliteFree(pParse->zErrMsg);
sqlite3_free(pParse->zErrMsg);
pParse->zErrMsg = 0;
pParse->nErr = 0;
}
@ -421,10 +420,16 @@ int sqlite3GetInt32(const char *zNum, int *pValue){
zNum++;
}
while( zNum[0]=='0' ) zNum++;
for(i=0; i<10 && (c = zNum[i] - '0')>=0 && c<=9; i++){
for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
v = v*10 + c;
}
if( i>9 ){
/* The longest decimal representation of a 32 bit integer is 10 digits:
**
** 1234567890
** 2^31 -> 2147483648
*/
if( i>10 ){
return 0;
}
if( v-neg>2147483647 ){
@ -631,13 +636,13 @@ static int hexToInt(int h){
** binary value has been obtained from malloc and must be freed by
** the calling routine.
*/
void *sqlite3HexToBlob(const char *z){
void *sqlite3HexToBlob(sqlite3 *db, const char *z){
char *zBlob;
int i;
int n = strlen(z);
if( n%2 ) return 0;
zBlob = (char *)sqliteMalloc(n/2);
zBlob = (char *)sqlite3DbMallocRaw(db, n/2);
if( zBlob ){
for(i=0; i<n; i+=2){
zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]);
@ -699,34 +704,3 @@ int sqlite3SafetyOff(sqlite3 *db){
return 1;
}
}
/*
** Return a pointer to the ThreadData associated with the calling thread.
*/
ThreadData *sqlite3ThreadData(){
ThreadData *p = (ThreadData*)sqlite3OsThreadSpecificData(1);
if( !p ){
sqlite3FailedMalloc();
}
return p;
}
/*
** Return a pointer to the ThreadData associated with the calling thread.
** If no ThreadData has been allocated to this thread yet, return a pointer
** to a substitute ThreadData structure that is all zeros.
*/
const ThreadData *sqlite3ThreadDataReadOnly(){
static const ThreadData zeroData = {0}; /* Initializer to silence warnings
** from broken compilers */
const ThreadData *pTd = sqlite3OsThreadSpecificData(0);
return pTd ? pTd : &zeroData;
}
/*
** Check to see if the ThreadData for this thread is all zero. If it
** is, then deallocate it.
*/
void sqlite3ReleaseThreadData(){
sqlite3OsThreadSpecificData(-1);
}

View File

@ -18,7 +18,6 @@
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
#include "os.h"
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
/*
@ -26,6 +25,9 @@
*/
static int execSql(sqlite3 *db, const char *zSql){
sqlite3_stmt *pStmt;
if( !zSql ){
return SQLITE_NOMEM;
}
if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
return sqlite3_errcode(db);
}
@ -112,7 +114,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
pTemp = db->aDb[db->nDb-1].pBt;
sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain),
sqlite3BtreeGetReserve(pMain));
if( sqlite3MallocFailed() ){
if( db->mallocFailed ){
rc = SQLITE_NOMEM;
goto end_of_vacuum;
}
@ -248,9 +250,7 @@ end_of_vacuum:
db->autoCommit = 1;
if( pDb ){
sqlite3MallocDisallow();
sqlite3BtreeClose(pDb->pBt);
sqlite3MallocAllow();
pDb->pBt = 0;
pDb->pSchema = 0;
}

View File

@ -46,7 +46,6 @@
** $Id$
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <math.h>
#include "vdbeInt.h"
@ -110,15 +109,6 @@ int sqlite3_max_blobsize = 0;
if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc)) \
{ goto no_mem; }
/*
** Convert the given stack entity into a string that has been obtained
** from sqliteMalloc(). This is different from Stringify() above in that
** Stringify() will use the NBFS bytes of static string space if the string
** will fit but this routine always mallocs for space.
** Return non-zero if we run out of memory.
*/
#define Dynamicify(P,enc) sqlite3VdbeMemDynamicify(P)
/*
** The header of a record consists of a sequence variable-length integers.
** These integers are almost always small and are encoded as a single byte.
@ -206,7 +196,7 @@ static Cursor *allocateCursor(Vdbe *p, int iCur, int iDb){
if( p->apCsr[iCur] ){
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
}
p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) );
p->apCsr[iCur] = pCx = sqlite3MallocZero( sizeof(Cursor) );
if( pCx ){
pCx->iDb = iDb;
}
@ -256,7 +246,11 @@ static void applyNumericAffinity(Mem *pRec){
** SQLITE_AFF_NONE:
** No-op. pRec is unchanged.
*/
static void applyAffinity(Mem *pRec, char affinity, u8 enc){
static void applyAffinity(
Mem *pRec, /* The value to apply affinity to */
char affinity, /* The affinity to be applied */
u8 enc /* Use this text encoding */
){
if( affinity==SQLITE_AFF_TEXT ){
/* Only attempt the conversion to TEXT if there is an integer or real
** representation (blob and NULL do not get converted) but no string
@ -295,7 +289,11 @@ int sqlite3_value_numeric_type(sqlite3_value *pVal){
** Exported version of applyAffinity(). This one works on sqlite3_value*,
** not the internal Mem* type.
*/
void sqlite3ValueApplyAffinity(sqlite3_value *pVal, u8 affinity, u8 enc){
void sqlite3ValueApplyAffinity(
sqlite3_value *pVal,
u8 affinity,
u8 enc
){
applyAffinity((Mem *)pVal, affinity, enc);
}
@ -429,7 +427,7 @@ __inline__ unsigned long long int hwtime(void){
** return SQLITE_BUSY.
**
** If an error occurs, an error message is written to memory obtained
** from sqliteMalloc() and p->zErrMsg is made to point to that memory.
** from sqlite3_malloc() and p->zErrMsg is made to point to that memory.
** The error code is stored in p->rc and this routine returns SQLITE_ERROR.
**
** If the callback ever returns non-zero, then the program exits
@ -467,6 +465,7 @@ int sqlite3VdbeExec(
if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
assert( db->magic==SQLITE_MAGIC_BUSY );
pTos = p->pTos;
sqlite3BtreeMutexArrayEnter(&p->aMutex);
if( p->rc==SQLITE_NOMEM ){
/* This happens if a malloc() inside a call to sqlite3_column_text() or
** sqlite3_column_text16() failed. */
@ -485,7 +484,7 @@ int sqlite3VdbeExec(
sqlite3VdbeIOTraceSql(p);
#ifdef SQLITE_DEBUG
if( (p->db->flags & SQLITE_VdbeListing)!=0
|| sqlite3OsFileExists("vdbe_explain")
|| sqlite3OsAccess(db->pVfs, "vdbe_explain", SQLITE_ACCESS_EXISTS)
){
int i;
printf("VDBE Program Listing:\n");
@ -494,14 +493,14 @@ int sqlite3VdbeExec(
sqlite3VdbePrintOp(stdout, i, &p->aOp[i]);
}
}
if( sqlite3OsFileExists("vdbe_trace") ){
if( sqlite3OsAccess(db->pVfs, "vdbe_trace", SQLITE_ACCESS_EXISTS) ){
p->trace = stdout;
}
#endif
for(pc=p->pc; rc==SQLITE_OK; pc++){
assert( pc>=0 && pc<p->nOp );
assert( pTos<=&p->aStack[pc] );
if( sqlite3MallocFailed() ) goto no_mem;
if( db->mallocFailed ) goto no_mem;
#ifdef VDBE_PROFILE
origPc = pc;
start = hwtime();
@ -518,7 +517,8 @@ int sqlite3VdbeExec(
}
sqlite3VdbePrintOp(p->trace, pc, pOp);
}
if( p->trace==0 && pc==0 && sqlite3OsFileExists("vdbe_sqltrace") ){
if( p->trace==0 && pc==0
&& sqlite3OsAccess(db->pVfs, "vdbe_sqltrace", SQLITE_ACCESS_EXISTS) ){
sqlite3VdbePrintSql(p);
}
#endif
@ -686,10 +686,11 @@ case OP_Halt: { /* no-push */
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK );
if( rc==SQLITE_BUSY ){
p->rc = SQLITE_BUSY;
return SQLITE_BUSY;
p->rc = rc = SQLITE_BUSY;
}else{
rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
}
return p->rc ? SQLITE_ERROR : SQLITE_DONE;
goto vdbe_return;
}
/* Opcode: Integer P1 * *
@ -757,7 +758,7 @@ case OP_String8: { /* same as TK_STRING */
pTos->flags &= ~(MEM_Dyn);
pTos->flags |= MEM_Static;
if( pOp->p3type==P3_DYNAMIC ){
sqliteFree(pOp->p3);
sqlite3_free(pOp->p3);
}
pOp->p3type = P3_DYNAMIC;
pOp->p3 = pTos->z;
@ -811,16 +812,16 @@ case OP_HexBlob: { /* same as TK_BLOB */
assert( SQLITE_MAX_SQL_LENGTH < SQLITE_MAX_LENGTH );
assert( pOp->p1 < SQLITE_MAX_LENGTH );
if( pOp->p1 ){
char *zBlob = sqlite3HexToBlob(pOp->p3);
char *zBlob = sqlite3HexToBlob(db, pOp->p3);
if( !zBlob ) goto no_mem;
if( pOp->p3type==P3_DYNAMIC ){
sqliteFree(pOp->p3);
sqlite3_free(pOp->p3);
}
pOp->p3 = zBlob;
pOp->p3type = P3_DYNAMIC;
}else{
if( pOp->p3type==P3_DYNAMIC ){
sqliteFree(pOp->p3);
sqlite3_free(pOp->p3);
}
pOp->p3type = P3_STATIC;
pOp->p3 = "";
@ -1004,7 +1005,8 @@ case OP_Callback: { /* no-push */
p->popStack = pOp->p1;
p->pc = pc + 1;
p->pTos = pTos;
return SQLITE_ROW;
rc = SQLITE_ROW;
goto vdbe_return;
}
/* Opcode: Concat P1 P2 *
@ -1015,7 +1017,7 @@ case OP_Callback: { /* no-push */
** any element of the stack is NULL, then the result is NULL.
**
** When P1==1, this routine makes a copy of the top stack element
** into memory obtained from sqliteMalloc().
** into memory obtained from sqlite3_malloc().
*/
case OP_Concat: { /* same as TK_CONCAT */
char *zNew;
@ -1056,7 +1058,7 @@ case OP_Concat: { /* same as TK_CONCAT */
if( nByte+2>SQLITE_MAX_LENGTH ){
goto too_big;
}
zNew = sqliteMallocRaw( nByte+2 );
zNew = sqlite3DbMallocRaw(db, nByte+2 );
if( zNew==0 ) goto no_mem;
j = 0;
pTerm = &pTos[1-nField];
@ -1279,6 +1281,7 @@ case OP_Function: {
ctx.s.flags = MEM_Null;
ctx.s.z = 0;
ctx.s.xDel = 0;
ctx.s.db = db;
ctx.isError = 0;
if( ctx.pFunc->needCollSeq ){
assert( pOp>p->aOp );
@ -1289,7 +1292,19 @@ case OP_Function: {
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
(*ctx.pFunc->xFunc)(&ctx, n, apVal);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( sqlite3MallocFailed() ) goto no_mem;
if( db->mallocFailed ){
/* Even though a malloc() has failed, the implementation of the
** user function may have called an sqlite3_result_XXX() function
** to return a value. The following call releases any resources
** associated with such a value.
**
** Note: Maybe MemRelease() should be called if sqlite3SafetyOn()
** fails also (the if(...) statement above). But if people are
** misusing sqlite, they have bigger problems than a leaked value.
*/
sqlite3VdbeMemRelease(&ctx.s);
goto no_mem;
}
popStack(&pTos, n);
/* If any auxilary data functions have been called by this user function,
@ -2063,7 +2078,7 @@ case OP_Column: {
aType = pC->aType;
if( aType==0 ){
pC->aType = aType = sqliteMallocRaw( 2*nField*sizeof(aType) );
pC->aType = aType = sqlite3DbMallocRaw(db, 2*nField*sizeof(aType) );
}
if( aType==0 ){
goto no_mem;
@ -2159,7 +2174,7 @@ case OP_Column: {
zData = &zRec[aOffset[p2]];
}else{
len = sqlite3VdbeSerialTypeLen(aType[p2]);
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex,&sMem);
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex, &sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
}
@ -2334,7 +2349,7 @@ case OP_MakeRecord: {
/* Allocate space for the new record. */
if( nByte>sizeof(zTemp) ){
zNewRecord = sqliteMallocRaw(nByte);
zNewRecord = sqlite3DbMallocRaw(db, nByte);
if( !zNewRecord ){
goto no_mem;
}
@ -2406,6 +2421,7 @@ case OP_Statement: { /* no-push */
Btree *pBt;
if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt)!=0 && !(db->autoCommit) ){
assert( sqlite3BtreeIsInTrans(pBt) );
assert( (p->btreeMask & (1<<i))!=0 );
if( !sqlite3BtreeIsInStmt(pBt) ){
rc = sqlite3BtreeBeginStmt(pBt);
p->openedStatement = 1;
@ -2450,15 +2466,16 @@ case OP_AutoCommit: { /* no-push */
p->pTos = pTos;
p->pc = pc;
db->autoCommit = 1-i;
p->rc = SQLITE_BUSY;
return SQLITE_BUSY;
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
}
}
if( p->rc==SQLITE_OK ){
return SQLITE_DONE;
rc = SQLITE_DONE;
}else{
return SQLITE_ERROR;
rc = SQLITE_ERROR;
}
goto vdbe_return;
}else{
sqlite3SetString(&p->zErrMsg,
(!i)?"cannot start a transaction within a transaction":(
@ -2495,15 +2512,16 @@ case OP_Transaction: { /* no-push */
Btree *pBt;
assert( i>=0 && i<db->nDb );
assert( (p->btreeMask & (1<<i))!=0 );
pBt = db->aDb[i].pBt;
if( pBt ){
rc = sqlite3BtreeBeginTrans(pBt, pOp->p2);
if( rc==SQLITE_BUSY ){
p->pc = pc;
p->rc = SQLITE_BUSY;
p->rc = rc = SQLITE_BUSY;
p->pTos = pTos;
return SQLITE_BUSY;
goto vdbe_return;
}
if( rc!=SQLITE_OK && rc!=SQLITE_READONLY /* && rc!=SQLITE_BUSY */ ){
goto abort_due_to_error;
@ -2541,6 +2559,7 @@ case OP_ReadCookie: {
}
assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pBt!=0 );
assert( (p->btreeMask & (1<<iDb))!=0 );
/* The indexing of meta values at the schema layer is off by one from
** the indexing in the btree layer. The btree considers meta[0] to
** be the number of free pages in the database (a read-only value)
@ -2569,6 +2588,7 @@ case OP_SetCookie: { /* no-push */
Db *pDb;
assert( pOp->p2<SQLITE_N_BTREE_META );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
pDb = &db->aDb[pOp->p1];
assert( pDb->pBt!=0 );
assert( pTos>=p->aStack );
@ -2613,6 +2633,7 @@ case OP_VerifyCookie: { /* no-push */
int iMeta;
Btree *pBt;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
pBt = db->aDb[pOp->p1].pBt;
if( pBt ){
rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&iMeta);
@ -2621,7 +2642,8 @@ case OP_VerifyCookie: { /* no-push */
iMeta = 0;
}
if( rc==SQLITE_OK && iMeta!=pOp->p2 ){
sqlite3SetString(&p->zErrMsg, "database schema has changed", (char*)0);
sqlite3_free(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
** not reload the schema from the database file.
@ -2703,6 +2725,7 @@ case OP_OpenWrite: { /* no-push */
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
assert( iDb>=0 && iDb<db->nDb );
assert( (p->btreeMask & (1<<iDb))!=0 );
pDb = &db->aDb[iDb];
pX = pDb->pBt;
assert( pX!=0 );
@ -2743,9 +2766,9 @@ case OP_OpenWrite: { /* no-push */
switch( rc ){
case SQLITE_BUSY: {
p->pc = pc;
p->rc = SQLITE_BUSY;
p->rc = rc = SQLITE_BUSY;
p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */
return SQLITE_BUSY;
goto vdbe_return;
}
case SQLITE_OK: {
int flags = sqlite3BtreeFlags(pCur->pCursor);
@ -2806,11 +2829,19 @@ case OP_OpenWrite: { /* no-push */
case OP_OpenEphemeral: { /* no-push */
int i = pOp->p1;
Cursor *pCx;
static const int openFlags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXCLUSIVE |
SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_TRANSIENT_DB;
assert( i>=0 );
pCx = allocateCursor(p, i, -1);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
rc = sqlite3BtreeFactory(db, 0, 1, SQLITE_DEFAULT_TEMP_CACHE_SIZE, &pCx->pBt);
rc = sqlite3BtreeFactory(db, 0, 1, SQLITE_DEFAULT_TEMP_CACHE_SIZE, openFlags,
&pCx->pBt);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
}
@ -3064,12 +3095,15 @@ case OP_Found: { /* no-push */
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pC = p->apCsr[i])->pCursor!=0 ){
int res, rx;
int res;
assert( pC->isTable==0 );
assert( pTos->flags & MEM_Blob );
Stringify(pTos, encoding);
rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res);
alreadyExists = rx==SQLITE_OK && res==0;
rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res);
if( rc!=SQLITE_OK ){
break;
}
alreadyExists = (res==0);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
}
@ -3456,14 +3490,14 @@ case OP_Insert: { /* no-push */
assert( pTos->flags & (MEM_Blob|MEM_Str) );
}
if( pC->pseudoTable ){
sqliteFree(pC->pData);
sqlite3_free(pC->pData);
pC->iKey = iKey;
pC->nData = pTos->n;
if( pTos->flags & MEM_Dyn ){
pC->pData = pTos->z;
pTos->flags = MEM_Null;
}else{
pC->pData = sqliteMallocRaw( pC->nData+2 );
pC->pData = sqlite3_malloc( pC->nData+2 );
if( !pC->pData ) goto no_mem;
memcpy(pC->pData, pTos->z, pC->nData);
pC->pData[pC->nData] = 0;
@ -3632,7 +3666,7 @@ case OP_RowData: {
pTos->flags = MEM_Blob | MEM_Short;
pTos->z = pTos->zShort;
}else{
char *z = sqliteMallocRaw( n );
char *z = sqlite3_malloc( n );
if( z==0 ) goto no_mem;
pTos->flags = MEM_Blob | MEM_Dyn;
pTos->xDel = 0;
@ -4058,6 +4092,7 @@ case OP_Destroy: {
rc = SQLITE_LOCKED;
}else{
assert( iCnt==1 );
assert( (p->btreeMask & (1<<pOp->p2))!=0 );
rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved);
pTos++;
pTos->flags = MEM_Int;
@ -4119,6 +4154,7 @@ case OP_Clear: { /* no-push */
}
}
#endif
assert( (p->btreeMask & (1<<pOp->p2))!=0 );
rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1);
break;
}
@ -4149,6 +4185,7 @@ case OP_CreateTable: {
int flags;
Db *pDb;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
pDb = &db->aDb[pOp->p1];
assert( pDb->pBt!=0 );
if( pOp->opcode==OP_CreateTable ){
@ -4194,21 +4231,20 @@ case OP_ParseSchema: { /* no-push */
initData.db = db;
initData.iDb = pOp->p1;
initData.pzErrMsg = &p->zErrMsg;
zSql = sqlite3MPrintf(
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s",
db->aDb[iDb].zName, zMaster, pOp->p3);
if( zSql==0 ) goto no_mem;
sqlite3SafetyOff(db);
assert( db->init.busy==0 );
db->init.busy = 1;
assert( !sqlite3MallocFailed() );
assert( !db->mallocFailed );
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
if( rc==SQLITE_ABORT ) rc = initData.rc;
sqliteFree(zSql);
sqlite3_free(zSql);
db->init.busy = 0;
sqlite3SafetyOn(db);
if( rc==SQLITE_NOMEM ){
sqlite3FailedMalloc();
goto no_mem;
}
break;
@ -4299,18 +4335,20 @@ case OP_IntegrityCk: {
if( (pTos[-nRoot].flags & MEM_Int)==0 ) break;
}
assert( nRoot>0 );
aRoot = sqliteMallocRaw( sizeof(int*)*(nRoot+1) );
aRoot = sqlite3_malloc( sizeof(int)*(nRoot+1) );
if( aRoot==0 ) goto no_mem;
j = pOp->p1;
assert( j>=0 && j<p->nMem );
pnErr = &p->aMem[j];
assert( (pnErr->flags & MEM_Int)!=0 );
for(j=0; j<nRoot; j++){
aRoot[j] = pTos[-j].u.i;
aRoot[j] = (pTos-j)->u.i;
}
aRoot[j] = 0;
popStack(&pTos, nRoot);
pTos++;
assert( pOp->p2>=0 && pOp->p2<db->nDb );
assert( (p->btreeMask & (1<<pOp->p2))!=0 );
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot,
pnErr->u.i, &nErr);
pnErr->u.i -= nErr;
@ -4325,7 +4363,7 @@ case OP_IntegrityCk: {
}
pTos->enc = SQLITE_UTF8;
sqlite3VdbeChangeEncoding(pTos, encoding);
sqliteFree(aRoot);
sqlite3_free(aRoot);
break;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
@ -4338,7 +4376,9 @@ case OP_IntegrityCk: {
case OP_FifoWrite: { /* no-push */
assert( pTos>=p->aStack );
sqlite3VdbeMemIntegerify(pTos);
sqlite3VdbeFifoPush(&p->sFifo, pTos->u.i);
if( sqlite3VdbeFifoPush(&p->sFifo, pTos->u.i)==SQLITE_NOMEM ){
goto no_mem;
}
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
break;
@ -4378,7 +4418,7 @@ case OP_ContextPush: { /* no-push */
/* FIX ME: This should be allocated as part of the vdbe at compile-time */
if( i>=p->contextStackDepth ){
p->contextStackDepth = i+1;
p->contextStack = sqliteReallocOrFree(p->contextStack,
p->contextStack = sqlite3DbReallocOrFree(db, p->contextStack,
sizeof(Context)*(i+1));
if( p->contextStack==0 ) goto no_mem;
}
@ -4610,6 +4650,7 @@ case OP_AggStep: { /* no-push */
ctx.s.flags = MEM_Null;
ctx.s.z = 0;
ctx.s.xDel = 0;
ctx.s.db = db;
ctx.isError = 0;
ctx.pColl = 0;
if( ctx.pFunc->needCollSeq ){
@ -4682,6 +4723,7 @@ case OP_IncrVacuum: { /* no-push */
Btree *pBt;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
pBt = db->aDb[pOp->p1].pBt;
rc = sqlite3BtreeIncrVacuum(pBt);
if( rc==SQLITE_DONE ){
@ -4733,6 +4775,8 @@ case OP_TableLock: { /* no-push */
if( isWriteLock ){
p1 = (-1*p1)-1;
}
assert( p1>=0 && p1<db->nDb );
assert( (p->btreeMask & (1<<p1))!=0 );
rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
if( rc==SQLITE_LOCKED ){
const char *z = (const char *)pOp->p3;
@ -4808,6 +4852,7 @@ case OP_VOpen: { /* no-push */
pCur->pVtabCursor = pVtabCursor;
pCur->pModule = pVtabCursor->pVtab->pModule;
}else{
db->mallocFailed = 1;
pModule->xClose(pVtabCursor);
}
}
@ -4932,6 +4977,7 @@ case OP_VColumn: {
sqlite3_context sContext;
memset(&sContext, 0, sizeof(sContext));
sContext.s.flags = MEM_Null;
sContext.s.db = db;
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
@ -5132,6 +5178,7 @@ default: {
** cell, so avoid calling MemSanity() in this case.
*/
if( pTos>=p->aStack && pTos->flags ){
assert( pTos->db==db );
sqlite3VdbeMemSanity(pTos);
assert( !sqlite3VdbeMemTooBig(pTos) );
}
@ -5176,6 +5223,12 @@ vdbe_halt:
}
sqlite3VdbeHalt(p);
p->pTos = pTos;
/* This is the only way out of this procedure. We have to
** release the mutexes on btrees that were acquired at the
** top. */
vdbe_return:
sqlite3BtreeMutexArrayLeave(&p->aMutex);
return rc;
/* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH
@ -5189,6 +5242,7 @@ too_big:
/* Jump to here if a malloc() fails.
*/
no_mem:
db->mallocFailed = 1;
sqlite3SetString(&p->zErrMsg, "out of memory", (char*)0);
rc = SQLITE_NOMEM;
goto vdbe_halt;
@ -5204,7 +5258,7 @@ abort_due_to_misuse:
*/
abort_due_to_error:
if( p->zErrMsg==0 ){
if( sqlite3MallocFailed() ) rc = SQLITE_NOMEM;
if( db->mallocFailed ) rc = SQLITE_NOMEM;
sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0);
}
goto vdbe_halt;

View File

@ -120,6 +120,7 @@ void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
void sqlite3VdbeJumpHere(Vdbe*, int addr);
void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
void sqlite3VdbeUsesBtree(Vdbe*, int);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
int sqlite3VdbeMakeLabel(Vdbe*);
void sqlite3VdbeDelete(Vdbe*);

View File

@ -25,13 +25,6 @@
#define keyToInt(X) (X)
#define intToKey(X) (X)
/*
** The makefile scans the vdbe.c source file and creates the following
** array of string constants which are the names of all VDBE opcodes. This
** array is defined in a separate source code file named opcode.c which is
** automatically generated by the makefile.
*/
extern const char *const sqlite3OpcodeNames[];
/*
** SQL is translated into a sequence of instructions to be
@ -130,6 +123,7 @@ struct Mem {
FuncDef *pDef; /* Used only when flags==MEM_Agg */
} u;
double r; /* Real value */
sqlite3 *db; /* The associated database connection */
char *z; /* String or BLOB value */
int n; /* Number of characters in string value, including '\0' */
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
@ -323,7 +317,7 @@ struct Vdbe {
unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */
int errorAction; /* Recovery action to do in case of an error */
int inTempTrans; /* True if temp database is transactioned */
int returnStack[100]; /* Return address stack for OP_Gosub & OP_Return */
int returnStack[25]; /* Return address stack for OP_Gosub & OP_Return */
int returnDepth; /* Next unused element in returnStack[] */
int nResColumn; /* Number of columns in one row of the result set */
char **azResColumn; /* Values for one row of result */
@ -338,6 +332,8 @@ struct Vdbe {
u8 inVtabMethod; /* See comments above */
int nChange; /* Number of db changes made since last reset */
i64 startTime; /* Time when query started - used for profiling */
int btreeMask; /* Bitmask of db->aDb[] entries referenced */
BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */
int nSql; /* Number of bytes in zSql */
char *zSql; /* Text of the SQL statement that generated this */
#ifdef SQLITE_DEBUG
@ -374,7 +370,7 @@ int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*);
int sqlite3VdbeIdxKeyCompare(Cursor*,int,const unsigned char*,int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*);
@ -405,6 +401,8 @@ int sqlite3VdbeMemNumerify(Mem*);
int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
void sqlite3VdbeMemRelease(Mem *p);
int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
const char *sqlite3OpcodeName(int);
#ifndef NDEBUG
void sqlite3VdbeMemSanity(Mem*);
int sqlite3VdbeOpcodeNoPush(u8);

View File

@ -15,7 +15,6 @@
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
#include "os.h"
/*
** Return TRUE (non-zero) of the statement supplied as an argument needs
@ -30,6 +29,68 @@ int sqlite3_expired(sqlite3_stmt *pStmt){
return p==0 || p->expired;
}
/*
** The following routine destroys a virtual machine that is created by
** the sqlite3_compile() routine. The integer returned is an SQLITE_
** success/failure code that describes the result of executing the virtual
** machine.
**
** This routine sets the error code and string returned by
** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
*/
int sqlite3_finalize(sqlite3_stmt *pStmt){
int rc;
if( pStmt==0 ){
rc = SQLITE_OK;
}else{
Vdbe *v = (Vdbe*)pStmt;
sqlite3_mutex *mutex = v->db->mutex;
sqlite3_mutex_enter(mutex);
rc = sqlite3VdbeFinalize(v);
sqlite3_mutex_leave(mutex);
}
return rc;
}
/*
** Terminate the current execution of an SQL statement and reset it
** back to its starting state so that it can be reused. A success code from
** the prior execution is returned.
**
** This routine sets the error code and string returned by
** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
*/
int sqlite3_reset(sqlite3_stmt *pStmt){
int rc;
if( pStmt==0 ){
rc = SQLITE_OK;
}else{
Vdbe *v = (Vdbe*)pStmt;
sqlite3_mutex_enter(v->db->mutex);
rc = sqlite3VdbeReset(v);
sqlite3VdbeMakeReady(v, -1, 0, 0, 0);
assert( (rc & (v->db->errMask))==rc );
sqlite3_mutex_leave(v->db->mutex);
}
return rc;
}
/*
** Set all the parameters in the compiled SQL statement to NULL.
*/
int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
int i;
int rc = SQLITE_OK;
Vdbe *v = (Vdbe*)pStmt;
sqlite3_mutex_enter(v->db->mutex);
for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){
rc = sqlite3_bind_null(pStmt, i);
}
sqlite3_mutex_leave(v->db->mutex);
return rc;
}
/**************************** sqlite3_value_ *******************************
** The following routines extract information from a Mem or sqlite3_value
** structure.
@ -77,7 +138,6 @@ const void *sqlite3_value_text16le(sqlite3_value *pVal){
int sqlite3_value_type(sqlite3_value* pVal){
return pVal->type;
}
/* sqlite3_value_numeric_type() defined in vdbe.c */
/**************************** sqlite3_result_ *******************************
** The following routines are used by user-defined functions to specify
@ -90,28 +150,35 @@ void sqlite3_result_blob(
void (*xDel)(void *)
){
assert( n>=0 );
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetStr(&pCtx->s, z, n, 0, xDel);
}
void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetDouble(&pCtx->s, rVal);
}
void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
pCtx->isError = 1;
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
}
#ifndef SQLITE_OMIT_UTF16
void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
pCtx->isError = 1;
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
}
#endif
void sqlite3_result_int(sqlite3_context *pCtx, int iVal){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetInt64(&pCtx->s, (i64)iVal);
}
void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetInt64(&pCtx->s, iVal);
}
void sqlite3_result_null(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetNull(&pCtx->s);
}
void sqlite3_result_text(
@ -120,6 +187,7 @@ void sqlite3_result_text(
int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, xDel);
}
#ifndef SQLITE_OMIT_UTF16
@ -129,6 +197,7 @@ void sqlite3_result_text16(
int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, xDel);
}
void sqlite3_result_text16be(
@ -137,6 +206,7 @@ void sqlite3_result_text16be(
int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16BE, xDel);
}
void sqlite3_result_text16le(
@ -145,21 +215,32 @@ void sqlite3_result_text16le(
int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16LE, xDel);
}
#endif /* SQLITE_OMIT_UTF16 */
void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemCopy(&pCtx->s, pValue);
}
void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetZeroBlob(&pCtx->s, n);
}
/* Force an SQLITE_TOOBIG error. */
void sqlite3_result_error_toobig(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetZeroBlob(&pCtx->s, SQLITE_MAX_LENGTH+1);
}
/* An SQLITE_NOMEM error. */
void sqlite3_result_error_nomem(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetNull(&pCtx->s);
pCtx->isError = 1;
pCtx->s.db->mallocFailed = 1;
}
/*
** Execute the statement pStmt, either until a row of data is ready, the
@ -175,7 +256,8 @@ static int sqlite3Step(Vdbe *p){
int rc;
/* Assert that malloc() has not failed */
assert( !sqlite3MallocFailed() );
db = p->db;
assert( !db->mallocFailed );
if( p==0 || p->magic!=VDBE_MAGIC_RUN ){
return SQLITE_MISUSE;
@ -190,7 +272,6 @@ static int sqlite3Step(Vdbe *p){
rc = SQLITE_ERROR;
goto end_of_step;
}
db = p->db;
if( sqlite3SafetyOn(db) ){
p->rc = SQLITE_MISUSE;
return SQLITE_MISUSE;
@ -221,7 +302,7 @@ static int sqlite3Step(Vdbe *p){
}
if( db->xProfile && !db->init.busy ){
double rNow;
sqlite3OsCurrentTime(&rNow);
sqlite3OsCurrentTime(db->pVfs, &rNow);
p->startTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0;
}
#endif
@ -258,7 +339,7 @@ static int sqlite3Step(Vdbe *p){
double rNow;
u64 elapseTime;
sqlite3OsCurrentTime(&rNow);
sqlite3OsCurrentTime(db->pVfs, &rNow);
elapseTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0 - p->startTime;
assert( p->nOp>0 );
assert( p->aOp[p->nOp-1].opcode==OP_Noop );
@ -291,19 +372,27 @@ end_of_step:
*/
#ifdef SQLITE_OMIT_PARSER
int sqlite3_step(sqlite3_stmt *pStmt){
return sqlite3Step((Vdbe*)pStmt);
int rc;
Vdbe *v;
v = (Vdbe*)pStmt;
sqlite3_mutex_enter(v->db->mutex);
rc = sqlite3Step(v);
sqlite3_mutex_leave(v->db->mutex);
return rc;
}
#else
int sqlite3_step(sqlite3_stmt *pStmt){
int cnt = 0;
int rc;
Vdbe *v = (Vdbe*)pStmt;
sqlite3_mutex_enter(v->db->mutex);
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < 5
&& sqlite3Reprepare(v) ){
sqlite3_reset(pStmt);
v->expired = 0;
}
sqlite3_mutex_leave(v->db->mutex);
return rc;
}
#endif
@ -332,10 +421,10 @@ void sqlite3InvalidFunction(
){
const char *zName = context->pFunc->zName;
char *zErr;
zErr = sqlite3MPrintf(
zErr = sqlite3MPrintf(0,
"unable to use function %s in the requested context", zName);
sqlite3_result_error(context, zErr, -1);
sqliteFree(zErr);
sqlite3_free(zErr);
}
/*
@ -344,21 +433,23 @@ void sqlite3InvalidFunction(
** same context that was returned on prior calls.
*/
void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
Mem *pMem = p->pMem;
Mem *pMem;
assert( p && p->pFunc && p->pFunc->xStep );
assert( sqlite3_mutex_held(p->s.db->mutex) );
pMem = p->pMem;
if( (pMem->flags & MEM_Agg)==0 ){
if( nByte==0 ){
assert( pMem->flags==MEM_Null );
pMem->z = 0;
}else{
pMem->flags = MEM_Agg;
pMem->xDel = sqlite3FreeX;
pMem->xDel = sqlite3_free;
pMem->u.pDef = p->pFunc;
if( nByte<=NBFS ){
pMem->z = pMem->zShort;
memset(pMem->z, 0, nByte);
}else{
pMem->z = sqliteMalloc( nByte );
pMem->z = sqlite3DbMallocZero(p->s.db, nByte);
}
}
}
@ -370,7 +461,10 @@ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
** the user-function defined by pCtx.
*/
void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
VdbeFunc *pVdbeFunc = pCtx->pVdbeFunc;
VdbeFunc *pVdbeFunc;
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
pVdbeFunc = pCtx->pVdbeFunc;
if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){
return 0;
}
@ -390,16 +484,19 @@ void sqlite3_set_auxdata(
){
struct AuxData *pAuxData;
VdbeFunc *pVdbeFunc;
if( iArg<0 ) return;
if( iArg<0 ) goto failed;
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
pVdbeFunc = pCtx->pVdbeFunc;
if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){
int nAux = (pVdbeFunc ? pVdbeFunc->nAux : 0);
int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg;
pVdbeFunc = sqliteRealloc(pVdbeFunc, nMalloc);
if( !pVdbeFunc ) return;
pVdbeFunc = sqlite3DbRealloc(pCtx->s.db, pVdbeFunc, nMalloc);
if( !pVdbeFunc ){
goto failed;
}
pCtx->pVdbeFunc = pVdbeFunc;
memset(&pVdbeFunc->apAux[pVdbeFunc->nAux], 0,
sizeof(struct AuxData)*(iArg+1-pVdbeFunc->nAux));
memset(&pVdbeFunc->apAux[nAux], 0, sizeof(struct AuxData)*(iArg+1-nAux));
pVdbeFunc->nAux = iArg+1;
pVdbeFunc->pFunc = pCtx->pFunc;
}
@ -410,6 +507,12 @@ void sqlite3_set_auxdata(
}
pAuxData->pAux = pAux;
pAuxData->xDelete = xDelete;
return;
failed:
if( xDelete ){
xDelete(pAux);
}
}
/*
@ -452,14 +555,24 @@ int sqlite3_data_count(sqlite3_stmt *pStmt){
** of NULL.
*/
static Mem *columnMem(sqlite3_stmt *pStmt, int i){
Vdbe *pVm = (Vdbe *)pStmt;
int vals = sqlite3_data_count(pStmt);
if( pVm==0 || pVm->resOnStack==0 || i>=pVm->nResColumn || i<0 ){
static const Mem nullMem = {{0}, 0.0, "", 0, MEM_Null, SQLITE_NULL };
sqlite3Error(pVm->db, SQLITE_RANGE, 0);
return (Mem*)&nullMem;
Vdbe *pVm;
int vals;
Mem *pOut;
pVm = (Vdbe *)pStmt;
if( pVm && pVm->resOnStack && i<pVm->nResColumn && i>=0 ){
sqlite3_mutex_enter(pVm->db->mutex);
vals = sqlite3_data_count(pStmt);
pOut = &pVm->pTos[(1-vals)+i];
}else{
static const Mem nullMem = {{0}, 0.0, 0, "", 0, MEM_Null, SQLITE_NULL };
if( pVm->db ){
sqlite3_mutex_enter(pVm->db->mutex);
sqlite3Error(pVm->db, SQLITE_RANGE, 0);
}
pOut = (Mem*)&nullMem;
}
return &pVm->pTos[(1-vals)+i];
return pOut;
}
/*
@ -469,7 +582,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
** malloc() has failed, the threads mallocFailed flag is cleared and the result
** code of statement pStmt set to SQLITE_NOMEM.
**
** Specificly, this is called from within:
** Specifically, this is called from within:
**
** sqlite3_column_int()
** sqlite3_column_int64()
@ -489,7 +602,10 @@ static void columnMallocFailure(sqlite3_stmt *pStmt)
** and _finalize() will return NOMEM.
*/
Vdbe *p = (Vdbe *)pStmt;
p->rc = sqlite3ApiExit(0, p->rc);
if( p ){
p->rc = sqlite3ApiExit(p->db, p->rc);
sqlite3_mutex_leave(p->db->mutex);
}
}
/**************************** sqlite3_column_ *******************************
@ -537,7 +653,9 @@ const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){
return val;
}
sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){
return columnMem(pStmt, i);
sqlite3_value *pOut = columnMem(pStmt, i);
columnMallocFailure(pStmt);
return pOut;
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
@ -547,7 +665,9 @@ const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
}
#endif /* SQLITE_OMIT_UTF16 */
int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
return sqlite3_value_type( columnMem(pStmt,i) );
int iType = sqlite3_value_type( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return iType;
}
/* The following function is experimental and subject to change or
@ -579,20 +699,28 @@ static const void *columnName(
const void *(*xFunc)(Mem*),
int useType
){
const void *ret;
const void *ret = 0;
Vdbe *p = (Vdbe *)pStmt;
int n = sqlite3_column_count(pStmt);
int n;
if( p==0 || N>=n || N<0 ){
return 0;
if( p!=0 ){
n = sqlite3_column_count(pStmt);
if( N<n && N>=0 ){
N += useType*n;
sqlite3_mutex_enter(p->db->mutex);
ret = xFunc(&p->aColName[N]);
/* A malloc may have failed inside of the xFunc() call. If this
** is the case, clear the mallocFailed flag and return NULL.
*/
if( p->db && p->db->mallocFailed ){
p->db->mallocFailed = 0;
ret = 0;
}
sqlite3_mutex_leave(p->db->mutex);
}
}
N += useType*n;
ret = xFunc(&p->aColName[N]);
/* A malloc may have failed inside of the xFunc() call. If this is the case,
** clear the mallocFailed flag and return NULL.
*/
sqlite3ApiExit(0, 0);
return ret;
}
@ -711,29 +839,33 @@ static int vdbeUnbind(Vdbe *p, int i){
** Bind a text or BLOB value.
*/
static int bindText(
sqlite3_stmt *pStmt,
int i,
const void *zData,
int nData,
void (*xDel)(void*),
int encoding
sqlite3_stmt *pStmt, /* The statement to bind against */
int i, /* Index of the parameter to bind */
const void *zData, /* Pointer to the data to be bound */
int nData, /* Number of bytes of data to be bound */
void (*xDel)(void*), /* Destructor for the data */
int encoding /* Encoding for the data */
){
Vdbe *p = (Vdbe *)pStmt;
Mem *pVar;
int rc;
if( p==0 ){
return SQLITE_MISUSE;
}
sqlite3_mutex_enter(p->db->mutex);
rc = vdbeUnbind(p, i);
if( rc || zData==0 ){
return rc;
if( rc==SQLITE_OK && zData!=0 ){
pVar = &p->aVar[i-1];
rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
if( rc==SQLITE_OK && encoding!=0 ){
rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
}
sqlite3Error(p->db, rc, 0);
rc = sqlite3ApiExit(p->db, rc);
}
pVar = &p->aVar[i-1];
rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
if( rc==SQLITE_OK && encoding!=0 ){
rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
}
sqlite3Error(((Vdbe *)pStmt)->db, rc, 0);
return sqlite3ApiExit(((Vdbe *)pStmt)->db, rc);
sqlite3_mutex_leave(p->db->mutex);
return rc;
}
@ -752,10 +884,12 @@ int sqlite3_bind_blob(
int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
sqlite3_mutex_enter(p->db->mutex);
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
}
sqlite3_mutex_leave(p->db->mutex);
return rc;
}
int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
@ -764,14 +898,21 @@ int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
sqlite3_mutex_enter(p->db->mutex);
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
}
sqlite3_mutex_leave(p->db->mutex);
return rc;
}
int sqlite3_bind_null(sqlite3_stmt* p, int i){
return vdbeUnbind((Vdbe *)p, i);
int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
int rc;
Vdbe *p = (Vdbe*)pStmt;
sqlite3_mutex_enter(p->db->mutex);
rc = vdbeUnbind(p, i);
sqlite3_mutex_leave(p->db->mutex);
return rc;
}
int sqlite3_bind_text(
sqlite3_stmt *pStmt,
@ -796,19 +937,23 @@ int sqlite3_bind_text16(
int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
sqlite3_mutex_enter(p->db->mutex);
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3VdbeMemCopy(&p->aVar[i-1], pValue);
rc = sqlite3VdbeMemCopy(&p->aVar[i-1], pValue);
}
sqlite3_mutex_leave(p->db->mutex);
return rc;
}
int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
int rc;
Vdbe *p = (Vdbe *)pStmt;
sqlite3_mutex_enter(p->db->mutex);
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
}
sqlite3_mutex_leave(p->db->mutex);
return rc;
}
@ -828,15 +973,19 @@ int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
*/
static void createVarMap(Vdbe *p){
if( !p->okVar ){
int j;
Op *pOp;
for(j=0, pOp=p->aOp; j<p->nOp; j++, pOp++){
if( pOp->opcode==OP_Variable ){
assert( pOp->p1>0 && pOp->p1<=p->nVar );
p->azVar[pOp->p1-1] = pOp->p3;
sqlite3_mutex_enter(p->db->mutex);
if( !p->okVar ){
int j;
Op *pOp;
for(j=0, pOp=p->aOp; j<p->nOp; j++, pOp++){
if( pOp->opcode==OP_Variable ){
assert( pOp->p1>0 && pOp->p1<=p->nVar );
p->azVar[pOp->p1-1] = pOp->p3;
}
}
p->okVar = 1;
}
p->okVar = 1;
sqlite3_mutex_leave(p->db->mutex);
}
}
@ -888,17 +1037,20 @@ int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
Vdbe *pTo = (Vdbe*)pToStmt;
int i, rc = SQLITE_OK;
if( (pFrom->magic!=VDBE_MAGIC_RUN && pFrom->magic!=VDBE_MAGIC_HALT)
|| (pTo->magic!=VDBE_MAGIC_RUN && pTo->magic!=VDBE_MAGIC_HALT) ){
|| (pTo->magic!=VDBE_MAGIC_RUN && pTo->magic!=VDBE_MAGIC_HALT)
|| pTo->db!=pFrom->db ){
return SQLITE_MISUSE;
}
if( pFrom->nVar!=pTo->nVar ){
return SQLITE_ERROR;
}
sqlite3_mutex_enter(pTo->db->mutex);
for(i=0; rc==SQLITE_OK && i<pFrom->nVar; i++){
sqlite3MallocDisallow();
rc = sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]);
sqlite3MallocAllow();
}
sqlite3_mutex_leave(pTo->db->mutex);
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
return rc;
}

View File

@ -15,11 +15,11 @@
** But that file was getting too big so this subroutines were split out.
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"
/*
** When debugging the code generator in a symbolic debugger, one can
** set the sqlite3_vdbe_addop_trace to 1 and all opcodes will be printed
@ -35,7 +35,7 @@ int sqlite3_vdbe_addop_trace = 0;
*/
Vdbe *sqlite3VdbeCreate(sqlite3 *db){
Vdbe *p;
p = sqliteMalloc( sizeof(Vdbe) );
p = sqlite3DbMallocZero(db, sizeof(Vdbe) );
if( p==0 ) return 0;
p->db = db;
if( db->pVdbe ){
@ -54,7 +54,7 @@ Vdbe *sqlite3VdbeCreate(sqlite3 *db){
void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n){
if( p==0 ) return;
assert( p->zSql==0 );
p->zSql = sqlite3StrNDup(z, n);
p->zSql = sqlite3DbStrNDup(p->db, z, n);
}
/*
@ -115,7 +115,7 @@ static void resizeOpArray(Vdbe *p, int N){
VdbeOp *pNew;
int nNew = N + 100*(!runMode);
int oldSize = p->nOpAlloc;
pNew = sqliteRealloc(p->aOp, nNew*sizeof(Op));
pNew = sqlite3DbRealloc(p->db, p->aOp, nNew*sizeof(Op));
if( pNew ){
p->nOpAlloc = nNew;
p->aOp = pNew;
@ -150,7 +150,7 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){
assert( p->magic==VDBE_MAGIC_INIT );
if( p->nOpAlloc<=i ){
resizeOpArray(p, i+1);
if( sqlite3MallocFailed() ){
if( p->db->mallocFailed ){
return 0;
}
}
@ -197,7 +197,7 @@ int sqlite3VdbeMakeLabel(Vdbe *p){
assert( p->magic==VDBE_MAGIC_INIT );
if( i>=p->nLabelAlloc ){
p->nLabelAlloc = p->nLabelAlloc*2 + 10;
p->aLabel = sqliteReallocOrFree(p->aLabel,
p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
p->nLabelAlloc*sizeof(p->aLabel[0]));
}
if( p->aLabel ){
@ -325,7 +325,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
assert( -1-pOp->p2<p->nLabel );
pOp->p2 = aLabel[-1-pOp->p2];
}
sqliteFree(p->aLabel);
sqlite3_free(p->aLabel);
p->aLabel = 0;
*pMaxFuncArgs = nMaxArgs;
@ -361,7 +361,7 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
int addr;
assert( p->magic==VDBE_MAGIC_INIT );
resizeOpArray(p, p->nOp + nOp);
if( sqlite3MallocFailed() ){
if( p->db->mallocFailed ){
return 0;
}
addr = p->nOp;
@ -427,7 +427,7 @@ void sqlite3VdbeJumpHere(Vdbe *p, int addr){
*/
static void freeEphemeralFunction(FuncDef *pDef){
if( pDef && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){
sqliteFree(pDef);
sqlite3_free(pDef);
}
}
@ -440,7 +440,7 @@ static void freeP3(int p3type, void *p3){
case P3_DYNAMIC:
case P3_KEYINFO:
case P3_KEYINFO_HANDOFF: {
sqliteFree(p3);
sqlite3_free(p3);
break;
}
case P3_MPRINTF: {
@ -451,7 +451,7 @@ static void freeP3(int p3type, void *p3){
VdbeFunc *pVdbeFunc = (VdbeFunc *)p3;
freeEphemeralFunction(pVdbeFunc->pFunc);
sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
sqliteFree(pVdbeFunc);
sqlite3_free(pVdbeFunc);
break;
}
case P3_FUNCDEF: {
@ -489,15 +489,15 @@ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
** few minor changes to the program.
**
** If n>=0 then the P3 operand is dynamic, meaning that a copy of
** the string is made into memory obtained from sqliteMalloc().
** the string is made into memory obtained from sqlite3_malloc().
** A value of n==0 means copy bytes of zP3 up to and including the
** first null byte. If n>0 then copy n+1 bytes of zP3.
**
** If n==P3_KEYINFO it means that zP3 is a pointer to a KeyInfo structure.
** A copy is made of the KeyInfo structure into memory obtained from
** sqliteMalloc, to be freed when the Vdbe is finalized.
** sqlite3_malloc, to be freed when the Vdbe is finalized.
** n==P3_KEYINFO_HANDOFF indicates that zP3 points to a KeyInfo structure
** stored in memory that the caller has obtained from sqliteMalloc. The
** stored in memory that the caller has obtained from sqlite3_malloc. The
** caller should not free the allocation, it will be freed when the Vdbe is
** finalized.
**
@ -510,7 +510,7 @@ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
Op *pOp;
assert( p==0 || p->magic==VDBE_MAGIC_INIT );
if( p==0 || p->aOp==0 || sqlite3MallocFailed() ){
if( p==0 || p->aOp==0 || p->db->mallocFailed ){
if (n != P3_KEYINFO) {
freeP3(n, (void*)*(char**)&zP3);
}
@ -532,7 +532,7 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
nField = ((KeyInfo*)zP3)->nField;
nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField;
pKeyInfo = sqliteMallocRaw( nByte );
pKeyInfo = sqlite3_malloc( nByte );
pOp->p3 = (char*)pKeyInfo;
if( pKeyInfo ){
unsigned char *aSortOrder;
@ -544,6 +544,7 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
}
pOp->p3type = P3_KEYINFO;
}else{
p->db->mallocFailed = 1;
pOp->p3type = P3_NOTUSED;
}
}else if( n==P3_KEYINFO_HANDOFF ){
@ -554,7 +555,7 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
pOp->p3type = n;
}else{
if( n==0 ) n = strlen(zP3);
pOp->p3 = sqliteStrNDup(zP3, n);
pOp->p3 = sqlite3DbStrNDup(p->db, zP3, n);
pOp->p3type = P3_DYNAMIC;
}
}
@ -567,9 +568,9 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
va_list ap;
assert( p->nOp>0 || p->aOp==0 );
assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0 || sqlite3MallocFailed() );
assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0 || p->db->mallocFailed );
va_start(ap, zFormat);
sqlite3VdbeChangeP3(p, -1, sqlite3VMPrintf(zFormat, ap), P3_DYNAMIC);
sqlite3VdbeChangeP3(p, -1, sqlite3VMPrintf(p->db, zFormat, ap), P3_DYNAMIC);
va_end(ap);
}
#endif
@ -579,7 +580,7 @@ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
*/
VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
assert( p->magic==VDBE_MAGIC_INIT );
assert( (addr>=0 && addr<p->nOp) || sqlite3MallocFailed() );
assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed );
return ((addr>=0 && addr<p->nOp)?(&p->aOp[addr]):0);
}
@ -655,6 +656,21 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){
}
#endif
/*
** Declare to the Vdbe that the BTree object at db->aDb[i] is used.
**
*/
void sqlite3VdbeUsesBtree(Vdbe *p, int i){
int mask;
assert( i>=0 && i<p->db->nDb );
assert( i<sizeof(p->btreeMask)*8 );
mask = 1<<i;
if( (p->btreeMask & mask)==0 ){
p->btreeMask |= mask;
sqlite3BtreeMutexArrayInsert(&p->aMutex, p->db->aDb[i].pBt);
}
}
#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
/*
@ -667,7 +683,7 @@ void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
if( pOut==0 ) pOut = stdout;
zP3 = displayP3(pOp, zPtr, sizeof(zPtr));
fprintf(pOut, zFormat1,
pc, sqlite3OpcodeNames[pOp->opcode], pOp->p1, pOp->p2, zP3);
pc, sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, zP3);
fflush(pOut);
}
#endif
@ -678,6 +694,7 @@ void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
static void releaseMemArray(Mem *p, int N){
if( p ){
while( N-->0 ){
assert( N<2 || p[0].db==p[1].db );
sqlite3VdbeMemRelease(p++);
}
}
@ -731,7 +748,7 @@ int sqlite3VdbeList(
pMem++;
pMem->flags = MEM_Static|MEM_Str|MEM_Term;
pMem->z = (char*)sqlite3OpcodeNames[pOp->opcode]; /* Opcode */
pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
assert( pMem->z!=0 );
pMem->n = strlen(pMem->z);
pMem->type = SQLITE_TEXT;
@ -793,8 +810,9 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){
if( nOp<1 ) return;
pOp = &p->aOp[nOp-1];
if( pOp->opcode==OP_Noop && pOp->p3!=0 ){
char *z = sqlite3StrDup(pOp->p3);
int i, j;
char z[1000];
sqlite3_snprintf(sizeof(z), z, "%s", pOp->p3);
for(i=0; isspace((unsigned char)z[i]); i++){}
for(j=0; z[i]; i++){
if( isspace((unsigned char)z[i]) ){
@ -807,7 +825,6 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){
}
z[j] = 0;
sqlite3_io_trace("SQL %s\n", z);
sqliteFree(z);
}
}
#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */
@ -830,6 +847,7 @@ void sqlite3VdbeMakeReady(
int isExplain /* True if the EXPLAIN keywords is present */
){
int n;
sqlite3 *db = p->db;
assert( p!=0 );
assert( p->magic==VDBE_MAGIC_INIT );
@ -864,7 +882,7 @@ void sqlite3VdbeMakeReady(
if( isExplain ){
nStack = 10;
}
p->aStack = sqliteMalloc(
p->aStack = sqlite3DbMallocZero(db,
nStack*sizeof(p->aStack[0]) /* aStack */
+ nArg*sizeof(Mem*) /* apArg */
+ nVar*sizeof(Mem) /* aVar */
@ -872,7 +890,7 @@ void sqlite3VdbeMakeReady(
+ nMem*sizeof(Mem) /* aMem */
+ nCursor*sizeof(Cursor*) /* apCsr */
);
if( !sqlite3MallocFailed() ){
if( !db->mallocFailed ){
p->aMem = &p->aStack[nStack];
p->nMem = nMem;
p->aVar = &p->aMem[nMem];
@ -884,11 +902,16 @@ void sqlite3VdbeMakeReady(
p->nCursor = nCursor;
for(n=0; n<nVar; n++){
p->aVar[n].flags = MEM_Null;
p->aVar[n].db = db;
}
for(n=0; n<nStack; n++){
p->aStack[n].db = db;
}
}
}
for(n=0; n<p->nMem; n++){
p->aMem[n].flags = MEM_Null;
p->aMem[n].db = db;
}
p->pTos = &p->aStack[-1];
@ -916,7 +939,7 @@ void sqlite3VdbeMakeReady(
}
/*
** Close a cursor and release all the resources that cursor happens
** Close a VDBE cursor and release all the resources that cursor happens
** to hold.
*/
void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){
@ -940,20 +963,22 @@ void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){
p->inVtabMethod = 0;
}
#endif
sqliteFree(pCx->pData);
sqliteFree(pCx->aType);
sqliteFree(pCx);
sqlite3_free(pCx->pData);
sqlite3_free(pCx->aType);
sqlite3_free(pCx);
}
/*
** Close all cursors
** Close all cursors except for VTab cursors that are currently
** in use.
*/
static void closeAllCursors(Vdbe *p){
static void closeAllCursorsExceptActiveVtabs(Vdbe *p){
int i;
if( p->apCsr==0 ) return;
for(i=0; i<p->nCursor; i++){
if( !p->inVtabMethod || (p->apCsr[i] && !p->apCsr[i]->pVtabCursor) ){
sqlite3VdbeFreeCursor(p, p->apCsr[i]);
Cursor *pC = p->apCsr[i];
if( pC && (!p->inVtabMethod || !pC->pVtabCursor) ){
sqlite3VdbeFreeCursor(p, pC);
p->apCsr[i] = 0;
}
}
@ -972,19 +997,19 @@ static void Cleanup(Vdbe *p){
releaseMemArray(p->aStack, 1 + (p->pTos - p->aStack));
p->pTos = &p->aStack[-1];
}
closeAllCursors(p);
closeAllCursorsExceptActiveVtabs(p);
releaseMemArray(p->aMem, p->nMem);
sqlite3VdbeFifoClear(&p->sFifo);
if( p->contextStack ){
for(i=0; i<p->contextStackTop; i++){
sqlite3VdbeFifoClear(&p->contextStack[i].sFifo);
}
sqliteFree(p->contextStack);
sqlite3_free(p->contextStack);
}
p->contextStack = 0;
p->contextStackDepth = 0;
p->contextStackTop = 0;
sqliteFree(p->zErrMsg);
sqlite3_free(p->zErrMsg);
p->zErrMsg = 0;
p->resOnStack = 0;
}
@ -998,14 +1023,17 @@ static void Cleanup(Vdbe *p){
void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
Mem *pColName;
int n;
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
sqliteFree(p->aColName);
sqlite3_free(p->aColName);
n = nResColumn*COLNAME_N;
p->nResColumn = nResColumn;
p->aColName = pColName = (Mem*)sqliteMalloc( sizeof(Mem)*n );
p->aColName = pColName = (Mem*)sqlite3DbMallocZero(p->db, sizeof(Mem)*n );
if( p->aColName==0 ) return;
while( n-- > 0 ){
(pColName++)->flags = MEM_Null;
pColName->flags = MEM_Null;
pColName->db = p->db;
pColName++;
}
}
@ -1017,7 +1045,7 @@ void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
**
** If N==P3_STATIC it means that zName is a pointer to a constant static
** string and we can just copy the pointer. If it is P3_DYNAMIC, then
** the string is freed using sqliteFree() when the vdbe is finished with
** the string is freed using sqlite3_free() 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){
@ -1025,7 +1053,7 @@ int sqlite3VdbeSetColName(Vdbe *p, int idx, int var, const char *zName, int N){
Mem *pColName;
assert( idx<p->nResColumn );
assert( var<COLNAME_N );
if( sqlite3MallocFailed() ) return SQLITE_NOMEM;
if( p->db->mallocFailed ) return SQLITE_NOMEM;
assert( p->aColName!=0 );
pColName = &(p->aColName[idx+var*p->nResColumn]);
if( N==P3_DYNAMIC || N==P3_STATIC ){
@ -1071,7 +1099,7 @@ static int vdbeCommit(sqlite3 *db){
*/
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt && sqlite3BtreeIsInTrans(pBt) ){
if( sqlite3BtreeIsInTrans(pBt) ){
needXcommit = 1;
if( i!=1 ) nTrans++;
}
@ -1126,26 +1154,31 @@ static int vdbeCommit(sqlite3 *db){
*/
#ifndef SQLITE_OMIT_DISKIO
else{
sqlite3_vfs *pVfs = db->pVfs;
int needSync = 0;
char *zMaster = 0; /* File-name for the master journal */
char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
OsFile *master = 0;
sqlite3_file *pMaster = 0;
i64 offset = 0;
/* Select a master journal file name */
do {
u32 random;
sqliteFree(zMaster);
sqlite3_free(zMaster);
sqlite3Randomness(sizeof(random), &random);
zMaster = sqlite3MPrintf("%s-mj%08X", zMainFile, random&0x7fffffff);
zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, random&0x7fffffff);
if( !zMaster ){
return SQLITE_NOMEM;
}
}while( sqlite3OsFileExists(zMaster) );
}while( sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS) );
/* Open the master journal. */
rc = sqlite3OsOpenExclusive(zMaster, &master, 0);
rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
);
if( rc!=SQLITE_OK ){
sqliteFree(zMaster);
sqlite3_free(zMaster);
return rc;
}
@ -1155,36 +1188,36 @@ static int vdbeCommit(sqlite3 *db){
** still have 'null' as the master journal pointer, so they will roll
** back independently if a failure occurs.
*/
for(i=0; i<db->nDb; i++){
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( i==1 ) continue; /* Ignore the TEMP database */
if( pBt && sqlite3BtreeIsInTrans(pBt) ){
if( sqlite3BtreeIsInTrans(pBt) ){
char const *zFile = sqlite3BtreeGetJournalname(pBt);
if( zFile[0]==0 ) continue; /* Ignore :memory: databases */
if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){
needSync = 1;
}
rc = sqlite3OsWrite(master, zFile, strlen(zFile)+1);
rc = sqlite3OsWrite(pMaster, zFile, strlen(zFile)+1, offset);
offset += strlen(zFile)+1;
if( rc!=SQLITE_OK ){
sqlite3OsClose(&master);
sqlite3OsDelete(zMaster);
sqliteFree(zMaster);
sqlite3OsCloseFree(pMaster);
sqlite3OsDelete(pVfs, zMaster, 0);
sqlite3_free(zMaster);
return rc;
}
}
}
/* Sync the master journal file. Before doing this, open the directory
** the master journal file is store in so that it gets synced too.
/* Sync the master journal file. If the IOCAP_SEQUENTIAL device
** flag is set this is not required.
*/
zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt);
rc = sqlite3OsOpenDirectory(master, zMainFile);
if( rc!=SQLITE_OK ||
(needSync && (rc=sqlite3OsSync(master,0))!=SQLITE_OK) ){
sqlite3OsClose(&master);
sqlite3OsDelete(zMaster);
sqliteFree(zMaster);
if( (needSync
&& (0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL))
&& (rc=sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))!=SQLITE_OK) ){
sqlite3OsCloseFree(pMaster);
sqlite3OsDelete(pVfs, zMaster, 0);
sqlite3_free(zMaster);
return rc;
}
@ -1200,13 +1233,13 @@ static int vdbeCommit(sqlite3 *db){
*/
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt && sqlite3BtreeIsInTrans(pBt) ){
if( pBt ){
rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster);
}
}
sqlite3OsClose(&master);
sqlite3OsCloseFree(pMaster);
if( rc!=SQLITE_OK ){
sqliteFree(zMaster);
sqlite3_free(zMaster);
return rc;
}
@ -1214,23 +1247,12 @@ static int vdbeCommit(sqlite3 *db){
** doing this the directory is synced again before any individual
** transaction files are deleted.
*/
rc = sqlite3OsDelete(zMaster);
sqliteFree(zMaster);
rc = sqlite3OsDelete(pVfs, zMaster, 1);
sqlite3_free(zMaster);
zMaster = 0;
if( rc ){
return rc;
}
rc = sqlite3OsSyncDirectory(zMainFile);
if( rc!=SQLITE_OK ){
/* This is not good. The master journal file has been deleted, but
** the directory sync failed. There is no completely safe course of
** action from here. The individual journals contain the name of the
** master journal file, but there is no way of knowing if that
** master journal exists now or if it will exist after the operating
** system crash that may follow the fsync() failure.
*/
return rc;
}
/* All files and directories have already been synced, so the following
** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and
@ -1282,21 +1304,28 @@ static void checkActiveVdbeCnt(sqlite3 *db){
#endif
/*
** Find every active VM other than pVdbe and change its status to
** aborted. This happens when one VM causes a rollback due to an
** ON CONFLICT ROLLBACK clause (for example). The other VMs must be
** aborted so that they do not have data rolled out from underneath
** them leading to a segfault.
** For every Btree that in database connection db which
** has been modified, "trip" or invalidate each cursor in
** that Btree might have been modified so that the cursor
** can never be used again. This happens when a rollback
*** occurs. We have to trip all the other cursors, even
** cursor from other VMs in different database connections,
** so that none of them try to use the data at which they
** were pointing and which now may have been changed due
** to the rollback.
**
** Remember that a rollback can delete tables complete and
** reorder rootpages. So it is not sufficient just to save
** the state of the cursor. We have to invalidate the cursor
** so that it is never used again.
*/
void sqlite3AbortOtherActiveVdbes(sqlite3 *db, Vdbe *pExcept){
Vdbe *pOther;
for(pOther=db->pVdbe; pOther; pOther=pOther->pNext){
if( pOther==pExcept ) continue;
if( pOther->magic!=VDBE_MAGIC_RUN || pOther->pc<0 ) continue;
checkActiveVdbeCnt(db);
closeAllCursors(pOther);
checkActiveVdbeCnt(db);
pOther->aborted = 1;
void invalidateCursorsOnModifiedBtrees(sqlite3 *db){
int i;
for(i=0; i<db->nDb; i++){
Btree *p = db->aDb[i].pBt;
if( p && sqlite3BtreeIsInTrans(p) ){
sqlite3BtreeTripAllCursors(p, SQLITE_ABORT);
}
}
}
@ -1306,7 +1335,8 @@ void sqlite3AbortOtherActiveVdbes(sqlite3 *db, Vdbe *pExcept){
** changes. If a rollback is needed, then do the rollback.
**
** This routine is the only way to move the state of a VM from
** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT.
** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. It is harmless to
** call this on a VM that is in the SQLITE_MAGIC_HALT state.
**
** Return an error code. If the commit could not complete because of
** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it
@ -1322,51 +1352,38 @@ int sqlite3VdbeHalt(Vdbe *p){
** transaction will be committed or rolled back as a result of the
** execution of this virtual machine.
**
** Special errors:
** If any of the following errors occur:
**
** If an SQLITE_NOMEM error has occured in a statement that writes to
** the database, then either a statement or transaction must be rolled
** back to ensure the tree-structures are in a consistent state. A
** statement transaction is rolled back if one is open, otherwise the
** entire transaction must be rolled back.
**
** If an SQLITE_IOERR error has occured in a statement that writes to
** the database, then the entire transaction must be rolled back. The
** I/O error may have caused garbage to be written to the journal
** file. Were the transaction to continue and eventually be rolled
** back that garbage might end up in the database file.
**
** In both of the above cases, the Vdbe.errorAction variable is
** ignored. If the sqlite3.autoCommit flag is false and a transaction
** is rolled back, it will be set to true.
**
** Other errors:
**
** No error:
** SQLITE_NOMEM
** SQLITE_IOERR
** SQLITE_FULL
** SQLITE_INTERRUPT
**
** Then the internal cache might have been left in an inconsistent
** state. We need to rollback the statement transaction, if there is
** one, or the complete transaction if there is no statement transaction.
*/
if( sqlite3MallocFailed() ){
if( p->db->mallocFailed ){
p->rc = SQLITE_NOMEM;
}
closeAllCursorsExceptActiveVtabs(p);
if( p->magic!=VDBE_MAGIC_RUN ){
/* Already halted. Nothing to do. */
assert( p->magic==VDBE_MAGIC_HALT );
#ifndef SQLITE_OMIT_VIRTUALTABLE
closeAllCursors(p);
#endif
return SQLITE_OK;
}
closeAllCursors(p);
checkActiveVdbeCnt(db);
/* No commit or rollback needed if the program never started */
if( p->pc>=0 ){
int mrc; /* Primary error code from p->rc */
/* Check for one of the special errors - SQLITE_NOMEM or SQLITE_IOERR */
/* Lock all btrees used by the statement */
sqlite3BtreeMutexArrayEnter(&p->aMutex);
/* Check for one of the special errors */
mrc = p->rc & 0xff;
isSpecialError = (
(mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR || mrc==SQLITE_INTERRUPT)?1:0);
isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
|| mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL ;
if( isSpecialError ){
/* This loop does static analysis of the query to see which of the
** following three categories it falls into:
@ -1381,46 +1398,35 @@ int sqlite3VdbeHalt(Vdbe *p){
** this is probably easier. Todo: Might be an opportunity to reduce
** code size a very small amount though...
*/
int isReadOnly = 1;
int notReadOnly = 0;
int isStatement = 0;
assert(p->aOp || p->nOp==0);
for(i=0; i<p->nOp; i++){
switch( p->aOp[i].opcode ){
case OP_Transaction:
/* This is a bit strange. If we hit a malloc() or IO error and
** the statement did not open a statement transaction, we will
** rollback any active transaction and abort all other active
** statements. Or, if this is an SQLITE_INTERRUPT error, we
** will only rollback if the interrupted statement was a write.
**
** It could be argued that read-only statements should never
** rollback anything. But careful analysis is required before
** making this change
*/
if( p->aOp[i].p2 || mrc!=SQLITE_INTERRUPT ){
isReadOnly = 0;
}
notReadOnly |= p->aOp[i].p2;
break;
case OP_Statement:
isStatement = 1;
break;
}
}
/* If the query was read-only, we need do no rollback at all. Otherwise,
** proceed with the special handling.
*/
if( !isReadOnly ){
if( notReadOnly || mrc!=SQLITE_INTERRUPT ){
if( p->rc==SQLITE_IOERR_BLOCKED && isStatement ){
xFunc = sqlite3BtreeRollbackStmt;
p->rc = SQLITE_BUSY;
} else if( p->rc==SQLITE_NOMEM && isStatement ){
} else if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && isStatement ){
xFunc = sqlite3BtreeRollbackStmt;
}else{
/* We are forced to roll back the active transaction. Before doing
** so, abort any other statements this handle currently has active.
*/
sqlite3AbortOtherActiveVdbes(db, p);
invalidateCursorsOnModifiedBtrees(db);
sqlite3RollbackAll(db);
db->autoCommit = 1;
}
@ -1435,12 +1441,13 @@ int sqlite3VdbeHalt(Vdbe *p){
*/
if( db->autoCommit && db->activeVdbeCnt==1 ){
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
/* The auto-commit flag is true, and the vdbe program was
/* The auto-commit flag is true, and the vdbe program was
** successful or hit an 'OR FAIL' constraint. This means a commit
** is required.
*/
int rc = vdbeCommit(db);
if( rc==SQLITE_BUSY ){
sqlite3BtreeMutexArrayLeave(&p->aMutex);
return SQLITE_BUSY;
}else if( rc!=SQLITE_OK ){
p->rc = rc;
@ -1459,7 +1466,7 @@ int sqlite3VdbeHalt(Vdbe *p){
}else if( p->errorAction==OE_Abort ){
xFunc = sqlite3BtreeRollbackStmt;
}else{
sqlite3AbortOtherActiveVdbes(db, p);
invalidateCursorsOnModifiedBtrees(db);
sqlite3RollbackAll(db);
db->autoCommit = 1;
}
@ -1503,6 +1510,9 @@ int sqlite3VdbeHalt(Vdbe *p){
sqlite3ResetInternalSchema(db, 0);
db->flags = (db->flags | SQLITE_InternChanges);
}
/* Release the locks */
sqlite3BtreeMutexArrayLeave(&p->aMutex);
}
/* We have successfully halted and closed the VM. Record this fact. */
@ -1511,10 +1521,15 @@ int sqlite3VdbeHalt(Vdbe *p){
}
p->magic = VDBE_MAGIC_HALT;
checkActiveVdbeCnt(db);
if( p->db->mallocFailed ){
p->rc = SQLITE_NOMEM;
}
checkActiveVdbeCnt(db);
return SQLITE_OK;
}
/*
** Each VDBE holds the result of the most recent sqlite3_step() call
** in p->rc. This routine sets that result back to SQLITE_OK.
@ -1553,7 +1568,7 @@ int sqlite3VdbeReset(Vdbe *p){
*/
if( p->pc>=0 ){
if( p->zErrMsg ){
sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, sqlite3FreeX);
sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,sqlite3_free);
db->errCode = p->rc;
p->zErrMsg = 0;
}else if( p->rc ){
@ -1600,9 +1615,6 @@ int sqlite3VdbeReset(Vdbe *p){
#endif
p->magic = VDBE_MAGIC_INIT;
p->aborted = 0;
if( p->rc==SQLITE_SCHEMA ){
sqlite3ResetInternalSchema(db, 0);
}
return p->rc & db->errMask;
}
@ -1662,16 +1674,16 @@ void sqlite3VdbeDelete(Vdbe *p){
Op *pOp = &p->aOp[i];
freeP3(pOp->p3type, pOp->p3);
}
sqliteFree(p->aOp);
sqlite3_free(p->aOp);
}
releaseMemArray(p->aVar, p->nVar);
sqliteFree(p->aLabel);
sqliteFree(p->aStack);
sqlite3_free(p->aLabel);
sqlite3_free(p->aStack);
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
sqliteFree(p->aColName);
sqliteFree(p->zSql);
sqlite3_free(p->aColName);
sqlite3_free(p->zSql);
p->magic = VDBE_MAGIC_DEAD;
sqliteFree(p);
sqlite3_free(p);
}
/*
@ -1816,11 +1828,24 @@ int sqlite3VdbeSerialTypeLen(u32 serial_type){
** application using -DSQLITE_DEBUG=1 at least once. With DEBUG
** enabled, some asserts below will ensure that the byte order of
** floating point values is correct.
**
** (2007-08-30) Frank van Vugt has studied this problem closely
** and has send his findings to the SQLite developers. Frank
** writes that some Linux kernels offer floating point hardware
** emulation that uses only 32-bit mantissas instead of a full
** 48-bits as required by the IEEE standard. (This is the
** CONFIG_FPE_FASTFPE option.) On such systems, floating point
** byte swapping becomes very complicated. To avoid problems,
** the necessary byte swapping is carried out using a 64-bit integer
** rather than a 64-bit float. Frank assures us that the code here
** works for him. We, the developers, have no way to independently
** verify this, but Frank seems to know what he is talking about
** so we trust him.
*/
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
static double floatSwap(double in){
static u64 floatSwap(u64 in){
union {
double r;
u64 r;
u32 i[2];
} u;
u32 t;
@ -1864,8 +1889,8 @@ int sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){
int i;
if( serial_type==7 ){
assert( sizeof(v)==sizeof(pMem->r) );
swapMixedEndianFloat(pMem->r);
memcpy(&v, &pMem->r, sizeof(v));
swapMixedEndianFloat(v);
}else{
v = pMem->u.i;
}
@ -1955,9 +1980,9 @@ int sqlite3VdbeSerialGet(
*/
static const u64 t1 = ((u64)0x3ff00000)<<32;
static const double r1 = 1.0;
double r2 = r1;
swapMixedEndianFloat(r2);
assert( sizeof(r2)==sizeof(t1) && memcmp(&r2, &t1, sizeof(r1))==0 );
u64 t2 = t1;
swapMixedEndianFloat(t2);
assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
#endif
x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
@ -1968,8 +1993,8 @@ int sqlite3VdbeSerialGet(
pMem->flags = MEM_Int;
}else{
assert( sizeof(x)==8 && sizeof(pMem->r)==8 );
swapMixedEndianFloat(x);
memcpy(&pMem->r, &x, sizeof(x));
swapMixedEndianFloat(pMem->r);
pMem->flags = MEM_Real;
}
return 8;
@ -2038,7 +2063,9 @@ int sqlite3VdbeRecordCompare(
Mem mem1;
Mem mem2;
mem1.enc = pKeyInfo->enc;
mem1.db = pKeyInfo->db;
mem2.enc = pKeyInfo->enc;
mem2.db = pKeyInfo->db;
idx1 = GetVarint(aKey1, szHdr1);
d1 = szHdr1;
@ -2178,6 +2205,7 @@ int sqlite3VdbeIdxKeyCompare(
** sqlite3_changes() on the database handle 'db'.
*/
void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){
assert( sqlite3_mutex_held(db->mutex) );
db->nChange = nChange;
db->nTotalChange += nChange;
}

View File

@ -30,6 +30,7 @@ struct Incrblob {
int iOffset; /* Byte offset of blob in cursor data */
BtCursor *pCsr; /* Cursor pointing at blob row */
sqlite3_stmt *pStmt; /* Statement holding cursor open */
sqlite3 *db; /* The associated database */
};
/*
@ -87,6 +88,7 @@ int sqlite3_blob_open(
char zErr[128];
zErr[0] = 0;
sqlite3_mutex_enter(db->mutex);
do {
Parse sParse;
Table *pTab;
@ -96,17 +98,20 @@ int sqlite3_blob_open(
rc = sqlite3SafetyOn(db);
if( rc!=SQLITE_OK ){
sqlite3_mutex_leave(db->mutex);
return rc;
}
sqlite3BtreeEnterAll(db);
pTab = sqlite3LocateTable(&sParse, zTable, zDb);
if( !pTab ){
if( sParse.zErrMsg ){
sqlite3_snprintf(sizeof(zErr), zErr, "%s", sParse.zErrMsg);
}
sqliteFree(sParse.zErrMsg);
sqlite3_free(sParse.zErrMsg);
rc = SQLITE_ERROR;
sqlite3SafetyOff(db);
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
@ -120,6 +125,7 @@ int sqlite3_blob_open(
sqlite3_snprintf(sizeof(zErr), zErr, "no such column: \"%s\"", zColumn);
rc = SQLITE_ERROR;
sqlite3SafetyOff(db);
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
@ -137,6 +143,7 @@ int sqlite3_blob_open(
"cannot open indexed column for writing");
rc = SQLITE_ERROR;
sqlite3SafetyOff(db);
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
}
@ -156,6 +163,9 @@ int sqlite3_blob_open(
sqlite3VdbeChangeP1(v, 1, iDb);
sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie);
/* Make sure a mutex is held on the table to be accessed */
sqlite3VdbeUsesBtree(v, iDb);
/* Configure the db number pushed onto the stack */
sqlite3VdbeChangeP1(v, 2, iDb);
@ -173,13 +183,14 @@ int sqlite3_blob_open(
** and offset cache without causing any IO.
*/
sqlite3VdbeChangeP2(v, 5, pTab->nCol+1);
if( !sqlite3MallocFailed() ){
if( !db->mallocFailed ){
sqlite3VdbeMakeReady(v, 1, 0, 1, 0);
}
}
sqlite3BtreeLeaveAll(db);
rc = sqlite3SafetyOff(db);
if( rc!=SQLITE_OK || sqlite3MallocFailed() ){
if( rc!=SQLITE_OK || db->mallocFailed ){
goto blob_open_out;
}
@ -208,17 +219,20 @@ int sqlite3_blob_open(
rc = SQLITE_ERROR;
goto blob_open_out;
}
pBlob = (Incrblob *)sqliteMalloc(sizeof(Incrblob));
if( sqlite3MallocFailed() ){
sqliteFree(pBlob);
pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
if( db->mallocFailed ){
sqlite3_free(pBlob);
goto blob_open_out;
}
pBlob->flags = flags;
pBlob->pCsr = v->apCsr[0]->pCursor;
sqlite3BtreeEnterCursor(pBlob->pCsr);
sqlite3BtreeCacheOverflow(pBlob->pCsr);
sqlite3BtreeLeaveCursor(pBlob->pCsr);
pBlob->pStmt = (sqlite3_stmt *)v;
pBlob->iOffset = v->apCsr[0]->aOffset[iCol];
pBlob->nByte = sqlite3VdbeSerialTypeLen(type);
pBlob->db = db;
*ppBlob = (sqlite3_blob *)pBlob;
rc = SQLITE_OK;
}else if( rc==SQLITE_OK ){
@ -228,11 +242,13 @@ int sqlite3_blob_open(
blob_open_out:
zErr[sizeof(zErr)-1] = '\0';
if( rc!=SQLITE_OK || sqlite3MallocFailed() ){
if( rc!=SQLITE_OK || db->mallocFailed ){
sqlite3_finalize((sqlite3_stmt *)v);
}
sqlite3Error(db, rc, (rc==SQLITE_OK?0:zErr));
return sqlite3ApiExit(db, rc);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*
@ -241,12 +257,16 @@ blob_open_out:
*/
int sqlite3_blob_close(sqlite3_blob *pBlob){
Incrblob *p = (Incrblob *)pBlob;
sqlite3_stmt *pStmt = p->pStmt;
sqliteFree(p);
return sqlite3_finalize(pStmt);
int rc;
rc = sqlite3_finalize(p->pStmt);
sqlite3_free(p);
return rc;
}
/*
** Perform a read or write operation on a blob
*/
static int blobReadWrite(
sqlite3_blob *pBlob,
void *z,
@ -256,33 +276,40 @@ static int blobReadWrite(
){
int rc;
Incrblob *p = (Incrblob *)pBlob;
Vdbe *v = (Vdbe *)(p->pStmt);
sqlite3 *db;
/* If there is no statement handle, then the blob-handle has
** already been invalidated. Return SQLITE_ABORT in this case.
*/
if( !v ) return SQLITE_ABORT;
Vdbe *v;
sqlite3 *db = p->db;
/* Request is out of range. Return a transient error. */
if( (iOffset+n)>p->nByte ){
return SQLITE_ERROR;
}
sqlite3_mutex_enter(db->mutex);
/* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is
** returned, clean-up the statement handle.
/* If there is no statement handle, then the blob-handle has
** already been invalidated. Return SQLITE_ABORT in this case.
*/
db = v->db;
rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
if( rc==SQLITE_ABORT ){
sqlite3VdbeFinalize(v);
p->pStmt = 0;
v = (Vdbe*)p->pStmt;
if( v==0 ){
rc = SQLITE_ABORT;
}else{
db->errCode = rc;
v->rc = rc;
/* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is
** returned, clean-up the statement handle.
*/
assert( db == v->db );
sqlite3BtreeEnterCursor(p->pCsr);
rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
sqlite3BtreeLeaveCursor(p->pCsr);
if( rc==SQLITE_ABORT ){
sqlite3VdbeFinalize(v);
p->pStmt = 0;
}else{
db->errCode = rc;
v->rc = rc;
}
}
return sqlite3ApiExit(db, rc);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*
@ -301,6 +328,9 @@ int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
/*
** Query a blob handle for the size of the data.
**
** The Incrblob.nByte field is fixed for the lifetime of the Incrblob
** so no mutex is required for access.
*/
int sqlite3_blob_bytes(sqlite3_blob *pBlob){
Incrblob *p = (Incrblob *)pBlob;

View File

@ -24,7 +24,7 @@ static FifoPage *allocateFifoPage(int nEntry){
if( nEntry>32767 ){
nEntry = 32767;
}
pPage = sqliteMallocRaw( sizeof(FifoPage) + sizeof(i64)*(nEntry-1) );
pPage = sqlite3_malloc( sizeof(FifoPage) + sizeof(i64)*(nEntry-1) );
if( pPage ){
pPage->nSlot = nEntry;
pPage->iWrite = 0;
@ -87,7 +87,7 @@ int sqlite3VdbeFifoPop(Fifo *pFifo, i64 *pVal){
pFifo->nEntry--;
if( pPage->iRead>=pPage->iWrite ){
pFifo->pFirst = pPage->pNext;
sqliteFree(pPage);
sqlite3_free(pPage);
if( pFifo->nEntry==0 ){
assert( pFifo->pLast==pPage );
pFifo->pLast = 0;
@ -108,7 +108,7 @@ void sqlite3VdbeFifoClear(Fifo *pFifo){
FifoPage *pPage, *pNextPage;
for(pPage=pFifo->pFirst; pPage; pPage=pNextPage){
pNextPage = pPage->pNext;
sqliteFree(pPage);
sqlite3_free(pPage);
}
sqlite3VdbeFifoInit(pFifo);
}

View File

@ -16,7 +16,6 @@
** name sqlite_value
*/
#include "sqliteInt.h"
#include "os.h"
#include <math.h>
#include <ctype.h>
#include "vdbeInt.h"
@ -45,11 +44,11 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
return SQLITE_OK;
}
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
#ifdef SQLITE_OMIT_UTF16
return SQLITE_ERROR;
#else
/* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned,
** then the encoding of the value may not have changed.
*/
@ -69,6 +68,7 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
int sqlite3VdbeMemDynamicify(Mem *pMem){
int n;
u8 *z;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
expandBlob(pMem);
if( (pMem->flags & (MEM_Ephem|MEM_Static|MEM_Short))==0 ){
return SQLITE_OK;
@ -76,7 +76,7 @@ int sqlite3VdbeMemDynamicify(Mem *pMem){
assert( (pMem->flags & MEM_Dyn)==0 );
n = pMem->n;
assert( pMem->flags & (MEM_Str|MEM_Blob) );
z = sqliteMallocRaw( n+2 );
z = sqlite3DbMallocRaw(pMem->db, n+2 );
if( z==0 ){
return SQLITE_NOMEM;
}
@ -102,8 +102,9 @@ int sqlite3VdbeMemExpandBlob(Mem *pMem){
assert( (pMem->flags & MEM_Blob)!=0 );
nByte = pMem->n + pMem->u.i;
if( nByte<=0 ) nByte = 1;
pNew = sqliteMalloc(nByte);
if( pNew==0 ){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
pNew = sqlite3DbMallocRaw(pMem->db, nByte);
if( pNew==0 ){
return SQLITE_NOMEM;
}
memcpy(pNew, pMem->z, pMem->n);
@ -129,6 +130,7 @@ int sqlite3VdbeMemExpandBlob(Mem *pMem){
int sqlite3VdbeMemMakeWriteable(Mem *pMem){
int n;
u8 *z;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
expandBlob(pMem);
if( (pMem->flags & (MEM_Ephem|MEM_Static))==0 ){
return SQLITE_OK;
@ -139,7 +141,7 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){
z = (u8*)pMem->zShort;
pMem->flags |= MEM_Short|MEM_Term;
}else{
z = sqliteMallocRaw( n+2 );
z = sqlite3DbMallocRaw(pMem->db, n+2 );
if( z==0 ){
return SQLITE_NOMEM;
}
@ -159,6 +161,7 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){
** Make sure the given Mem is \u0000 terminated.
*/
int sqlite3VdbeMemNulTerminate(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){
return SQLITE_OK; /* Nothing to do */
}
@ -167,16 +170,17 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){
}else{
char *z;
sqlite3VdbeMemExpandBlob(pMem);
z = sqliteMalloc(pMem->n+2);
if( !z ) return SQLITE_NOMEM;
z = sqlite3DbMallocRaw(pMem->db, pMem->n+2);
if( !z ){
return SQLITE_NOMEM;
}
memcpy(z, pMem->z, pMem->n);
z[pMem->n] = 0;
z[pMem->n+1] = 0;
if( pMem->xDel ){
pMem->xDel(pMem->z);
}else{
sqliteFree(pMem->z);
sqlite3_free(pMem->z);
}
pMem->xDel = 0;
pMem->z = z;
@ -203,6 +207,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){
int fg = pMem->flags;
char *z = pMem->zShort;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( !(fg&MEM_Zero) );
assert( !(fg&(MEM_Str|MEM_Blob)) );
assert( fg&(MEM_Int|MEM_Real) );
@ -240,22 +245,22 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
if( pFunc && pFunc->xFinalize ){
sqlite3_context ctx;
assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
ctx.s.flags = MEM_Null;
ctx.s.z = pMem->zShort;
ctx.s.db = pMem->db;
ctx.pMem = pMem;
ctx.pFunc = pFunc;
ctx.isError = 0;
pFunc->xFinalize(&ctx);
if( pMem->z && pMem->z!=pMem->zShort ){
sqliteFree( pMem->z );
sqlite3_free( pMem->z );
}
*pMem = ctx.s;
if( pMem->flags & MEM_Short ){
pMem->z = pMem->zShort;
}
if( ctx.isError ){
rc = SQLITE_ERROR;
}
rc = (ctx.isError?SQLITE_ERROR:SQLITE_OK);
}
return rc;
}
@ -266,6 +271,7 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
** (Mem.type==SQLITE_TEXT).
*/
void sqlite3VdbeMemRelease(Mem *p){
assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
if( p->flags & (MEM_Dyn|MEM_Agg) ){
if( p->xDel ){
if( p->flags & MEM_Agg ){
@ -276,7 +282,7 @@ void sqlite3VdbeMemRelease(Mem *p){
p->xDel((void *)p->z);
}
}else{
sqliteFree(p->z);
sqlite3_free(p->z);
}
p->z = 0;
p->xDel = 0;
@ -294,7 +300,9 @@ void sqlite3VdbeMemRelease(Mem *p){
** If pMem is a string, its encoding might be changed.
*/
i64 sqlite3VdbeIntValue(Mem *pMem){
int flags = pMem->flags;
int flags;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
flags = pMem->flags;
if( flags & MEM_Int ){
return pMem->u.i;
}else if( flags & MEM_Real ){
@ -321,6 +329,7 @@ i64 sqlite3VdbeIntValue(Mem *pMem){
** If it is a NULL, return 0.0.
*/
double sqlite3VdbeRealValue(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
if( pMem->flags & MEM_Real ){
return pMem->r;
}else if( pMem->flags & MEM_Int ){
@ -346,6 +355,7 @@ double sqlite3VdbeRealValue(Mem *pMem){
*/
void sqlite3VdbeIntegerAffinity(Mem *pMem){
assert( pMem->flags & MEM_Real );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
pMem->u.i = pMem->r;
if( ((double)pMem->u.i)==pMem->r ){
pMem->flags |= MEM_Int;
@ -356,6 +366,7 @@ void sqlite3VdbeIntegerAffinity(Mem *pMem){
** Convert pMem to type integer. Invalidate any prior representations.
*/
int sqlite3VdbeMemIntegerify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
pMem->u.i = sqlite3VdbeIntValue(pMem);
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Int;
@ -367,6 +378,7 @@ int sqlite3VdbeMemIntegerify(Mem *pMem){
** Invalidate any prior representations.
*/
int sqlite3VdbeMemRealify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
pMem->r = sqlite3VdbeRealValue(pMem);
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Real;
@ -382,6 +394,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
i64 i;
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 );
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
r1 = sqlite3VdbeRealValue(pMem);
i = (i64)r1;
r2 = (double)i;
@ -505,6 +518,9 @@ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
*/
int sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
int rc;
assert( pFrom->db==0 || sqlite3_mutex_held(pFrom->db->mutex) );
assert( pTo->db==0 || sqlite3_mutex_held(pTo->db->mutex) );
assert( pFrom->db==0 || pTo->db==0 || pFrom->db==pTo->db );
if( pTo->flags & MEM_Dyn ){
sqlite3VdbeMemRelease(pTo);
}
@ -532,13 +548,13 @@ int sqlite3VdbeMemSetStr(
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
sqlite3VdbeMemRelease(pMem);
if( !z ){
pMem->flags = MEM_Null;
pMem->type = SQLITE_NULL;
return SQLITE_OK;
}
pMem->z = (char *)z;
if( xDel==SQLITE_STATIC ){
pMem->flags = MEM_Static;
@ -731,7 +747,10 @@ int sqlite3VdbeMemFromBtree(
){
char *zData; /* Data from the btree layer */
int available = 0; /* Number of bytes available on the local btree page */
sqlite3 *db; /* Database connection */
db = sqlite3BtreeCursorDb(pCur);
assert( sqlite3_mutex_held(db->mutex) );
if( key ){
zData = (char *)sqlite3BtreeKeyFetch(pCur, &available);
}else{
@ -739,6 +758,7 @@ int sqlite3VdbeMemFromBtree(
}
assert( zData!=0 );
pMem->db = db;
pMem->n = amt;
if( offset+amt<=available ){
pMem->z = &zData[offset];
@ -746,7 +766,7 @@ int sqlite3VdbeMemFromBtree(
}else{
int rc;
if( amt>NBFS-2 ){
zData = (char *)sqliteMallocRaw(amt+2);
zData = (char *)sqlite3DbMallocRaw(db, amt+2);
if( !zData ){
return SQLITE_NOMEM;
}
@ -771,7 +791,7 @@ int sqlite3VdbeMemFromBtree(
if( amt>NBFS-2 ){
assert( zData!=pMem->zShort );
assert( pMem->flags & MEM_Dyn );
sqliteFree(zData);
sqlite3_free(zData);
} else {
assert( zData==pMem->zShort );
assert( pMem->flags & MEM_Short );
@ -844,6 +864,8 @@ void sqlite3VdbeMemSanity(Mem *pMem){
*/
const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
if( !pVal ) return 0;
assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
if( pVal->flags&MEM_Null ){
@ -866,7 +888,8 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
sqlite3VdbeMemStringify(pVal, enc);
assert( 0==(1&(int)pVal->z) );
}
assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || sqlite3MallocFailed() );
assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0
|| pVal->db->mallocFailed );
if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){
return pVal->z;
}else{
@ -877,11 +900,12 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
/*
** Create a new sqlite3_value object.
*/
sqlite3_value *sqlite3ValueNew(void){
Mem *p = sqliteMalloc(sizeof(*p));
sqlite3_value *sqlite3ValueNew(sqlite3 *db){
Mem *p = sqlite3DbMallocZero(db, sizeof(*p));
if( p ){
p->flags = MEM_Null;
p->type = SQLITE_NULL;
p->db = db;
}
return p;
}
@ -897,10 +921,11 @@ sqlite3_value *sqlite3ValueNew(void){
** cannot be converted to a value, then *ppVal is set to NULL.
*/
int sqlite3ValueFromExpr(
Expr *pExpr,
u8 enc,
u8 affinity,
sqlite3_value **ppVal
sqlite3 *db, /* The database connection */
Expr *pExpr, /* The expression to evaluate */
u8 enc, /* Encoding to use */
u8 affinity, /* Affinity to use */
sqlite3_value **ppVal /* Write the new value here */
){
int op;
char *zVal = 0;
@ -913,18 +938,18 @@ int sqlite3ValueFromExpr(
op = pExpr->op;
if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
zVal = sqliteStrNDup((char*)pExpr->token.z, pExpr->token.n);
pVal = sqlite3ValueNew();
zVal = sqlite3StrNDup((char*)pExpr->token.z, pExpr->token.n);
pVal = sqlite3ValueNew(db);
if( !zVal || !pVal ) goto no_mem;
sqlite3Dequote(zVal);
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, sqlite3FreeX);
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, sqlite3_free);
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, enc);
}else{
sqlite3ValueApplyAffinity(pVal, affinity, enc);
}
}else if( op==TK_UMINUS ) {
if( SQLITE_OK==sqlite3ValueFromExpr(pExpr->pLeft, enc, affinity, &pVal) ){
if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){
pVal->u.i = -1 * pVal->u.i;
pVal->r = -1.0 * pVal->r;
}
@ -932,13 +957,13 @@ int sqlite3ValueFromExpr(
#ifndef SQLITE_OMIT_BLOB_LITERAL
else if( op==TK_BLOB ){
int nVal;
pVal = sqlite3ValueNew();
zVal = sqliteStrNDup((char*)pExpr->token.z+1, pExpr->token.n-1);
pVal = sqlite3ValueNew(db);
zVal = sqlite3StrNDup((char*)pExpr->token.z+1, pExpr->token.n-1);
if( !zVal || !pVal ) goto no_mem;
sqlite3Dequote(zVal);
nVal = strlen(zVal)/2;
sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(zVal), nVal, 0, sqlite3FreeX);
sqliteFree(zVal);
sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal), nVal,0,sqlite3_free);
sqlite3_free(zVal);
}
#endif
@ -946,7 +971,8 @@ int sqlite3ValueFromExpr(
return SQLITE_OK;
no_mem:
sqliteFree(zVal);
db->mallocFailed = 1;
sqlite3_free(zVal);
sqlite3ValueFree(pVal);
*ppVal = 0;
return SQLITE_NOMEM;
@ -956,11 +982,11 @@ no_mem:
** Change the string value of an sqlite3_value object
*/
void sqlite3ValueSetStr(
sqlite3_value *v,
int n,
const void *z,
u8 enc,
void (*xDel)(void*)
sqlite3_value *v, /* Value to be set */
int n, /* Length of string z */
const void *z, /* Text of the new string */
u8 enc, /* Encoding to use */
void (*xDel)(void*) /* Destructor for the string */
){
if( v ) sqlite3VdbeMemSetStr((Mem *)v, z, n, enc, xDel);
}
@ -971,7 +997,7 @@ void sqlite3ValueSetStr(
void sqlite3ValueFree(sqlite3_value *v){
if( !v ) return;
sqlite3ValueSetStr(v, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
sqliteFree(v);
sqlite3_free(v);
}
/*
@ -982,7 +1008,7 @@ int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
Mem *p = (Mem*)pVal;
if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){
if( p->flags & MEM_Zero ){
return (int)(p->n+p->u.i);
return p->n+p->u.i;
}else{
return p->n;
}

View File

@ -23,8 +23,12 @@ static int createModule(
void *pAux, /* Context pointer for xCreate/xConnect */
void (*xDestroy)(void *) /* Module destructor function */
) {
int nName = strlen(zName);
Module *pMod = (Module *)sqliteMallocRaw(sizeof(Module) + nName + 1);
int rc, nName;
Module *pMod;
sqlite3_mutex_enter(db->mutex);
nName = strlen(zName);
pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1);
if( pMod ){
char *zCopy = (char *)(&pMod[1]);
memcpy(zCopy, zName, nName+1);
@ -36,10 +40,12 @@ static int createModule(
if( pMod && pMod->xDestroy ){
pMod->xDestroy(pMod->pAux);
}
sqliteFree(pMod);
sqlite3_free(pMod);
sqlite3ResetInternalSchema(db, 0);
}
return sqlite3ApiExit(db, SQLITE_OK);
rc = sqlite3ApiExit(db, SQLITE_OK);
sqlite3_mutex_leave(db->mutex);
return rc;
}
@ -114,9 +120,9 @@ void sqlite3VtabClear(Table *p){
if( p->azModuleArg ){
int i;
for(i=0; i<p->nModuleArg; i++){
sqliteFree(p->azModuleArg[i]);
sqlite3_free(p->azModuleArg[i]);
}
sqliteFree(p->azModuleArg);
sqlite3_free(p->azModuleArg);
}
}
@ -126,18 +132,18 @@ void sqlite3VtabClear(Table *p){
** string will be freed automatically when the table is
** deleted.
*/
static void addModuleArgument(Table *pTable, char *zArg){
static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){
int i = pTable->nModuleArg++;
int nBytes = sizeof(char *)*(1+pTable->nModuleArg);
char **azModuleArg;
azModuleArg = sqliteRealloc(pTable->azModuleArg, nBytes);
azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes);
if( azModuleArg==0 ){
int j;
for(j=0; j<i; j++){
sqliteFree(pTable->azModuleArg[j]);
sqlite3_free(pTable->azModuleArg[j]);
}
sqliteFree(zArg);
sqliteFree(pTable->azModuleArg);
sqlite3_free(zArg);
sqlite3_free(pTable->azModuleArg);
pTable->nModuleArg = 0;
}else{
azModuleArg[i] = zArg;
@ -159,27 +165,27 @@ void sqlite3VtabBeginParse(
){
int iDb; /* The database the table is being created in */
Table *pTable; /* The new virtual table */
sqlite3 *db; /* Database connection */
#ifndef SQLITE_OMIT_SHARED_CACHE
if( sqlite3ThreadDataReadOnly()->useSharedData ){
if( pParse->db->flags & SQLITE_SharedCache ){
sqlite3ErrorMsg(pParse, "Cannot use virtual tables in shared-cache mode");
return;
}
#endif
sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0);
pTable = pParse->pNewTable;
if( pTable==0 || pParse->nErr ) return;
assert( 0==pTable->pIndex );
iDb = sqlite3SchemaToIndex(pParse->db, pTable->pSchema);
db = pParse->db;
iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
assert( iDb>=0 );
pTable->isVirtual = 1;
pTable->nModuleArg = 0;
addModuleArgument(pTable, sqlite3NameFromToken(pModuleName));
addModuleArgument(pTable, sqlite3StrDup(pParse->db->aDb[iDb].zName));
addModuleArgument(pTable, sqlite3StrDup(pTable->zName));
addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
addModuleArgument(db, pTable, sqlite3DbStrDup(db, db->aDb[iDb].zName));
addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName));
pParse->sNameToken.n = pModuleName->z + pModuleName->n - pName1->z;
#ifndef SQLITE_OMIT_AUTHORIZATION
@ -204,7 +210,8 @@ static void addArgumentToVtab(Parse *pParse){
if( pParse->sArg.z && pParse->pNewTable ){
const char *z = (const char*)pParse->sArg.z;
int n = pParse->sArg.n;
addModuleArgument(pParse->pNewTable, sqliteStrNDup(z, n));
sqlite3 *db = pParse->db;
addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n));
}
}
@ -246,7 +253,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
if( pEnd ){
pParse->sNameToken.n = pEnd->z - pParse->sNameToken.z + pEnd->n;
}
zStmt = sqlite3MPrintf("CREATE VIRTUAL TABLE %T", &pParse->sNameToken);
zStmt = sqlite3MPrintf(db, "CREATE VIRTUAL TABLE %T", &pParse->sNameToken);
/* A slot for the record has already been allocated in the
** SQLITE_MASTER table. We just need to update that slot with all
@ -267,12 +274,12 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
pTab->zName,
zStmt
);
sqliteFree(zStmt);
sqlite3_free(zStmt);
v = sqlite3GetVdbe(pParse);
sqlite3ChangeCookie(db, v, iDb);
sqlite3VdbeAddOp(v, OP_Expire, 0, 0);
zWhere = sqlite3MPrintf("name='%q'", pTab->zName);
zWhere = sqlite3MPrintf(db, "name='%q'", pTab->zName);
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 1, zWhere, P3_DYNAMIC);
sqlite3VdbeOp3(v, OP_VCreate, iDb, 0, pTab->zName, strlen(pTab->zName) + 1);
}
@ -288,6 +295,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
int nName = strlen(zName) + 1;
pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab);
if( pOld ){
db->mallocFailed = 1;
assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */
return;
}
@ -335,11 +343,11 @@ static int vtabCallConstructor(
){
int rc;
int rc2;
sqlite3_vtab *pVtab;
sqlite3_vtab *pVtab = 0;
const char *const*azArg = (const char *const*)pTab->azModuleArg;
int nArg = pTab->nModuleArg;
char *zErr = 0;
char *zModuleName = sqlite3MPrintf("%s", pTab->zName);
char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
if( !zModuleName ){
return SQLITE_NOMEM;
@ -351,31 +359,31 @@ static int vtabCallConstructor(
db->pVTab = pTab;
rc = sqlite3SafetyOff(db);
assert( rc==SQLITE_OK );
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pTab->pVtab, &zErr);
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVtab, &zErr);
rc2 = sqlite3SafetyOn(db);
pVtab = pTab->pVtab;
if( rc==SQLITE_OK && pVtab ){
pVtab->pModule = pMod->pModule;
pVtab->nRef = 1;
pTab->pVtab = pVtab;
}
if( SQLITE_OK!=rc ){
if( zErr==0 ){
*pzErr = sqlite3MPrintf("vtable constructor failed: %s", zModuleName);
*pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
}else {
*pzErr = sqlite3MPrintf("%s", zErr);
*pzErr = sqlite3MPrintf(db, "%s", zErr);
sqlite3_free(zErr);
}
}else if( db->pVTab ){
const char *zFormat = "vtable constructor did not declare schema: %s";
*pzErr = sqlite3MPrintf(zFormat, pTab->zName);
*pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
rc = SQLITE_ERROR;
}
if( rc==SQLITE_OK ){
rc = rc2;
}
db->pVTab = 0;
sqliteFree(zModuleName);
sqlite3_free(zModuleName);
/* If everything went according to plan, loop through the columns
** of the table to see if any of them contain the token "hidden".
@ -444,7 +452,7 @@ int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
if( rc!=SQLITE_OK ){
sqlite3ErrorMsg(pParse, "%s", zErr);
}
sqliteFree(zErr);
sqlite3_free(zErr);
}
return rc;
@ -460,7 +468,7 @@ static int addToVTrans(sqlite3 *db, sqlite3_vtab *pVtab){
if( (db->nVTrans%ARRAY_INCR)==0 ){
sqlite3_vtab **aVTrans;
int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR);
aVTrans = sqliteRealloc((void *)db->aVTrans, nBytes);
aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes);
if( !aVTrans ){
return SQLITE_NOMEM;
}
@ -480,7 +488,7 @@ static int addToVTrans(sqlite3 *db, sqlite3_vtab *pVtab){
**
** 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 sqliteFree() on *pzErr.
** In this case the caller must call sqlite3_free() on *pzErr.
*/
int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
int rc = SQLITE_OK;
@ -498,7 +506,7 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
** error. Otherwise, do nothing.
*/
if( !pMod ){
*pzErr = sqlite3MPrintf("no such module: %s", zModule);
*pzErr = sqlite3MPrintf(db, "no such module: %s", zModule);
rc = SQLITE_ERROR;
}else{
rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr);
@ -520,11 +528,14 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
Parse sParse;
int rc = SQLITE_OK;
Table *pTab = db->pVTab;
Table *pTab;
char *zErr = 0;
sqlite3_mutex_enter(db->mutex);
pTab = db->pVTab;
if( !pTab ){
sqlite3Error(db, SQLITE_MISUSE, 0);
sqlite3_mutex_leave(db->mutex);
return SQLITE_MISUSE;
}
assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0);
@ -546,7 +557,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
db->pVTab = 0;
} else {
sqlite3Error(db, SQLITE_ERROR, zErr);
sqliteFree(zErr);
sqlite3_free(zErr);
rc = SQLITE_ERROR;
}
sParse.declareVtab = 0;
@ -556,7 +567,9 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
sParse.pNewTable = 0;
assert( (rc&0xff)==rc );
return sqlite3ApiExit(db, rc);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*
@ -607,7 +620,7 @@ static void callFinaliser(sqlite3 *db, int offset){
if( x ) x(pVtab);
sqlite3VtabUnlock(db, pVtab);
}
sqliteFree(db->aVTrans);
sqlite3_free(db->aVTrans);
db->nVTrans = 0;
db->aVTrans = 0;
}
@ -724,6 +737,7 @@ int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){
** SQLITE_FUNC_EPHEM flag.
*/
FuncDef *sqlite3VtabOverloadFunction(
sqlite3 *db, /* Database connection for reporting malloc problems */
FuncDef *pDef, /* Function to possibly overload */
int nArg, /* Number of arguments to the function */
Expr *pExpr /* First argument to the function */
@ -734,7 +748,7 @@ FuncDef *sqlite3VtabOverloadFunction(
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
void *pArg;
FuncDef *pNew;
int rc;
int rc = 0;
char *zLowerName;
unsigned char *z;
@ -751,22 +765,24 @@ FuncDef *sqlite3VtabOverloadFunction(
pMod = (sqlite3_module *)pVtab->pModule;
if( pMod->xFindFunction==0 ) return pDef;
/* Call the xFuncFunction method on the virtual table implementation
/* Call the xFindFunction method on the virtual table implementation
** to see if the implementation wants to overload this function
*/
zLowerName = sqlite3StrDup(pDef->zName);
for(z=(unsigned char*)zLowerName; *z; z++){
*z = sqlite3UpperToLower[*z];
zLowerName = sqlite3DbStrDup(db, pDef->zName);
if( zLowerName ){
for(z=(unsigned char*)zLowerName; *z; z++){
*z = sqlite3UpperToLower[*z];
}
rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg);
sqlite3_free(zLowerName);
}
rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg);
sqliteFree(zLowerName);
if( rc==0 ){
return pDef;
}
/* Create a new ephemeral function definition for the overloaded
** function */
pNew = sqliteMalloc( sizeof(*pNew) + strlen(pDef->zName) );
pNew = sqlite3DbMallocZero(db, sizeof(*pNew) + strlen(pDef->zName) );
if( pNew==0 ){
return pDef;
}

View File

@ -207,7 +207,7 @@ static void whereClauseClear(WhereClause *pWC){
}
}
if( pWC->a!=pWC->aStatic ){
sqliteFree(pWC->a);
sqlite3_free(pWC->a);
}
}
@ -228,8 +228,9 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, int flags){
int idx;
if( pWC->nTerm>=pWC->nSlot ){
WhereTerm *pOld = pWC->a;
pWC->a = sqliteMalloc( sizeof(pWC->a[0])*pWC->nSlot*2 );
pWC->a = sqlite3_malloc( sizeof(pWC->a[0])*pWC->nSlot*2 );
if( pWC->a==0 ){
pWC->pParse->db->mallocFailed = 1;
if( flags & TERM_DYNAMIC ){
sqlite3ExprDelete(p);
}
@ -237,7 +238,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, int flags){
}
memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
if( pOld!=pWC->aStatic ){
sqliteFree(pOld);
sqlite3_free(pOld);
}
pWC->nSlot *= 2;
}
@ -349,15 +350,14 @@ static Bitmask exprListTableUsage(ExprMaskSet *pMaskSet, ExprList *pList){
return mask;
}
static Bitmask exprSelectTableUsage(ExprMaskSet *pMaskSet, Select *pS){
Bitmask mask;
if( pS==0 ){
mask = 0;
}else{
mask = exprListTableUsage(pMaskSet, pS->pEList);
Bitmask mask = 0;
while( pS ){
mask |= exprListTableUsage(pMaskSet, pS->pEList);
mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
mask |= exprTableUsage(pMaskSet, pS->pWhere);
mask |= exprTableUsage(pMaskSet, pS->pHaving);
pS = pS->pPrior;
}
return mask;
}
@ -383,10 +383,22 @@ static int allowedOp(int op){
/*
** Commute a comparision operator. Expressions of the form "X op Y"
** are converted into "Y op X".
**
** If a collation sequence is associated with either the left or right
** side of the comparison, it remains associated with the same side after
** the commutation. So "Y collate NOCASE op X" becomes
** "X collate NOCASE op Y". This is because any collation sequence on
** the left hand side of a comparison overrides any collation sequence
** attached to the right. For the same reason the EP_ExpCollate flag
** is not commuted.
*/
static void exprCommute(Expr *pExpr){
u16 expRight = (pExpr->pRight->flags & EP_ExpCollate);
u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate);
assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft;
pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight;
SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
if( pExpr->op>=TK_GT ){
assert( TK_LT==TK_GT+2 );
@ -538,7 +550,7 @@ static int isLikeOrGlob(
(pColl->type!=SQLITE_COLL_NOCASE || !noCase) ){
return 0;
}
sqlite3DequoteExpr(pRight);
sqlite3DequoteExpr(db, pRight);
z = (char *)pRight->token.z;
for(cnt=0; (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2]; cnt++){}
if( cnt==0 || 255==(u8)z[cnt] ){
@ -703,8 +715,10 @@ static void exprAnalyze(
int nPattern;
int isComplete;
int op;
Parse *pParse = pWC->pParse;
sqlite3 *db = pParse->db;
if( sqlite3MallocFailed() ) return;
if( db->mallocFailed ) return;
prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
op = pExpr->op;
if( op==TK_IN ){
@ -737,8 +751,8 @@ static void exprAnalyze(
Expr *pDup;
if( pTerm->leftCursor>=0 ){
int idxNew;
pDup = sqlite3ExprDup(pExpr);
if( sqlite3MallocFailed() ){
pDup = sqlite3ExprDup(db, pExpr);
if( db->mallocFailed ){
sqlite3ExprDelete(pDup);
return;
}
@ -776,8 +790,8 @@ static void exprAnalyze(
for(i=0; i<2; i++){
Expr *pNewExpr;
int idxNew;
pNewExpr = sqlite3Expr(ops[i], sqlite3ExprDup(pExpr->pLeft),
sqlite3ExprDup(pList->a[i].pExpr), 0);
pNewExpr = sqlite3Expr(db, ops[i], sqlite3ExprDup(db, pExpr->pLeft),
sqlite3ExprDup(db, pList->a[i].pExpr), 0);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
exprAnalyze(pSrc, pWC, idxNew);
pTerm = &pWC->a[idxTerm];
@ -837,13 +851,13 @@ static void exprAnalyze(
Expr *pLeft = 0;
for(i=sOr.nTerm-1, pOrTerm=sOr.a; i>=0 && ok; i--, pOrTerm++){
if( (pOrTerm->flags & TERM_OR_OK)==0 ) continue;
pDup = sqlite3ExprDup(pOrTerm->pExpr->pRight);
pList = sqlite3ExprListAppend(pList, pDup, 0);
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight);
pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup, 0);
pLeft = pOrTerm->pExpr->pLeft;
}
assert( pLeft!=0 );
pDup = sqlite3ExprDup(pLeft);
pNew = sqlite3Expr(TK_IN, pDup, 0, 0);
pDup = sqlite3ExprDup(db, pLeft);
pNew = sqlite3Expr(db, TK_IN, pDup, 0, 0);
if( pNew ){
int idxNew;
transferJoinMarkings(pNew, pExpr);
@ -866,7 +880,7 @@ or_not_possible:
/* Add constraints to reduce the search space on a LIKE or GLOB
** operator.
*/
if( isLikeOrGlob(pWC->pParse->db, pExpr, &nPattern, &isComplete) ){
if( isLikeOrGlob(db, pExpr, &nPattern, &isComplete) ){
Expr *pLeft, *pRight;
Expr *pStr1, *pStr2;
Expr *pNewExpr1, *pNewExpr2;
@ -874,21 +888,21 @@ or_not_possible:
pLeft = pExpr->pList->a[1].pExpr;
pRight = pExpr->pList->a[0].pExpr;
pStr1 = sqlite3Expr(TK_STRING, 0, 0, 0);
pStr1 = sqlite3PExpr(pParse, TK_STRING, 0, 0, 0);
if( pStr1 ){
sqlite3TokenCopy(&pStr1->token, &pRight->token);
sqlite3TokenCopy(db, &pStr1->token, &pRight->token);
pStr1->token.n = nPattern;
pStr1->flags = EP_Dequoted;
}
pStr2 = sqlite3ExprDup(pStr1);
pStr2 = sqlite3ExprDup(db, pStr1);
if( pStr2 ){
assert( pStr2->token.dyn );
++*(u8*)&pStr2->token.z[nPattern-1];
}
pNewExpr1 = sqlite3Expr(TK_GE, sqlite3ExprDup(pLeft), pStr1, 0);
pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft), pStr1, 0);
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
exprAnalyze(pSrc, pWC, idxNew1);
pNewExpr2 = sqlite3Expr(TK_LT, sqlite3ExprDup(pLeft), pStr2, 0);
pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db,pLeft), pStr2, 0);
idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
exprAnalyze(pSrc, pWC, idxNew2);
pTerm = &pWC->a[idxTerm];
@ -919,7 +933,7 @@ or_not_possible:
prereqColumn = exprTableUsage(pMaskSet, pLeft);
if( (prereqExpr & prereqColumn)==0 ){
Expr *pNewExpr;
pNewExpr = sqlite3Expr(TK_MATCH, 0, sqlite3ExprDup(pRight), 0);
pNewExpr = sqlite3Expr(db, TK_MATCH, 0, sqlite3ExprDup(db, pRight), 0);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
pNewTerm = &pWC->a[idxNew];
pNewTerm->prereqRight = prereqExpr;
@ -1245,7 +1259,7 @@ static double bestVirtualIndex(
/* Allocate the sqlite3_index_info structure
*/
pIdxInfo = sqliteMalloc( sizeof(*pIdxInfo)
pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
+ (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
+ sizeof(*pIdxOrderBy)*nOrderBy );
if( pIdxInfo==0 ){
@ -1274,7 +1288,7 @@ static double bestVirtualIndex(
if( pTerm->eOperator==WO_IN ) continue;
pIdxCons[j].iColumn = pTerm->leftColumn;
pIdxCons[j].iTermOffset = i;
pIdxCons[j].op = (unsigned char)pTerm->eOperator;
pIdxCons[j].op = pTerm->eOperator;
/* The direct assignment in the previous line is possible only because
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
** following asserts verify this fact. */
@ -1363,7 +1377,7 @@ static double bestVirtualIndex(
TRACE_IDX_OUTPUTS(pIdxInfo);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM ){
sqlite3FailedMalloc();
pParse->db->mallocFailed = 1;
}else {
sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
}
@ -1551,7 +1565,7 @@ static double bestIndex(
&& nEq==pProbe->nColumn ){
flags |= WHERE_UNIQUE;
}
WHERETRACE(("...... nEq=%d inMult=%.9g cost=%.9g\n", nEq, inMultiplier, cost));
WHERETRACE(("...... nEq=%d inMult=%.9g cost=%.9g\n",nEq,inMultiplier,cost));
/* Look for range constraints
*/
@ -1612,10 +1626,9 @@ static double bestIndex(
/* If this index has achieved the lowest cost so far, then use it.
*/
if( cost < lowestCost ){
if( flags && cost < lowestCost ){
bestIdx = pProbe;
lowestCost = cost;
assert( flags!=0 );
bestFlags = flags;
bestNEq = nEq;
}
@ -1724,7 +1737,7 @@ static void codeEqualityTerm(
pLevel->nxt = sqlite3VdbeMakeLabel(v);
}
pLevel->nIn++;
pLevel->aInLoop = sqliteReallocOrFree(pLevel->aInLoop,
pLevel->aInLoop = sqlite3DbReallocOrFree(pParse->db, pLevel->aInLoop,
sizeof(pLevel->aInLoop[0])*pLevel->nIn);
pIn = pLevel->aInLoop;
if( pIn ){
@ -1843,10 +1856,10 @@ static void whereInfoFree(WhereInfo *pWInfo){
*/
sqlite3_free(pInfo->idxStr);
}
sqliteFree(pInfo);
sqlite3_free(pInfo);
}
}
sqliteFree(pWInfo);
sqlite3_free(pWInfo);
}
}
@ -1957,6 +1970,7 @@ WhereInfo *sqlite3WhereBegin(
WhereLevel *pLevel; /* A single level in the pWInfo list */
int iFrom; /* First unused FROM clause element */
int andFlags; /* AND-ed combination of all wc.a[].flags */
sqlite3 *db; /* Database connection */
/* The number of tables in the FROM clause is limited by the number of
** bits in a Bitmask
@ -1976,8 +1990,10 @@ WhereInfo *sqlite3WhereBegin(
/* Allocate and initialize the WhereInfo structure that will become the
** return value.
*/
pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel));
if( sqlite3MallocFailed() ){
db = pParse->db;
pWInfo = sqlite3DbMallocZero(db,
sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel));
if( db->mallocFailed ){
goto whereBeginNoMem;
}
pWInfo->nLevel = pTabList->nSrc;
@ -2002,7 +2018,7 @@ WhereInfo *sqlite3WhereBegin(
createMask(&maskSet, pTabList->a[i].iCursor);
}
exprAnalyzeAll(pTabList, &wc);
if( sqlite3MallocFailed() ){
if( db->mallocFailed ){
goto whereBeginNoMem;
}
@ -2134,24 +2150,24 @@ WhereInfo *sqlite3WhereBegin(
if( pParse->explain==2 ){
char *zMsg;
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
zMsg = sqlite3MPrintf("TABLE %s", pItem->zName);
zMsg = sqlite3MPrintf(db, "TABLE %s", pItem->zName);
if( pItem->zAlias ){
zMsg = sqlite3MPrintf("%z AS %s", zMsg, pItem->zAlias);
zMsg = sqlite3MPrintf(db, "%z AS %s", zMsg, pItem->zAlias);
}
if( (pIx = pLevel->pIdx)!=0 ){
zMsg = sqlite3MPrintf("%z WITH INDEX %s", zMsg, pIx->zName);
zMsg = sqlite3MPrintf(db, "%z WITH INDEX %s", zMsg, pIx->zName);
}else if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
zMsg = sqlite3MPrintf("%z USING PRIMARY KEY", zMsg);
zMsg = sqlite3MPrintf(db, "%z USING PRIMARY KEY", zMsg);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( pLevel->pBestIdx ){
sqlite3_index_info *pBestIdx = pLevel->pBestIdx;
zMsg = sqlite3MPrintf("%z VIRTUAL TABLE INDEX %d:%s", zMsg,
zMsg = sqlite3MPrintf(db, "%z VIRTUAL TABLE INDEX %d:%s", zMsg,
pBestIdx->idxNum, pBestIdx->idxStr);
}
#endif
if( pLevel->flags & WHERE_ORDERBY ){
zMsg = sqlite3MPrintf("%z ORDER BY", zMsg);
zMsg = sqlite3MPrintf(db, "%z ORDER BY", zMsg);
}
sqlite3VdbeOp3(v, OP_Explain, i, pLevel->iFrom, zMsg, P3_DYNAMIC);
}
@ -2679,7 +2695,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3VdbeAddOp(v, OP_Next, pIn->iCur, pIn->topAddr);
sqlite3VdbeJumpHere(v, pIn->topAddr-1);
}
sqliteFree(pLevel->aInLoop);
sqlite3_free(pLevel->aInLoop);
}
sqlite3VdbeResolveLabel(v, pLevel->brk);
if( pLevel->iLeftJoin ){