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:
parent
dc746c5806
commit
f78ceafdce
@ -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;
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,7 @@ private:
|
||||
Handle_t m_Handle;
|
||||
IMutex *m_pOpenLock;
|
||||
List<SqDbInfo> m_Cache;
|
||||
bool m_bThreadSafe;
|
||||
};
|
||||
|
||||
extern SqDriver g_SqDriver;
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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
@ -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_ */
|
||||
|
@ -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;
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}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);
|
||||
|
@ -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 ){
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
sqliteFree(z);
|
||||
sqlite3_free(z);
|
||||
pTopNC->nErr++;
|
||||
}else{
|
||||
db->mallocFailed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
@ -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++){
|
||||
@ -2058,7 +2091,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
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,
|
||||
@ -2427,7 +2462,6 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
|
||||
SrcList *pSrcList = pNC->pSrcList;
|
||||
AggInfo *pAggInfo = pNC->pAggInfo;
|
||||
|
||||
|
||||
switch( pExpr->op ){
|
||||
case TK_AGG_COLUMN:
|
||||
case TK_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;
|
||||
|
@ -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;
|
||||
}else if( c==esc ){
|
||||
c = sqlite3Utf8Read(zPattern, 0, &zPattern);
|
||||
if( c==0 ){
|
||||
return 0;
|
||||
}
|
||||
if( c==0 ) return 1;
|
||||
if( c==matchSet ){
|
||||
}else if( c==matchSet ){
|
||||
assert( esc==0 ); /* This is GLOB, not LIKE */
|
||||
while( *zString && patternCompare(&zPattern[1],zString,pInfo,esc)==0 ){
|
||||
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 ){
|
||||
}
|
||||
while( (c2 = sqlite3Utf8Read(zString,0,&zString))!=0 ){
|
||||
if( noCase ){
|
||||
c2 = sqlite3UpperToLower[c2];
|
||||
c = sqlite3UpperToLower[c];
|
||||
while( c2 != 0 && c2 != c ){ c2 = sqlite3UpperToLower[*++zString]; }
|
||||
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 = *++zString; }
|
||||
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( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}else if( !prevEscape && c==matchOne ){
|
||||
if( *zString==0 ) return 0;
|
||||
SQLITE_SKIP_UTF8(zString);
|
||||
zPattern++;
|
||||
if( sqlite3Utf8Read(zString, 0, &zString)==0 ){
|
||||
return 0;
|
||||
}
|
||||
}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 ){
|
||||
}else{
|
||||
if( c==c2 ){
|
||||
seen = 1;
|
||||
prior_c = c2;
|
||||
}else{
|
||||
}
|
||||
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,8 +706,8 @@ 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 = contextMalloc(context, i+n+3);
|
||||
if( z ){
|
||||
z[0] = '\'';
|
||||
for(i=0, j=1; zArg[i]; i++){
|
||||
z[j++] = zArg[i];
|
||||
@ -711,8 +717,8 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
}
|
||||
z[j++] = '\'';
|
||||
z[j] = 0;
|
||||
sqlite3_result_text(context, z, j, SQLITE_TRANSIENT);
|
||||
sqliteFree(z);
|
||||
sqlite3_result_text(context, z, j, sqlite3_free);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -737,8 +743,8 @@ 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;
|
||||
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];
|
||||
@ -747,6 +753,7 @@ static void hexFunc(
|
||||
*z = 0;
|
||||
sqlite3_result_text(context, zHex, n*2, sqlite3_free);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The zeroblob(N) function returns a zero-filled blob of size N bytes.
|
||||
@ -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 ){
|
||||
|
||||
/* 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;
|
||||
}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;
|
||||
}
|
||||
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 ){
|
||||
@ -1126,7 +1138,11 @@ static void test_auxdata(
|
||||
}
|
||||
}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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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*);
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
238
extensions/sqlite/sqlite-source/journal.c
Normal file
238
extensions/sqlite/sqlite-source/journal.c
Normal 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
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE,
|
||||
pUserData, xFunc, xStep, xFinal);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
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 ){
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
/* 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 */
|
||||
return SQLITE_OK;
|
||||
#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>
|
||||
*/
|
||||
|
||||
#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.
|
||||
** Allocate and zero memory.
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
** 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 ){
|
||||
sqlite3FreeX(p);
|
||||
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 *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){
|
||||
void *pNew;
|
||||
pNew = sqlite3DbRealloc(db, p, n);
|
||||
if( !pNew ){
|
||||
sqlite3_free(p);
|
||||
}
|
||||
void sqlite3ThreadSafeFree(void *p){
|
||||
(void)ENTER_MALLOC;
|
||||
if( p ){
|
||||
OSFREE(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
|
||||
|
229
extensions/sqlite/sqlite-source/mem1.c
Normal file
229
extensions/sqlite/sqlite-source/mem1.c
Normal 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 */
|
546
extensions/sqlite/sqlite-source/mem2.c
Normal file
546
extensions/sqlite/sqlite-source/mem2.c
Normal 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 */
|
126
extensions/sqlite/sqlite-source/mutex.c
Normal file
126
extensions/sqlite/sqlite-source/mutex.c
Normal 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 */
|
82
extensions/sqlite/sqlite-source/mutex.h
Normal file
82
extensions/sqlite/sqlite-source/mutex.h
Normal 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 */
|
223
extensions/sqlite/sqlite-source/mutex_unix.c
Normal file
223
extensions/sqlite/sqlite-source/mutex_unix.c
Normal 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 */
|
208
extensions/sqlite/sqlite-source/mutex_w32.c
Normal file
208
extensions/sqlite/sqlite-source/mutex_w32.c
Normal 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 */
|
@ -1,7 +1,8 @@
|
||||
/* 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[] = { "?",
|
||||
const char *sqlite3OpcodeName(int i){
|
||||
static const char *const azName[] = { "?",
|
||||
/* 1 */ "MemLoad",
|
||||
/* 2 */ "VNext",
|
||||
/* 3 */ "Column",
|
||||
@ -145,4 +146,6 @@ const char *const sqlite3OpcodeNames[] = { "?",
|
||||
/* 141 */ "ToInt",
|
||||
/* 142 */ "ToReal",
|
||||
};
|
||||
return azName[i];
|
||||
}
|
||||
#endif
|
||||
|
@ -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);
|
||||
int sqlite3OsClose(sqlite3_file *pId){
|
||||
int rc = SQLITE_OK;
|
||||
if( pId->pMethods ){
|
||||
rc = pId->pMethods->xClose(pId);
|
||||
pId->pMethods = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
|
||||
DO_OS_MALLOC_TEST;
|
||||
return id->pMethods->xRead(id, pBuf, amt, offset);
|
||||
}
|
||||
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 sqlite3OsTruncate(sqlite3_file *id, i64 size){
|
||||
return id->pMethods->xTruncate(id, size);
|
||||
}
|
||||
int sqlite3OsSync(sqlite3_file *id, int flags){
|
||||
DO_OS_MALLOC_TEST;
|
||||
return id->pMethods->xSync(id, flags);
|
||||
}
|
||||
int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
|
||||
return id->pMethods->xFileSize(id, pSize);
|
||||
}
|
||||
int sqlite3OsLock(sqlite3_file *id, int lockType){
|
||||
DO_OS_MALLOC_TEST;
|
||||
return id->pMethods->xLock(id, lockType);
|
||||
}
|
||||
int sqlite3OsUnlock(sqlite3_file *id, int lockType){
|
||||
return id->pMethods->xUnlock(id, lockType);
|
||||
}
|
||||
int sqlite3OsCheckReservedLock(sqlite3_file *id){
|
||||
return id->pMethods->xCheckReservedLock(id);
|
||||
}
|
||||
int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
return id->pMethods->xFileControl(id,op,pArg);
|
||||
}
|
||||
|
||||
#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 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
|
||||
|
||||
/*
|
||||
** The next group of routines are convenience wrappers around the
|
||||
** VFS methods.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
int sqlite3OsOpenDirectory(OsFile *id, const char *zName){
|
||||
return id->pMethod->xOpenDirectory(id, zName);
|
||||
}
|
||||
int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
|
||||
return id->pMethod->xRead(id, pBuf, amt);
|
||||
}
|
||||
int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
|
||||
return id->pMethod->xWrite(id, pBuf, amt);
|
||||
}
|
||||
int sqlite3OsSeek(OsFile *id, i64 offset){
|
||||
return id->pMethod->xSeek(id, offset);
|
||||
}
|
||||
int sqlite3OsTruncate(OsFile *id, i64 size){
|
||||
return id->pMethod->xTruncate(id, size);
|
||||
}
|
||||
int sqlite3OsSync(OsFile *id, int fullsync){
|
||||
return id->pMethod->xSync(id, fullsync);
|
||||
}
|
||||
void sqlite3OsSetFullSync(OsFile *id, int value){
|
||||
id->pMethod->xSetFullSync(id, value);
|
||||
}
|
||||
int sqlite3OsFileSize(OsFile *id, i64 *pSize){
|
||||
return id->pMethod->xFileSize(id, pSize);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
#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);
|
||||
}
|
||||
int sqlite3OsLockState(OsFile *id){
|
||||
return id->pMethod->xLockState(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.
|
||||
** Unregister a VFS so that it is no longer accessible.
|
||||
*/
|
||||
struct sqlite3OsVtbl *sqlite3_os_switch(void){
|
||||
return &sqlite3Os;
|
||||
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
|
||||
|
@ -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:
|
||||
@ -346,203 +229,56 @@ extern unsigned int sqlite3_pending_byte;
|
||||
#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*);
|
||||
|
||||
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
|
||||
int sqlite3OsFileHandle(OsFile *id);
|
||||
int sqlite3OsLockState(OsFile *id);
|
||||
#endif
|
||||
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 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.
|
||||
** Functions for accessing sqlite3_vfs methods
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_REDEF_IO
|
||||
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*);
|
||||
|
||||
/*
|
||||
** 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.
|
||||
** Convenience functions for opening and closing files using
|
||||
** sqlite3_malloc() to obtain space for the file-handle structure.
|
||||
*/
|
||||
struct sqlite3OsVtbl {
|
||||
int (*xOpenReadWrite)(const char*, OsFile**, int*);
|
||||
int (*xOpenExclusive)(const char*, OsFile**, int);
|
||||
int (*xOpenReadOnly)(const char*, OsFile**);
|
||||
int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
|
||||
int sqlite3OsCloseFree(sqlite3_file *);
|
||||
|
||||
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
|
||||
/*
|
||||
** 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.
|
||||
*/
|
||||
#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_ */
|
||||
|
@ -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
@ -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
@ -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 */
|
||||
|
@ -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,27 +483,30 @@ 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) ){
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memset(&sParse, 0, sizeof(sParse));
|
||||
sParse.db = db;
|
||||
@ -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.
|
||||
@ -578,12 +618,14 @@ int sqlite3Reprepare(Vdbe *p){
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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,7 +729,9 @@ 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->zText ){
|
||||
if( pM->nChar + nNewChar + 1 > pM->nAlloc ){
|
||||
if( pM->xRealloc==0 ){
|
||||
nNewChar = pM->nAlloc - pM->nChar - 1;
|
||||
@ -736,7 +739,11 @@ static void mout(void *arg, const char *zNewText, int nNewChar){
|
||||
int nAlloc = pM->nChar + nNewChar*2 + 1;
|
||||
if( pM->zText==pM->zBase ){
|
||||
pM->zText = pM->xRealloc(0, nAlloc);
|
||||
if( pM->zText && pM->nChar ){
|
||||
if( pM->zText==0 ){
|
||||
pM->nAlloc = 0;
|
||||
pM->iMallocFailed = 1;
|
||||
return;
|
||||
}else if( pM->nChar ){
|
||||
memcpy(pM->zText, pM->zBase, pM->nChar);
|
||||
}
|
||||
}else{
|
||||
@ -745,13 +752,16 @@ static void mout(void *arg, const char *zNewText, int nNewChar){
|
||||
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( pM->zText ){
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
@ -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;
|
||||
|
@ -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
|
||||
};
|
||||
@ -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
|
||||
** 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 int sqlite3_always_code_trigger_setup;
|
||||
|
||||
/*
|
||||
** A lookup table used by the SQLITE_READ_UTF8 macro. The definition
|
||||
** is in utf.c.
|
||||
*/
|
||||
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 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 *);
|
||||
|
||||
#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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,7 +683,7 @@ 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);
|
||||
@ -686,8 +696,8 @@ static int codeTriggerProgram(
|
||||
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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
|
@ -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*);
|
||||
|
@ -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
|
||||
@ -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);
|
||||
|
@ -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 };
|
||||
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);
|
||||
return (Mem*)&nullMem;
|
||||
}
|
||||
return &pVm->pTos[(1-vals)+i];
|
||||
pOut = (Mem*)&nullMem;
|
||||
}
|
||||
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.
|
||||
/* 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);
|
||||
if( p->db && p->db->mallocFailed ){
|
||||
p->db->mallocFailed = 0;
|
||||
ret = 0;
|
||||
}
|
||||
sqlite3_mutex_leave(p->db->mutex);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
rc = vdbeUnbind(p, i);
|
||||
if( rc || zData==0 ){
|
||||
return rc;
|
||||
if( p==0 ){
|
||||
return SQLITE_MISUSE;
|
||||
}
|
||||
sqlite3_mutex_enter(p->db->mutex);
|
||||
rc = vdbeUnbind(p, i);
|
||||
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(((Vdbe *)pStmt)->db, rc, 0);
|
||||
return sqlite3ApiExit(((Vdbe *)pStmt)->db, rc);
|
||||
sqlite3Error(p->db, rc, 0);
|
||||
rc = sqlite3ApiExit(p->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;
|
||||
}
|
||||
|
||||
@ -827,6 +972,8 @@ int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
|
||||
** exist.
|
||||
*/
|
||||
static void createVarMap(Vdbe *p){
|
||||
if( !p->okVar ){
|
||||
sqlite3_mutex_enter(p->db->mutex);
|
||||
if( !p->okVar ){
|
||||
int j;
|
||||
Op *pOp;
|
||||
@ -838,6 +985,8 @@ static void createVarMap(Vdbe *p){
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
@ -1158,33 +1191,33 @@ static int vdbeCommit(sqlite3 *db){
|
||||
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,25 +1398,13 @@ 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;
|
||||
@ -1407,20 +1412,21 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
@ -1441,6 +1447,7 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
@ -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,24 +276,29 @@ 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);
|
||||
|
||||
/* If there is no statement handle, then the blob-handle has
|
||||
** already been invalidated. Return SQLITE_ABORT in this case.
|
||||
*/
|
||||
v = (Vdbe*)p->pStmt;
|
||||
if( v==0 ){
|
||||
rc = SQLITE_ABORT;
|
||||
}else{
|
||||
/* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is
|
||||
** returned, clean-up the statement handle.
|
||||
*/
|
||||
db = v->db;
|
||||
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;
|
||||
@ -281,8 +306,10 @@ static int blobReadWrite(
|
||||
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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,7 +102,8 @@ int sqlite3VdbeMemExpandBlob(Mem *pMem){
|
||||
assert( (pMem->flags & MEM_Blob)!=0 );
|
||||
nByte = pMem->n + pMem->u.i;
|
||||
if( nByte<=0 ) nByte = 1;
|
||||
pNew = sqliteMalloc(nByte);
|
||||
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
||||
pNew = sqlite3DbMallocRaw(pMem->db, nByte);
|
||||
if( pNew==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
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);
|
||||
sqliteFree(zLowerName);
|
||||
sqlite3_free(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;
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
@ -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 ){
|
||||
|
Loading…
Reference in New Issue
Block a user