diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/auth.c | 4 | ||||
-rw-r--r-- | src/btree.c | 9 | ||||
-rw-r--r-- | src/btree.h | 3 | ||||
-rw-r--r-- | src/build.c | 3 | ||||
-rw-r--r-- | src/callback.c | 6 | ||||
-rw-r--r-- | src/complete.c | 6 | ||||
-rw-r--r-- | src/date.c | 8 | ||||
-rw-r--r-- | src/func.c | 10 | ||||
-rw-r--r-- | src/loadext.c | 17 | ||||
-rw-r--r-- | src/main.c | 8 | ||||
-rw-r--r-- | src/malloc.c | 68 | ||||
-rw-r--r-- | src/prepare.c | 29 | ||||
-rw-r--r-- | src/sqlite.h.in | 14 | ||||
-rw-r--r-- | src/sqliteInt.h | 11 | ||||
-rw-r--r-- | src/test1.c | 22 | ||||
-rw-r--r-- | src/test5.c | 10 | ||||
-rw-r--r-- | src/utf.c | 24 | ||||
-rw-r--r-- | src/util.c | 6 | ||||
-rw-r--r-- | src/vdbe.c | 122 | ||||
-rw-r--r-- | src/vdbeInt.h | 32 | ||||
-rw-r--r-- | src/vdbeapi.c | 64 | ||||
-rw-r--r-- | src/vdbeaux.c | 24 | ||||
-rw-r--r-- | src/vdbeblob.c | 3 | ||||
-rw-r--r-- | src/vdbemem.c | 141 |
24 files changed, 367 insertions, 277 deletions
diff --git a/src/auth.c b/src/auth.c index 79940c273..145f4020a 100644 --- a/src/auth.c +++ b/src/auth.c @@ -14,7 +14,7 @@ ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 ** -** $Id: auth.c,v 1.26 2007/05/14 11:34:47 drh Exp $ +** $Id: auth.c,v 1.27 2007/08/21 19:33:56 drh Exp $ */ #include "sqliteInt.h" @@ -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; } diff --git a/src/btree.c b/src/btree.c index 8f648a909..3e8ef4929 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.405 2007/08/21 13:11:01 danielk1977 Exp $ +** $Id: btree.c,v 1.406 2007/08/21 19:33:56 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -3707,6 +3707,13 @@ int sqlite3BtreeEof(BtCursor *pCur){ } /* +** Return the database connection handle for a cursor. +*/ +sqlite3 *sqlite3BtreeCursorDb(const BtCursor *pCur){ + return pCur->pBtree->pSqlite; +} + +/* ** Advance the cursor to the next entry in the database. If ** successful then set *pRes=0. If the cursor ** was already pointing to the last entry in the database before diff --git a/src/btree.h b/src/btree.h index 5f15d101b..b35856255 100644 --- a/src/btree.h +++ b/src/btree.h @@ -13,7 +13,7 @@ ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.84 2007/08/20 22:48:42 drh Exp $ +** @(#) $Id: btree.h,v 1.85 2007/08/21 19:33:56 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -150,6 +150,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); diff --git a/src/build.c b/src/build.c index bd7b7305a..0e7523c19 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.436 2007/08/17 01:14:38 drh Exp $ +** $Id: build.c,v 1.437 2007/08/21 19:33:56 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -3369,6 +3369,7 @@ KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ 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++){ diff --git a/src/callback.c b/src/callback.c index 9c0df707b..46de7661a 100644 --- a/src/callback.c +++ b/src/callback.c @@ -13,7 +13,7 @@ ** This file contains functions used to access the internal hash tables ** of user defined functions and collation sequences. ** -** $Id: callback.c,v 1.20 2007/08/16 10:09:02 danielk1977 Exp $ +** $Id: callback.c,v 1.21 2007/08/21 19:33:56 drh Exp $ */ #include "sqliteInt.h" @@ -36,8 +36,8 @@ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){ if( db->xCollNeeded16 ){ char const *zExternal; sqlite3_value *pTmp = sqlite3ValueNew(db); - sqlite3ValueSetStr(db, pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC); - zExternal = sqlite3ValueText(db, pTmp, SQLITE_UTF16NATIVE); + sqlite3ValueSetStr(pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC); + zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); if( zExternal ){ db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal); } diff --git a/src/complete.c b/src/complete.c index 052b9ab1e..6571df63f 100644 --- a/src/complete.c +++ b/src/complete.c @@ -16,7 +16,7 @@ ** separating it out, the code will be automatically omitted from ** static links that do not use it. ** -** $Id: complete.c,v 1.4 2007/08/16 10:09:02 danielk1977 Exp $ +** $Id: complete.c,v 1.5 2007/08/21 19:33:56 drh Exp $ */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_COMPLETE @@ -251,8 +251,8 @@ int sqlite3_complete16(const void *zSql){ int rc = SQLITE_NOMEM; pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(0, pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); - zSql8 = sqlite3ValueText(0, pVal, SQLITE_UTF8); + sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); + zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8); if( zSql8 ){ rc = sqlite3_complete(zSql8); } diff --git a/src/date.c b/src/date.c index 33fe92c87..a807f3525 100644 --- a/src/date.c +++ b/src/date.c @@ -16,7 +16,7 @@ ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.70 2007/08/21 10:44:16 drh Exp $ +** $Id: date.c,v 1.71 2007/08/21 19:33:56 drh Exp $ ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon @@ -905,7 +905,7 @@ static void ctimeFunc( ){ sqlite3_value *pVal = sqlite3ValueNew(0); if( pVal ){ - sqlite3ValueSetStr(0, pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC); + sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC); timeFunc(context, 1, &pVal); sqlite3ValueFree(pVal); } @@ -923,7 +923,7 @@ static void cdateFunc( ){ sqlite3_value *pVal = sqlite3ValueNew(0); if( pVal ){ - sqlite3ValueSetStr(0, pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC); + sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC); dateFunc(context, 1, &pVal); sqlite3ValueFree(pVal); } @@ -941,7 +941,7 @@ static void ctimestampFunc( ){ sqlite3_value *pVal = sqlite3ValueNew(0); if( pVal ){ - sqlite3ValueSetStr(0, pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC); + sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC); datetimeFunc(context, 1, &pVal); sqlite3ValueFree(pVal); } diff --git a/src/func.c b/src/func.c index 699ef1724..224f88f08 100644 --- a/src/func.c +++ b/src/func.c @@ -16,7 +16,7 @@ ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.167 2007/08/21 10:44:16 drh Exp $ +** $Id: func.c,v 1.168 2007/08/21 19:33:56 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -1062,13 +1062,13 @@ static void test_destructor( test_destructor_count_var++; assert( nArg==1 ); if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - len = sqlite3ValueBytes(0, argv[0], ENC(db)); + len = sqlite3ValueBytes(argv[0], ENC(db)); zVal = sqlite3MallocZero(len+3); zVal[len] = 0; zVal[len-1] = 0; assert( zVal ); zVal++; - memcpy(zVal, sqlite3ValueText(0, argv[0], ENC(db)), len); + memcpy(zVal, sqlite3ValueText(argv[0], ENC(db)), len); if( ENC(db)==SQLITE_UTF8 ){ sqlite3_result_text(pCtx, zVal, -1, destructor); #ifndef SQLITE_OMIT_UTF16 @@ -1271,10 +1271,10 @@ static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv) max = sqlite3_user_data(context)!=0; cmp = sqlite3MemCompare(pBest, pArg, pColl); if( (max && cmp<0) || (!max && cmp>0) ){ - sqlite3VdbeMemCopy(0, pBest, pArg); + sqlite3VdbeMemCopy(pBest, pArg); } }else{ - sqlite3VdbeMemCopy(0, pBest, pArg); + sqlite3VdbeMemCopy(pBest, pArg); } } static void minMaxFinalize(sqlite3_context *context){ diff --git a/src/loadext.c b/src/loadext.c index b5dc4f5fd..a4c57c2c6 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -260,7 +260,7 @@ const sqlite3_api_routines sqlite3_apis = { ** error message text. The calling function should free this memory ** by calling sqlite3_free(). */ -int sqlite3_load_extension( +static int sqlite3LoadExtension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ @@ -329,6 +329,18 @@ int sqlite3_load_extension( db->aExtension[db->nExtension-1] = handle; return SQLITE_OK; } +int sqlite3_load_extension( + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +){ + int rc; + sqlite3_mutex_enter(db->mutex); + rc = sqlite3LoadExtension(db, zFile, zProc, pzErrMsg); + sqlite3_mutex_leave(db->mutex); + return rc; +} /* ** Call this routine when the database connection is closing in order @@ -336,6 +348,7 @@ int sqlite3_load_extension( */ void sqlite3CloseExtensions(sqlite3 *db){ int i; + assert( sqlite3_mutex_held(db->mutex) ); for(i=0; i<db->nExtension; i++){ sqlite3OsDlClose(db->pVfs, db->aExtension[i]); } @@ -347,11 +360,13 @@ void sqlite3CloseExtensions(sqlite3 *db){ ** default so as not to open security holes in older applications. */ int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ + sqlite3_mutex_enter(db->mutex); if( onoff ){ db->flags |= SQLITE_LoadExtension; }else{ db->flags &= ~SQLITE_LoadExtension; } + sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } diff --git a/src/main.c b/src/main.c index b0aa877d5..69e49752b 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.392 2007/08/21 16:15:56 drh Exp $ +** $Id: main.c,v 1.393 2007/08/21 19:33:56 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -819,7 +819,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){ assert( !db->mallocFailed ); z = sqlite3_value_text16(db->pErr); if( z==0 ){ - sqlite3ValueSetStr(db, db->pErr, -1, sqlite3ErrStr(db->errCode), + sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode), SQLITE_UTF8, SQLITE_STATIC); z = sqlite3_value_text16(db->pErr); } @@ -1116,8 +1116,8 @@ int sqlite3_open16( assert( ppDb ); *ppDb = 0; pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(0, pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC); - zFilename8 = sqlite3ValueText(0, pVal, SQLITE_UTF8); + sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC); + zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8); if( zFilename8 ){ rc = openDatabase(zFilename8, ppDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); diff --git a/src/malloc.c b/src/malloc.c index 3f9466cb7..482e7636f 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -12,24 +12,46 @@ ** Memory allocation functions used throughout sqlite. ** ** -** $Id: malloc.c,v 1.7 2007/08/21 10:44:16 drh Exp $ +** $Id: malloc.c,v 1.8 2007/08/21 19:33:56 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* -** Set the soft heap-size limit for the current thread. Passing a negative -** value indicates no limit. +** 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_uint64 inUse, + unsigned int allocSize +){ + sqlite3_release_memory(allocSize); +} + +/* +** 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){ -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - 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(); -#endif } /* @@ -63,7 +85,7 @@ void *sqlite3DbMallocZero(sqlite3 *db, unsigned n){ void *p = sqlite3_malloc(n); if( p ){ memset(p, 0, n); - }else{ + }else if( db ){ db->mallocFailed = 1; } return p; @@ -196,29 +218,3 @@ int sqlite3ApiExit(sqlite3* db, int rc){ } return rc & (db ? db->errMask : 0xff); } - -#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. -*/ -#if 0 -void sqlite3MallocDisallow(){ -#if 0 - assert( sqlite3_mallocDisallowed>=0 ); - sqlite3_mallocDisallowed++; -#endif -} - -/* -** This function clears the flag set in the thread-specific-data structure set -** by sqlite3MallocDisallow(). -*/ -void sqlite3MallocAllow(){ -#if 0 - assert( sqlite3_mallocDisallowed>0 ); - sqlite3_mallocDisallowed--; -#endif -} -#endif -#endif diff --git a/src/prepare.c b/src/prepare.c index 376fd4e9b..0cbbf2ed7 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.55 2007/08/21 10:44:16 drh Exp $ +** $Id: prepare.c,v 1.56 2007/08/21 19:33:56 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -470,6 +470,7 @@ int sqlite3Prepare( if( sqlite3SafetyOn(db) ){ return SQLITE_MISUSE; } + assert( sqlite3_mutex_held(db->mutex) ); /* If any attached database schemas are locked, do not proceed with ** compilation. Instead return SQLITE_LOCKED immediately. @@ -563,6 +564,20 @@ int sqlite3Prepare( 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; + sqlite3_mutex_enter(db->mutex); + rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail); + sqlite3_mutex_leave(db->mutex); + return rc; +} /* ** Rerun the compilation of a statement after a schema change. @@ -574,12 +589,13 @@ int sqlite3Reprepare(Vdbe *p){ sqlite3_stmt *pNew; const char *zSql; sqlite3 *db; - + zSql = sqlite3VdbeGetSql(p); if( zSql==0 ){ return 0; } db = sqlite3VdbeDb(p); + assert( sqlite3_mutex_held(db->mutex) ); rc = sqlite3Prepare(db, zSql, -1, 0, &pNew, 0); if( rc ){ assert( pNew==0 ); @@ -610,7 +626,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. */ @@ -619,7 +635,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); } @@ -646,6 +662,7 @@ static int sqlite3Prepare16( if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } + sqlite3_mutex_enter(db->mutex); zSql8 = sqlite3Utf16to8(db, zSql, nBytes); if( zSql8 ){ rc = sqlite3Prepare(db, zSql8, -1, saveSqlFlag, ppStmt, &zTail8); @@ -661,7 +678,9 @@ static int sqlite3Prepare16( *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed); } sqlite3_free(zSql8); - return sqlite3ApiExit(db, rc); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; } /* diff --git a/src/sqlite.h.in b/src/sqlite.h.in index abecd1d19..ba1731864 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -30,7 +30,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.233 2007/08/21 16:15:56 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.234 2007/08/21 19:33:56 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -2257,7 +2257,7 @@ void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); ** the implementation of the function using this call. ** ** This routine must be called from the same thread in which -** the SQL function was originally invoked. +** the SQL function is running. */ void *sqlite3_user_data(sqlite3_context*); @@ -2291,8 +2291,8 @@ void *sqlite3_user_data(sqlite3_context*); ** expressions that are constant at compile time. This includes literal ** values and SQL variables. ** -** These routine must be called from the same thread in which -** the SQL function was originally invoked. +** These routines must be called from the same thread in which +** the SQL function is running. */ void *sqlite3_get_auxdata(sqlite3_context*, int); void sqlite3_set_auxdata(sqlite3_context*, int, void*, void (*)(void*)); @@ -2658,6 +2658,12 @@ int sqlite3_release_memory(int); ** continue without error or notification. This is why the limit is ** called a "soft" limit. It is advisory only. ** +** The soft heap limit is implemented using the [sqlite3_memory_alarm()] +** interface. Only a single memory alarm is available in the default +** implementation. This means that if the application also uses the +** memory alarm interface it will interfere with the operation of the +** soft heap limit and undefined behavior will result. +** ** Prior to SQLite version 3.5.0, this routine only constrained the memory ** allocated by a single thread - the same thread in which this routine ** runs. Beginning with SQLite version 3.5.0, the soft heap limit is diff --git a/src/sqliteInt.h b/src/sqliteInt.h index d388afffd..f09d0a8fd 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.594 2007/08/21 13:51:23 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.595 2007/08/21 19:33:56 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -793,6 +793,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[] */ @@ -1744,15 +1745,15 @@ int sqlite3CheckCollSeq(Parse *, CollSeq *); int sqlite3CheckObjectName(Parse *, const char *); void sqlite3VdbeSetChanges(sqlite3 *, int); -const void *sqlite3ValueText(sqlite3 *db, sqlite3_value*, u8); -int sqlite3ValueBytes(sqlite3 *db, sqlite3_value*, u8); -void sqlite3ValueSetStr(sqlite3 *,sqlite3_value*, int, const void *,u8, +const void *sqlite3ValueText(sqlite3_value*, u8); +int sqlite3ValueBytes(sqlite3_value*, u8); +void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); void sqlite3ValueFree(sqlite3_value*); sqlite3_value *sqlite3ValueNew(sqlite3 *); char *sqlite3Utf16to8(sqlite3 *, const void*, int); int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); -void sqlite3ValueApplyAffinity(sqlite3 *, sqlite3_value *, u8, u8); +void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); extern const unsigned char sqlite3UpperToLower[]; void sqlite3RootPageMoved(Db*, int, int); void sqlite3Reindex(Parse*, Token*, Token*); diff --git a/src/test1.c b/src/test1.c index d04d8f67e..c28b514b8 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.266 2007/08/21 10:44:16 drh Exp $ +** $Id: test1.c,v 1.267 2007/08/21 19:33:57 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -921,10 +921,10 @@ static int test_create_function( sqlite3_iMallocFail++; } #endif - pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(0,pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); + pVal = sqlite3ValueNew(db); + sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); rc = sqlite3_create_function16(db, - sqlite3ValueText(0, pVal, SQLITE_UTF16NATIVE), + sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0); sqlite3ValueFree(pVal); } @@ -2056,11 +2056,11 @@ static int test_collate_func( } pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(0, pVal, nA, zA, encin, SQLITE_STATIC); + sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); n = sqlite3_value_bytes(pVal); Tcl_ListObjAppendElement(i,pX, Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); - sqlite3ValueSetStr(0, pVal, nB, zB, encin, SQLITE_STATIC); + sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC); n = sqlite3_value_bytes(pVal); Tcl_ListObjAppendElement(i,pX, Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); @@ -2101,9 +2101,9 @@ static int test_collate( } #endif pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(0, pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC); + sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC); rc = sqlite3_create_collation16(db, - sqlite3ValueText(0, pVal, SQLITE_UTF16NATIVE), SQLITE_UTF16BE, + sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), SQLITE_UTF16BE, (void *)SQLITE_UTF16BE, val?test_collate_func:0); sqlite3ValueFree(pVal); } @@ -2270,7 +2270,7 @@ static void test_function_utf8( Tcl_DecrRefCount(pX); sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT); pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(0, pVal, -1, Tcl_GetStringResult(interp), + sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), SQLITE_UTF8, SQLITE_STATIC); sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal), -1, SQLITE_TRANSIENT); @@ -2293,7 +2293,7 @@ static void test_function_utf16le( Tcl_EvalObjEx(interp, pX, 0); Tcl_DecrRefCount(pX); pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(0, pVal, -1, Tcl_GetStringResult(interp), + sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), SQLITE_UTF8, SQLITE_STATIC); sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT); sqlite3ValueFree(pVal); @@ -2315,7 +2315,7 @@ static void test_function_utf16be( Tcl_EvalObjEx(interp, pX, 0); Tcl_DecrRefCount(pX); pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(0, pVal, -1, Tcl_GetStringResult(interp), + sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), SQLITE_UTF8, SQLITE_STATIC); sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal), -1, SQLITE_TRANSIENT); diff --git a/src/test5.c b/src/test5.c index 88831b79c..58d65aa28 100644 --- a/src/test5.c +++ b/src/test5.c @@ -15,7 +15,7 @@ ** is used for testing the SQLite routines for converting between ** the various supported unicode encodings. ** -** $Id: test5.c,v 1.19 2007/08/21 10:44:16 drh Exp $ +** $Id: test5.c,v 1.20 2007/08/21 19:33:57 drh Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" @@ -156,7 +156,7 @@ static int test_translate( if( objc==5 ){ z = sqlite3StrDup(z); } - sqlite3ValueSetStr(0, pVal, -1, z, enc_from, xDel); + sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel); }else{ z = (char*)Tcl_GetByteArrayFromObj(objv[1], &len); if( objc==5 ){ @@ -164,11 +164,11 @@ static int test_translate( z = sqlite3_malloc(len); memcpy(z, zTmp, len); } - sqlite3ValueSetStr(0, pVal, -1, z, enc_from, xDel); + sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel); } - z = (char *)sqlite3ValueText(0, pVal, enc_to); - len = sqlite3ValueBytes(0, pVal, enc_to) + (enc_to==SQLITE_UTF8?1:2); + z = (char *)sqlite3ValueText(pVal, enc_to); + len = sqlite3ValueBytes(pVal, enc_to) + (enc_to==SQLITE_UTF8?1:2); Tcl_SetObjResult(interp, Tcl_NewByteArrayObj((u8*)z, len)); sqlite3ValueFree(pVal); @@ -12,7 +12,7 @@ ** This file contains routines used to translate between UTF-8, ** UTF-16, UTF-16BE, and UTF-16LE. ** -** $Id: utf.c,v 1.55 2007/08/16 10:09:03 danielk1977 Exp $ +** $Id: utf.c,v 1.56 2007/08/21 19:33:57 drh Exp $ ** ** Notes on UTF-8: ** @@ -187,7 +187,7 @@ int sqlite3Utf8Read( ** desiredEnc. It is an error if the string is already of the desired ** encoding, or if *pMem does not contain a string value. */ -int sqlite3VdbeMemTranslate(sqlite3 *db, Mem *pMem, u8 desiredEnc){ +int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ unsigned char zShort[NBFS]; /* Temporary short output buffer */ int len; /* Maximum length of output string in bytes */ unsigned char *zOut; /* Output buffer */ @@ -196,6 +196,7 @@ int sqlite3VdbeMemTranslate(sqlite3 *db, 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 ); @@ -216,7 +217,7 @@ int sqlite3VdbeMemTranslate(sqlite3 *db, Mem *pMem, u8 desiredEnc){ if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){ u8 temp; int rc; - rc = sqlite3VdbeMemMakeWriteable(db, pMem); + rc = sqlite3VdbeMemMakeWriteable(pMem); if( rc!=SQLITE_OK ){ assert( rc==SQLITE_NOMEM ); return SQLITE_NOMEM; @@ -260,8 +261,10 @@ int sqlite3VdbeMemTranslate(sqlite3 *db, Mem *pMem, u8 desiredEnc){ zIn = (u8*)pMem->z; zTerm = &zIn[pMem->n]; if( len>NBFS ){ - zOut = sqlite3DbMallocRaw(db, len); - if( !zOut ) return SQLITE_NOMEM; + zOut = sqlite3DbMallocRaw(pMem->db, len); + if( !zOut ){ + return SQLITE_NOMEM; + } }else{ zOut = zShort; } @@ -336,7 +339,7 @@ translate_out: ** The allocation (static, dynamic etc.) and encoding of the Mem may be ** changed by this function. */ -int sqlite3VdbeMemHandleBom(sqlite3 *db, Mem *pMem){ +int sqlite3VdbeMemHandleBom(Mem *pMem){ int rc = SQLITE_OK; u8 bom = 0; @@ -364,11 +367,11 @@ int sqlite3VdbeMemHandleBom(sqlite3 *db, Mem *pMem){ char *z = pMem->z; pMem->z = 0; pMem->xDel = 0; - rc = sqlite3VdbeMemSetStr(db, pMem, &z[2], pMem->n-2, bom, + rc = sqlite3VdbeMemSetStr(pMem, &z[2], pMem->n-2, bom, SQLITE_TRANSIENT); xDel(z); }else{ - rc = sqlite3VdbeMemSetStr(db, pMem, &pMem->z[2], pMem->n-2, bom, + rc = sqlite3VdbeMemSetStr(pMem, &pMem->z[2], pMem->n-2, bom, SQLITE_TRANSIENT); } } @@ -411,8 +414,9 @@ int sqlite3Utf8CharLen(const char *zIn, int nByte){ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte){ Mem m; memset(&m, 0, sizeof(m)); - sqlite3VdbeMemSetStr(db, &m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC); - sqlite3VdbeChangeEncoding(db, &m, SQLITE_UTF8); + m.db = db; + sqlite3VdbeMemSetStr(&m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC); + sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8); 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); diff --git a/src/util.c b/src/util.c index 694d7da0b..75992b678 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.210 2007/08/21 10:44:16 drh Exp $ +** $Id: util.c,v 1.211 2007/08/21 19:33:57 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> @@ -51,9 +51,9 @@ void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ va_start(ap, zFormat); z = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); - sqlite3ValueSetStr(db, db->pErr, -1, z, SQLITE_UTF8, sqlite3_free); + sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, sqlite3_free); }else{ - sqlite3ValueSetStr(db, db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC); + sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC); } } } diff --git a/src/vdbe.c b/src/vdbe.c index 80b77615d..f23c05c76 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.643 2007/08/21 10:44:16 drh Exp $ +** $Id: vdbe.c,v 1.644 2007/08/21 19:33:57 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -105,8 +105,8 @@ int sqlite3_max_blobsize = 0; ** Convert the given stack entity into a string if it isn't one ** already. Return non-zero if a malloc() fails. */ -#define Stringify(db, P, enc) \ - if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(db,P,enc)) \ +#define Stringify(P, enc) \ + if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc)) \ { goto no_mem; } /* @@ -137,15 +137,15 @@ int sqlite3_max_blobsize = 0; ** string that the stack entry itself controls. In other words, it ** converts an MEM_Ephem string into an MEM_Dyn string. */ -#define Deephemeralize(db,P) \ +#define Deephemeralize(P) \ if( ((P)->flags&MEM_Ephem)!=0 \ - && sqlite3VdbeMemMakeWriteable(db, P) ){ goto no_mem;} + && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} /* ** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*) ** P if required. */ -#define ExpandBlob(D,P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(D,P):0) +#define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0) /* ** Argument pMem points at a memory cell that will be passed to a @@ -209,14 +209,14 @@ static Cursor *allocateCursor(Vdbe *p, int iCur, int iDb){ ** looks like a number, convert it into a number. If it does not ** look like a number, leave it alone. */ -static void applyNumericAffinity(sqlite3 *db, Mem *pRec){ +static void applyNumericAffinity(Mem *pRec){ if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){ int realnum; - sqlite3VdbeMemNulTerminate(db, pRec); + sqlite3VdbeMemNulTerminate(pRec); if( (pRec->flags&MEM_Str) && sqlite3IsNumber(pRec->z, &realnum, pRec->enc) ){ i64 value; - sqlite3VdbeChangeEncoding(db, pRec, SQLITE_UTF8); + sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8); if( !realnum && sqlite3Atoi64(pRec->z, &value) ){ sqlite3VdbeMemRelease(pRec); pRec->u.i = value; @@ -247,7 +247,6 @@ static void applyNumericAffinity(sqlite3 *db, Mem *pRec){ ** No-op. pRec is unchanged. */ static void applyAffinity( - sqlite3 *db, /* Report malloc() errors to this db connection */ Mem *pRec, /* The value to apply affinity to */ char affinity, /* The affinity to be applied */ u8 enc /* Use this text encoding */ @@ -258,13 +257,13 @@ static void applyAffinity( ** representation. */ if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){ - sqlite3VdbeMemStringify(db, pRec, enc); + sqlite3VdbeMemStringify(pRec, enc); } pRec->flags &= ~(MEM_Real|MEM_Int); }else if( affinity!=SQLITE_AFF_NONE ){ assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL || affinity==SQLITE_AFF_NUMERIC ); - applyNumericAffinity(db, pRec); + applyNumericAffinity(pRec); if( pRec->flags & MEM_Real ){ sqlite3VdbeIntegerAffinity(pRec); } @@ -281,7 +280,7 @@ static void applyAffinity( */ int sqlite3_value_numeric_type(sqlite3_value *pVal){ Mem *pMem = (Mem*)pVal; - applyNumericAffinity(0, pMem); + applyNumericAffinity(pMem); storeTypeInfo(pMem, 0); return pMem->type; } @@ -291,12 +290,11 @@ int sqlite3_value_numeric_type(sqlite3_value *pVal){ ** not the internal Mem* type. */ void sqlite3ValueApplyAffinity( - sqlite3 *db, sqlite3_value *pVal, u8 affinity, u8 enc ){ - applyAffinity(db, (Mem *)pVal, affinity, enc); + applyAffinity((Mem *)pVal, affinity, enc); } #ifdef SQLITE_DEBUG @@ -733,7 +731,7 @@ case OP_Real: { /* same as TK_FLOAT, */ pTos->enc = SQLITE_UTF8; pTos->r = sqlite3VdbeRealValue(pTos); pTos->flags |= MEM_Real; - sqlite3VdbeChangeEncoding(db, pTos, encoding); + sqlite3VdbeChangeEncoding(pTos, encoding); break; } @@ -752,9 +750,9 @@ case OP_String8: { /* same as TK_STRING */ #ifndef SQLITE_OMIT_UTF16 if( encoding!=SQLITE_UTF8 ){ pTos++; - sqlite3VdbeMemSetStr(db, pTos, pOp->p3, -1, SQLITE_UTF8, SQLITE_STATIC); - if( SQLITE_OK!=sqlite3VdbeChangeEncoding(db, pTos, encoding) ) goto no_mem; - if( SQLITE_OK!=sqlite3VdbeMemDynamicify(db, pTos) ) goto no_mem; + sqlite3VdbeMemSetStr(pTos, pOp->p3, -1, SQLITE_UTF8, SQLITE_STATIC); + if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pTos, encoding) ) goto no_mem; + if( SQLITE_OK!=sqlite3VdbeMemDynamicify(pTos) ) goto no_mem; pTos->flags &= ~(MEM_Dyn); pTos->flags |= MEM_Static; if( pOp->p3type==P3_DYNAMIC ){ @@ -842,7 +840,7 @@ case OP_HexBlob: { /* same as TK_BLOB */ case OP_Blob: { pTos++; assert( pOp->p1 < SQLITE_MAX_LENGTH ); /* Due to SQLITE_MAX_SQL_LENGTH */ - sqlite3VdbeMemSetStr(db, pTos, pOp->p3, pOp->p1, 0, 0); + sqlite3VdbeMemSetStr(pTos, pOp->p3, pOp->p1, 0, 0); pTos->enc = encoding; break; } @@ -903,7 +901,7 @@ case OP_Dup: { pTos++; sqlite3VdbeMemShallowCopy(pTos, pFrom, MEM_Ephem); if( pOp->p2 ){ - Deephemeralize(db, pTos); + Deephemeralize(pTos); } break; } @@ -924,9 +922,9 @@ case OP_Pull: { /* no-push */ Mem ts; ts = *pFrom; - Deephemeralize(db, pTos); + Deephemeralize(pTos); for(i=0; i<pOp->p1; i++, pFrom++){ - Deephemeralize(db, &pFrom[1]); + Deephemeralize(&pFrom[1]); assert( (pFrom[1].flags & MEM_Ephem)==0 ); *pFrom = pFrom[1]; if( pFrom->flags & MEM_Short ){ @@ -954,7 +952,7 @@ case OP_Push: { /* no-push */ Mem *pTo = &pTos[-pOp->p1]; assert( pTo>=p->aStack ); - sqlite3VdbeMemMove(db, pTo, pTos); + sqlite3VdbeMemMove(pTo, pTos); pTos--; break; } @@ -982,7 +980,7 @@ case OP_Callback: { /* no-push */ */ pFirstColumn = &pTos[0-pOp->p1]; for(pMem = p->aStack; pMem<pFirstColumn; pMem++){ - Deephemeralize(db, pMem); + Deephemeralize(pMem); } /* Invalidate all ephemeral cursor row caches */ @@ -993,7 +991,7 @@ case OP_Callback: { /* no-push */ ** as side effect. */ for(; pMem<=pTos; pMem++ ){ - sqlite3VdbeMemNulTerminate(db, pMem); + sqlite3VdbeMemNulTerminate(pMem); storeTypeInfo(pMem, encoding); } @@ -1035,8 +1033,8 @@ case OP_Concat: { /* same as TK_CONCAT */ nByte = -1; break; } - ExpandBlob(db, pTerm); - Stringify(db, pTerm, encoding); + ExpandBlob(pTerm); + Stringify(pTerm, encoding); nByte += pTerm->n; } @@ -1280,6 +1278,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 ); @@ -1321,10 +1320,10 @@ case OP_Function: { } /* Copy the result of the function to the top of the stack */ - sqlite3VdbeChangeEncoding(db, &ctx.s, encoding); + sqlite3VdbeChangeEncoding(&ctx.s, encoding); pTos++; pTos->flags = 0; - sqlite3VdbeMemMove(db, pTos, &ctx.s); + sqlite3VdbeMemMove(pTos, &ctx.s); if( sqlite3VdbeMemTooBig(pTos) ){ goto too_big; } @@ -1417,7 +1416,7 @@ case OP_AddImm: { /* no-push */ case OP_ForceInt: { /* no-push */ i64 v; assert( pTos>=p->aStack ); - applyAffinity(db, pTos, SQLITE_AFF_NUMERIC, encoding); + applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding); if( (pTos->flags & (MEM_Int|MEM_Real))==0 ){ Release(pTos); pTos--; @@ -1452,7 +1451,7 @@ case OP_ForceInt: { /* no-push */ */ case OP_MustBeInt: { /* no-push */ assert( pTos>=p->aStack ); - applyAffinity(db, pTos, SQLITE_AFF_NUMERIC, encoding); + applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding); if( (pTos->flags & MEM_Int)==0 ){ if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; @@ -1500,8 +1499,8 @@ case OP_ToText: { /* same as TK_TO_TEXT, no-push */ if( pTos->flags & MEM_Null ) break; assert( MEM_Str==(MEM_Blob>>3) ); pTos->flags |= (pTos->flags&MEM_Blob)>>3; - applyAffinity(db, pTos, SQLITE_AFF_TEXT, encoding); - rc = ExpandBlob(db, pTos); + applyAffinity(pTos, SQLITE_AFF_TEXT, encoding); + rc = ExpandBlob(pTos); assert( pTos->flags & MEM_Str ); pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Blob); break; @@ -1520,7 +1519,7 @@ case OP_ToBlob: { /* same as TK_TO_BLOB, no-push */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; if( (pTos->flags & MEM_Blob)==0 ){ - applyAffinity(db, pTos, SQLITE_AFF_TEXT, encoding); + applyAffinity(pTos, SQLITE_AFF_TEXT, encoding); assert( pTos->flags & MEM_Str ); pTos->flags |= MEM_Blob; } @@ -1701,13 +1700,13 @@ case OP_Ge: { /* same as TK_GE, no-push */ affinity = pOp->p1 & 0xFF; if( affinity ){ - applyAffinity(db, pNos, affinity, encoding); - applyAffinity(db, pTos, affinity, encoding); + applyAffinity(pNos, affinity, encoding); + applyAffinity(pTos, affinity, encoding); } assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 ); - ExpandBlob(db, pNos); - ExpandBlob(db, pTos); + ExpandBlob(pNos); + ExpandBlob(pTos); res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3); switch( pOp->opcode ){ case OP_Eq: res = res==0; break; @@ -2118,7 +2117,7 @@ case OP_Column: { ** acquire the complete header text. */ if( !zRec && avail<offset ){ - rc = sqlite3VdbeMemFromBtree(db, pCrsr, 0, offset, pC->isIndex, &sMem); + rc = sqlite3VdbeMemFromBtree(pCrsr, 0, offset, pC->isIndex, &sMem); if( rc!=SQLITE_OK ){ goto op_column_out; } @@ -2172,8 +2171,7 @@ case OP_Column: { zData = &zRec[aOffset[p2]]; }else{ len = sqlite3VdbeSerialTypeLen(aType[p2]); - rc = sqlite3VdbeMemFromBtree( - db, pCrsr, aOffset[p2], len, pC->isIndex, &sMem); + rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex, &sMem); if( rc!=SQLITE_OK ){ goto op_column_out; } @@ -2205,7 +2203,7 @@ case OP_Column: { /* pTos->z might be pointing to sMem.zShort[]. Fix that so that we ** can abandon sMem */ - rc = sqlite3VdbeMemMakeWriteable(db, pTos); + rc = sqlite3VdbeMemMakeWriteable(pTos); op_column_out: break; @@ -2301,13 +2299,13 @@ case OP_MakeRecord: { for(pRec=pData0; pRec<=pTos; pRec++){ int len; if( zAffinity ){ - applyAffinity(db, pRec, zAffinity[pRec-pData0], encoding); + applyAffinity(pRec, zAffinity[pRec-pData0], encoding); } if( pRec->flags&MEM_Null ){ containsNull = 1; } if( pRec->flags&MEM_Zero && pRec->n>0 ){ - ExpandBlob(db, pRec); + ExpandBlob(pRec); } serial_type = sqlite3VdbeSerialType(pRec, file_format); len = sqlite3VdbeSerialTypeLen(serial_type); @@ -2973,7 +2971,7 @@ case OP_MoveGt: { /* no-push */ pC->rowidIsValid = res==0; }else{ assert( pTos->flags & MEM_Blob ); - ExpandBlob(db, pTos); + ExpandBlob(pTos); rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; @@ -3081,7 +3079,7 @@ case OP_Found: { /* no-push */ int res, rx; assert( pC->isTable==0 ); assert( pTos->flags & MEM_Blob ); - Stringify(db, pTos, encoding); + Stringify(pTos, encoding); rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res); alreadyExists = rx==SQLITE_OK && res==0; pC->deferredMoveto = 0; @@ -3149,7 +3147,7 @@ case OP_IsUnique: { /* no-push */ /* Make sure K is a string and make zKey point to K */ assert( pNos->flags & MEM_Blob ); - Stringify(db, pNos, encoding); + Stringify(pNos, encoding); zKey = pNos->z; nKey = pNos->n; @@ -3172,7 +3170,7 @@ case OP_IsUnique: { /* no-push */ break; } } - rc = sqlite3VdbeIdxKeyCompare(db, pCx, len, (u8*)zKey, &res); + rc = sqlite3VdbeIdxKeyCompare(pCx, len, (u8*)zKey, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; if( res>0 ){ pc = pOp->p2 - 1; @@ -3184,7 +3182,7 @@ case OP_IsUnique: { /* no-push */ ** final rowid column is different from R. If it equals R then jump ** immediately to P2. */ - rc = sqlite3VdbeIdxRowid(db, pCrsr, &v); + rc = sqlite3VdbeIdxRowid(pCrsr, &v); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } @@ -3876,7 +3874,7 @@ case OP_IdxInsert: { /* no-push */ assert( pTos->flags & MEM_Blob ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ assert( pC->isTable==0 ); - rc = ExpandBlob(db, pTos); + rc = ExpandBlob(pTos); if( rc==SQLITE_OK ){ int nKey = pTos->n; const char *zKey = pTos->z; @@ -3943,7 +3941,7 @@ case OP_IdxRowid: { if( pC->nullRow ){ pTos->flags = MEM_Null; }else{ - rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid); + rc = sqlite3VdbeIdxRowid(pCrsr, &rowid); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } @@ -4012,10 +4010,10 @@ case OP_IdxGE: { /* no-push */ assert( pTos->flags & MEM_Blob ); /* Created using OP_MakeRecord */ assert( pC->deferredMoveto==0 ); - ExpandBlob(db, pTos); + ExpandBlob(pTos); *pC->pIncrKey = pOp->p3!=0; assert( pOp->p3==0 || pOp->opcode!=OP_IdxGT ); - rc = sqlite3VdbeIdxKeyCompare(db, pC, pTos->n, (u8*)pTos->z, &res); + rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, (u8*)pTos->z, &res); *pC->pIncrKey = 0; if( rc!=SQLITE_OK ){ break; @@ -4337,7 +4335,7 @@ case OP_IntegrityCk: { pTos->xDel = 0; } pTos->enc = SQLITE_UTF8; - sqlite3VdbeChangeEncoding(db, pTos, encoding); + sqlite3VdbeChangeEncoding(pTos, encoding); sqlite3_free(aRoot); break; } @@ -4435,7 +4433,7 @@ case OP_ContextPop: { /* no-push */ case OP_MemStore: { /* no-push */ assert( pTos>=p->aStack ); assert( pOp->p1>=0 && pOp->p1<p->nMem ); - rc = sqlite3VdbeMemMove(db, &p->aMem[pOp->p1], pTos); + rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], pTos); pTos--; /* If P2 is 0 then fall thru to the next opcode, OP_MemLoad, that will @@ -4589,7 +4587,7 @@ case OP_MemInt: { case OP_MemMove: { assert( pOp->p1>=0 && pOp->p1<p->nMem ); assert( pOp->p2>=0 && pOp->p2<p->nMem ); - rc = sqlite3VdbeMemMove(db, &p->aMem[pOp->p1], &p->aMem[pOp->p2]); + rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], &p->aMem[pOp->p2]); break; } @@ -4625,9 +4623,9 @@ 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; - ctx.db = db; if( ctx.pFunc->needCollSeq ){ assert( pOp>p->aOp ); assert( pOp[-1].p3type==P3_COLLSEQ ); @@ -4949,6 +4947,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); @@ -4956,10 +4955,10 @@ case OP_VColumn: { ** do this regardless of whether or not an error occured to ensure any ** dynamic allocation in sContext.s (a Mem struct) is released. */ - sqlite3VdbeChangeEncoding(db, &sContext.s, encoding); + sqlite3VdbeChangeEncoding(&sContext.s, encoding); pTos++; pTos->flags = 0; - sqlite3VdbeMemMove(db, pTos, &sContext.s); + sqlite3VdbeMemMove(pTos, &sContext.s); if( sqlite3SafetyOn(db) ){ goto abort_due_to_misuse; @@ -5028,7 +5027,7 @@ case OP_VRename: { /* no-push */ sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3); assert( pVtab->pModule->xRename ); - Stringify(db, pTos, encoding); + Stringify(pTos, encoding); if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; sqlite3VtabLock(pVtab); @@ -5149,6 +5148,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) ); } diff --git a/src/vdbeInt.h b/src/vdbeInt.h index caf27f0c2..37a049e11 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -130,6 +130,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. */ @@ -219,7 +220,6 @@ struct sqlite3_context { Mem *pMem; /* Memory cell used to store aggregate context */ u8 isError; /* Set to true for an error */ CollSeq *pColl; /* Collating sequence */ - sqlite3 *db; /* Database connection */ }; /* @@ -375,56 +375,56 @@ int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); void sqlite3VdbeDeleteAuxData(VdbeFunc*, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); -int sqlite3VdbeIdxKeyCompare(sqlite3*,Cursor*,int,const unsigned char*,int*); -int sqlite3VdbeIdxRowid(sqlite3 *, BtCursor *, i64 *); +int sqlite3VdbeIdxKeyCompare(Cursor*,int,const unsigned char*,int*); +int sqlite3VdbeIdxRowid(BtCursor *, i64 *); int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*); int sqlite3VdbeIdxRowidLen(const u8*); int sqlite3VdbeExec(Vdbe*); int sqlite3VdbeList(Vdbe*); int sqlite3VdbeHalt(Vdbe*); -int sqlite3VdbeChangeEncoding(sqlite3 *, Mem *, int); +int sqlite3VdbeChangeEncoding(Mem *, int); int sqlite3VdbeMemTooBig(Mem*); -int sqlite3VdbeMemCopy(sqlite3*, Mem*, const Mem*); +int sqlite3VdbeMemCopy(Mem*, const Mem*); void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); -int sqlite3VdbeMemMove(sqlite3*, Mem*, Mem*); -int sqlite3VdbeMemNulTerminate(sqlite3 *, Mem*); -int sqlite3VdbeMemSetStr(sqlite3 *, Mem*, const char*, int, u8, void(*)(void*)); +int sqlite3VdbeMemMove(Mem*, Mem*); +int sqlite3VdbeMemNulTerminate(Mem*); +int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); void sqlite3VdbeMemSetInt64(Mem*, i64); void sqlite3VdbeMemSetDouble(Mem*, double); void sqlite3VdbeMemSetNull(Mem*); void sqlite3VdbeMemSetZeroBlob(Mem*,int); -int sqlite3VdbeMemMakeWriteable(sqlite3 *, Mem*); -int sqlite3VdbeMemDynamicify(sqlite3 *, Mem*); -int sqlite3VdbeMemStringify(sqlite3*, Mem*, int); +int sqlite3VdbeMemMakeWriteable(Mem*); +int sqlite3VdbeMemDynamicify(Mem*); +int sqlite3VdbeMemStringify(Mem*, int); i64 sqlite3VdbeIntValue(Mem*); int sqlite3VdbeMemIntegerify(Mem*); double sqlite3VdbeRealValue(Mem*); void sqlite3VdbeIntegerAffinity(Mem*); int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemNumerify(Mem*); -int sqlite3VdbeMemFromBtree(sqlite3*,BtCursor*,int,int,int,Mem*); +int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*); void sqlite3VdbeMemRelease(Mem *p); int sqlite3VdbeMemFinalize(Mem*, FuncDef*); #ifndef NDEBUG void sqlite3VdbeMemSanity(Mem*); int sqlite3VdbeOpcodeNoPush(u8); #endif -int sqlite3VdbeMemTranslate(sqlite3 *, Mem*, u8); +int sqlite3VdbeMemTranslate(Mem*, u8); #ifdef SQLITE_DEBUG void sqlite3VdbePrintSql(Vdbe*); void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf); #endif -int sqlite3VdbeMemHandleBom(sqlite3 *, Mem *pMem); +int sqlite3VdbeMemHandleBom(Mem *pMem); void sqlite3VdbeFifoInit(Fifo*); int sqlite3VdbeFifoPush(Fifo*, i64); int sqlite3VdbeFifoPop(Fifo*, i64*); void sqlite3VdbeFifoClear(Fifo*); #ifndef SQLITE_OMIT_INCRBLOB - int sqlite3VdbeMemExpandBlob(sqlite3 *, Mem *); + int sqlite3VdbeMemExpandBlob(Mem *); #else - #define sqlite3VdbeMemExpandBlob(d,x) SQLITE_OK + #define sqlite3VdbeMemExpandBlob(x) SQLITE_OK #endif #endif /* !defined(_VDBEINT_H_) */ diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 253b47780..20767fd62 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -97,7 +97,7 @@ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ const void *sqlite3_value_blob(sqlite3_value *pVal){ Mem *p = (Mem*)pVal; if( p->flags & (MEM_Blob|MEM_Str) ){ - sqlite3VdbeMemExpandBlob(0, p); + sqlite3VdbeMemExpandBlob(p); p->flags &= ~MEM_Str; p->flags |= MEM_Blob; return p->z; @@ -106,10 +106,10 @@ const void *sqlite3_value_blob(sqlite3_value *pVal){ } } int sqlite3_value_bytes(sqlite3_value *pVal){ - return sqlite3ValueBytes(0, pVal, SQLITE_UTF8); + return sqlite3ValueBytes(pVal, SQLITE_UTF8); } int sqlite3_value_bytes16(sqlite3_value *pVal){ - return sqlite3ValueBytes(0, pVal, SQLITE_UTF16NATIVE); + return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE); } double sqlite3_value_double(sqlite3_value *pVal){ return sqlite3VdbeRealValue((Mem*)pVal); @@ -121,17 +121,17 @@ sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal); } const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ - return (const unsigned char *)sqlite3ValueText(0, pVal, SQLITE_UTF8); + return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); } #ifndef SQLITE_OMIT_UTF16 const void *sqlite3_value_text16(sqlite3_value* pVal){ - return sqlite3ValueText(0, pVal, SQLITE_UTF16NATIVE); + return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); } const void *sqlite3_value_text16be(sqlite3_value *pVal){ - return sqlite3ValueText(0, pVal, SQLITE_UTF16BE); + return sqlite3ValueText(pVal, SQLITE_UTF16BE); } const void *sqlite3_value_text16le(sqlite3_value *pVal){ - return sqlite3ValueText(0, pVal, SQLITE_UTF16LE); + return sqlite3ValueText(pVal, SQLITE_UTF16LE); } #endif /* SQLITE_OMIT_UTF16 */ int sqlite3_value_type(sqlite3_value* pVal){ @@ -150,19 +150,19 @@ void sqlite3_result_blob( void (*xDel)(void *) ){ assert( n>=0 ); - sqlite3VdbeMemSetStr(0, &pCtx->s, z, n, 0, xDel); + sqlite3VdbeMemSetStr(&pCtx->s, z, n, 0, xDel); } void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ sqlite3VdbeMemSetDouble(&pCtx->s, rVal); } void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ pCtx->isError = 1; - sqlite3VdbeMemSetStr(0, &pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); + 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){ pCtx->isError = 1; - sqlite3VdbeMemSetStr(0, &pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); + sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); } #endif void sqlite3_result_int(sqlite3_context *pCtx, int iVal){ @@ -180,7 +180,7 @@ void sqlite3_result_text( int n, void (*xDel)(void *) ){ - sqlite3VdbeMemSetStr(0, &pCtx->s, z, n, SQLITE_UTF8, xDel); + sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, xDel); } #ifndef SQLITE_OMIT_UTF16 void sqlite3_result_text16( @@ -189,7 +189,7 @@ void sqlite3_result_text16( int n, void (*xDel)(void *) ){ - sqlite3VdbeMemSetStr(0, &pCtx->s, z, n, SQLITE_UTF16NATIVE, xDel); + sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, xDel); } void sqlite3_result_text16be( sqlite3_context *pCtx, @@ -197,7 +197,7 @@ void sqlite3_result_text16be( int n, void (*xDel)(void *) ){ - sqlite3VdbeMemSetStr(0, &pCtx->s, z, n, SQLITE_UTF16BE, xDel); + sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16BE, xDel); } void sqlite3_result_text16le( sqlite3_context *pCtx, @@ -205,11 +205,11 @@ void sqlite3_result_text16le( int n, void (*xDel)(void *) ){ - sqlite3VdbeMemSetStr(0, &pCtx->s, z, n, SQLITE_UTF16LE, xDel); + sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16LE, xDel); } #endif /* SQLITE_OMIT_UTF16 */ void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ - sqlite3VdbeMemCopy(0, &pCtx->s, pValue); + sqlite3VdbeMemCopy(&pCtx->s, pValue); } void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ sqlite3VdbeMemSetZeroBlob(&pCtx->s, n); @@ -351,19 +351,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 @@ -404,8 +412,10 @@ 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 ); @@ -418,7 +428,7 @@ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ pMem->z = pMem->zShort; memset(pMem->z, 0, nByte); }else{ - pMem->z = sqlite3DbMallocZero(p->db, nByte); + pMem->z = sqlite3DbMallocZero(p->s.db, nByte); } } } @@ -430,7 +440,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; } @@ -452,13 +465,14 @@ void sqlite3_set_auxdata( VdbeFunc *pVdbeFunc; 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 = sqlite3_realloc(pVdbeFunc, nMalloc); if( !pVdbeFunc ){ - pCtx->db->mallocFailed = 1; + pCtx->s.db->mallocFailed = 1; goto failed; } pCtx->pVdbeFunc = pVdbeFunc; @@ -524,7 +538,7 @@ 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 }; + static const Mem nullMem = {{0}, 0.0, 0, "", 0, MEM_Null, SQLITE_NULL }; sqlite3Error(pVm->db, SQLITE_RANGE, 0); return (Mem*)&nullMem; } @@ -800,9 +814,9 @@ static int bindText( return rc; } pVar = &p->aVar[i-1]; - rc = sqlite3VdbeMemSetStr(p->db, pVar, zData, nData, encoding, xDel); + rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); if( rc==SQLITE_OK && encoding!=0 ){ - rc = sqlite3VdbeChangeEncoding(p->db, pVar, ENC(p->db)); + rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); } sqlite3Error(p->db, rc, 0); rc = sqlite3ApiExit(p->db, rc); @@ -882,7 +896,7 @@ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ sqlite3_mutex_enter(p->db->mutex); rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ - rc = sqlite3VdbeMemCopy(0, &p->aVar[i-1], pValue); + rc = sqlite3VdbeMemCopy(&p->aVar[i-1], pValue); } sqlite3_mutex_leave(p->db->mutex); return rc; @@ -987,7 +1001,7 @@ int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ } for(i=0; rc==SQLITE_OK && i<pFrom->nVar; i++){ sqlite3MallocDisallow(); - rc = sqlite3VdbeMemMove(0, &pTo->aVar[i], &pFrom->aVar[i]); + rc = sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]); sqlite3MallocAllow(); } assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 5eb9d22a6..85edcba11 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -680,6 +680,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++); } } @@ -887,11 +888,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]; @@ -1032,11 +1038,9 @@ int sqlite3VdbeSetColName(Vdbe *p, int idx, int var, const char *zName, int N){ assert( p->aColName!=0 ); pColName = &(p->aColName[idx+var*p->nResColumn]); if( N==P3_DYNAMIC || N==P3_STATIC ){ - rc = sqlite3VdbeMemSetStr(p->db, - pColName, zName, -1, SQLITE_UTF8, SQLITE_STATIC); + rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, SQLITE_STATIC); }else{ - rc = sqlite3VdbeMemSetStr(p->db, - pColName, zName, N, SQLITE_UTF8, SQLITE_TRANSIENT); + rc = sqlite3VdbeMemSetStr(pColName, zName, N, SQLITE_UTF8,SQLITE_TRANSIENT); } if( rc==SQLITE_OK && N==P3_DYNAMIC ){ pColName->flags = (pColName->flags&(~MEM_Static))|MEM_Dyn; @@ -1550,7 +1554,7 @@ int sqlite3VdbeReset(Vdbe *p){ */ if( p->pc>=0 ){ if( p->zErrMsg ){ - sqlite3ValueSetStr(db,db->pErr,-1,p->zErrMsg,SQLITE_UTF8,sqlite3_free); + sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,sqlite3_free); db->errCode = p->rc; p->zErrMsg = 0; }else if( p->rc ){ @@ -2032,7 +2036,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; @@ -2106,7 +2112,7 @@ int sqlite3VdbeIdxRowidLen(const u8 *aKey){ ** Read the rowid (the last field in the record) and store it in *rowid. ** Return SQLITE_OK if everything works, or an error code otherwise. */ -int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ +int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){ i64 nCellKey = 0; int rc; u32 szHdr; /* Size of the header */ @@ -2118,7 +2124,7 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ if( nCellKey<=0 ){ return SQLITE_CORRUPT_BKPT; } - rc = sqlite3VdbeMemFromBtree(db, pCur, 0, nCellKey, 1, &m); + rc = sqlite3VdbeMemFromBtree(pCur, 0, nCellKey, 1, &m); if( rc ){ return rc; } @@ -2142,7 +2148,6 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ ** is ignored as well. */ int sqlite3VdbeIdxKeyCompare( - sqlite3 *db, Cursor *pC, /* The cursor to compare against */ int nKey, const u8 *pKey, /* The key to compare */ int *res /* Write the comparison result here */ @@ -2158,7 +2163,7 @@ int sqlite3VdbeIdxKeyCompare( *res = 0; return SQLITE_OK; } - rc = sqlite3VdbeMemFromBtree(db, pC->pCursor, 0, nCellKey, 1, &m); + rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m); if( rc ){ return rc; } @@ -2173,6 +2178,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; } diff --git a/src/vdbeblob.c b/src/vdbeblob.c index 216803123..6acbe4023 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -12,7 +12,7 @@ ** ** This file contains code used to implement incremental BLOB I/O. ** -** $Id: vdbeblob.c,v 1.13 2007/08/21 15:13:19 drh Exp $ +** $Id: vdbeblob.c,v 1.14 2007/08/21 19:33:57 drh Exp $ */ #include "sqliteInt.h" @@ -247,7 +247,6 @@ blob_open_out: */ int sqlite3_blob_close(sqlite3_blob *pBlob){ Incrblob *p = (Incrblob *)pBlob; - sqlite3_stmt *pStmt; sqlite3_mutex *mutex = p->db->mutex; int rc; diff --git a/src/vdbemem.c b/src/vdbemem.c index ad911fa0e..71d7ecd52 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -24,7 +24,7 @@ ** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*) ** P if required. */ -#define expandBlob(D,P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(D,P):0) +#define expandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0) /* ** If pMem is an object with a valid string representation, this routine @@ -39,11 +39,12 @@ ** SQLITE_NOMEM may be returned if a malloc() fails during conversion ** between formats. */ -int sqlite3VdbeChangeEncoding(sqlite3 *db, Mem *pMem, int desiredEnc){ +int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ int rc; 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 @@ -51,7 +52,7 @@ int sqlite3VdbeChangeEncoding(sqlite3 *db, Mem *pMem, int desiredEnc){ /* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned, ** then the encoding of the value may not have changed. */ - rc = sqlite3VdbeMemTranslate(db, pMem, desiredEnc); + rc = sqlite3VdbeMemTranslate(pMem, desiredEnc); assert(rc==SQLITE_OK || rc==SQLITE_NOMEM); assert(rc==SQLITE_OK || pMem->enc!=desiredEnc); assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc); @@ -64,17 +65,18 @@ int sqlite3VdbeChangeEncoding(sqlite3 *db, Mem *pMem, int desiredEnc){ ** ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. */ -int sqlite3VdbeMemDynamicify(sqlite3 *db, Mem *pMem){ +int sqlite3VdbeMemDynamicify(Mem *pMem){ int n; u8 *z; - expandBlob(db, pMem); + 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; } assert( (pMem->flags & MEM_Dyn)==0 ); n = pMem->n; assert( pMem->flags & (MEM_Str|MEM_Blob) ); - z = sqlite3_malloc( n+2 ); + z = sqlite3DbMallocRaw(pMem->db, n+2 ); if( z==0 ){ return SQLITE_NOMEM; } @@ -93,16 +95,16 @@ int sqlite3VdbeMemDynamicify(sqlite3 *db, Mem *pMem){ ** blob stored in dynamically allocated space. */ #ifndef SQLITE_OMIT_INCRBLOB -int sqlite3VdbeMemExpandBlob(sqlite3 *db, Mem *pMem){ +int sqlite3VdbeMemExpandBlob(Mem *pMem){ if( pMem->flags & MEM_Zero ){ char *pNew; int nByte; assert( (pMem->flags & MEM_Blob)!=0 ); nByte = pMem->n + pMem->u.i; if( nByte<=0 ) nByte = 1; - pNew = sqlite3_malloc(nByte); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + pNew = sqlite3DbMallocRaw(pMem->db, nByte); if( pNew==0 ){ - if( db ) db->mallocFailed = 1; return SQLITE_NOMEM; } memcpy(pNew, pMem->z, pMem->n); @@ -125,10 +127,11 @@ int sqlite3VdbeMemExpandBlob(sqlite3 *db, Mem *pMem){ ** ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. */ -int sqlite3VdbeMemMakeWriteable(sqlite3 *db, Mem *pMem){ +int sqlite3VdbeMemMakeWriteable(Mem *pMem){ int n; u8 *z; - expandBlob(db, pMem); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + expandBlob(pMem); if( (pMem->flags & (MEM_Ephem|MEM_Static))==0 ){ return SQLITE_OK; } @@ -138,9 +141,8 @@ int sqlite3VdbeMemMakeWriteable(sqlite3 *db, Mem *pMem){ z = (u8*)pMem->zShort; pMem->flags |= MEM_Short|MEM_Term; }else{ - z = sqlite3_malloc( n+2 ); + z = sqlite3DbMallocRaw(pMem->db, n+2 ); if( z==0 ){ - db->mallocFailed = 1; return SQLITE_NOMEM; } pMem->flags |= MEM_Dyn|MEM_Term; @@ -158,18 +160,18 @@ int sqlite3VdbeMemMakeWriteable(sqlite3 *db, Mem *pMem){ /* ** Make sure the given Mem is \u0000 terminated. */ -int sqlite3VdbeMemNulTerminate(sqlite3 *db, Mem *pMem){ +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 */ } if( pMem->flags & (MEM_Static|MEM_Ephem) ){ - return sqlite3VdbeMemMakeWriteable(db, pMem); + return sqlite3VdbeMemMakeWriteable(pMem); }else{ char *z; - sqlite3VdbeMemExpandBlob(db, pMem); - z = sqlite3_malloc(pMem->n+2); + sqlite3VdbeMemExpandBlob(pMem); + z = sqlite3DbMallocRaw(pMem->db, pMem->n+2); if( !z ){ - db->mallocFailed = 1; return SQLITE_NOMEM; } memcpy(z, pMem->z, pMem->n); @@ -200,11 +202,12 @@ int sqlite3VdbeMemNulTerminate(sqlite3 *db, Mem *pMem){ ** keys are strings. In the former case a NULL pointer is returned the ** user and the later is an internal programming error. */ -int sqlite3VdbeMemStringify(sqlite3 *db, Mem *pMem, int enc){ +int sqlite3VdbeMemStringify(Mem *pMem, int enc){ int rc = SQLITE_OK; 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) ); @@ -225,7 +228,7 @@ int sqlite3VdbeMemStringify(sqlite3 *db, Mem *pMem, int enc){ pMem->z = z; pMem->enc = SQLITE_UTF8; pMem->flags |= MEM_Str | MEM_Short | MEM_Term; - sqlite3VdbeChangeEncoding(db, pMem, enc); + sqlite3VdbeChangeEncoding(pMem, enc); return rc; } @@ -242,8 +245,10 @@ 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; @@ -268,6 +273,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 ){ @@ -296,7 +302,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 ){ @@ -304,8 +312,8 @@ i64 sqlite3VdbeIntValue(Mem *pMem){ }else if( flags & (MEM_Str|MEM_Blob) ){ i64 value; pMem->flags |= MEM_Str; - if( sqlite3VdbeChangeEncoding(0, pMem, SQLITE_UTF8) - || sqlite3VdbeMemNulTerminate(0, pMem) ){ + if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) + || sqlite3VdbeMemNulTerminate(pMem) ){ return 0; } assert( pMem->z ); @@ -323,6 +331,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 ){ @@ -330,8 +339,8 @@ double sqlite3VdbeRealValue(Mem *pMem){ }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ double val = 0.0; pMem->flags |= MEM_Str; - if( sqlite3VdbeChangeEncoding(0, pMem, SQLITE_UTF8) - || sqlite3VdbeMemNulTerminate(0, pMem) ){ + if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) + || sqlite3VdbeMemNulTerminate(pMem) ){ return 0.0; } assert( pMem->z ); @@ -348,6 +357,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; @@ -358,6 +368,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; @@ -369,6 +380,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; @@ -384,6 +396,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; @@ -483,14 +496,14 @@ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ ** Make a full copy of pFrom into pTo. Prior contents of pTo are ** freed before the copy is made. */ -int sqlite3VdbeMemCopy(sqlite3 *db, Mem *pTo, const Mem *pFrom){ +int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ int rc; if( pTo->flags & MEM_Dyn ){ sqlite3VdbeMemRelease(pTo); } sqlite3VdbeMemShallowCopy(pTo, pFrom, MEM_Ephem); if( pTo->flags & MEM_Ephem ){ - rc = sqlite3VdbeMemMakeWriteable(db, pTo); + rc = sqlite3VdbeMemMakeWriteable(pTo); }else{ rc = SQLITE_OK; } @@ -505,8 +518,11 @@ int sqlite3VdbeMemCopy(sqlite3 *db, Mem *pTo, const Mem *pFrom){ ** might be returned if pFrom held ephemeral data and we were unable ** to allocate enough space to make a copy. */ -int sqlite3VdbeMemMove(sqlite3 *db, Mem *pTo, 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); } @@ -517,7 +533,7 @@ int sqlite3VdbeMemMove(sqlite3 *db, Mem *pTo, Mem *pFrom){ pFrom->flags = MEM_Null; pFrom->xDel = 0; if( pTo->flags & MEM_Ephem ){ - rc = sqlite3VdbeMemMakeWriteable(db, pTo); + rc = sqlite3VdbeMemMakeWriteable(pTo); }else{ rc = SQLITE_OK; } @@ -528,20 +544,19 @@ int sqlite3VdbeMemMove(sqlite3 *db, Mem *pTo, Mem *pFrom){ ** Change the value of a Mem to be a string or a BLOB. */ int sqlite3VdbeMemSetStr( - sqlite3 *db, Mem *pMem, /* Memory cell to set to string value */ const char *z, /* String pointer */ int n, /* Bytes in string, or negative */ 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; @@ -580,13 +595,13 @@ int sqlite3VdbeMemSetStr( pMem->n = sqlite3Utf16ByteLen(pMem->z,-1); pMem->flags |= MEM_Term; } - if( sqlite3VdbeMemHandleBom(db, pMem) ){ + if( sqlite3VdbeMemHandleBom(pMem) ){ return SQLITE_NOMEM; } #endif /* SQLITE_OMIT_UTF16 */ } if( pMem->flags&MEM_Ephem ){ - return sqlite3VdbeMemMakeWriteable(db, pMem); + return sqlite3VdbeMemMakeWriteable(pMem); } return SQLITE_OK; } @@ -686,17 +701,17 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ int n1, n2; /* Convert the strings into the encoding that the comparison ** function expects */ - v1 = sqlite3ValueText(0, (sqlite3_value*)pMem1, pColl->enc); + v1 = sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc); n1 = v1==0 ? 0 : pMem1->n; - assert( n1==sqlite3ValueBytes(0, (sqlite3_value*)pMem1, pColl->enc) ); - v2 = sqlite3ValueText(0, (sqlite3_value*)pMem2, pColl->enc); + assert( n1==sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc) ); + v2 = sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc); n2 = v2==0 ? 0 : pMem2->n; - assert( n2==sqlite3ValueBytes(0, (sqlite3_value*)pMem2, pColl->enc) ); + assert( n2==sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc) ); /* Do the comparison */ rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); /* Convert the strings back into the database encoding */ - sqlite3ValueText(0, (sqlite3_value*)pMem1, origEnc); - sqlite3ValueText(0, (sqlite3_value*)pMem2, origEnc); + sqlite3ValueText((sqlite3_value*)pMem1, origEnc); + sqlite3ValueText((sqlite3_value*)pMem2, origEnc); return rc; } } @@ -726,7 +741,6 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ ** to read from the disk) then the pMem is left in an inconsistent state. */ int sqlite3VdbeMemFromBtree( - sqlite3 *db, /* Database connect to report malloc errors to */ BtCursor *pCur, /* Cursor pointing at record to retrieve. */ int offset, /* Offset from the start of data to return bytes from. */ int amt, /* Number of bytes to return. */ @@ -735,7 +749,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{ @@ -743,6 +760,7 @@ int sqlite3VdbeMemFromBtree( } assert( zData!=0 ); + pMem->db = db; pMem->n = amt; if( offset+amt<=available ){ pMem->z = &zData[offset]; @@ -750,9 +768,8 @@ int sqlite3VdbeMemFromBtree( }else{ int rc; if( amt>NBFS-2 ){ - zData = (char *)sqlite3_malloc(amt+2); + zData = (char *)sqlite3DbMallocRaw(db, amt+2); if( !zData ){ - db->mallocFailed = 1; return SQLITE_NOMEM; } pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term; @@ -847,8 +864,10 @@ void sqlite3VdbeMemSanity(Mem *pMem){ ** If that is the case, then the result must be aligned on an even byte ** boundary. */ -const void *sqlite3ValueText(sqlite3 *db, sqlite3_value* pVal, u8 enc){ +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 ){ @@ -856,22 +875,23 @@ const void *sqlite3ValueText(sqlite3 *db, sqlite3_value* pVal, u8 enc){ } assert( (MEM_Blob>>3) == MEM_Str ); pVal->flags |= (pVal->flags & MEM_Blob)>>3; - expandBlob(db, pVal); + expandBlob(pVal); if( pVal->flags&MEM_Str ){ - sqlite3VdbeChangeEncoding(db, pVal, enc & ~SQLITE_UTF16_ALIGNED); + sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&(int)pVal->z) ){ assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 ); - if( sqlite3VdbeMemMakeWriteable(db, pVal)!=SQLITE_OK ){ + if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){ return 0; } } - sqlite3VdbeMemNulTerminate(db, pVal); + sqlite3VdbeMemNulTerminate(pVal); }else{ assert( (pVal->flags&MEM_Blob)==0 ); - sqlite3VdbeMemStringify(db, pVal, enc); + sqlite3VdbeMemStringify(pVal, enc); assert( 0==(1&(int)pVal->z) ); } - assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || db->mallocFailed ); + assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 + || pVal->db->mallocFailed ); if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){ return pVal->z; }else{ @@ -887,6 +907,7 @@ sqlite3_value *sqlite3ValueNew(sqlite3 *db){ if( p ){ p->flags = MEM_Null; p->type = SQLITE_NULL; + p->db = db; }else{ db->mallocFailed = 1; } @@ -904,7 +925,7 @@ sqlite3_value *sqlite3ValueNew(sqlite3 *db){ ** cannot be converted to a value, then *ppVal is set to NULL. */ int sqlite3ValueFromExpr( - sqlite3 *db, /* Report malloc() errors here */ + sqlite3 *db, /* The database connection */ Expr *pExpr, /* The expression to evaluate */ u8 enc, /* Encoding to use */ u8 affinity, /* Affinity to use */ @@ -925,14 +946,14 @@ int sqlite3ValueFromExpr( pVal = sqlite3ValueNew(db); if( !zVal || !pVal ) goto no_mem; sqlite3Dequote(zVal); - sqlite3ValueSetStr(db, pVal, -1, zVal, SQLITE_UTF8, sqlite3_free); + sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, sqlite3_free); if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){ - sqlite3ValueApplyAffinity(db, pVal, SQLITE_AFF_NUMERIC, enc); + sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, enc); }else{ - sqlite3ValueApplyAffinity(db, pVal, affinity, enc); + sqlite3ValueApplyAffinity(pVal, affinity, enc); } }else if( op==TK_UMINUS ) { - if( SQLITE_OK==sqlite3ValueFromExpr(db, 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; } @@ -945,8 +966,7 @@ int sqlite3ValueFromExpr( if( !zVal || !pVal ) goto no_mem; sqlite3Dequote(zVal); nVal = strlen(zVal)/2; - sqlite3VdbeMemSetStr( - db, pVal, sqlite3HexToBlob(db, zVal), nVal, 0, sqlite3_free); + sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal), nVal,0,sqlite3_free); sqlite3_free(zVal); } #endif @@ -966,14 +986,13 @@ no_mem: ** Change the string value of an sqlite3_value object */ void sqlite3ValueSetStr( - sqlite3 *db, /* Report malloc errors here */ 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(db, (Mem *)v, z, n, enc, xDel); + if( v ) sqlite3VdbeMemSetStr((Mem *)v, z, n, enc, xDel); } /* @@ -981,7 +1000,7 @@ void sqlite3ValueSetStr( */ void sqlite3ValueFree(sqlite3_value *v){ if( !v ) return; - sqlite3ValueSetStr(0, v, 0, 0, SQLITE_UTF8, SQLITE_STATIC); + sqlite3ValueSetStr(v, 0, 0, SQLITE_UTF8, SQLITE_STATIC); sqlite3_free(v); } @@ -989,9 +1008,9 @@ void sqlite3ValueFree(sqlite3_value *v){ ** Return the number of bytes in the sqlite3_value object assuming ** that it uses the encoding "enc" */ -int sqlite3ValueBytes(sqlite3 *db, sqlite3_value *pVal, u8 enc){ +int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ Mem *p = (Mem*)pVal; - if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(db, pVal, enc) ){ + if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){ if( p->flags & MEM_Zero ){ return p->n+p->u.i; }else{ |