From b21c8cd4f636a85920e8a7b9c60410b52e4e876d Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 21 Aug 2007 19:33:56 +0000 Subject: [PATCH] The sqlite3_value object now carries an sqlite3* pointer to use for recording malloc failures. This eliminates the need to pass sqlite3* pointers into many internal interfaces. Also added more mutexing. (CVS 4263) FossilOrigin-Name: 9287276191a582c1cf7cf6b71d8399727d8e534d --- manifest | 58 ++++++++++---------- manifest.uuid | 2 +- src/auth.c | 4 +- src/btree.c | 9 +++- src/btree.h | 3 +- src/build.c | 3 +- src/callback.c | 6 +-- src/complete.c | 6 +-- src/date.c | 8 +-- src/func.c | 10 ++-- src/loadext.c | 17 +++++- src/main.c | 8 +-- src/malloc.c | 68 +++++++++++------------ src/prepare.c | 29 ++++++++-- src/sqlite.h.in | 14 +++-- src/sqliteInt.h | 11 ++-- src/test1.c | 22 ++++---- src/test5.c | 10 ++-- src/utf.c | 24 +++++---- src/util.c | 6 +-- src/vdbe.c | 122 ++++++++++++++++++++--------------------- src/vdbeInt.h | 32 +++++------ src/vdbeapi.c | 64 +++++++++++++--------- src/vdbeaux.c | 24 +++++---- src/vdbeblob.c | 3 +- src/vdbemem.c | 141 +++++++++++++++++++++++++++--------------------- 26 files changed, 397 insertions(+), 307 deletions(-) diff --git a/manifest b/manifest index 2d12762f24..cc0aa52cb7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Adding\smore\sthread\slocking\scode.\s\sThis\sis\san\sincremental\scheck-in.\s(CVS\s4262) -D 2007-08-21T16:15:56 +C The\ssqlite3_value\sobject\snow\scarries\san\ssqlite3*\spointer\sto\suse\sfor\nrecording\smalloc\sfailures.\s\sThis\seliminates\sthe\sneed\sto\spass\ssqlite3*\npointers\sinto\smany\sinternal\sinterfaces.\s\sAlso\sadded\smore\smutexing.\s(CVS\s4263) +D 2007-08-21T19:33:56 F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -79,26 +79,26 @@ F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a F src/alter.c f0aac0060ae8102e58f210b44d35b53438d53173 F src/analyze.c a14237d869c6bea0846493b59317e4097e81a0b6 F src/attach.c a52225c75b107be8c5bc144a2b6d20201be3f8f8 -F src/auth.c 5ea90bc93dfea46e9fe4bf531e14c7cd98219ecb -F src/btree.c 8e529f390d8d1d83acbaf13cb1c09da8361cf5b1 -F src/btree.h 525105564c87111922412368f2e4301c36e74ac1 +F src/auth.c 083c1205b45e3f52291ec539d396b4fc557856b3 +F src/btree.c 4cfe2fe8d61dd906662833732919dc27116ffce7 +F src/btree.h aeb85d6a48573785666fb97566bf5802d5f9b7ca F src/btreeInt.h e93edf57832278138b98cf60cbc54241103c6988 -F src/build.c add67be992307b4b11849a6611bfd3352aacde92 -F src/callback.c 143436453bb93e831c9574fea0b9b9eb90e40ff3 -F src/complete.c ea63834e798a0ab14159bdc6e6cabc3df21aa346 -F src/date.c 70a5af1944c0b76bed917cab3c1ca47e5f97d359 +F src/build.c 2159551184160e2cf17ff945e9a05fbe6f331c3d +F src/callback.c fdd527372162a974094103eae82119fcfcf11260 +F src/complete.c b6dea59fb6d7b3201fa1e0e552cda8c2258a4f50 +F src/date.c a80b33f6e70d619978622547d2c78ab8b036b31a F src/delete.c 849846d06d29851dde0d9f424a5de5817eb140d1 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b F src/expr.c 3ea108a9e409f58b8203e29c54442da5085be5bf -F src/func.c 8516d5f97ddc1004537490fbaffa9a8b0da5c4bb +F src/func.c 36440cb02589fd4697cbbf0b351eeedc160d1f4b F src/hash.c 2f322979071dd2bdba7503b5276d66f028744382 F src/hash.h 3ad3da76bfb954978d227bf495568b0e6da2c19e F src/insert.c 633322aef1799f6604fa805e12488bc628570b0c F src/legacy.c a83519a8fbb488c3155fca577b010d590ec479e9 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35 -F src/loadext.c 780748f3f55a3b5af6ed0adfd58035f728cde4ca -F src/main.c 1f6f46975182c589c4942c708c9821db7c5d5772 -F src/malloc.c c2f5da620d8e030c6974a0ddcaeb7b408c9bdb3d +F src/loadext.c dd803303fd06ef0b13913faaa4a7fc7d8c8c4e77 +F src/main.c 7cec512d2c83afea2b83977b384633b9edb1ae1d +F src/malloc.c c291b07b6b03ba1a1db0c24f630b745071679ed0 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217 F src/mem1.c 30bf8be3846f92fdf88c490c5e5378512383bcbe F src/mem2.c 482f0aaf14e8ef1db64cb8c5b9a9bfe708297c92 @@ -118,23 +118,23 @@ F src/pager.c df16604a2a8c6808cd9b309a7e1bdb556d868c8e F src/pager.h 53087c6fb9db01aed17c7fd044662a27507e89b8 F src/parse.y 2d2ce439dc6184621fb0b86f4fc5aca7f391a590 F src/pragma.c 9b989506a1b7c8aecd6befb8235e2f57a4aba7e5 -F src/prepare.c 5bc8c7a943215302943fec831f8c646f6dfdf76a +F src/prepare.c d30764fabc3eb704c0d18bdeb9f38df028f19567 F src/printf.c a8f46e0ed360c18d40e89aa636533be300b406c2 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da F src/select.c 98c367bce3f38c5adfcc97de9ab5c79b0e5dc2b2 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c ac29402b538515fa4697282387be9c1205e6e9eb -F src/sqlite.h.in c691ae04f7c064d853710a1eff4707549a54e1f8 +F src/sqlite.h.in 95e159919060f9c6e060ff420ce17490f7b6a0f3 F src/sqlite3ext.h 647a6b8a8f76ff6c9611e4a071531d8e63ff2d6b -F src/sqliteInt.h c9ba3861d1e8835caeb0c89fca7cddd12779e1ac +F src/sqliteInt.h 23eb6a5b1f10d5d3d34c3c7846b7c3b93acf1276 F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa F src/table.c c725e47f6f3092b9a7b569fc58e408e2173ee008 F src/tclsqlite.c 299fb45c5cf983b49b2c984b87b936b8132fbfe2 -F src/test1.c 9e9651b0b9f85654b4bf28dfad787bc21a33aae5 +F src/test1.c 70b96fc5ef8d013e2da0f936a62fe76e387faf83 F src/test2.c 4f742e99ed1bea5c14692f627bdb59a146f30504 F src/test3.c 2e4da0fe90a0aa8cf9276ea34cbe92e91dc1db07 F src/test4.c d97b87919dc3db1cc5fccc04a33f030d5940e1a9 -F src/test5.c 81353afad5d795ae7155bffce1e4deef10ee8e22 +F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4 F src/test6.c da83a0e49c03e8a25f4ce6e25c537c6617c14fc0 F src/test7.c 50f5aa04fd751528ad5ee50e9be9ecee6f0b574a F src/test8.c 4bf571b82e502094846ae06e30fe028f190aaaae @@ -153,17 +153,17 @@ F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59 F src/tokenize.c e39527c9c867774a92716c669a48ad8fbc3cdc63 F src/trigger.c dccc6fbf37d12193c90ede5b026bbd195d505ff4 F src/update.c e89b980b443d44b68bfc0b1746cdb6308e049ac9 -F src/utf.c 853f97ce0d3cff8dbaef517a6dc475f7001a67c5 -F src/util.c 23251cee7867dfdcc80b05d278dbca71586d95cf +F src/utf.c 4af6259d5906b5a1bf3035cc387c4d7907bdd56e +F src/util.c 3f9c0387b54f977726790f52ab92cd3d9379b367 F src/vacuum.c 318ccae7c4e3ddf241aeaee4d2611bfe1949a373 -F src/vdbe.c f1a9a29da48ccfa49042df478abb478520589f37 +F src/vdbe.c 9d4d00589c174aad9a616f1615464ddddebba0ec F src/vdbe.h 001c5b257567c1d3de7feb2203aac71d0d7b16a3 -F src/vdbeInt.h 8e360d326328e7a66100f468697edf9cfb4567dc -F src/vdbeapi.c b4a1f4d56906a43f40c2bc47d7b142db3759c14e -F src/vdbeaux.c 14b48bfc6334682e5e5858a0835f8b00d8751953 -F src/vdbeblob.c ac223e6d3acaa3321ce09c11c47bf0d05b37372f +F src/vdbeInt.h 39fb069ce04137545ca0bc790f80ddc64a8c99d9 +F src/vdbeapi.c 09eb4fe5ce6e8e4558ca3fa1e22241f2d3895bf0 +F src/vdbeaux.c b0aeed4ff33352904b392ee6c7408bae5b141b9b +F src/vdbeblob.c d12ed95dac0992e1e372d079d76af047cc42f7c7 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 -F src/vdbemem.c 2843e6f91e8f19cfd72cfc7b24a03f1647db3c28 +F src/vdbemem.c 3de25d78e7b1d0af7a05199de905cea8c43aed5d F src/vtab.c ee29237ecc9b310dc43c0c2ac5caa6c6a20787be F src/where.c 2776a0caf8cbbfd6ec79cfb1cd9bc25074055e5e F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 @@ -558,7 +558,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 3787563e90d7210d349ee36484c3f008c955552e -R 059b95f5c37a602e37abf433f570fd9a +P 7428732b1fa04b83eda0a3539834693ef351313e +R 913d5d6bd631d176ac289a9e0cf82ff0 U drh -Z da09ba003aea60219dd1a004da17c3aa +Z c581f4a42a4b4dc59e9659821c9fdece diff --git a/manifest.uuid b/manifest.uuid index d6a9e84d4a..d5508f39d3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7428732b1fa04b83eda0a3539834693ef351313e \ No newline at end of file +9287276191a582c1cf7cf6b71d8399727d8e534d \ No newline at end of file diff --git a/src/auth.c b/src/auth.c index 79940c2733..145f4020a0 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 8f648a9094..3e8ef4929e 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. @@ -3706,6 +3706,13 @@ int sqlite3BtreeEof(BtCursor *pCur){ return (CURSOR_VALID!=pCur->eState); } +/* +** 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 diff --git a/src/btree.h b/src/btree.h index 5f15d101bd..b358562553 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 bd7b7305a2..0e7523c191 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 @@ -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; ixCollNeeded16 ){ 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 052b9ab1e9..6571df63f7 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 33fe92c873..a807f35253 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 699ef17242..224f88f082 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 @@ -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 b5dc4f5fd1..a4c57c2c69 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; inExtension; 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 b0aa877d5c..69e49752b7 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 @@ -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 3f9466cb73..482e7636ff 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 #include /* -** 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 376fd4e9b6..0cbbf2ed71 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 @@ -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 abecd1d190..ba1731864d 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 d388afffdf..f09d0a8fd3 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 d04d8f67ea..c28b514b81 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 88831b79cd..58d65aa28f 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); diff --git a/src/utf.c b/src/utf.c index 3c1a16f108..eba0b586bd 100644 --- a/src/utf.c +++ b/src/utf.c @@ -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 694d7da0b8..75992b6787 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 @@ -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 80b77615d9..f23c05c764 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 @@ -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; ip1; 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; pMemn; } @@ -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 && availisIndex, &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->p1nMem ); - 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->p1nMem ); assert( pOp->p2>=0 && pOp->p2nMem ); - 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 caf27f0c2d..37a049e11f 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 253b477801..20767fd628 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 && inVar; 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 5eb9d22a6f..85edcba113 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; naVar[n].flags = MEM_Null; + p->aVar[n].db = db; + } + for(n=0; naStack[n].db = db; } } } for(n=0; nnMem; 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 216803123a..6acbe40232 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 ad911fa0e7..71d7ecd52b 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{