From: drh Date: Mon, 28 Jul 2008 19:34:53 +0000 (+0000) Subject: Implement the "lookaside" memory allocation cache. Use of this cache makes X-Git-Tag: version-3.6.10~689 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=633e6d57d92e943fbd3a52ea6627e1a1d0c338b7;p=thirdparty%2Fsqlite.git Implement the "lookaside" memory allocation cache. Use of this cache makes the speed1.test script run about 15% faster. Added new interfaces to control the cache. (CVS 5488) FossilOrigin-Name: e48f9697e9fea339e150ddc32940760027dd07d9 --- diff --git a/manifest b/manifest index a6d8cd3932..22da79fbfc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\smem6.c\sto\sMakefile.in.\sTicket\s#3253.\s(CVS\s5487) -D 2008-07-28T05:26:33 +C Implement\sthe\s"lookaside"\smemory\sallocation\scache.\s\sUse\sof\sthis\scache\smakes\nthe\sspeed1.test\sscript\srun\sabout\s15%\sfaster.\s\sAdded\snew\sinterfaces\sto\ncontrol\sthe\scache.\s(CVS\s5488) +D 2008-07-28T19:34:53 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in bbb62eecc851379aef5a48a1bf8787eb13e6ec06 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -90,46 +90,46 @@ F sqlite.pc.in c322c6244c6395955dca34d87955aabde7df7623 F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.def a1be7b9a4b8b51ac41c6ff6e8e44a14ef66b338b F sqlite3.pc.in 32b8a014799c2028c8e0c9cc5659718262fc493f -F src/alter.c 73ec449c299bccd175aede22b56400134055f9db -F src/analyze.c 9ee63497ee720728abe630d169ab91323ac7519c -F src/attach.c b18ba42c77f7d3941f5d23d2ca20fa1d841a4e91 +F src/alter.c 2c541aaa88d720301253f181799d4af7bb9ddf1c +F src/analyze.c 747ce8cb6b318bb0d0576cfb5277aed98cbbeb5c +F src/attach.c a85c14612e7e3410e0c3d2e0241832fa9688bd14 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/bitvec.c 95c86bd18d8fedf0533f5af196192546e10a7e7d F src/btmutex.c 709cad2cdca0afd013f0f612363810e53f59ec53 -F src/btree.c 1318ab0eaad158aad791d73611c1c63c9b5e981f +F src/btree.c 540186cc76840ef9c6be5ec55793de79e33cf409 F src/btree.h 03256ed7ee42b5ecacbe887070b0f8249e7d069d F src/btreeInt.h 6e4cb69a9192a8d609c27034ae5f921cf0ecdde1 -F src/build.c bac7233d984be3805aaa41cf500f7ee12dc97249 -F src/callback.c aa492a0ad8c2d454edff9fb8a57fae13743cf71d +F src/build.c 77d5518a64c0a905024bee80f6df2e794f4f5d43 +F src/callback.c c9f75a4c403f166af3761df47d78a806587d63af F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c -F src/date.c 243677c51b740933761b63c660eb85b01bf3c74d -F src/delete.c 4a1f98fb2ffead69c8c685dcac33253ac6f9d56d -F src/expr.c 18d04f1c15e760d4329b5e0383a0c8a8320f0005 +F src/date.c 52a54811218a76da6235420f532ece841159a96d +F src/delete.c 0d115c173863b3c688c3083ef7857c7f2e9f7a18 +F src/expr.c 4f5221197384d923525fdfd117298eab073e9539 F src/fault.c 3638519d1e0b82bccfafcb9f5ff491918b28f8e1 -F src/func.c 08422a7bd06c25c5e6823d525f7c63563e3fcf61 -F src/global.c f12dc84d23f52d2ed42d1bdb5460fa3caf63e890 +F src/func.c 54efe220cc1ef3859a4b738011621b63a0d697c5 +F src/global.c b9c96ee2317a6e1391763c7db1098a6473a91863 F src/hash.c eb64e48f3781100e5934f759fbe72a63a8fe78cb F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 F src/hwtime.h 745961687a65ef8918cd551c02e5ccb4b8e772de -F src/insert.c e8efc17d037346e4a4a6949e72aab850befe3d5d +F src/insert.c 89cd9af52a5ea6fb7d0cfc9c3b935d6406c360c4 F src/journal.c cffd2cd214e58c0e99c3ff632b3bee6c7cbb260e -F src/legacy.c 3626c71fb70912abec9a4312beba753a9ce800df -F src/loadext.c ae0eed9fa96d74172d2a90ee63b5bc36d284295c -F src/main.c 97b638ed3bab4b804439209e4a20fc8017fb859f -F src/malloc.c c4b525896b8c188dab98609180d13dbeeeb33a84 +F src/legacy.c 3635cc6a5889918086b3501de8287cbbecb55917 +F src/loadext.c 9ab55455f59dce0ae6388952216a1505ce7f9d13 +F src/main.c 70d285dce241ad8daa320f78b060edb73bba637e +F src/malloc.c 2aa685ca13019d6c46d43516578596afefa59425 F src/md5.c 008216bbb5d34c6fbab5357aa68575ad8a31516a F src/mem1.c 3a7fe31d8290baa3bb203af72f7dfd6323966bcd F src/mem2.c 87381b143530cc377592e868bd548e881c2498a3 F src/mem3.c c73e935d0b900abc51d5fa45f880937b062f4a9f F src/mem4.c 6703adb1717b26d9d70a1c2586b4b7b7ffee7909 F src/mem5.c 0b0ba1c2a02d86eb812dea6debacee841e3856f7 -F src/mem6.c d1767b3715c31b830955bda1f3f1852619dcb687 +F src/mem6.c a3932c3d2f6382f077d7c94cf6a6e15e0a8cbd07 F src/mutex.c a485a0eac8ee2cd95f66e565b4c6696c18db968f F src/mutex.h e52ffa1dfc6a6077e8b1823d2c2b7dfcbcf85594 F src/mutex_os2.c 9c5637aa4c307c552566d0f0b3bd206245b54a97 F src/mutex_unix.c 29049a61755cccddb2ee53904e6906bb7674223c F src/mutex_w32.c f0d21ff1f6981e5aedc56796adf3a347423ef736 -F src/os.c 292b3b4a49fe5bf6cf2f1cf0af186ebd334e80b8 +F src/os.c 939ae7690a01d9401685ba124b4ba45fd4a7a2ad F src/os.h ef8abeb9afc694b82dbd169a91c9b7e26db3c892 F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60 F src/os_os2.c da14449fc210cd313eb56cf511ae05b350e323d6 @@ -137,28 +137,28 @@ F src/os_unix.c 1df6108efdb7957a9f28b9700600e58647c9c12d F src/os_win.c 50ec783403b418ddc9e6e05d541c6027dfd41070 F src/pager.c a6ecad26297469a8a3d1fd7a7c3dc2d603955044 F src/pager.h 588c1ac195228b2da45c4e5f7ab6c2fd253d1751 -F src/parse.y d1316f1b8b251412bdf4926c4c34803977958b65 -F src/pragma.c 6fad83fbcc7ec6e76d91fe2805fe972ff3af6a0c -F src/prepare.c c9bb0aacb7a571d049805699ed18f2bb136ea091 -F src/printf.c 2174222bc346a11b1eac2a654ccc4f635355ae7e +F src/parse.y 5ce0b04d2d35b987ccca8b46cfc2527dd932f040 +F src/pragma.c 6e207b4f69901089758c02c02e0bf86ed12a4d8f +F src/prepare.c d2d53aec81517f8666450aa5fd1a041a3b72320e +F src/printf.c 2e984b2507291a7e16d89dc9bb60582904f6247d F src/random.c 5c754319d38abdd6acd74601ee0105504adc508a -F src/select.c a152b1436d7117e25ce010453c61d1002214e337 +F src/select.c ef18af5624fc3189014e6b617a36562394740f91 F src/shell.c 4b835fe734304ac22a3385868cd3790c1e4f7aa1 -F src/sqlite.h.in 534688abf1580de0a458f017c97770a96c3827ac +F src/sqlite.h.in c1afc4a05dde8c6b9c8ea783b0b5a624892e299b F src/sqlite3ext.h 1e3887c9bd3ae66cb599e922824b04cd0d0f2c3e -F src/sqliteInt.h f9036237debe48d3542595fae2a18dcb41cd71e9 +F src/sqliteInt.h a4d6bcf383b1ff207f175f7e274a83d1283c73d7 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8 -F src/status.c 0f72b854aa75bb209718e0bb37728602c7ecdee6 +F src/status.c ca61c18b6f1c632b771514e0c39a7d662c805bbf F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8 F src/tclsqlite.c ec46084184f033ba396a9ee7b5514b695083d0f3 F src/test1.c 346e9262793be825ebadd9e69600d1b4682650f1 F src/test2.c 7a634c1e044be3ea5845e65155fdd1cab13936cb F src/test3.c e00795839be38f0345a4845170426fb17d828bf9 -F src/test4.c ff4ecde3cafc71337b04e8cb7da5bb88e85d70e7 -F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4 +F src/test4.c 41056378671e7b00e6305fa9ac6fa27e6f96f406 +F src/test5.c 847eb5cfe89c197b6b494858ccf60be981235bdf F src/test6.c 0a0304a69cfa4962a429d084c6d451ff9e4fb572 -F src/test7.c 19474b1802858cd2017493c907f70ac2d57ab092 -F src/test8.c cc541736127cb95fe6966120f546c051e1c8aed8 +F src/test7.c 475b1fa7e3275408b40a3cbdc9508cbdc41ffa02 +F src/test8.c ae09a70c009097561d0d21e0291d383ad059d3f8 F src/test9.c 904ebe0ed1472d6bad17a81e2ecbfc20017dc237 F src/test_async.c da9f58f49faccd3a26ba89f58de125862351b6e2 F src/test_autoext.c f53b0cdf7bf5f08100009572a5d65cdb540bd0ad @@ -168,7 +168,7 @@ F src/test_devsym.c 6012cb8e3acf812513511025a4fa5d626e0ba19b F src/test_func.c 24a556989685495013e08f311ae31c4ef86ddb8c F src/test_hexio.c 2f1122aa3f012fa0142ee3c36ce5c902a70cd12f F src/test_loadext.c df8ab3a6481ddebbdf0d28ebac5d9e0790f7860f -F src/test_malloc.c daacb05668cc10e43c71291afc23088ff372488e +F src/test_malloc.c f760300736b923c98f5bb620a3146d31845e4acc F src/test_md5.c 28209a4e2068711b5443c33104fe41f21d160071 F src/test_mutex.c d3422d9f60cc1330249d102e74b333f0d24a0cb6 F src/test_onefile.c 243157b10275251c5dc2d6619aee2ff9ae22379c @@ -177,22 +177,22 @@ F src/test_schema.c 4b4bf7bb329326458c491b0e6facd4c8c4c5b479 F src/test_server.c f0a403b5f699c09bd2b1236b6f69830fd6221f6b F src/test_tclvar.c 73530070df8378571c8ce6bbbbb993236ae3ad0b F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730 -F src/tokenize.c 70c6b5c394761816522611e70098e8c9bd58b486 -F src/trigger.c bdb56bb9db1a7b18f8505484051221ab5123f21d -F src/update.c 4e698fcc0c91c241a960304c4236dc3a49603155 +F src/tokenize.c bfdc945527a4645bf54c8bf34d1f18c019b37117 +F src/trigger.c b61aaf7bff8e3763b234dbf46a1a64fb88a34e64 +F src/update.c 79b77a3cc8ed5f8903a7f37055fcedd69388dcae F src/utf.c 8d52f620a7153d90b058502124fe51d821fcdf57 -F src/util.c 06c5476b440f141987e5d829efd25900df72f629 +F src/util.c afe659ccc05d1f8af9e8631dabfec3ee3a7144af F src/vacuum.c ef342828002debc97514617af3424aea8ef8522c -F src/vdbe.c aa0922d62e58dae8440d78a81a312531655db882 +F src/vdbe.c 40b188e5bed3d942596471fb5cb526a6516ebcec F src/vdbe.h c46155c221418bea29ee3a749d5950fcf85a70e2 -F src/vdbeInt.h 3c12ae0982c03ddac43a2531d41e6eca9fd89eb2 -F src/vdbeapi.c 17fa6f432197d759b15d3b37a7d672a34043c078 -F src/vdbeaux.c 0d221c85240eddbce498cc0136a5edd43927d67e -F src/vdbeblob.c a20fe9345062b1a1b4cc187dc5fad45c9414033b -F src/vdbefifo.c c46dae1194e4277bf007144d7e5b0c0b1c24f136 -F src/vdbemem.c 0c72b58ffd759676ce4829f42bacb83842a58c21 -F src/vtab.c e67eaa311446ba216d0ffea916586da46e4e13f5 -F src/where.c e4c40d224cc6931bece3a33b35bd6b6a8deade3f +F src/vdbeInt.h 1672cc137eb1d693090a17ded6682927fc851ca9 +F src/vdbeapi.c 25dd01c8b12978c14ec30e9a50666b23da767b27 +F src/vdbeaux.c 706d722088350fe18bc9c41250b4f19509f00390 +F src/vdbeblob.c f93110888ddc246215e9ba1f831d3d375bfd8355 +F src/vdbefifo.c 20fda2a7c4c0bcee1b90eb7e545fefcdbf2e1de7 +F src/vdbemem.c 7ab2a77d7f07ae74d678b6754488bcd50c4ea3aa +F src/vtab.c 691813795f1bba5df57389c1cec62f9e73eebd9d +F src/where.c ee4878e42ac97e2b3389b44cee34b35458321488 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/all.test 89e09ed0074083ac6f208dc3243429e8f89efb69 @@ -412,7 +412,7 @@ F test/malloc_common.tcl 17d60dfefc1598d1a7fe6da6511933536caea1d7 F test/manydb.test 8de36b8d33aab5ef295b11d9e95310aeded31af8 F test/memdb.test a67bda4ff90a38f2b19f6c7f95aa7289e051d893 F test/memleak.test d2d2a1ff7105d32dc3fdf691458cf6cba58c7217 -F test/memsubsys1.test ac18e8a045480611a467a3dc72c2ece4f530b9e4 +F test/memsubsys1.test 567ec52e742b669fac69cec303a93aead9377ce3 F test/memsubsys2.test c05b541f9c2a1234a9dc2ff2233b3a9544fa5139 F test/minmax.test 722d80816f7e096bf2c04f4111f1a6c1ba65453d F test/minmax2.test 33504c01a03bd99226144e4b03f7631a274d66e0 @@ -474,7 +474,7 @@ F test/sidedelete.test 736ac1da08b3b1aa62df97fef2fcdb1b660111b9 F test/soak.test 3c317b3e55e1160731030c8e865d1858fab66fea F test/softheap1.test 73ebd6e020d2954d965da2072baba5922fc8fb6a F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5 -F test/speed1.test cd5d9302f18946c18570e9ce6c736a5e283c8fcf +F test/speed1.test 7ac6aecd2ab834de2fb81058944a5092f0368f67 F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb F test/speed1p.test 1c932ff428cd7c26f0324a6ac59b16dfb2fd8efa F test/speed2.test 53177056baf6556dcbdcf032bbdfc41c1aa74ded @@ -590,8 +590,8 @@ F test/where6.test 42c4373595f4409d9c6a9987b4a60000ad664faf F test/zeroblob.test 792124852ec61458a2eb527b5091791215e0be95 F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439 -F tool/lemon.c 13e9c37ab9e0cc182cc10b93ac0e5270bbf472c8 -F tool/lempar.c 49e9b3b9b48f6b0799560ed4d090627c51513344 +F tool/lemon.c bd3f56f7e949fc016639159d77936d07a29ad418 +F tool/lempar.c 4d115ee7c0c8a749d5b22abed731abb4e6546a5f F tool/memleak.awk 4e7690a51bf3ed757e611273d43fe3f65b510133 F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8 F tool/memleak3.tcl 7707006ee908cffff210c98158788d85bb3fcdbf @@ -612,7 +612,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 1ffdd46f0bf5c82c652dedf74660e913b5699b18 -R 5006c92fb864a0ff2f6bebcd27de2d76 -U danielk1977 -Z 66bcbf1b22aa20922ecfd56da69c3011 +P 51be2e4463ca32f290feb610f59553b55bc67a5c +R 1624ec122f5ffb86a37761ed2b47d75a +U drh +Z 5a311db47e066a208f5f741cb81e1882 diff --git a/manifest.uuid b/manifest.uuid index 69390dad28..5aad7c290a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -51be2e4463ca32f290feb610f59553b55bc67a5c \ No newline at end of file +e48f9697e9fea339e150ddc32940760027dd07d9 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index c0a8109094..ba929beddc 100644 --- a/src/alter.c +++ b/src/alter.c @@ -12,7 +12,7 @@ ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: alter.c,v 1.46 2008/07/15 14:47:19 drh Exp $ +** $Id: alter.c,v 1.47 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" #include @@ -80,7 +80,7 @@ static void renameTableFunc( zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql, zTableName, tname.z+tname.n); - sqlite3_result_text(context, zRet, -1, sqlite3_free); + sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } } @@ -155,7 +155,7 @@ static void renameTriggerFunc( */ zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql, zTableName, tname.z+tname.n); - sqlite3_result_text(context, zRet, -1, sqlite3_free); + sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } } #endif /* !SQLITE_OMIT_TRIGGER */ @@ -198,7 +198,7 @@ static char *whereTempTriggers(Parse *pParse, Table *pTab){ }else{ tmp = zWhere; zWhere = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, pTrig->name); - sqlite3_free(tmp); + sqlite3DbFree(db, tmp); } } } @@ -409,7 +409,7 @@ void sqlite3AlterRenameTable( "sql = sqlite_rename_trigger(sql, %Q), " "tbl_name = %Q " "WHERE %s;", zName, zName, zWhere); - sqlite3_free(zWhere); + sqlite3DbFree(db, zWhere); } #endif @@ -417,8 +417,8 @@ void sqlite3AlterRenameTable( reloadTableSchema(pParse, pTab, zName); exit_rename_table: - sqlite3SrcListDelete(pSrc); - sqlite3_free(zName); + sqlite3SrcListDelete(db, pSrc); + sqlite3DbFree(db, zName); } @@ -518,7 +518,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1, zTab ); - sqlite3_free(zCol); + sqlite3DbFree(db, zCol); } /* If the default value of the new column is NULL, then set the file @@ -585,6 +585,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ if( !pNew ) goto exit_begin_add_column; pParse->pNewTable = pNew; pNew->nRef = 1; + pNew->db = db; pNew->nCol = pTab->nCol; assert( pNew->nCol>0 ); nAlloc = (((pNew->nCol-1)/8)*8)+8; @@ -614,7 +615,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ sqlite3ChangeCookie(pParse, iDb); exit_begin_add_column: - sqlite3SrcListDelete(pSrc); + sqlite3SrcListDelete(db, pSrc); return; } #endif /* SQLITE_ALTER_TABLE */ diff --git a/src/analyze.c b/src/analyze.c index aeb9972745..2c57d7fd0b 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code associated with the ANALYZE command. ** -** @(#) $Id: analyze.c,v 1.42 2008/03/25 09:47:35 danielk1977 Exp $ +** @(#) $Id: analyze.c,v 1.43 2008/07/28 19:34:53 drh Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" @@ -316,7 +316,7 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ z = sqlite3NameFromToken(db, pName1); if( z ){ pTab = sqlite3LocateTable(pParse, 0, z, 0); - sqlite3_free(z); + sqlite3DbFree(db, z); if( pTab ){ analyzeTable(pParse, pTab); } @@ -330,7 +330,7 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ z = sqlite3NameFromToken(db, pTableName); if( z ){ pTab = sqlite3LocateTable(pParse, 0, z, zDb); - sqlite3_free(z); + sqlite3DbFree(db, z); if( pTab ){ analyzeTable(pParse, pTab); } @@ -417,7 +417,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ (void)sqlite3SafetyOff(db); rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); (void)sqlite3SafetyOn(db); - sqlite3_free(zSql); + sqlite3DbFree(db, zSql); return rc; } diff --git a/src/attach.c b/src/attach.c index 3964f379e0..b8668f52bb 100644 --- a/src/attach.c +++ b/src/attach.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: attach.c,v 1.76 2008/06/15 02:51:47 drh Exp $ +** $Id: attach.c,v 1.77 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" @@ -214,7 +214,7 @@ attach_error: /* Return an error if we get here */ if( zErrDyn ){ sqlite3_result_error(context, zErrDyn, -1); - sqlite3_free(zErrDyn); + sqlite3DbFree(db, zErrDyn); }else{ zErr[sizeof(zErr)-1] = 0; sqlite3_result_error(context, zErr, -1); @@ -305,7 +305,7 @@ static void codeAttach( goto attach_end; } rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); - sqlite3_free(zAuthArg); + sqlite3DbFree(db, zAuthArg); if(rc!=SQLITE_OK ){ goto attach_end; } @@ -345,9 +345,9 @@ static void codeAttach( } attach_end: - sqlite3ExprDelete(pFilename); - sqlite3ExprDelete(pDbname); - sqlite3ExprDelete(pKey); + sqlite3ExprDelete(db, pFilename); + sqlite3ExprDelete(db, pDbname); + sqlite3ExprDelete(db, pKey); } /* diff --git a/src/btree.c b/src/btree.c index a51ed1b782..0e91a5f1fa 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.491 2008/07/19 14:25:16 danielk1977 Exp $ +** $Id: btree.c,v 1.492 2008/07/28 19:34:53 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -6814,7 +6814,7 @@ char *sqlite3BtreeIntegrityCheck( nRef = sqlite3PagerRefcount(pBt->pPager); if( lockBtreeWithRetry(p)!=SQLITE_OK ){ sqlite3BtreeLeave(p); - return sqlite3StrDup("Unable to acquire a read lock on the database"); + return sqlite3DbStrDup(0, "Unable to acquire a read lock on the database"); } sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; diff --git a/src/build.c b/src/build.c index 8a1d4bb755..19f09dc8d8 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.490 2008/07/08 23:40:20 drh Exp $ +** $Id: build.c,v 1.491 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" #include @@ -239,24 +239,24 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ va_list ap; char *zSql; char *zErrMsg = 0; + sqlite3 *db = pParse->db; # define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar)) char saveBuf[SAVE_SZ]; if( pParse->nErr ) return; assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ va_start(ap, zFormat); - zSql = sqlite3VMPrintf(pParse->db, zFormat, ap); + zSql = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); if( zSql==0 ){ - pParse->db->mallocFailed = 1; return; /* A malloc must have failed */ } pParse->nested++; memcpy(saveBuf, &pParse->nVar, SAVE_SZ); memset(&pParse->nVar, 0, SAVE_SZ); sqlite3RunParser(pParse, zSql, &zErrMsg); - sqlite3_free(zErrMsg); - sqlite3_free(zSql); + sqlite3DbFree(db, zErrMsg); + sqlite3DbFree(db, zSql); memcpy(&pParse->nVar, saveBuf, SAVE_SZ); pParse->nested--; } @@ -358,8 +358,9 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ ** Reclaim the memory used by an index */ static void freeIndex(Index *p){ - sqlite3_free(p->zColAff); - sqlite3_free(p); + sqlite3 *db = p->pTable->db; + sqlite3DbFree(db, p->zColAff); + sqlite3DbFree(db, p); } /* @@ -453,7 +454,7 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ for(i=j=2; inDb; i++){ struct Db *pDb = &db->aDb[i]; if( pDb->pBt==0 ){ - sqlite3_free(pDb->zName); + sqlite3DbFree(db, pDb->zName); pDb->zName = 0; continue; } @@ -466,7 +467,7 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ db->nDb = j; if( db->nDb<=2 && db->aDb!=db->aDbStatic ){ memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0])); - sqlite3_free(db->aDb); + sqlite3DbFree(db, db->aDb); db->aDb = db->aDbStatic; } } @@ -484,15 +485,16 @@ void sqlite3CommitInternalChanges(sqlite3 *db){ static void sqliteResetColumnNames(Table *pTable){ int i; Column *pCol; + sqlite3 *db = pTable->db; assert( pTable!=0 ); if( (pCol = pTable->aCol)!=0 ){ for(i=0; inCol; i++, pCol++){ - sqlite3_free(pCol->zName); - sqlite3ExprDelete(pCol->pDflt); - sqlite3_free(pCol->zType); - sqlite3_free(pCol->zColl); + sqlite3DbFree(db, pCol->zName); + sqlite3ExprDelete(db, pCol->pDflt); + sqlite3DbFree(db, pCol->zType); + sqlite3DbFree(db, pCol->zColl); } - sqlite3_free(pTable->aCol); + sqlite3DbFree(db, pTable->aCol); } pTable->aCol = 0; pTable->nCol = 0; @@ -511,8 +513,10 @@ static void sqliteResetColumnNames(Table *pTable){ void sqlite3DeleteTable(Table *pTable){ Index *pIndex, *pNext; FKey *pFKey, *pNextFKey; + sqlite3 *db; if( pTable==0 ) return; + db = pTable->db; /* Do not delete the table until the reference count reaches zero. */ pTable->nRef--; @@ -537,21 +541,21 @@ void sqlite3DeleteTable(Table *pTable){ pNextFKey = pFKey->pNextFrom; assert( sqlite3HashFind(&pTable->pSchema->aFKey, pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey ); - sqlite3_free(pFKey); + sqlite3DbFree(db, pFKey); } #endif /* Delete the Table structure itself. */ sqliteResetColumnNames(pTable); - sqlite3_free(pTable->zName); - sqlite3_free(pTable->zColAff); - sqlite3SelectDelete(pTable->pSelect); + sqlite3DbFree(db, pTable->zName); + sqlite3DbFree(db, pTable->zColAff); + sqlite3SelectDelete(db, pTable->pSelect); #ifndef SQLITE_OMIT_CHECK - sqlite3ExprDelete(pTable->pCheck); + sqlite3ExprDelete(db, pTable->pCheck); #endif sqlite3VtabClear(pTable); - sqlite3_free(pTable); + sqlite3DbFree(db, pTable); } /* @@ -641,7 +645,7 @@ int sqlite3FindDb(sqlite3 *db, Token *pName){ break; } } - sqlite3_free(zName); + sqlite3DbFree(db, zName); } return i; } @@ -832,6 +836,7 @@ void sqlite3StartTable( pTable->iPKey = -1; pTable->pSchema = db->aDb[iDb].pSchema; pTable->nRef = 1; + pTable->db = db; if( pParse->pNewTable ) sqlite3DeleteTable(pParse->pNewTable); pParse->pNewTable = pTable; @@ -911,7 +916,7 @@ void sqlite3StartTable( /* If an error occurs, we jump here */ begin_table_error: - sqlite3_free(zName); + sqlite3DbFree(db, zName); return; } @@ -954,7 +959,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){ for(i=0; inCol; i++){ if( STRICMP(z, p->aCol[i].zName) ){ sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); - sqlite3_free(z); + sqlite3DbFree(db, z); return; } } @@ -962,7 +967,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){ Column *aNew; aNew = sqlite3DbRealloc(pParse->db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0])); if( aNew==0 ){ - sqlite3_free(z); + sqlite3DbFree(db, z); return; } p->aCol = aNew; @@ -1069,13 +1074,15 @@ void sqlite3AddColumnType(Parse *pParse, Token *pType){ Table *p; int i; Column *pCol; + sqlite3 *db; if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; if( i<0 ) return; pCol = &p->aCol[i]; - sqlite3_free(pCol->zType); - pCol->zType = sqlite3NameFromToken(pParse->db, pType); + db = pParse->db; + sqlite3DbFree(db, pCol->zType); + pCol->zType = sqlite3NameFromToken(db, pType); pCol->affinity = sqlite3AffinityType(pType); } @@ -1092,6 +1099,7 @@ void sqlite3AddColumnType(Parse *pParse, Token *pType){ void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){ Table *p; Column *pCol; + sqlite3 *db = pParse->db; if( (p = pParse->pNewTable)!=0 ){ pCol = &(p->aCol[p->nCol-1]); if( !sqlite3ExprIsConstantOrFunction(pExpr) ){ @@ -1099,15 +1107,14 @@ void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){ pCol->zName); }else{ Expr *pCopy; - sqlite3 *db = pParse->db; - sqlite3ExprDelete(pCol->pDflt); + sqlite3ExprDelete(db, pCol->pDflt); pCol->pDflt = pCopy = sqlite3ExprDup(db, pExpr); if( pCopy ){ sqlite3TokenCopy(db, &pCopy->span, &pExpr->span); } } } - sqlite3ExprDelete(pExpr); + sqlite3ExprDelete(db, pExpr); } /* @@ -1180,7 +1187,7 @@ void sqlite3AddPrimaryKey( } primary_key_exit: - sqlite3ExprListDelete(pList); + sqlite3ExprListDelete(pParse->db, pList); return; } @@ -1191,9 +1198,9 @@ void sqlite3AddCheckConstraint( Parse *pParse, /* Parsing context */ Expr *pCheckExpr /* The check expression */ ){ + sqlite3 *db = pParse->db; #ifndef SQLITE_OMIT_CHECK Table *pTab = pParse->pNewTable; - sqlite3 *db = pParse->db; if( pTab && !IN_DECLARE_VTAB ){ /* The CHECK expression must be duplicated so that tokens refer ** to malloced space and not the (ephemeral) text of the CREATE TABLE @@ -1202,7 +1209,7 @@ void sqlite3AddCheckConstraint( sqlite3ExprDup(db, pCheckExpr)); } #endif - sqlite3ExprDelete(pCheckExpr); + sqlite3ExprDelete(db, pCheckExpr); } /* @@ -1213,11 +1220,12 @@ void sqlite3AddCollateType(Parse *pParse, Token *pToken){ Table *p; int i; char *zColl; /* Dequoted name of collation sequence */ + sqlite3 *db; if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; - - zColl = sqlite3NameFromToken(pParse->db, pToken); + db = pParse->db; + zColl = sqlite3NameFromToken(db, pToken); if( !zColl ) return; if( sqlite3LocateCollSeq(pParse, zColl, -1) ){ @@ -1235,7 +1243,7 @@ void sqlite3AddCollateType(Parse *pParse, Token *pToken){ } } }else{ - sqlite3_free(zColl); + sqlite3DbFree(db, zColl); } } @@ -1568,7 +1576,7 @@ void sqlite3EndTable( zStmt, pParse->regRowid ); - sqlite3_free(zStmt); + sqlite3DbFree(db, zStmt); sqlite3ChangeCookie(pParse, iDb); #ifndef SQLITE_OMIT_AUTOINCREMENT @@ -1658,13 +1666,13 @@ void sqlite3CreateView( if( pParse->nVar>0 ){ sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); - sqlite3SelectDelete(pSelect); + sqlite3SelectDelete(db, pSelect); return; } sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); p = pParse->pNewTable; if( p==0 || pParse->nErr ){ - sqlite3SelectDelete(pSelect); + sqlite3SelectDelete(db, pSelect); return; } sqlite3TwoPartName(pParse, pName1, pName2, &pName); @@ -1672,7 +1680,7 @@ void sqlite3CreateView( if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName) && sqlite3FixSelect(&sFix, pSelect) ){ - sqlite3SelectDelete(pSelect); + sqlite3SelectDelete(db, pSelect); return; } @@ -1682,7 +1690,7 @@ void sqlite3CreateView( ** they will persist after the current sqlite3_exec() call returns. */ p->pSelect = sqlite3SelectDup(db, pSelect); - sqlite3SelectDelete(pSelect); + sqlite3SelectDelete(db, pSelect); if( db->mallocFailed ){ return; } @@ -1789,7 +1797,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ pTable->nCol = 0; nErr++; } - sqlite3SelectDelete(pSel); + sqlite3SelectDelete(db, pSel); } else { nErr++; } @@ -2105,7 +2113,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ sqliteViewResetAll(db, iDb); exit_drop_table: - sqlite3SrcListDelete(pName); + sqlite3SrcListDelete(db, pName); } /* @@ -2140,8 +2148,10 @@ void sqlite3CreateForeignKey( int i; int nCol; char *z; + sqlite3 *db; assert( pTo!=0 ); + db = pParse->db; if( p==0 || pParse->nErr || IN_DECLARE_VTAB ) goto fk_end; if( pFromCol==0 ){ int iCol = p->nCol-1; @@ -2167,7 +2177,7 @@ void sqlite3CreateForeignKey( nByte += strlen(pToCol->a[i].zName) + 1; } } - pFKey = sqlite3DbMallocZero(pParse->db, nByte ); + pFKey = sqlite3DbMallocZero(db, nByte ); if( pFKey==0 ){ goto fk_end; } @@ -2221,10 +2231,10 @@ void sqlite3CreateForeignKey( pFKey = 0; fk_end: - sqlite3_free(pFKey); + sqlite3DbFree(db, pFKey); #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ - sqlite3ExprListDelete(pFromCol); - sqlite3ExprListDelete(pToCol); + sqlite3ExprListDelete(db, pFromCol); + sqlite3ExprListDelete(db, pToCol); } /* @@ -2711,7 +2721,7 @@ void sqlite3CreateIndex( iMem, zStmt ); - sqlite3_free(zStmt); + sqlite3DbFree(db, zStmt); /* Fill the index with data and reparse the schema. Code an OP_Expire ** to invalidate all pre-compiled statements. @@ -2751,9 +2761,9 @@ exit_create_index: if( pIndex ){ freeIndex(pIndex); } - sqlite3ExprListDelete(pList); - sqlite3SrcListDelete(pTblName); - sqlite3_free(zName); + sqlite3ExprListDelete(db, pList); + sqlite3SrcListDelete(db, pTblName); + sqlite3DbFree(db, zName); return; } @@ -2882,7 +2892,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){ } exit_drop_index: - sqlite3SrcListDelete(pName); + sqlite3SrcListDelete(db, pName); } /* @@ -2952,7 +2962,7 @@ IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){ &i ); if( i<0 ){ - sqlite3IdListDelete(pList); + sqlite3IdListDelete(db, pList); return 0; } pList->a[i].zName = sqlite3NameFromToken(db, pToken); @@ -2962,14 +2972,14 @@ IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){ /* ** Delete an IdList. */ -void sqlite3IdListDelete(IdList *pList){ +void sqlite3IdListDelete(sqlite3 *db, IdList *pList){ int i; if( pList==0 ) return; for(i=0; inId; i++){ - sqlite3_free(pList->a[i].zName); + sqlite3DbFree(db, pList->a[i].zName); } - sqlite3_free(pList->a); - sqlite3_free(pList); + sqlite3DbFree(db, pList->a); + sqlite3DbFree(db, pList); } /* @@ -3028,7 +3038,7 @@ SrcList *sqlite3SrcListAppend( pNew = sqlite3DbRealloc(db, pList, sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) ); if( pNew==0 ){ - sqlite3SrcListDelete(pList); + sqlite3SrcListDelete(db, pList); return 0; } pList = pNew; @@ -3072,20 +3082,20 @@ void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ /* ** Delete an entire SrcList including all its substructure. */ -void sqlite3SrcListDelete(SrcList *pList){ +void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){ int i; struct SrcList_item *pItem; if( pList==0 ) return; for(pItem=pList->a, i=0; inSrc; i++, pItem++){ - sqlite3_free(pItem->zDatabase); - sqlite3_free(pItem->zName); - sqlite3_free(pItem->zAlias); + sqlite3DbFree(db, pItem->zDatabase); + sqlite3DbFree(db, pItem->zName); + sqlite3DbFree(db, pItem->zAlias); sqlite3DeleteTable(pItem->pTab); - sqlite3SelectDelete(pItem->pSelect); - sqlite3ExprDelete(pItem->pOn); - sqlite3IdListDelete(pItem->pUsing); + sqlite3SelectDelete(db, pItem->pSelect); + sqlite3ExprDelete(db, pItem->pOn); + sqlite3IdListDelete(db, pItem->pUsing); } - sqlite3_free(pList); + sqlite3DbFree(db, pList); } /* @@ -3118,9 +3128,9 @@ SrcList *sqlite3SrcListAppendFromTerm( sqlite3 *db = pParse->db; p = sqlite3SrcListAppend(db, p, pTable, pDatabase); if( p==0 || p->nSrc==0 ){ - sqlite3ExprDelete(pOn); - sqlite3IdListDelete(pUsing); - sqlite3SelectDelete(pSubquery); + sqlite3ExprDelete(db, pOn); + sqlite3IdListDelete(db, pUsing); + sqlite3SelectDelete(db, pSubquery); return p; } pItem = &p->a[p->nSrc-1]; @@ -3425,11 +3435,11 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ if( pColl ){ if( zColl ){ reindexDatabases(pParse, zColl); - sqlite3_free(zColl); + sqlite3DbFree(db, zColl); } return; } - sqlite3_free(zColl); + sqlite3DbFree(db, zColl); } iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); if( iDb<0 ) return; @@ -3439,11 +3449,11 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ pTab = sqlite3FindTable(db, z, zDb); if( pTab ){ reindexTable(pParse, pTab, 0); - sqlite3_free(z); + sqlite3DbFree(db, z); return; } pIndex = sqlite3FindIndex(db, z, zDb); - sqlite3_free(z); + sqlite3DbFree(db, z); if( pIndex ){ sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3RefillIndex(pParse, pIndex, -1); @@ -3458,7 +3468,7 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ ** with OP_OpenRead or OP_OpenWrite to access database index pIdx. ** ** If successful, a pointer to the new structure is returned. In this case -** the caller is responsible for calling sqlite3_free() on the returned +** the caller is responsible for calling sqlite3DbFree(db, ) on the returned ** pointer. If an error occurs (out of memory or missing collation ** sequence), NULL is returned and the state of pParse updated to reflect ** the error. @@ -3467,7 +3477,8 @@ KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ int i; int nCol = pIdx->nColumn; int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol; - KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(pParse->db, nBytes); + sqlite3 *db = pParse->db; + KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(db, nBytes); if( pKey ){ pKey->db = pParse->db; @@ -3483,7 +3494,7 @@ KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ } if( pParse->nErr ){ - sqlite3_free(pKey); + sqlite3DbFree(db, pKey); pKey = 0; } return pKey; diff --git a/src/callback.c b/src/callback.c index 09f6841d95..a77f994100 100644 --- a/src/callback.c +++ b/src/callback.c @@ -13,7 +13,7 @@ ** This file contains functions used to access the internal hash tables ** of user defined functions and collation sequences. ** -** $Id: callback.c,v 1.25 2008/07/08 14:52:10 drh Exp $ +** $Id: callback.c,v 1.26 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" @@ -30,7 +30,7 @@ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){ char *zExternal = sqlite3DbStrNDup(db, zName, nName); if( !zExternal ) return; db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal); - sqlite3_free(zExternal); + sqlite3DbFree(db, zExternal); } #ifndef SQLITE_OMIT_UTF16 if( db->xCollNeeded16 ){ @@ -182,7 +182,7 @@ static CollSeq *findCollSeqEntry( assert( pDel==0 || pDel==pColl ); if( pDel!=0 ){ db->mallocFailed = 1; - sqlite3_free(pDel); + sqlite3DbFree(db, pDel); pColl = 0; } } @@ -312,7 +312,7 @@ FuncDef *sqlite3FindFunction( pBest->zName[nName] = 0; if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){ db->mallocFailed = 1; - sqlite3_free(pBest); + sqlite3DbFree(db, pBest); return 0; } } @@ -325,7 +325,7 @@ FuncDef *sqlite3FindFunction( /* ** Free all resources held by the schema structure. The void* argument points -** at a Schema struct. This function does not call sqlite3_free() on the +** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the ** pointer itself, it just cleans up subsiduary resources (i.e. the contents ** of the schema hash tables). ** @@ -343,7 +343,7 @@ void sqlite3SchemaFree(void *p){ sqlite3HashClear(&pSchema->aFKey); sqlite3HashClear(&pSchema->idxHash); for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ - sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem)); + sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem)); } sqlite3HashClear(&temp2); sqlite3HashInit(&pSchema->tblHash, SQLITE_HASH_STRING, 0); diff --git a/src/date.c b/src/date.c index d9b39b8b60..08ee30c38a 100644 --- a/src/date.c +++ b/src/date.c @@ -16,7 +16,7 @@ ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.86 2008/07/25 16:39:25 drh Exp $ +** $Id: date.c,v 1.87 2008/07/28 19:34:53 drh Exp $ ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon @@ -849,9 +849,11 @@ static void strftimeFunc( u64 n; int i, j; char *z; + sqlite3 *db; const char *zFmt = (const char*)sqlite3_value_text(argv[0]); char zBuf[100]; if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return; + db = sqlite3_context_db_handle(context); for(i=0, n=1; zFmt[i]; i++, n++){ if( zFmt[i]=='%' ){ switch( zFmt[i+1] ){ @@ -887,11 +889,11 @@ static void strftimeFunc( } if( nsqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH] ){ + }else if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ sqlite3_result_error_toobig(context); return; }else{ - z = sqlite3Malloc( n ); + z = sqlite3DbMallocRaw(db, n); if( z==0 ){ sqlite3_result_error_nomem(context); return; @@ -956,7 +958,7 @@ static void strftimeFunc( } z[j] = 0; sqlite3_result_text(context, z, -1, - z==zBuf ? SQLITE_TRANSIENT : sqlite3_free); + z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC); } /* diff --git a/src/delete.c b/src/delete.c index 654570bc53..26824241e2 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** -** $Id: delete.c,v 1.170 2008/07/08 23:40:20 drh Exp $ +** $Id: delete.c,v 1.171 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" @@ -107,7 +107,7 @@ void sqlite3MaterializeView( } sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3Select(pParse, pDup, &dest, 0, 0, 0); - sqlite3SelectDelete(pDup); + sqlite3SelectDelete(db, pDup); } #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */ @@ -415,8 +415,8 @@ void sqlite3DeleteFrom( delete_from_cleanup: sqlite3AuthContextPop(&sContext); - sqlite3SrcListDelete(pTabList); - sqlite3ExprDelete(pWhere); + sqlite3SrcListDelete(db, pTabList); + sqlite3ExprDelete(db, pWhere); return; } diff --git a/src/expr.c b/src/expr.c index 87be4a9157..e8d8a1e993 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.386 2008/07/18 17:03:53 drh Exp $ +** $Id: expr.c,v 1.387 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" #include @@ -56,7 +56,8 @@ char sqlite3ExprAffinity(Expr *pExpr){ Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){ char *zColl = 0; /* Dequoted name of collation sequence */ CollSeq *pColl; - zColl = sqlite3NameFromToken(pParse->db, pName); + sqlite3 *db = pParse->db; + zColl = sqlite3NameFromToken(db, pName); if( pExpr && zColl ){ pColl = sqlite3LocateCollSeq(pParse, zColl, -1); if( pColl ){ @@ -64,7 +65,7 @@ Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){ pExpr->flags |= EP_ExpCollate; } } - sqlite3_free(zColl); + sqlite3DbFree(db, zColl); return pExpr; } @@ -367,8 +368,8 @@ Expr *sqlite3Expr( ** this function must always be allocated with sqlite3Expr() for this ** reason. */ - sqlite3ExprDelete(pLeft); - sqlite3ExprDelete(pRight); + sqlite3ExprDelete(db, pLeft); + sqlite3ExprDelete(db, pRight); return 0; } pNew->op = op; @@ -477,10 +478,11 @@ void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ */ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ Expr *pNew; + sqlite3 *db = pParse->db; assert( pToken ); - pNew = sqlite3DbMallocZero(pParse->db, sizeof(Expr) ); + pNew = sqlite3DbMallocZero(db, sizeof(Expr) ); if( pNew==0 ){ - sqlite3ExprListDelete(pList); /* Avoid leaking memory when malloc fails */ + sqlite3ExprListDelete(db, pList); /* Avoid leaking memory when malloc fails */ return 0; } pNew->op = TK_FUNCTION; @@ -578,15 +580,15 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ /* ** Recursively delete an expression tree. */ -void sqlite3ExprDelete(Expr *p){ +void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p==0 ) return; - if( p->span.dyn ) sqlite3_free((char*)p->span.z); - if( p->token.dyn ) sqlite3_free((char*)p->token.z); - sqlite3ExprDelete(p->pLeft); - sqlite3ExprDelete(p->pRight); - sqlite3ExprListDelete(p->pList); - sqlite3SelectDelete(p->pSelect); - sqlite3_free(p); + if( p->span.dyn ) sqlite3DbFree(db, (char*)p->span.z); + if( p->token.dyn ) sqlite3DbFree(db, (char*)p->token.z); + sqlite3ExprDelete(db, p->pLeft); + sqlite3ExprDelete(db, p->pRight); + sqlite3ExprListDelete(db, p->pList); + sqlite3SelectDelete(db, p->pSelect); + sqlite3DbFree(db, p); } /* @@ -637,7 +639,7 @@ Expr *sqlite3ExprDup(sqlite3 *db, Expr *p){ return pNew; } void sqlite3TokenCopy(sqlite3 *db, Token *pTo, Token *pFrom){ - if( pTo->dyn ) sqlite3_free((char*)pTo->z); + if( pTo->dyn ) sqlite3DbFree(db, (char*)pTo->z); if( pFrom->z ){ pTo->n = pFrom->n; pTo->z = (u8*)sqlite3DbStrNDup(db, (char*)pFrom->z, pFrom->n); @@ -657,7 +659,7 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p){ pNew->nExpr = pNew->nAlloc = p->nExpr; pNew->a = pItem = sqlite3DbMallocRaw(db, p->nExpr*sizeof(p->a[0]) ); if( pItem==0 ){ - sqlite3_free(pNew); + sqlite3DbFree(db, pNew); return 0; } pOldItem = p->a; @@ -728,7 +730,7 @@ IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){ pNew->nId = pNew->nAlloc = p->nId; pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) ); if( pNew->a==0 ){ - sqlite3_free(pNew); + sqlite3DbFree(db, pNew); return 0; } for(i=0; inId; i++){ @@ -814,8 +816,8 @@ ExprList *sqlite3ExprListAppend( no_mem: /* Avoid leaking memory if malloc has failed. */ - sqlite3ExprDelete(pExpr); - sqlite3ExprListDelete(pList); + sqlite3ExprDelete(db, pExpr); + sqlite3ExprListDelete(db, pList); return 0; } @@ -839,18 +841,18 @@ void sqlite3ExprListCheckLength( /* ** Delete an entire expression list. */ -void sqlite3ExprListDelete(ExprList *pList){ +void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ int i; struct ExprList_item *pItem; if( pList==0 ) return; assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) ); assert( pList->nExpr<=pList->nAlloc ); for(pItem=pList->a, i=0; inExpr; i++, pItem++){ - sqlite3ExprDelete(pItem->pExpr); - sqlite3_free(pItem->zName); + sqlite3ExprDelete(db, pItem->pExpr); + sqlite3DbFree(db, pItem->zName); } - sqlite3_free(pList->a); - sqlite3_free(pList); + sqlite3DbFree(db, pList->a); + sqlite3DbFree(db, pList); } /* @@ -1264,7 +1266,7 @@ static int lookupName( pOrig = pEList->a[j].pExpr; if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); - sqlite3_free(zCol); + sqlite3DbFree(db, zCol); return 2; } pDup = sqlite3ExprDup(db, pOrig); @@ -1272,10 +1274,10 @@ static int lookupName( pDup->pColl = pExpr->pColl; pDup->flags |= EP_ExpCollate; } - if( pExpr->span.dyn ) sqlite3_free((char*)pExpr->span.z); - if( pExpr->token.dyn ) sqlite3_free((char*)pExpr->token.z); + if( pExpr->span.dyn ) sqlite3DbFree(db, (char*)pExpr->span.z); + if( pExpr->token.dyn ) sqlite3DbFree(db, (char*)pExpr->token.z); memcpy(pExpr, pDup, sizeof(*pExpr)); - sqlite3_free(pDup); + sqlite3DbFree(db, pDup); cnt = 1; pMatch = 0; assert( zTab==0 && zDb==0 ); @@ -1303,7 +1305,7 @@ static int lookupName( ** fields are not changed in any context. */ if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){ - sqlite3_free(zCol); + sqlite3DbFree(db, zCol); return 0; } @@ -1343,15 +1345,15 @@ static int lookupName( lookupname_end: /* Clean up and return */ - sqlite3_free(zDb); - sqlite3_free(zTab); - sqlite3ExprDelete(pExpr->pLeft); + sqlite3DbFree(db, zDb); + sqlite3DbFree(db, zTab); + sqlite3ExprDelete(db, pExpr->pLeft); pExpr->pLeft = 0; - sqlite3ExprDelete(pExpr->pRight); + sqlite3ExprDelete(db, pExpr->pRight); pExpr->pRight = 0; pExpr->op = TK_COLUMN; lookupname_end_2: - sqlite3_free(zCol); + sqlite3DbFree(db, zCol); if( cnt==1 ){ assert( pNC!=0 ); sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); @@ -1966,7 +1968,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHaveNull){ sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iParm); VdbeComment((v, "Init EXISTS result")); } - sqlite3ExprDelete(pSel->pLimit); + sqlite3ExprDelete(pParse->db, pSel->pLimit); pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one); if( sqlite3Select(pParse, pSel, &dest, 0, 0, 0) ){ return; diff --git a/src/func.c b/src/func.c index 47709caab7..d4489f9d4c 100644 --- a/src/func.c +++ b/src/func.c @@ -16,7 +16,7 @@ ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.195 2008/07/08 22:28:49 shane Exp $ +** $Id: func.c,v 1.196 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" #include @@ -832,14 +832,14 @@ static void replaceFunc( nOut += nRep - nPattern; if( nOut>=db->aLimit[SQLITE_LIMIT_LENGTH] ){ sqlite3_result_error_toobig(context); - sqlite3_free(zOut); + sqlite3DbFree(db, zOut); return; } zOld = zOut; zOut = sqlite3_realloc(zOut, (int)nOut); if( zOut==0 ){ sqlite3_result_error_nomem(context); - sqlite3_free(zOld); + sqlite3DbFree(db, zOld); return; } memcpy(&zOut[j], zRep, nRep); diff --git a/src/global.c b/src/global.c index 4211c58356..fa59d4a848 100644 --- a/src/global.c +++ b/src/global.c @@ -12,7 +12,7 @@ ** ** This file contains definitions of global variables and contants. ** -** $Id: global.c,v 1.3 2008/07/08 14:52:10 drh Exp $ +** $Id: global.c,v 1.4 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" @@ -66,4 +66,12 @@ const unsigned char sqlite3UpperToLower[] = { ** The following singleton contains the global configuration for ** the SQLite library. */ -struct Sqlite3Config sqlite3Config = { 1, 1, 1, 0x7ffffffe }; +struct Sqlite3Config sqlite3Config = { + 1, /* bMemstat */ + 1, /* bCoreMutex */ + 1, /* bFullMutex */ + 0x7ffffffe, /* mxStrlen */ + 100, /* szLookaside */ + 500, /* nLookaside */ + /* Other fields all default to zero */ +}; diff --git a/src/insert.c b/src/insert.c index 9dda3954f1..9a3d46f1b3 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.247 2008/07/08 23:40:20 drh Exp $ +** $Id: insert.c,v 1.248 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" @@ -45,8 +45,9 @@ void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ int n; Table *pTab = pIdx->pTable; sqlite3 *db = sqlite3VdbeDb(v); - pIdx->zColAff = (char *)sqlite3DbMallocRaw(db, pIdx->nColumn+2); + pIdx->zColAff = (char *)sqlite3Malloc(pIdx->nColumn+2); if( !pIdx->zColAff ){ + db->mallocFailed = 1; return; } for(n=0; nnColumn; n++){ @@ -86,8 +87,9 @@ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ int i; sqlite3 *db = sqlite3VdbeDb(v); - zColAff = (char *)sqlite3DbMallocRaw(db, pTab->nCol+1); + zColAff = (char *)sqlite3Malloc(pTab->nCol+1); if( !zColAff ){ + db->mallocFailed = 1; return; } @@ -994,11 +996,11 @@ void sqlite3Insert( } insert_cleanup: - sqlite3SrcListDelete(pTabList); - sqlite3ExprListDelete(pList); - sqlite3SelectDelete(pSelect); - sqlite3IdListDelete(pColumn); - sqlite3_free(aRegIdx); + sqlite3SrcListDelete(db, pTabList); + sqlite3ExprListDelete(db, pList); + sqlite3SelectDelete(db, pSelect); + sqlite3IdListDelete(db, pColumn); + sqlite3DbFree(db, aRegIdx); } /* diff --git a/src/legacy.c b/src/legacy.c index 6d84d70391..825c57b25d 100644 --- a/src/legacy.c +++ b/src/legacy.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: legacy.c,v 1.27 2008/06/15 02:51:47 drh Exp $ +** $Id: legacy.c,v 1.28 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" @@ -122,13 +122,13 @@ int sqlite3_exec( } } - sqlite3_free(azCols); + sqlite3DbFree(db, azCols); azCols = 0; } exec_out: if( pStmt ) sqlite3_finalize(pStmt); - if( azCols ) sqlite3_free(azCols); + sqlite3DbFree(db, azCols); rc = sqlite3ApiExit(db, rc); if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){ diff --git a/src/loadext.c b/src/loadext.c index b9b47b6ed3..2d44f315be 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -12,7 +12,7 @@ ** This file contains code used to dynamically load extensions into ** the SQLite library. ** -** $Id: loadext.c,v 1.51 2008/07/08 14:17:35 danielk1977 Exp $ +** $Id: loadext.c,v 1.52 2008/07/28 19:34:53 drh Exp $ */ #ifndef SQLITE_CORE @@ -326,7 +326,7 @@ static const sqlite3_api_routines sqlite3Apis = { ** ** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with ** error message text. The calling function should free this memory -** by calling sqlite3_free(). +** by calling sqlite3DbFree(db, ). */ static int sqlite3LoadExtension( sqlite3 *db, /* Load the extension into this database connection */ @@ -365,7 +365,7 @@ static int sqlite3LoadExtension( sqlite3_snprintf(sizeof(zErr)-1, zErr, "unable to open shared library [%s]", zFile); sqlite3OsDlError(pVfs, sizeof(zErr)-1, zErr); - *pzErrMsg = sqlite3DbStrDup(db, zErr); + *pzErrMsg = sqlite3DbStrDup(0, zErr); } return SQLITE_ERROR; } @@ -378,7 +378,7 @@ static int sqlite3LoadExtension( sqlite3_snprintf(sizeof(zErr)-1, zErr, "no entry point [%s] in shared library [%s]", zProc,zFile); sqlite3OsDlError(pVfs, sizeof(zErr)-1, zErr); - *pzErrMsg = sqlite3DbStrDup(db, zErr); + *pzErrMsg = sqlite3DbStrDup(0, zErr); sqlite3OsDlClose(pVfs, handle); } return SQLITE_ERROR; @@ -400,7 +400,7 @@ static int sqlite3LoadExtension( if( db->nExtension>0 ){ memcpy(aHandle, db->aExtension, sizeof(handle)*(db->nExtension-1)); } - sqlite3_free(db->aExtension); + sqlite3DbFree(db, db->aExtension); db->aExtension = aHandle; db->aExtension[db->nExtension-1] = handle; @@ -429,7 +429,7 @@ void sqlite3CloseExtensions(sqlite3 *db){ for(i=0; inExtension; i++){ sqlite3OsDlClose(db->pVfs, db->aExtension[i]); } - sqlite3_free(db->aExtension); + sqlite3DbFree(db, db->aExtension); } /* diff --git a/src/main.c b/src/main.c index cf55878398..92e259fc75 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.482 2008/07/25 08:49:00 danielk1977 Exp $ +** $Id: main.c,v 1.483 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" #include @@ -275,6 +275,12 @@ int sqlite3_config(int op, ...){ } #endif + case SQLITE_CONFIG_LOOKASIDE: { + sqlite3Config.szLookaside = va_arg(ap, int); + sqlite3Config.nLookaside = va_arg(ap, int); + break; + } + default: { rc = SQLITE_ERROR; break; @@ -284,6 +290,60 @@ int sqlite3_config(int op, ...){ return rc; } +/* +** Set up the lookaside buffers for a database connection. +** Return SQLITE_OK on success. +** If lookaside is already active, return SQLITE_BUSY. +*/ +static int setupLookaside(sqlite3 *db, int sz, int cnt){ + void *pStart; + if( db->lookaside.nOut ){ + return SQLITE_BUSY; + } + if( sz<0 ) sz = 0; + if( cnt<0 ) cnt = 0; + sz = (sz+7)&~7; + sqlite3BeginBenignMalloc(); + pStart = sqlite3Malloc( sz*cnt ); + sqlite3EndBenignMalloc(); + if( pStart ){ + int i; + LookasideSlot *p; + sqlite3_free(db->lookaside.pStart); + db->lookaside.pFree = 0; + db->lookaside.pStart = pStart; + p = (LookasideSlot*)pStart; + for(i=cnt-1; i>=0; i--){ + p->pNext = db->lookaside.pFree; + db->lookaside.pFree = p; + p = (LookasideSlot*)&((u8*)p)[sz]; + } + db->lookaside.pEnd = p; + db->lookaside.bEnabled = 1; + db->lookaside.sz = sz; + } + return SQLITE_OK; +} + +/* +** Configuration settings for an individual database connection +*/ +int sqlite3_db_config(sqlite3 *db, int op, ...){ + va_list ap; + int rc = SQLITE_OK; + va_start(ap, op); + switch( op ){ + case SQLITE_CONFIG_LOOKASIDE: { + int sz = va_arg(ap, int); + int cnt = va_arg(ap, int); + rc = setupLookaside(db, sz, cnt); + break; + } + } + va_end(ap); + return rc; +} + /* ** Routine needed to support the testcase() macro. */ @@ -433,7 +493,7 @@ int sqlite3_close(sqlite3 *db){ FuncDef *pFunc, *pNext; for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){ pNext = pFunc->pNext; - sqlite3_free(pFunc); + sqlite3DbFree(db, pFunc); } } @@ -445,7 +505,7 @@ int sqlite3_close(sqlite3 *db){ pColl[j].xDel(pColl[j].pUser); } } - sqlite3_free(pColl); + sqlite3DbFree(db, pColl); } sqlite3HashClear(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -454,7 +514,7 @@ int sqlite3_close(sqlite3 *db){ if( pMod->xDestroy ){ pMod->xDestroy(pMod->pAux); } - sqlite3_free(pMod); + sqlite3DbFree(db, pMod); } sqlite3HashClear(&db->aModule); #endif @@ -474,10 +534,11 @@ int sqlite3_close(sqlite3 *db){ ** the same sqliteMalloc() as the one that allocates the database ** structure? */ - sqlite3_free(db->aDb[1].pSchema); + sqlite3DbFree(db, db->aDb[1].pSchema); sqlite3_mutex_leave(db->mutex); db->magic = SQLITE_MAGIC_CLOSED; sqlite3_mutex_free(db->mutex); + sqlite3_free(db->lookaside.pStart); sqlite3_free(db); return SQLITE_OK; } @@ -807,7 +868,7 @@ int sqlite3_create_function16( assert( !db->mallocFailed ); zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1); rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal); - sqlite3_free(zFunc8); + sqlite3DbFree(db, zFunc8); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; @@ -1312,6 +1373,7 @@ static int openDatabase( db->nDb = 2; db->magic = SQLITE_MAGIC_BUSY; db->aDb = db->aDbStatic; + assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); db->autoCommit = 1; @@ -1453,6 +1515,9 @@ static int openDatabase( SQLITE_DEFAULT_LOCKING_MODE); #endif + /* Enable the lookaside-malloc subsystem */ + setupLookaside(db, sqlite3Config.szLookaside, sqlite3Config.nLookaside); + opendb_out: if( db ){ assert( db->mutex!=0 || isThreadsafe==0 || sqlite3Config.bFullMutex==0 ); @@ -1580,7 +1645,7 @@ int sqlite3_create_collation16( zName8 = sqlite3Utf16to8(db, zName, -1); if( zName8 ){ rc = createCollation(db, zName8, enc, pCtx, xCompare, 0); - sqlite3_free(zName8); + sqlite3DbFree(db, zName8); } rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); @@ -1769,13 +1834,13 @@ error_out: if( pAutoinc ) *pAutoinc = autoinc; if( SQLITE_OK==rc && !pTab ){ - sqlite3_free(zErrMsg); + sqlite3DbFree(db, zErrMsg); zErrMsg = sqlite3MPrintf(db, "no such table column: %s.%s", zTableName, zColumnName); rc = SQLITE_ERROR; } sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg); - sqlite3_free(zErrMsg); + sqlite3DbFree(db, zErrMsg); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; diff --git a/src/malloc.c b/src/malloc.c index 86ba2be96c..f90e627536 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -12,7 +12,7 @@ ** ** Memory allocation functions used throughout sqlite. ** -** $Id: malloc.c,v 1.29 2008/07/18 18:56:17 drh Exp $ +** $Id: malloc.c,v 1.30 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" #include @@ -453,6 +453,13 @@ void sqlite3PageFree(void *p){ } } +/* +** TRUE if p is a lookaside memory allocation from db +*/ +static int isLookaside(sqlite3 *db, void *p){ + return db && p && p>=db->lookaside.pStart && plookaside.pEnd; +} + /* ** Return the size of a memory allocation previously obtained from ** sqlite3Malloc() or sqlite3_malloc(). @@ -460,6 +467,13 @@ void sqlite3PageFree(void *p){ int sqlite3MallocSize(void *p){ return sqlite3Config.m.xSize(p); } +int sqlite3DbMallocSize(sqlite3 *db, void *p){ + if( isLookaside(db, p) ){ + return db->lookaside.sz; + }else{ + return sqlite3Config.m.xSize(p); + } +} /* ** Free memory previously obtained from sqlite3Malloc(). @@ -476,6 +490,21 @@ void sqlite3_free(void *p){ } } +/* +** Free memory that might be associated with a particular database +** connection. +*/ +void sqlite3DbFree(sqlite3 *db, void *p){ + if( isLookaside(db, p) ){ + LookasideSlot *pBuf = (LookasideSlot*)p; + pBuf->pNext = db->lookaside.pFree; + db->lookaside.pFree = pBuf; + db->lookaside.nOut--; + }else{ + sqlite3_free(p); + } +} + /* ** Change the size of an existing memory allocation */ @@ -558,26 +587,53 @@ void *sqlite3DbMallocZero(sqlite3 *db, int n){ ** the mallocFailed flag in the connection pointer. */ void *sqlite3DbMallocRaw(sqlite3 *db, int n){ - void *p = 0; - if( !db || db->mallocFailed==0 ){ - p = sqlite3Malloc(n); - if( !p && db ){ - db->mallocFailed = 1; + void *p; + if( db ){ + LookasideSlot *pBuf; + if( db->mallocFailed ){ + return 0; + } + if( db->lookaside.bEnabled && n<=db->lookaside.sz + && (pBuf = db->lookaside.pFree)!=0 ){ + db->lookaside.pFree = pBuf->pNext; + db->lookaside.nOut++; + if( db->lookaside.nOut>db->lookaside.mxOut ){ + db->lookaside.mxOut = db->lookaside.nOut; + } + return (void*)pBuf; } } + p = sqlite3Malloc(n); + if( !p && db ){ + db->mallocFailed = 1; + } return p; } /* ** Resize the block of memory pointed to by p to n bytes. If the -** resize fails, set the mallocFailed flag inthe connection object. +** resize fails, set the mallocFailed flag in the connection object. */ void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){ void *pNew = 0; if( db->mallocFailed==0 ){ - pNew = sqlite3_realloc(p, n); - if( !pNew ){ - db->mallocFailed = 1; + if( p==0 ){ + return sqlite3DbMallocRaw(db, n); + } + if( isLookaside(db, p) ){ + if( n<=db->lookaside.sz ){ + return p; + } + pNew = sqlite3DbMallocRaw(db, n); + if( pNew ){ + memcpy(pNew, p, db->lookaside.sz); + sqlite3DbFree(db, p); + } + }else{ + pNew = sqlite3_realloc(p, n); + if( !pNew ){ + db->mallocFailed = 1; + } } } return pNew; @@ -591,7 +647,7 @@ void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){ void *pNew; pNew = sqlite3DbRealloc(db, p, n); if( !pNew ){ - sqlite3_free(p); + sqlite3DbFree(db, p); } return pNew; } @@ -603,37 +659,30 @@ void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){ ** called via macros that record the current file and line number in the ** ThreadData structure. */ -char *sqlite3StrDup(const char *z){ +char *sqlite3DbStrDup(sqlite3 *db, const char *z){ char *zNew; - int n; - if( z==0 ) return 0; + size_t n; + if( z==0 ){ + return 0; + } n = strlen(z)+1; - zNew = sqlite3Malloc(n); - if( zNew ) memcpy(zNew, z, n); - return zNew; -} -char *sqlite3StrNDup(const char *z, int n){ - char *zNew; - if( z==0 ) return 0; - zNew = sqlite3Malloc(n+1); + assert( (n&0x7fffffff)==n ); + zNew = sqlite3DbMallocRaw(db, (int)n); if( zNew ){ memcpy(zNew, z, n); - zNew[n] = 0; - } - return zNew; -} - -char *sqlite3DbStrDup(sqlite3 *db, const char *z){ - char *zNew = sqlite3StrDup(z); - if( z && !zNew ){ - db->mallocFailed = 1; } return zNew; } char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){ - char *zNew = sqlite3StrNDup(z, n); - if( z && !zNew ){ - db->mallocFailed = 1; + char *zNew; + if( z==0 ){ + return 0; + } + assert( (n&0x7fffffff)==n ); + zNew = sqlite3DbMallocRaw(db, n+1); + if( zNew ){ + memcpy(zNew, z, n); + zNew[n] = 0; } return zNew; } @@ -650,7 +699,7 @@ void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat, ...){ va_start(ap, zFormat); z = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); - sqlite3_free(*pz); + sqlite3DbFree(db, *pz); *pz = z; } diff --git a/src/mem6.c b/src/mem6.c index aafa568ece..95723ad39c 100644 --- a/src/mem6.c +++ b/src/mem6.c @@ -32,7 +32,7 @@ ** fragmentation. On some systems, heap fragmentation can cause a ** significant real-time slowdown. ** -** $Id: mem6.c,v 1.6 2008/07/25 16:07:01 danielk1977 Exp $ +** $Id: mem6.c,v 1.7 2008/07/28 19:34:53 drh Exp $ */ #ifdef SQLITE_ENABLE_MEMSYS6 @@ -418,8 +418,9 @@ static void memsys6Free(void *pPrior){ void *p = &((u32 *)pPrior)[-2]; iSlot = ((u32 *)p)[0]; if( iSlot ){ + Mem6Chunk *pChunk; mem6Enter(); - Mem6Chunk *pChunk = (Mem6Chunk *)(&((u8 *)p)[-1 * iSlot]); + pChunk = (Mem6Chunk *)(&((u8 *)p)[-1 * iSlot]); chunkFree(pChunk, p); if( chunkIsEmpty(pChunk) ){ freeChunk(pChunk); diff --git a/src/os.c b/src/os.c index 9d066d090b..0f141c3782 100644 --- a/src/os.c +++ b/src/os.c @@ -13,7 +13,7 @@ ** This file contains OS interface code that is common to all ** architectures. ** -** $Id: os.c,v 1.119 2008/06/26 18:16:06 drh Exp $ +** $Id: os.c,v 1.120 2008/07/28 19:34:53 drh Exp $ */ #define _SQLITE_OS_C_ 1 #include "sqliteInt.h" @@ -36,7 +36,7 @@ ** sqlite3OsLock() ** */ -#if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0) +#if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0) && 0 #define DO_OS_MALLOC_TEST if (1) { \ void *pTstAlloc = sqlite3Malloc(10); \ if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ diff --git a/src/parse.y b/src/parse.y index 7642fe93f3..8fe3acb757 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.246 2008/07/18 17:03:53 drh Exp $ +** @(#) $Id: parse.y,v 1.247 2008/07/28 19:34:53 drh Exp $ */ // All token codes are small integers with #defines that begin with "TK_" @@ -135,7 +135,7 @@ create_table_args ::= LP columnlist conslist_opt(X) RP(Y). { } create_table_args ::= AS select(S). { sqlite3EndTable(pParse,0,0,S); - sqlite3SelectDelete(S); + sqlite3SelectDelete(pParse->db, S); } columnlist ::= columnlist COMMA column. columnlist ::= column. @@ -362,13 +362,13 @@ cmd ::= DROP VIEW ifexists(E) fullname(X). { cmd ::= select(X). { SelectDest dest = {SRT_Callback, 0, 0, 0, 0}; sqlite3Select(pParse, X, &dest, 0, 0, 0); - sqlite3SelectDelete(X); + sqlite3SelectDelete(pParse->db, X); } %type select {Select*} -%destructor select {sqlite3SelectDelete($$);} +%destructor select {sqlite3SelectDelete(pParse->db, $$);} %type oneselect {Select*} -%destructor oneselect {sqlite3SelectDelete($$);} +%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);} select(A) ::= oneselect(X). {A = X;} %ifndef SQLITE_OMIT_COMPOUND_SELECT @@ -377,7 +377,7 @@ select(A) ::= select(X) multiselect_op(Y) oneselect(Z). { Z->op = Y; Z->pPrior = X; }else{ - sqlite3SelectDelete(X); + sqlite3SelectDelete(pParse->db, X); } A = Z; } @@ -405,9 +405,9 @@ distinct(A) ::= . {A = 0;} // opcode of TK_ALL. // %type selcollist {ExprList*} -%destructor selcollist {sqlite3ExprListDelete($$);} +%destructor selcollist {sqlite3ExprListDelete(pParse->db, $$);} %type sclp {ExprList*} -%destructor sclp {sqlite3ExprListDelete($$);} +%destructor sclp {sqlite3ExprListDelete(pParse->db, $$);} sclp(A) ::= selcollist(X) COMMA. {A = X;} sclp(A) ::= . {A = 0;} selcollist(A) ::= sclp(P) expr(X) as(Y). { @@ -434,11 +434,11 @@ as(X) ::= . {X.n = 0;} %type seltablist {SrcList*} -%destructor seltablist {sqlite3SrcListDelete($$);} +%destructor seltablist {sqlite3SrcListDelete(pParse->db, $$);} %type stl_prefix {SrcList*} -%destructor stl_prefix {sqlite3SrcListDelete($$);} +%destructor stl_prefix {sqlite3SrcListDelete(pParse->db, $$);} %type from {SrcList*} -%destructor from {sqlite3SrcListDelete($$);} +%destructor from {sqlite3SrcListDelete(pParse->db, $$);} // A complete FROM clause. // @@ -470,7 +470,7 @@ seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) on_opt(N) using_opt(U). { // a grouping of table and subqueries. // %type seltablist_paren {Select*} - %destructor seltablist_paren {sqlite3SelectDelete($$);} + %destructor seltablist_paren {sqlite3SelectDelete(pParse->db, $$);} seltablist_paren(A) ::= select(S). {A = S;} seltablist_paren(A) ::= seltablist(F). { sqlite3SrcListShiftJoinType(F); @@ -483,7 +483,7 @@ dbnm(A) ::= . {A.z=0; A.n=0;} dbnm(A) ::= DOT nm(X). {A = X;} %type fullname {SrcList*} -%destructor fullname {sqlite3SrcListDelete($$);} +%destructor fullname {sqlite3SrcListDelete(pParse->db, $$);} fullname(A) ::= nm(X) dbnm(Y). {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y);} %type joinop {int} @@ -495,22 +495,22 @@ joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN. { X = sqlite3JoinType(pParse,&A,&B,&C); } %type on_opt {Expr*} -%destructor on_opt {sqlite3ExprDelete($$);} +%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);} on_opt(N) ::= ON expr(E). {N = E;} on_opt(N) ::= . {N = 0;} %type using_opt {IdList*} -%destructor using_opt {sqlite3IdListDelete($$);} +%destructor using_opt {sqlite3IdListDelete(pParse->db, $$);} using_opt(U) ::= USING LP inscollist(L) RP. {U = L;} using_opt(U) ::= . {U = 0;} %type orderby_opt {ExprList*} -%destructor orderby_opt {sqlite3ExprListDelete($$);} +%destructor orderby_opt {sqlite3ExprListDelete(pParse->db, $$);} %type sortlist {ExprList*} -%destructor sortlist {sqlite3ExprListDelete($$);} +%destructor sortlist {sqlite3ExprListDelete(pParse->db, $$);} %type sortitem {Expr*} -%destructor sortitem {sqlite3ExprDelete($$);} +%destructor sortitem {sqlite3ExprDelete(pParse->db, $$);} orderby_opt(A) ::= . {A = 0;} orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;} @@ -531,12 +531,12 @@ sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;} sortorder(A) ::= . {A = SQLITE_SO_ASC;} %type groupby_opt {ExprList*} -%destructor groupby_opt {sqlite3ExprListDelete($$);} +%destructor groupby_opt {sqlite3ExprListDelete(pParse->db, $$);} groupby_opt(A) ::= . {A = 0;} groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;} %type having_opt {Expr*} -%destructor having_opt {sqlite3ExprDelete($$);} +%destructor having_opt {sqlite3ExprDelete(pParse->db, $$);} having_opt(A) ::= . {A = 0;} having_opt(A) ::= HAVING expr(X). {A = X;} @@ -550,8 +550,8 @@ having_opt(A) ::= HAVING expr(X). {A = X;} // except as a transient. So there is never anything to destroy. // //%destructor limit_opt { -// sqlite3ExprDelete($$.pLimit); -// sqlite3ExprDelete($$.pOffset); +// sqlite3ExprDelete(pParse->db, $$.pLimit); +// sqlite3ExprDelete(pParse->db, $$.pOffset); //} limit_opt(A) ::= . {A.pLimit = 0; A.pOffset = 0;} limit_opt(A) ::= LIMIT expr(X). {A.pLimit = X; A.pOffset = 0;} @@ -565,7 +565,7 @@ limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). cmd ::= DELETE FROM fullname(X) where_opt(Y). {sqlite3DeleteFrom(pParse,X,Y);} %type where_opt {Expr*} -%destructor where_opt {sqlite3ExprDelete($$);} +%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);} where_opt(A) ::= . {A = 0;} where_opt(A) ::= WHERE expr(X). {A = X;} @@ -578,7 +578,7 @@ cmd ::= UPDATE orconf(R) fullname(X) SET setlist(Y) where_opt(Z). { } %type setlist {ExprList*} -%destructor setlist {sqlite3ExprListDelete($$);} +%destructor setlist {sqlite3ExprListDelete(pParse->db, $$);} setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y). {A = sqlite3ExprListAppend(pParse,Z,Y,&X);} @@ -601,7 +601,7 @@ insert_cmd(A) ::= REPLACE. {A = OE_Replace;} %type itemlist {ExprList*} -%destructor itemlist {sqlite3ExprListDelete($$);} +%destructor itemlist {sqlite3ExprListDelete(pParse->db, $$);} itemlist(A) ::= itemlist(X) COMMA expr(Y). {A = sqlite3ExprListAppend(pParse,X,Y,0);} @@ -609,9 +609,9 @@ itemlist(A) ::= expr(X). {A = sqlite3ExprListAppend(pParse,0,X,0);} %type inscollist_opt {IdList*} -%destructor inscollist_opt {sqlite3IdListDelete($$);} +%destructor inscollist_opt {sqlite3IdListDelete(pParse->db, $$);} %type inscollist {IdList*} -%destructor inscollist {sqlite3IdListDelete($$);} +%destructor inscollist {sqlite3IdListDelete(pParse->db, $$);} inscollist_opt(A) ::= . {A = 0;} inscollist_opt(A) ::= LP inscollist(X) RP. {A = X;} @@ -624,9 +624,9 @@ inscollist(A) ::= nm(Y). // %type expr {Expr*} -%destructor expr {sqlite3ExprDelete($$);} +%destructor expr {sqlite3ExprDelete(pParse->db, $$);} %type term {Expr*} -%destructor term {sqlite3ExprDelete($$);} +%destructor term {sqlite3ExprDelete(pParse->db, $$);} expr(A) ::= term(X). {A = X;} expr(A) ::= LP(B) expr(X) RP(E). {A = X; sqlite3ExprSpan(A,&B,&E); } @@ -702,7 +702,7 @@ likeop(A) ::= NOT LIKE_KW(X). {A.eOperator = X; A.not = 1;} likeop(A) ::= MATCH(X). {A.eOperator = X; A.not = 0;} likeop(A) ::= NOT MATCH(X). {A.eOperator = X; A.not = 1;} %type escape {Expr*} -%destructor escape {sqlite3ExprDelete($$);} +%destructor escape {sqlite3ExprDelete(pParse->db, $$);} escape(X) ::= ESCAPE expr(A). [ESCAPE] {X = A;} escape(X) ::= . [ESCAPE] {X = 0;} expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE_KW] { @@ -760,7 +760,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { if( A ){ A->pList = pList; }else{ - sqlite3ExprListDelete(pList); + sqlite3ExprListDelete(pParse->db, pList); } if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); sqlite3ExprSpan(A,&W->span,&Y->span); @@ -775,7 +775,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A->pList = Y; sqlite3ExprSetHeight(pParse, A); }else{ - sqlite3ExprListDelete(Y); + sqlite3ExprListDelete(pParse->db, Y); } if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); sqlite3ExprSpan(A,&X->span,&E); @@ -786,7 +786,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A->pSelect = X; sqlite3ExprSetHeight(pParse, A); }else{ - sqlite3SelectDelete(X); + sqlite3SelectDelete(pParse->db, X); } sqlite3ExprSpan(A,&B,&E); } @@ -796,7 +796,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A->pSelect = Y; sqlite3ExprSetHeight(pParse, A); }else{ - sqlite3SelectDelete(Y); + sqlite3SelectDelete(pParse->db, Y); } if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); sqlite3ExprSpan(A,&X->span,&E); @@ -808,7 +808,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); sqlite3ExprSetHeight(pParse, A); }else{ - sqlite3SrcListDelete(pSrc); + sqlite3SrcListDelete(pParse->db, pSrc); } if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); sqlite3ExprSpan(A,&X->span,Z.z?&Z:&Y); @@ -820,7 +820,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { sqlite3ExprSpan(p,&B,&E); sqlite3ExprSetHeight(pParse, A); }else{ - sqlite3SelectDelete(Y); + sqlite3SelectDelete(pParse->db, Y); } } %endif SQLITE_OMIT_SUBQUERY @@ -832,12 +832,12 @@ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { A->pList = Y; sqlite3ExprSetHeight(pParse, A); }else{ - sqlite3ExprListDelete(Y); + sqlite3ExprListDelete(pParse->db, Y); } sqlite3ExprSpan(A, &C, &E); } %type case_exprlist {ExprList*} -%destructor case_exprlist {sqlite3ExprListDelete($$);} +%destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);} case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). { A = sqlite3ExprListAppend(pParse,X, Y, 0); A = sqlite3ExprListAppend(pParse,A, Z, 0); @@ -847,18 +847,18 @@ case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). { A = sqlite3ExprListAppend(pParse,A, Z, 0); } %type case_else {Expr*} -%destructor case_else {sqlite3ExprDelete($$);} +%destructor case_else {sqlite3ExprDelete(pParse->db, $$);} case_else(A) ::= ELSE expr(X). {A = X;} case_else(A) ::= . {A = 0;} %type case_operand {Expr*} -%destructor case_operand {sqlite3ExprDelete($$);} +%destructor case_operand {sqlite3ExprDelete(pParse->db, $$);} case_operand(A) ::= expr(X). {A = X;} case_operand(A) ::= . {A = 0;} %type exprlist {ExprList*} -%destructor exprlist {sqlite3ExprListDelete($$);} +%destructor exprlist {sqlite3ExprListDelete(pParse->db, $$);} %type nexprlist {ExprList*} -%destructor nexprlist {sqlite3ExprListDelete($$);} +%destructor nexprlist {sqlite3ExprListDelete(pParse->db, $$);} exprlist(A) ::= nexprlist(X). {A = X;} exprlist(A) ::= . {A = 0;} @@ -882,9 +882,9 @@ uniqueflag(A) ::= UNIQUE. {A = OE_Abort;} uniqueflag(A) ::= . {A = OE_None;} %type idxlist {ExprList*} -%destructor idxlist {sqlite3ExprListDelete($$);} +%destructor idxlist {sqlite3ExprListDelete(pParse->db, $$);} %type idxlist_opt {ExprList*} -%destructor idxlist_opt {sqlite3ExprListDelete($$);} +%destructor idxlist_opt {sqlite3ExprListDelete(pParse->db, $$);} %type idxitem {Token} idxlist_opt(A) ::= . {A = 0;} @@ -974,7 +974,7 @@ trigger_time(A) ::= INSTEAD OF. { A = TK_INSTEAD;} trigger_time(A) ::= . { A = TK_BEFORE; } %type trigger_event {struct TrigEvent} -%destructor trigger_event {sqlite3IdListDelete($$.b);} +%destructor trigger_event {sqlite3IdListDelete(pParse->db, $$.b);} trigger_event(A) ::= DELETE|INSERT(OP). {A.a = @OP; A.b = 0;} trigger_event(A) ::= UPDATE(OP). {A.a = @OP; A.b = 0;} trigger_event(A) ::= UPDATE OF inscollist(X). {A.a = TK_UPDATE; A.b = X;} @@ -983,12 +983,12 @@ foreach_clause ::= . foreach_clause ::= FOR EACH ROW. %type when_clause {Expr*} -%destructor when_clause {sqlite3ExprDelete($$);} +%destructor when_clause {sqlite3ExprDelete(pParse->db, $$);} when_clause(A) ::= . { A = 0; } when_clause(A) ::= WHEN expr(X). { A = X; } %type trigger_cmd_list {TriggerStep*} -%destructor trigger_cmd_list {sqlite3DeleteTriggerStep($$);} +%destructor trigger_cmd_list {sqlite3DeleteTriggerStep(pParse->db, $$);} trigger_cmd_list(A) ::= trigger_cmd_list(Y) trigger_cmd(X) SEMI. { if( Y ){ Y->pLast->pNext = X; @@ -1001,7 +1001,7 @@ trigger_cmd_list(A) ::= trigger_cmd_list(Y) trigger_cmd(X) SEMI. { trigger_cmd_list(A) ::= . { A = 0; } %type trigger_cmd {TriggerStep*} -%destructor trigger_cmd {sqlite3DeleteTriggerStep($$);} +%destructor trigger_cmd {sqlite3DeleteTriggerStep(pParse->db, $$);} // UPDATE trigger_cmd(A) ::= UPDATE orconf(R) nm(X) SET setlist(Y) where_opt(Z). { A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R); } @@ -1061,7 +1061,7 @@ cmd ::= DETACH database_kw_opt expr(D). { } %type key_opt {Expr*} -%destructor key_opt {sqlite3ExprDelete($$);} +%destructor key_opt {sqlite3ExprDelete(pParse->db, $$);} key_opt(A) ::= . { A = 0; } key_opt(A) ::= KEY expr(X). { A = X; } diff --git a/src/pragma.c b/src/pragma.c index bac601c0c3..6ffc60d58c 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.182 2008/07/08 07:35:52 danielk1977 Exp $ +** $Id: pragma.c,v 1.183 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" #include @@ -682,8 +682,7 @@ void sqlite3Pragma( } sqlite3_free(sqlite3_temp_directory); if( zRight[0] ){ - sqlite3_temp_directory = zRight; - zRight = 0; + sqlite3_temp_directory = sqlite3DbStrDup(0, zRight); }else{ sqlite3_temp_directory = 0; } @@ -1323,8 +1322,8 @@ void sqlite3Pragma( #endif } pragma_out: - sqlite3_free(zLeft); - sqlite3_free(zRight); + sqlite3DbFree(db, zLeft); + sqlite3DbFree(db, zRight); } #endif /* SQLITE_OMIT_PRAGMA || SQLITE_OMIT_PARSER */ diff --git a/src/prepare.c b/src/prepare.c index 6d984f1ad2..a8d98bddbd 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.89 2008/07/08 19:34:07 drh Exp $ +** $Id: prepare.c,v 1.90 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" #include @@ -32,7 +32,7 @@ static void corruptSchema( sqlite3SetString(pData->pzErrMsg, pData->db, "malformed database schema (%s)", zObj); if( zExtra && zExtra[0] ){ - *pData->pzErrMsg = sqlite3MPrintf(pData->db, "%z - %s", + *pData->pzErrMsg = sqlite3MAppendf(pData->db, *pData->pzErrMsg, "%s - %s", *pData->pzErrMsg, zExtra); } } @@ -79,11 +79,15 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ */ char *zErr; int rc; + u8 lookasideEnabled; assert( db->init.busy ); db->init.iDb = iDb; db->init.newTnum = atoi(argv[1]); + lookasideEnabled = db->lookaside.bEnabled; + db->lookaside.bEnabled = 0; rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); db->init.iDb = 0; + db->lookaside.bEnabled = lookasideEnabled; assert( rc!=SQLITE_OK || zErr==0 ); if( SQLITE_OK!=rc ){ pData->rc = rc; @@ -92,7 +96,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ }else if( rc!=SQLITE_INTERRUPT ){ corruptSchema(pData, argv[0], zErr); } - sqlite3_free(zErr); + sqlite3DbFree(db, zErr); return 1; } }else if( argv[0]==0 ){ @@ -336,7 +340,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ #endif if( rc==SQLITE_ABORT ) rc = initData.rc; (void)sqlite3SafetyOn(db); - sqlite3_free(zSql); + sqlite3DbFree(db, zSql); #ifndef SQLITE_OMIT_ANALYZE if( rc==SQLITE_OK ){ sqlite3AnalysisLoad(db, iDb); @@ -568,7 +572,7 @@ static int sqlite3Prepare( zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); if( zSqlCopy ){ sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); - sqlite3_free(zSqlCopy); + sqlite3DbFree(db, zSqlCopy); sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; }else{ sParse.zTail = &zSql[nBytes]; @@ -632,7 +636,7 @@ static int sqlite3Prepare( if( zErrMsg ){ sqlite3Error(db, rc, "%s", zErrMsg); - sqlite3_free(zErrMsg); + sqlite3DbFree(db, zErrMsg); }else{ sqlite3Error(db, rc, 0); } @@ -767,7 +771,7 @@ static int sqlite3Prepare16( int chars_parsed = sqlite3Utf8CharLen(zSql8, zTail8-zSql8); *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed); } - sqlite3_free(zSql8); + sqlite3DbFree(db, zSql8); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; diff --git a/src/printf.c b/src/printf.c index 5935f97e48..b88a7d8d0b 100644 --- a/src/printf.c +++ b/src/printf.c @@ -5,7 +5,7 @@ ** an historical reference. Most of the "enhancements" have been backed ** out so that the functionality is now the same as standard printf(). ** -** $Id: printf.c,v 1.92 2008/07/15 00:27:35 drh Exp $ +** $Id: printf.c,v 1.93 2008/07/28 19:34:53 drh Exp $ ** ************************************************************************** ** @@ -746,7 +746,7 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ }else{ p->nAlloc = szNew; } - zNew = sqlite3Malloc( p->nAlloc ); + zNew = sqlite3DbMallocRaw(p->db, p->nAlloc ); if( zNew ){ memcpy(zNew, p->zText, p->nChar); sqlite3StrAccumReset(p); @@ -771,7 +771,7 @@ char *sqlite3StrAccumFinish(StrAccum *p){ if( p->zText ){ p->zText[p->nChar] = 0; if( p->useMalloc && p->zText==p->zBase ){ - p->zText = sqlite3Malloc( p->nChar+1 ); + p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); if( p->zText ){ memcpy(p->zText, p->zBase, p->nChar+1); }else{ @@ -787,7 +787,7 @@ char *sqlite3StrAccumFinish(StrAccum *p){ */ void sqlite3StrAccumReset(StrAccum *p){ if( p->zText!=p->zBase ){ - sqlite3_free(p->zText); + sqlite3DbFree(p->db, p->zText); } p->zText = 0; } @@ -797,6 +797,7 @@ void sqlite3StrAccumReset(StrAccum *p){ */ void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){ p->zText = p->zBase = zBase; + p->db = 0; p->nChar = 0; p->nAlloc = n; p->mxAlloc = mx; @@ -815,6 +816,7 @@ char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){ StrAccum acc; sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH); + acc.db = db; sqlite3VXPrintf(&acc, 1, zFormat, ap); z = sqlite3StrAccumFinish(&acc); if( acc.mallocFailed && db ){ @@ -836,6 +838,24 @@ char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){ return z; } +/* +** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting +** the string and before returnning. This routine is intended to be used +** to modify an existing string. For example: +** +** x = sqlite3MPrintf(db, x, "prefix %s suffix", x); +** +*/ +char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zFormat, ...){ + va_list ap; + char *z; + va_start(ap, zFormat); + z = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + sqlite3DbFree(db, zStr); + return z; +} + /* ** Print into memory obtained from sqlite3_malloc(). Omit the internal ** %-conversion extensions. diff --git a/src/select.c b/src/select.c index 353ef06c99..56a75c97fa 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.459 2008/07/24 15:50:41 drh Exp $ +** $Id: select.c,v 1.460 2008/07/28 19:34:53 drh Exp $ */ #include "sqliteInt.h" @@ -21,16 +21,16 @@ ** Delete all the content of a Select structure but do not deallocate ** the select structure itself. */ -static void clearSelect(Select *p){ - sqlite3ExprListDelete(p->pEList); - sqlite3SrcListDelete(p->pSrc); - sqlite3ExprDelete(p->pWhere); - sqlite3ExprListDelete(p->pGroupBy); - sqlite3ExprDelete(p->pHaving); - sqlite3ExprListDelete(p->pOrderBy); - sqlite3SelectDelete(p->pPrior); - sqlite3ExprDelete(p->pLimit); - sqlite3ExprDelete(p->pOffset); +static void clearSelect(sqlite3 *db, Select *p){ + sqlite3ExprListDelete(db, p->pEList); + sqlite3SrcListDelete(db, p->pSrc); + sqlite3ExprDelete(db, p->pWhere); + sqlite3ExprListDelete(db, p->pGroupBy); + sqlite3ExprDelete(db, p->pHaving); + sqlite3ExprListDelete(db, p->pOrderBy); + sqlite3SelectDelete(db, p->pPrior); + sqlite3ExprDelete(db, p->pLimit); + sqlite3ExprDelete(db, p->pOffset); } /* @@ -88,7 +88,7 @@ Select *sqlite3SelectNew( pNew->addrOpenEphm[1] = -1; pNew->addrOpenEphm[2] = -1; if( pNew==&standin) { - clearSelect(pNew); + clearSelect(db, pNew); pNew = 0; } return pNew; @@ -97,10 +97,10 @@ Select *sqlite3SelectNew( /* ** Delete the given Select structure and all of its substructures. */ -void sqlite3SelectDelete(Select *p){ +void sqlite3SelectDelete(sqlite3 *db, Select *p){ if( p ){ - clearSelect(p); - sqlite3_free(p); + clearSelect(db, p); + sqlite3DbFree(db, p); } } @@ -1163,6 +1163,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ if( pTab==0 ){ return 0; } + pTab->db = db; pTab->nRef = 1; pTab->zName = zTabName ? sqlite3DbStrDup(db, zTabName) : 0; pEList = pSelect->pEList; @@ -1196,7 +1197,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ zName = sqlite3MPrintf(db, "%T", &p->span); } if( db->mallocFailed ){ - sqlite3_free(zName); + sqlite3DbFree(db, zName); break; } sqlite3Dequote(zName); @@ -1207,8 +1208,11 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ nName = strlen(zName); for(j=cnt=0; jpEList = pNew; } #if SQLITE_MAX_COLUMN @@ -1538,11 +1542,11 @@ static int matchOrderByTermToExprList( for(i=0; inExpr; i++){ char *zAs = pEList->a[i].zName; if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ - sqlite3_free(zCol); + sqlite3DbFree(db, zCol); return i+1; } } - sqlite3_free(zCol); + sqlite3DbFree(db, zCol); } /* Resolve all names in the ORDER BY term expression @@ -1631,7 +1635,7 @@ static int processOrderGroupBy( if( iCol>0 ){ CollSeq *pColl = pE->pColl; int flags = pE->flags & EP_ExpCollate; - sqlite3ExprDelete(pE); + sqlite3ExprDelete(db, pE); pE = sqlite3ExprDup(db, pEList->a[iCol-1].pExpr); pOrderBy->a[i].pExpr = pE; if( pE && pColl && flags ){ @@ -1702,7 +1706,7 @@ static int processCompoundOrderBy( assert(pDup); iCol = matchOrderByTermToExprList(pParse, pSelect, pDup, i+1, 1, 0); } - sqlite3ExprDelete(pDup); + sqlite3ExprDelete(db, pDup); if( iCol<0 ){ return 1; } @@ -1882,6 +1886,7 @@ static int multiSelect( Vdbe *v; /* Generate code to this VDBE */ SelectDest dest; /* Alternative data destination */ Select *pDelete = 0; /* Chain of simple selects to delete */ + sqlite3 *db; /* Database connection */ /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. @@ -1890,6 +1895,7 @@ static int multiSelect( rc = 1; goto multi_select_end; } + db = pParse->db; pPrior = p->pPrior; assert( pPrior->pRightmost!=pPrior ); assert( pPrior->pRightmost==p->pRightmost ); @@ -2026,11 +2032,11 @@ static int multiSelect( rc = sqlite3Select(pParse, p, &uniondest, 0, 0, 0); /* Query flattening in sqlite3Select() might refill p->pOrderBy. ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ - sqlite3ExprListDelete(p->pOrderBy); + sqlite3ExprListDelete(db, p->pOrderBy); pDelete = p->pPrior; p->pPrior = pPrior; p->pOrderBy = 0; - sqlite3ExprDelete(p->pLimit); + sqlite3ExprDelete(db, p->pLimit); p->pLimit = pLimit; p->pOffset = pOffset; p->iLimit = 0; @@ -2109,7 +2115,7 @@ static int multiSelect( rc = sqlite3Select(pParse, p, &intersectdest, 0, 0, 0); pDelete = p->pPrior; p->pPrior = pPrior; - sqlite3ExprDelete(p->pLimit); + sqlite3ExprDelete(db, p->pLimit); p->pLimit = pLimit; p->pOffset = pOffset; if( rc ){ @@ -2162,20 +2168,20 @@ static int multiSelect( assert( p->pRightmost==p ); nCol = p->pEList->nExpr; - pKeyInfo = sqlite3DbMallocZero(pParse->db, + pKeyInfo = sqlite3DbMallocZero(db, sizeof(*pKeyInfo)+nCol*(sizeof(CollSeq*) + 1)); if( !pKeyInfo ){ rc = SQLITE_NOMEM; goto multi_select_end; } - pKeyInfo->enc = ENC(pParse->db); + pKeyInfo->enc = ENC(db); pKeyInfo->nField = nCol; for(i=0, apColl=pKeyInfo->aColl; idb->pDfltColl; + *apColl = db->pDfltColl; } } @@ -2193,13 +2199,13 @@ static int multiSelect( pLoop->addrOpenEphm[i] = -1; } } - sqlite3_free(pKeyInfo); + sqlite3DbFree(db, pKeyInfo); } multi_select_end: pDest->iMem = dest.iMem; pDest->nMem = dest.nMem; - sqlite3SelectDelete(pDelete); + sqlite3SelectDelete(db, pDelete); return rc; } #endif /* SQLITE_OMIT_COMPOUND_SELECT */ @@ -2622,9 +2628,9 @@ static int multiSelectOrderBy( }else{ regLimitA = regLimitB = 0; } - sqlite3ExprDelete(p->pLimit); + sqlite3ExprDelete(db, p->pLimit); p->pLimit = 0; - sqlite3ExprDelete(p->pOffset); + sqlite3ExprDelete(db, p->pOffset); p->pOffset = 0; regAddrA = ++pParse->nMem; @@ -2786,7 +2792,7 @@ static int multiSelectOrderBy( /* Reassembly the compound query so that it will be freed correctly ** by the calling function */ if( p->pPrior ){ - sqlite3SelectDelete(p->pPrior); + sqlite3SelectDelete(db, p->pPrior); } p->pPrior = pPrior; @@ -3155,9 +3161,9 @@ static int flattenSubquery( nSubSrc = pSubSrc->nSrc; jointype = pSubitem->jointype; sqlite3DeleteTable(pSubitem->pTab); - sqlite3_free(pSubitem->zDatabase); - sqlite3_free(pSubitem->zName); - sqlite3_free(pSubitem->zAlias); + sqlite3DbFree(db, pSubitem->zDatabase); + sqlite3DbFree(db, pSubitem->zName); + sqlite3DbFree(db, pSubitem->zAlias); pSubitem->pTab = 0; pSubitem->zDatabase = 0; pSubitem->zName = 0; @@ -3254,7 +3260,7 @@ static int flattenSubquery( /* Finially, delete what is left of the subquery and return ** success. */ - sqlite3SelectDelete(pSub1); + sqlite3SelectDelete(db, pSub1); return 1; } @@ -3525,33 +3531,6 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ pAggInfo->directMode = 0; } -#if 0 -/* -** This function is used when a SELECT statement is used to create a -** temporary table for iterating through when running an INSTEAD OF -** UPDATE or INSTEAD OF DELETE trigger. -** -** If possible, the SELECT statement is modified so that NULL values -** are stored in the temporary table for all columns for which the -** corresponding bit in argument mask is not set. If mask takes the -** special value 0xffffffff, then all columns are populated. -*/ -void sqlite3SelectMask(Parse *pParse, Select *p, u32 mask){ - if( p && !p->pPrior && !p->isDistinct && mask!=0xffffffff ){ - ExprList *pEList; - int i; - sqlite3SelectResolve(pParse, p, 0); - pEList = p->pEList; - for(i=0; pEList && inExpr && i<32; i++){ - if( !(mask&((u32)1<a[i].pExpr); - pEList->a[i].pExpr = sqlite3Expr(pParse->db, TK_NULL, 0, 0, 0); - } - } - } -} -#endif - /* ** Generate code for the given SELECT statement. ** @@ -4144,7 +4123,7 @@ int sqlite3Select( resetAccumulator(pParse, &sAggInfo); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag); if( pWInfo==0 ){ - sqlite3ExprListDelete(pDel); + sqlite3ExprListDelete(db, pDel); goto select_end; } updateAccumulator(pParse, &sAggInfo); @@ -4161,7 +4140,7 @@ int sqlite3Select( selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1, pDest, addrEnd, addrEnd); - sqlite3ExprListDelete(pDel); + sqlite3ExprListDelete(db, pDel); } sqlite3VdbeResolveLabel(v, addrEnd); @@ -4208,8 +4187,8 @@ select_end: generateColumnNames(pParse, pTabList, pEList); } - sqlite3_free(sAggInfo.aCol); - sqlite3_free(sAggInfo.aFunc); + sqlite3DbFree(db, sAggInfo.aCol); + sqlite3DbFree(db, sAggInfo.aFunc); return rc; } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 10434e05bd..13d6fe5bce 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -30,7 +30,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.381 2008/07/28 05:22:36 danielk1977 Exp $ +** @(#) $Id: sqlite.h.in,v 1.382 2008/07/28 19:34:53 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -971,6 +971,14 @@ int sqlite3_os_end(void); */ int sqlite3_config(int, ...); +/* +** CAPI3REF: Configure database connections {H10180} +** +** The sqlite3_db_config() interface is used to make configuration +** changes to a [database connection]. +*/ +int sqlite3_db_config(sqlite3*, int, ...); + /* ** CAPI3REF: Memory Allocation Routines {H10155} ** @@ -1146,6 +1154,14 @@ struct sqlite3_mem_methods { ** This option can be used to overload the default mutex allocation ** routines with a wrapper used to track mutex usage for performance ** profiling or testing, for example. +** +**
SQLITE_CONFIG_LOOKASIDE
+**
This option takes two arguments that determine the default +** memory allcation lookaside optimization. The first argument is the +** size of each lookaside buffer slot and the second is the number of +** slots allocated to each database connection.
+** +** */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ @@ -1159,6 +1175,7 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ #define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ #define SQLITE_CONFIG_CHUNKALLOC 12 /* int threshold */ +#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ /* @@ -6073,6 +6090,7 @@ int sqlite3_test_control(int op, ...); ** removal in future releases of SQLite. */ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); +int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); /* ** CAPI3REF: Status Parameters {H17250} @@ -6136,6 +6154,18 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); #define SQLITE_STATUS_MALLOC_SIZE 5 #define SQLITE_STATUS_PARSER_STACK 6 +/* +** CAPI3REF: Status Parameters for database connections {H17275} +** +** Status verbs for [sqlite3_db_status()]. +** +**
+**
SQLITE_DBSTATUS_LOOKASIDE_USED
+**
This parameter returns the number of lookaside memory slots currently +** checked out.
+**
+*/ +#define SQLITE_DBSTATUS_LOOKASIDE_USED 0 /* ** Undo the hack that converts floating point types to integer for diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5672394900..518fa76f6c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.746 2008/07/25 15:39:04 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.747 2008/07/28 19:34:54 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -430,6 +430,12 @@ struct BusyHandler { */ #define ArraySize(X) (sizeof(X)/sizeof(X[0])) +/* +** The following value as a destructor means to use sqlite3DbFree(). +** This is an internal extension to SQLITE_STATIC and SQLITE_TRANSIENT. +*/ +#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3DbFree) + /* ** Forward references to structures */ @@ -448,6 +454,8 @@ typedef struct IdList IdList; typedef struct Index Index; typedef struct KeyClass KeyClass; typedef struct KeyInfo KeyInfo; +typedef struct Lookaside Lookaside; +typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; typedef struct Parse Parse; @@ -549,6 +557,32 @@ struct Schema { */ #define SQLITE_N_LIMIT (SQLITE_LIMIT_VARIABLE_NUMBER+1) +/* +** Lookaside malloc is a set of fixed-size buffers that can be used +** to satisify small transient memory allocation requests for objects +** associated with a particular database connection. The use of +** lookaside malloc provides a significant performance enhancement +** (approx 10%) by avoiding numerous malloc/free requests while parsing +** SQL statements. +** +** The Lookaside structure holds configuration information about the +** lookaside malloc subsystem. Each available memory allocation in +** the lookaside subsystem is stored on a linked list of LookasideSlot +** objects. +*/ +struct Lookaside { + u16 sz; /* Size of each buffer in bytes */ + u8 bEnabled; /* True if use lookaside. False to ignore it */ + int nOut; /* Number of buffers currently checked out */ + int mxOut; /* Highwater mark for nOut */ + LookasideSlot *pFree; /* List if available buffers */ + void *pStart; /* First byte of available memory space */ + void *pEnd; /* First byte past end of available space */ +}; +struct LookasideSlot { + LookasideSlot *pNext; /* Next buffer in the list of free buffers */ +}; + /* ** Each database is an instance of the following structure. ** @@ -628,6 +662,7 @@ struct sqlite3 { int isInterrupted; /* True if sqlite3_interrupt has been called */ double notUsed1; /* Spacer */ } u1; + Lookaside lookaside; /* Lookaside malloc configuration */ #ifndef SQLITE_OMIT_AUTHORIZATION int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); /* Access authorization function */ @@ -867,6 +902,7 @@ struct CollSeq { ** of a SELECT statement. */ struct Table { + sqlite3 *db; /* Associated database connection. Might be NULL. */ char *zName; /* Name of the table */ int nCol; /* Number of columns in this table */ Column *aCol; /* Information about each column */ @@ -1744,10 +1780,11 @@ struct DbFixer { ** do not necessarily know how big the string will be in the end. */ struct StrAccum { - char *zBase; /* A base allocation. Not from malloc. */ - char *zText; /* The string collected so far */ - int nChar; /* Length of the string so far */ - int nAlloc; /* Amount of space allocated in zText */ + sqlite3 *db; /* Optional database for lookaside. Can be NULL */ + char *zBase; /* A base allocation. Not from malloc. */ + char *zText; /* The string collected so far */ + int nChar; /* Length of the string so far */ + int nAlloc; /* Amount of space allocated in zText */ int mxAlloc; /* Maximum allowed string length */ u8 mallocFailed; /* Becomes true if any memory allocation fails */ u8 useMalloc; /* True if zText is enlargable using realloc */ @@ -1775,6 +1812,8 @@ struct Sqlite3Config { int bCoreMutex; /* True to enable core mutexing */ int bFullMutex; /* True to enable full mutexing */ int mxStrlen; /* Maximum string length */ + int szLookaside; /* Default lookaside buffer size */ + int nLookaside; /* Default lookaside buffer count */ sqlite3_mem_methods m; /* Low-level memory allocation interface */ sqlite3_mutex_methods mutex; /* Low-level mutex interface */ void *pHeap; /* Heap storage space */ @@ -1830,14 +1869,14 @@ void *sqlite3Malloc(int); void *sqlite3MallocZero(int); void *sqlite3DbMallocZero(sqlite3*, int); void *sqlite3DbMallocRaw(sqlite3*, int); -char *sqlite3StrDup(const char*); -char *sqlite3StrNDup(const char*, int); char *sqlite3DbStrDup(sqlite3*,const char*); char *sqlite3DbStrNDup(sqlite3*,const char*, int); void *sqlite3Realloc(void*, int); void *sqlite3DbReallocOrFree(sqlite3 *, void *, int); void *sqlite3DbRealloc(sqlite3 *, void *, int); -int sqlite3MallocSize(void *); +void sqlite3DbFree(sqlite3*, void*); +int sqlite3MallocSize(void*); +int sqlite3DbMallocSize(sqlite3*, void*); void *sqlite3ScratchMalloc(int); void sqlite3ScratchFree(void*); void *sqlite3PageMalloc(int); @@ -1866,6 +1905,7 @@ int sqlite3IsNaN(double); void sqlite3VXPrintf(StrAccum*, int, const char*, va_list); char *sqlite3MPrintf(sqlite3*,const char*, ...); char *sqlite3VMPrintf(sqlite3*,const char*, va_list); +char *sqlite3MAppendf(sqlite3*,char*,const char*,...); #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) void sqlite3DebugPrintf(const char*, ...); #endif @@ -1891,9 +1931,9 @@ Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); void sqlite3ExprSpan(Expr*,Token*,Token*); Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); void sqlite3ExprAssignVarNumber(Parse*, Expr*); -void sqlite3ExprDelete(Expr*); +void sqlite3ExprDelete(sqlite3*, Expr*); ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*,Token*); -void sqlite3ExprListDelete(ExprList*); +void sqlite3ExprListDelete(sqlite3*, ExprList*); int sqlite3Init(sqlite3*, char**); int sqlite3InitCallback(void*, int, char**, char**); void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); @@ -1938,15 +1978,15 @@ SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, Token*, Select*, Expr*, IdList*); void sqlite3SrcListShiftJoinType(SrcList*); void sqlite3SrcListAssignCursors(Parse*, SrcList*); -void sqlite3IdListDelete(IdList*); -void sqlite3SrcListDelete(SrcList*); +void sqlite3IdListDelete(sqlite3*, IdList*); +void sqlite3SrcListDelete(sqlite3*, SrcList*); void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, Token*, int, int); void sqlite3DropIndex(Parse*, SrcList*, int); int sqlite3Select(Parse*, Select*, SelectDest*, Select*, int, int*); Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, Expr*,ExprList*,int,Expr*,Expr*); -void sqlite3SelectDelete(Select*); +void sqlite3SelectDelete(sqlite3*, Select*); Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); @@ -2035,17 +2075,17 @@ void sqlite3MaterializeView(Parse*, Select*, Expr*, int); int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, int, int, u32*, u32*); void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); - void sqlite3DeleteTriggerStep(TriggerStep*); + void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*); TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*, ExprList*,Select*,int); TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, int); TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); - void sqlite3DeleteTrigger(Trigger*); + void sqlite3DeleteTrigger(sqlite3*, Trigger*); void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); #else # define sqlite3TriggersExist(A,B,C,D,E,F) 0 -# define sqlite3DeleteTrigger(A) +# define sqlite3DeleteTrigger(A,B) # define sqlite3DropTriggerPtr(A,B) # define sqlite3UnlinkAndDeleteTrigger(A,B,C) # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J,K) 0 diff --git a/src/status.c b/src/status.c index 504f44e50e..a5e45dd33a 100644 --- a/src/status.c +++ b/src/status.c @@ -13,7 +13,7 @@ ** This module implements the sqlite3_status() interface and related ** functionality. ** -** $Id: status.c,v 1.4 2008/07/25 15:39:04 drh Exp $ +** $Id: status.c,v 1.5 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" @@ -83,3 +83,26 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ } return SQLITE_OK; } + +/* +** Query status information for a single database connection +*/ +int sqlite3_db_status( + sqlite3 *db, /* The database connection whose status is desired */ + int op, /* Status verb */ + int *pCurrent, /* Write current value here */ + int *pHighwater, /* Write high-water mark here */ + int resetFlag /* Reset high-water mark if true */ +){ + switch( op ){ + case SQLITE_DBSTATUS_LOOKASIDE_USED: { + *pCurrent = db->lookaside.nOut; + *pHighwater = db->lookaside.mxOut; + if( resetFlag ){ + db->lookaside.mxOut = db->lookaside.nOut; + } + break; + } + } + return SQLITE_OK; +} diff --git a/src/test4.c b/src/test4.c index 622ca93bf1..de5d3a2e3c 100644 --- a/src/test4.c +++ b/src/test4.c @@ -11,7 +11,7 @@ ************************************************************************* ** Code for testing the the SQLite library in a multithreaded environment. ** -** $Id: test4.c,v 1.22 2008/06/26 10:41:19 danielk1977 Exp $ +** $Id: test4.c,v 1.23 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -142,7 +142,7 @@ static int tcl_thread_create( } threadset[i].busy = 1; sqlite3_free(threadset[i].zFilename); - threadset[i].zFilename = sqlite3StrDup(argv[2]); + threadset[i].zFilename = sqlite3DbStrDup(0, argv[2]); threadset[i].opnum = 1; threadset[i].completed = 0; rc = pthread_create(&x, 0, thread_main, &threadset[i]); @@ -476,7 +476,7 @@ static int tcl_thread_compile( thread_wait(&threadset[i]); threadset[i].xOp = do_compile; sqlite3_free(threadset[i].zArg); - threadset[i].zArg = sqlite3StrDup(argv[2]); + threadset[i].zArg = sqlite3DbStrDup(0, argv[2]); threadset[i].opnum++; return TCL_OK; } diff --git a/src/test5.c b/src/test5.c index 58d65aa28f..cbb8840a00 100644 --- a/src/test5.c +++ b/src/test5.c @@ -15,7 +15,7 @@ ** is used for testing the SQLite routines for converting between ** the various supported unicode encodings. ** -** $Id: test5.c,v 1.20 2007/08/21 19:33:57 drh Exp $ +** $Id: test5.c,v 1.21 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" @@ -154,7 +154,7 @@ static int test_translate( if( enc_from==SQLITE_UTF8 ){ z = Tcl_GetString(objv[1]); if( objc==5 ){ - z = sqlite3StrDup(z); + z = sqlite3DbStrDup(0, z); } sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel); }else{ diff --git a/src/test7.c b/src/test7.c index 04a10fa9dc..78754bfa79 100644 --- a/src/test7.c +++ b/src/test7.c @@ -12,7 +12,7 @@ ** Code for testing the client/server version of the SQLite library. ** Derived from test4.c. ** -** $Id: test7.c,v 1.11 2008/06/26 10:41:19 danielk1977 Exp $ +** $Id: test7.c,v 1.12 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -164,7 +164,7 @@ static int tcl_client_create( } threadset[i].busy = 1; sqlite3_free(threadset[i].zFilename); - threadset[i].zFilename = sqlite3StrDup(argv[2]); + threadset[i].zFilename = sqlite3DbStrDup(0, argv[2]); threadset[i].opnum = 1; threadset[i].completed = 0; rc = pthread_create(&x, 0, client_main, &threadset[i]); @@ -507,7 +507,7 @@ static int tcl_client_compile( client_wait(&threadset[i]); threadset[i].xOp = do_compile; sqlite3_free(threadset[i].zArg); - threadset[i].zArg = sqlite3StrDup(argv[2]); + threadset[i].zArg = sqlite3DbStrDup(0, argv[2]); threadset[i].opnum++; return TCL_OK; } diff --git a/src/test8.c b/src/test8.c index c64e55d465..effd768b8f 100644 --- a/src/test8.c +++ b/src/test8.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test8.c,v 1.68 2008/07/23 18:17:32 drh Exp $ +** $Id: test8.c,v 1.69 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -459,7 +459,7 @@ static int echoCreate( rc = sqlite3_exec(db, zSql, 0, 0, 0); sqlite3_free(zSql); if( rc!=SQLITE_OK ){ - *pzErr = sqlite3StrDup(sqlite3_errmsg(db)); + *pzErr = sqlite3DbStrDup(0, sqlite3_errmsg(db)); } } diff --git a/src/test_malloc.c b/src/test_malloc.c index 0c963ad400..d8cc15849a 100644 --- a/src/test_malloc.c +++ b/src/test_malloc.c @@ -13,7 +13,7 @@ ** This file contains code used to implement test interfaces to the ** memory allocation subsystem. ** -** $Id: test_malloc.c,v 1.41 2008/07/25 15:39:04 drh Exp $ +** $Id: test_malloc.c,v 1.42 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -978,6 +978,56 @@ static int test_config_chunkalloc( return TCL_OK; } +/* +** Usage: sqlite3_config_lookaside SIZE COUNT +** +*/ +static int test_config_lookaside( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc; + int sz, cnt; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SIZE COUNT"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &cnt) ) return TCL_ERROR; + rc = sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, cnt); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return TCL_OK; +} + + +/* +** Usage: sqlite3_db_config_lookaside CONNECTION SIZE COUNT +** +*/ +static int test_db_config_lookaside( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc; + int sz, cnt; + sqlite3 *db; + int getDbPointer(Tcl_Interp*, const char*, sqlite3**); + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SIZE COUNT"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &sz) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[3], &cnt) ) return TCL_ERROR; + rc = sqlite3_db_config(db, SQLITE_CONFIG_LOOKASIDE, sz, cnt); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return TCL_OK; +} + /* ** Usage: ** @@ -1112,6 +1162,57 @@ static int test_status( return TCL_OK; } +/* +** Usage: sqlite3_db_status DATABASE OPCODE RESETFLAG +** +** Return a list of three elements which are the sqlite3_db_status() return +** code, the current value, and the high-water mark value. +*/ +static int test_db_status( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc, iValue, mxValue; + int i, op, resetFlag; + const char *zOpName; + sqlite3 *db; + int getDbPointer(Tcl_Interp*, const char*, sqlite3**); + static const struct { + const char *zName; + int op; + } aOp[] = { + { "SQLITE_DBSTATUS_LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED }, + }; + Tcl_Obj *pResult; + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zOpName = Tcl_GetString(objv[2]); + for(i=0; i=ArraySize(aOp) ){ + if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR; + } + if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR; + iValue = 0; + mxValue = 0; + rc = sqlite3_db_status(db, op, &iValue, &mxValue, resetFlag); + pResult = Tcl_NewObj(); + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc)); + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue)); + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue)); + Tcl_SetObjResult(interp, pResult); + return TCL_OK; +} + /* ** install_malloc_faultsim BOOLEAN */ @@ -1162,10 +1263,13 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){ { "sqlite3_config_scratch", test_config_scratch ,0 }, { "sqlite3_config_pagecache", test_config_pagecache ,0 }, { "sqlite3_status", test_status ,0 }, + { "sqlite3_db_status", test_db_status ,0 }, { "install_malloc_faultsim", test_install_malloc_faultsim ,0 }, { "sqlite3_config_heap", test_config_heap ,0 }, { "sqlite3_config_memstatus", test_config_memstatus ,0 }, { "sqlite3_config_chunkalloc", test_config_chunkalloc ,0 }, + { "sqlite3_config_lookaside", test_config_lookaside ,0 }, + { "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 }, { "sqlite3_dump_memsys3", test_dump_memsys3 ,3 }, { "sqlite3_dump_memsys5", test_dump_memsys3 ,5 } }; diff --git a/src/tokenize.c b/src/tokenize.c index 70b2d3ad9f..bea8d5eba4 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -15,7 +15,7 @@ ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.147 2008/07/25 15:39:04 drh Exp $ +** $Id: tokenize.c,v 1.148 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" #include @@ -427,7 +427,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ break; } case TK_ILLEGAL: { - sqlite3_free(*pzErrMsg); + sqlite3DbFree(db, *pzErrMsg); *pzErrMsg = sqlite3MPrintf(db, "unrecognized token: \"%T\"", &pParse->sLastToken); nErr++; @@ -471,7 +471,7 @@ abort_parse: if( *pzErrMsg==0 ){ *pzErrMsg = pParse->zErrMsg; }else{ - sqlite3_free(pParse->zErrMsg); + sqlite3DbFree(db, pParse->zErrMsg); } pParse->zErrMsg = 0; nErr++; @@ -482,13 +482,13 @@ abort_parse: } #ifndef SQLITE_OMIT_SHARED_CACHE if( pParse->nested==0 ){ - sqlite3_free(pParse->aTableLock); + sqlite3DbFree(db, pParse->aTableLock); pParse->aTableLock = 0; pParse->nTableLock = 0; } #endif #ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3_free(pParse->apVtabLock); + sqlite3DbFree(db, pParse->apVtabLock); #endif if( !IN_DECLARE_VTAB ){ @@ -499,8 +499,8 @@ abort_parse: sqlite3DeleteTable(pParse->pNewTable); } - sqlite3DeleteTrigger(pParse->pNewTrigger); - sqlite3_free(pParse->apVarExpr); + sqlite3DeleteTrigger(db, pParse->pNewTrigger); + sqlite3DbFree(db, pParse->apVarExpr); if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){ pParse->rc = SQLITE_ERROR; } diff --git a/src/trigger.c b/src/trigger.c index ccee82917b..760c708c61 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -10,7 +10,7 @@ ************************************************************************* ** ** -** $Id: trigger.c,v 1.127 2008/07/08 23:40:20 drh Exp $ +** $Id: trigger.c,v 1.128 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" @@ -18,18 +18,18 @@ /* ** Delete a linked list of TriggerStep structures. */ -void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){ +void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){ while( pTriggerStep ){ TriggerStep * pTmp = pTriggerStep; pTriggerStep = pTriggerStep->pNext; - if( pTmp->target.dyn ) sqlite3_free((char*)pTmp->target.z); - sqlite3ExprDelete(pTmp->pWhere); - sqlite3ExprListDelete(pTmp->pExprList); - sqlite3SelectDelete(pTmp->pSelect); - sqlite3IdListDelete(pTmp->pIdList); + if( pTmp->target.dyn ) sqlite3DbFree(db, (char*)pTmp->target.z); + sqlite3ExprDelete(db, pTmp->pWhere); + sqlite3ExprListDelete(db, pTmp->pExprList); + sqlite3SelectDelete(db, pTmp->pSelect); + sqlite3IdListDelete(db, pTmp->pIdList); - sqlite3_free(pTmp); + sqlite3DbFree(db, pTmp); } } @@ -186,12 +186,12 @@ void sqlite3BeginTrigger( pParse->pNewTrigger = pTrigger; trigger_cleanup: - sqlite3_free(zName); - sqlite3SrcListDelete(pTableName); - sqlite3IdListDelete(pColumns); - sqlite3ExprDelete(pWhen); + sqlite3DbFree(db, zName); + sqlite3SrcListDelete(db, pTableName); + sqlite3IdListDelete(db, pColumns); + sqlite3ExprDelete(db, pWhen); if( !pParse->pNewTrigger ){ - sqlite3DeleteTrigger(pTrigger); + sqlite3DeleteTrigger(db, pTrigger); }else{ assert( pParse->pNewTrigger==pTrigger ); } @@ -241,7 +241,7 @@ void sqlite3FinishTrigger( "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrig->name, pTrig->table, z); - sqlite3_free(z); + sqlite3DbFree(db, z); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf( db, "type='trigger' AND name='%q'", pTrig->name), P4_DYNAMIC @@ -268,9 +268,9 @@ void sqlite3FinishTrigger( } triggerfinish_cleanup: - sqlite3DeleteTrigger(pTrig); + sqlite3DeleteTrigger(db, pTrig); assert( !pParse->pNewTrigger ); - sqlite3DeleteTriggerStep(pStepList); + sqlite3DeleteTriggerStep(db, pStepList); } /* @@ -290,22 +290,22 @@ static void sqlitePersistTriggerStep(sqlite3 *db, TriggerStep *p){ } if( p->pSelect ){ Select *pNew = sqlite3SelectDup(db, p->pSelect); - sqlite3SelectDelete(p->pSelect); + sqlite3SelectDelete(db, p->pSelect); p->pSelect = pNew; } if( p->pWhere ){ Expr *pNew = sqlite3ExprDup(db, p->pWhere); - sqlite3ExprDelete(p->pWhere); + sqlite3ExprDelete(db, p->pWhere); p->pWhere = pNew; } if( p->pExprList ){ ExprList *pNew = sqlite3ExprListDup(db, p->pExprList); - sqlite3ExprListDelete(p->pExprList); + sqlite3ExprListDelete(db, p->pExprList); p->pExprList = pNew; } if( p->pIdList ){ IdList *pNew = sqlite3IdListDup(db, p->pIdList); - sqlite3IdListDelete(p->pIdList); + sqlite3IdListDelete(db, p->pIdList); p->pIdList = pNew; } } @@ -320,7 +320,7 @@ static void sqlitePersistTriggerStep(sqlite3 *db, TriggerStep *p){ TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){ TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); if( pTriggerStep==0 ) { - sqlite3SelectDelete(pSelect); + sqlite3SelectDelete(db, pSelect); return 0; } @@ -362,9 +362,9 @@ TriggerStep *sqlite3TriggerInsertStep( pTriggerStep->orconf = orconf; sqlitePersistTriggerStep(db, pTriggerStep); }else{ - sqlite3IdListDelete(pColumn); - sqlite3ExprListDelete(pEList); - sqlite3SelectDelete(pSelect); + sqlite3IdListDelete(db, pColumn); + sqlite3ExprListDelete(db, pEList); + sqlite3SelectDelete(db, pSelect); } return pTriggerStep; @@ -384,8 +384,8 @@ TriggerStep *sqlite3TriggerUpdateStep( ){ TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); if( pTriggerStep==0 ){ - sqlite3ExprListDelete(pEList); - sqlite3ExprDelete(pWhere); + sqlite3ExprListDelete(db, pEList); + sqlite3ExprDelete(db, pWhere); return 0; } @@ -411,7 +411,7 @@ TriggerStep *sqlite3TriggerDeleteStep( ){ TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); if( pTriggerStep==0 ){ - sqlite3ExprDelete(pWhere); + sqlite3ExprDelete(db, pWhere); return 0; } @@ -427,15 +427,15 @@ TriggerStep *sqlite3TriggerDeleteStep( /* ** Recursively delete a Trigger structure */ -void sqlite3DeleteTrigger(Trigger *pTrigger){ +void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){ if( pTrigger==0 ) return; - sqlite3DeleteTriggerStep(pTrigger->step_list); - sqlite3_free(pTrigger->name); - sqlite3_free(pTrigger->table); - sqlite3ExprDelete(pTrigger->pWhen); - sqlite3IdListDelete(pTrigger->pColumns); - if( pTrigger->nameToken.dyn ) sqlite3_free((char*)pTrigger->nameToken.z); - sqlite3_free(pTrigger); + sqlite3DeleteTriggerStep(db, pTrigger->step_list); + sqlite3DbFree(db, pTrigger->name); + sqlite3DbFree(db, pTrigger->table); + sqlite3ExprDelete(db, pTrigger->pWhen); + sqlite3IdListDelete(db, pTrigger->pColumns); + if( pTrigger->nameToken.dyn ) sqlite3DbFree(db, (char*)pTrigger->nameToken.z); + sqlite3DbFree(db, pTrigger); } /* @@ -478,7 +478,7 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ sqlite3DropTriggerPtr(pParse, pTrigger); drop_trigger_cleanup: - sqlite3SrcListDelete(pName); + sqlite3SrcListDelete(db, pName); } /* @@ -570,7 +570,7 @@ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ } assert(cc); } - sqlite3DeleteTrigger(pTrigger); + sqlite3DeleteTrigger(db, pTrigger); db->flags |= SQLITE_InternChanges; } } @@ -681,7 +681,7 @@ static int codeTriggerProgram( sqlite3SelectDestInit(&dest, SRT_Discard, 0); sqlite3SelectResolve(pParse, ss, 0); sqlite3Select(pParse, ss, &dest, 0, 0, 0); - sqlite3SelectDelete(ss); + sqlite3SelectDelete(db, ss); } break; } @@ -831,11 +831,11 @@ int sqlite3CodeRowTrigger( whenExpr = sqlite3ExprDup(db, p->pWhen); if( db->mallocFailed || sqlite3ExprResolveNames(&sNC, whenExpr) ){ pParse->trigStack = trigStackEntry.pNext; - sqlite3ExprDelete(whenExpr); + sqlite3ExprDelete(db, whenExpr); return 1; } sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, SQLITE_JUMPIFNULL); - sqlite3ExprDelete(whenExpr); + sqlite3ExprDelete(db, whenExpr); codeTriggerProgram(pParse, p->step_list, orconf); diff --git a/src/update.c b/src/update.c index 9df83664f9..7647d4a7e2 100644 --- a/src/update.c +++ b/src/update.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.180 2008/07/09 16:51:51 drh Exp $ +** $Id: update.c,v 1.181 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" @@ -570,11 +570,11 @@ void sqlite3Update( update_cleanup: sqlite3AuthContextPop(&sContext); - sqlite3_free(aRegIdx); - sqlite3_free(aXRef); - sqlite3SrcListDelete(pTabList); - sqlite3ExprListDelete(pChanges); - sqlite3ExprDelete(pWhere); + sqlite3DbFree(db, aRegIdx); + sqlite3DbFree(db, aXRef); + sqlite3SrcListDelete(db, pTabList); + sqlite3ExprListDelete(db, pChanges); + sqlite3ExprDelete(db, pWhere); return; } @@ -668,7 +668,7 @@ static void updateVirtualTable( sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); /* Cleanup */ - sqlite3SelectDelete(pSelect); + sqlite3SelectDelete(db, pSelect); } #endif /* SQLITE_OMIT_VIRTUALTABLE */ diff --git a/src/util.c b/src/util.c index 18340837ba..919452c572 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.240 2008/07/24 17:06:48 drh Exp $ +** $Id: util.c,v 1.241 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" #include @@ -98,7 +98,7 @@ void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ va_start(ap, zFormat); z = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); - sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, sqlite3_free); + sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC); }else{ sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC); } @@ -124,10 +124,11 @@ void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ */ void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ va_list ap; + sqlite3 *db = pParse->db; pParse->nErr++; - sqlite3_free(pParse->zErrMsg); + sqlite3DbFree(db, pParse->zErrMsg); va_start(ap, zFormat); - pParse->zErrMsg = sqlite3VMPrintf(pParse->db, zFormat, ap); + pParse->zErrMsg = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); if( pParse->rc==SQLITE_OK ){ pParse->rc = SQLITE_ERROR; @@ -138,7 +139,7 @@ void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ ** Clear the error message in pParse, if any */ void sqlite3ErrorClear(Parse *pParse){ - sqlite3_free(pParse->zErrMsg); + sqlite3DbFree(pParse->db, pParse->zErrMsg); pParse->zErrMsg = 0; pParse->nErr = 0; } diff --git a/src/vdbe.c b/src/vdbe.c index caf6d5c028..cab2cde5ff 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.765 2008/07/26 18:47:27 danielk1977 Exp $ +** $Id: vdbe.c,v 1.766 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" #include @@ -895,7 +895,7 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */ pOut->flags |= MEM_Static; pOut->flags &= ~MEM_Dyn; if( pOp->p4type==P4_DYNAMIC ){ - sqlite3_free(pOp->p4.z); + sqlite3DbFree(db, pOp->p4.z); } pOp->p4type = P4_DYNAMIC; pOp->p4.z = pOut->z; @@ -2605,7 +2605,7 @@ case OP_VerifyCookie: { iMeta = 0; } if( rc==SQLITE_OK && iMeta!=pOp->p2 ){ - sqlite3_free(p->zErrMsg); + sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); /* If the schema-cookie from the database file matches the cookie ** stored with the in-memory representation of the schema, do @@ -3470,7 +3470,7 @@ case OP_Insert: { } if( pC->pseudoTable ){ if( !pC->ephemPseudoTable ){ - sqlite3_free(pC->pData); + sqlite3DbFree(db, pC->pData); } pC->iKey = iKey; pC->nData = pData->n; @@ -4149,7 +4149,7 @@ case OP_ParseSchema: { assert( !db->mallocFailed ); rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); if( rc==SQLITE_ABORT ) rc = initData.rc; - sqlite3_free(zSql); + sqlite3DbFree(db, zSql); db->init.busy = 0; (void)sqlite3SafetyOn(db); if( rc==SQLITE_NOMEM ){ @@ -4241,7 +4241,7 @@ case OP_IntegrityCk: { nRoot = pOp->p2; assert( nRoot>0 ); - aRoot = sqlite3Malloc( sizeof(int)*(nRoot+1) ); + aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) ); if( aRoot==0 ) goto no_mem; assert( pOp->p3>0 && pOp->p3<=p->nMem ); pnErr = &p->aMem[pOp->p3]; @@ -4265,7 +4265,7 @@ case OP_IntegrityCk: { } UPDATE_MAX_BLOBSIZE(pIn1); sqlite3VdbeChangeEncoding(pIn1, encoding); - sqlite3_free(aRoot); + sqlite3DbFree(db, aRoot); break; } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ @@ -4275,6 +4275,7 @@ case OP_IntegrityCk: { ** Write the integer from register P1 into the Fifo. */ case OP_FifoWrite: { /* in1 */ + p->sFifo.db = db; if( sqlite3VdbeFifoPush(&p->sFifo, sqlite3VdbeIntValue(pIn1))==SQLITE_NOMEM ){ goto no_mem; } @@ -4322,7 +4323,7 @@ case OP_ContextPush: { pContext->lastRowid = db->lastRowid; pContext->nChange = p->nChange; pContext->sFifo = p->sFifo; - sqlite3VdbeFifoInit(&p->sFifo); + sqlite3VdbeFifoInit(&p->sFifo, db); break; } @@ -4628,7 +4629,7 @@ case OP_VOpen: { assert(pVtab && pModule); if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; rc = pModule->xOpen(pVtab, &pVtabCursor); - sqlite3_free(p->zErrMsg); + sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = pVtab->zErrMsg; pVtab->zErrMsg = 0; if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; @@ -4860,7 +4861,7 @@ case OP_VRename: { if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; sqlite3VtabLock(pVtab); rc = pVtab->pModule->xRename(pVtab, pName->z); - sqlite3_free(p->zErrMsg); + sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = pVtab->zErrMsg; pVtab->zErrMsg = 0; sqlite3VtabUnlock(db, pVtab); @@ -4915,7 +4916,7 @@ case OP_VUpdate: { if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; sqlite3VtabLock(pVtab); rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid); - sqlite3_free(p->zErrMsg); + sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = pVtab->zErrMsg; pVtab->zErrMsg = 0; sqlite3VtabUnlock(db, pVtab); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 50c34d1b9d..6ce400e926 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -15,7 +15,7 @@ ** 6000 lines long) it was split up into several smaller files and ** this header information was factored out. ** -** $Id: vdbeInt.h,v 1.150 2008/07/26 18:26:10 danielk1977 Exp $ +** $Id: vdbeInt.h,v 1.151 2008/07/28 19:34:54 drh Exp $ */ #ifndef _VDBEINT_H_ #define _VDBEINT_H_ @@ -245,6 +245,7 @@ struct FifoPage { typedef struct Fifo Fifo; struct Fifo { int nEntry; /* Total number of entries */ + sqlite3 *db; /* The associated database connection */ FifoPage *pFirst; /* First page on the list */ FifoPage *pLast; /* Last page on the list */ }; @@ -434,7 +435,7 @@ int sqlite3VdbeMemTranslate(Mem*, u8); void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf); #endif int sqlite3VdbeMemHandleBom(Mem *pMem); -void sqlite3VdbeFifoInit(Fifo*); +void sqlite3VdbeFifoInit(Fifo*, sqlite3*); int sqlite3VdbeFifoPush(Fifo*, i64); int sqlite3VdbeFifoPop(Fifo*, i64*); void sqlite3VdbeFifoClear(Fifo*); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 1539c5bd7c..2dce141325 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -13,7 +13,7 @@ ** This file contains code use to implement APIs that are part of the ** VDBE. ** -** $Id: vdbeapi.c,v 1.135 2008/07/23 21:07:25 drh Exp $ +** $Id: vdbeapi.c,v 1.136 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" @@ -556,7 +556,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){ ** sqlite3_errmsg() and sqlite3_errcode(). */ const char *zErr = (const char *)sqlite3_value_text(db->pErr); - sqlite3_free(v->zErrMsg); + sqlite3DbFree(db, v->zErrMsg); if( !db->mallocFailed ){ v->zErrMsg = sqlite3DbStrDup(db, zErr); } else { diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 9082757030..9ab8ebd172 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -14,7 +14,7 @@ ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. ** -** $Id: vdbeaux.c,v 1.400 2008/07/26 18:26:10 danielk1977 Exp $ +** $Id: vdbeaux.c,v 1.401 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" #include @@ -302,7 +302,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ pOp->p2 = aLabel[-1-pOp->p2]; } } - sqlite3_free(p->aLabel); + sqlite3DbFree(p->db, p->aLabel); p->aLabel = 0; *pMaxFuncArgs = nMaxArgs; @@ -432,16 +432,16 @@ void sqlite3VdbeJumpHere(Vdbe *p, int addr){ ** If the input FuncDef structure is ephemeral, then free it. If ** the FuncDef is not ephermal, then do nothing. */ -static void freeEphemeralFunction(FuncDef *pDef){ +static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){ if( pDef && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){ - sqlite3_free(pDef); + sqlite3DbFree(db, pDef); } } /* ** Delete a P4 value if necessary. */ -static void freeP4(int p4type, void *p4){ +static void freeP4(sqlite3 *db, int p4type, void *p4){ if( p4 ){ switch( p4type ){ case P4_REAL: @@ -451,18 +451,18 @@ static void freeP4(int p4type, void *p4){ case P4_KEYINFO: case P4_INTARRAY: case P4_KEYINFO_HANDOFF: { - sqlite3_free(p4); + sqlite3DbFree(db, p4); break; } case P4_VDBEFUNC: { VdbeFunc *pVdbeFunc = (VdbeFunc *)p4; - freeEphemeralFunction(pVdbeFunc->pFunc); + freeEphemeralFunction(db, pVdbeFunc->pFunc); sqlite3VdbeDeleteAuxData(pVdbeFunc, 0); - sqlite3_free(pVdbeFunc); + sqlite3DbFree(db, pVdbeFunc); break; } case P4_FUNCDEF: { - freeEphemeralFunction((FuncDef*)p4); + freeEphemeralFunction(db, (FuncDef*)p4); break; } case P4_MEM: { @@ -480,8 +480,9 @@ static void freeP4(int p4type, void *p4){ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){ if( p && p->aOp ){ VdbeOp *pOp = &p->aOp[addr]; + sqlite3 *db = p->db; while( N-- ){ - freeP4(pOp->p4type, pOp->p4.p); + freeP4(db, pOp->p4type, pOp->p4.p); memset(pOp, 0, sizeof(pOp[0])); pOp->opcode = OP_Noop; pOp++; @@ -516,11 +517,13 @@ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){ */ void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){ Op *pOp; + sqlite3 *db; assert( p!=0 ); + db = p->db; assert( p->magic==VDBE_MAGIC_INIT ); - if( p->aOp==0 || p->db->mallocFailed ){ + if( p->aOp==0 || db->mallocFailed ){ if (n != P4_KEYINFO) { - freeP4(n, (void*)*(char**)&zP4); + freeP4(db, n, (void*)*(char**)&zP4); } return; } @@ -530,7 +533,7 @@ void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){ if( addr<0 ) return; } pOp = &p->aOp[addr]; - freeP4(pOp->p4type, pOp->p4.p); + freeP4(db, pOp->p4type, pOp->p4.p); pOp->p4.p = 0; if( n==P4_INT32 ){ /* Note: this cast is safe, because the origin data point was an int @@ -588,7 +591,7 @@ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ if( p->nOp ){ char **pz = &p->aOp[p->nOp-1].zComment; va_start(ap, zFormat); - sqlite3_free(*pz); + sqlite3DbFree(p->db, *pz); *pz = sqlite3VMPrintf(p->db, zFormat, ap); va_end(ap); } @@ -601,7 +604,7 @@ void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){ if( p->nOp ){ char **pz = &p->aOp[p->nOp-1].zComment; va_start(ap, zFormat); - sqlite3_free(*pz); + sqlite3DbFree(p->db, *pz); *pz = sqlite3VMPrintf(p->db, zFormat, ap); va_end(ap); } @@ -783,7 +786,7 @@ int sqlite3VdbeReleaseBuffers(Vdbe *p){ Mem *pMem = &p->aMem[ii]; if( pMem->z && pMem->flags&MEM_Dyn ){ assert( !pMem->xDel ); - nFree += sqlite3MallocSize(pMem->z); + nFree += sqlite3DbMallocSize(pMem->db, pMem->z); sqlite3VdbeMemRelease(pMem); } } @@ -1102,11 +1105,8 @@ void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){ } #endif if( !pCx->ephemPseudoTable ){ - sqlite3_free(pCx->pData); + sqlite3DbFree(p->db, pCx->pData); } - /* memset(pCx, 0, sizeof(Cursor)); */ - /* sqlite3_free(pCx->aType); */ - /* sqlite3_free(pCx); */ } /* @@ -1134,6 +1134,7 @@ static void closeAllCursorsExceptActiveVtabs(Vdbe *p){ */ static void Cleanup(Vdbe *p, int freebuffers){ int i; + sqlite3 *db = p->db; closeAllCursorsExceptActiveVtabs(p); for(i=1; i<=p->nMem; i++){ MemSetTypeFlag(&p->aMem[i], MEM_Null); @@ -1144,12 +1145,12 @@ static void Cleanup(Vdbe *p, int freebuffers){ for(i=0; icontextStackTop; i++){ sqlite3VdbeFifoClear(&p->contextStack[i].sFifo); } - sqlite3_free(p->contextStack); + sqlite3DbFree(db, p->contextStack); } p->contextStack = 0; p->contextStackDepth = 0; p->contextStackTop = 0; - sqlite3_free(p->zErrMsg); + sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; p->pResultSet = 0; } @@ -1163,12 +1164,13 @@ static void Cleanup(Vdbe *p, int freebuffers){ void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ Mem *pColName; int n; + sqlite3 *db = p->db; releaseMemArray(p->aColName, p->nResColumn*COLNAME_N, 1); - sqlite3_free(p->aColName); + sqlite3DbFree(db, p->aColName); n = nResColumn*COLNAME_N; p->nResColumn = nResColumn; - p->aColName = pColName = (Mem*)sqlite3DbMallocZero(p->db, sizeof(Mem)*n ); + p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n ); if( p->aColName==0 ) return; while( n-- > 0 ){ pColName->flags = MEM_Null; @@ -1185,7 +1187,7 @@ void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ ** ** If N==P4_STATIC it means that zName is a pointer to a constant static ** string and we can just copy the pointer. If it is P4_DYNAMIC, then -** the string is freed using sqlite3_free() when the vdbe is finished with +** the string is freed using sqlite3DbFree(db, ) when the vdbe is finished with ** it. Otherwise, N bytes of zName are copied. */ int sqlite3VdbeSetColName(Vdbe *p, int idx, int var, const char *zName, int N){ @@ -1305,7 +1307,7 @@ static int vdbeCommit(sqlite3 *db){ /* Select a master journal file name */ do { u32 random; - sqlite3_free(zMaster); + sqlite3DbFree(db, zMaster); sqlite3_randomness(sizeof(random), &random); zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, random&0x7fffffff); if( !zMaster ){ @@ -1321,7 +1323,7 @@ static int vdbeCommit(sqlite3 *db){ ); } if( rc!=SQLITE_OK ){ - sqlite3_free(zMaster); + sqlite3DbFree(db, zMaster); return rc; } @@ -1345,7 +1347,7 @@ static int vdbeCommit(sqlite3 *db){ if( rc!=SQLITE_OK ){ sqlite3OsCloseFree(pMaster); sqlite3OsDelete(pVfs, zMaster, 0); - sqlite3_free(zMaster); + sqlite3DbFree(db, zMaster); return rc; } } @@ -1360,7 +1362,7 @@ static int vdbeCommit(sqlite3 *db){ && (rc=sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))!=SQLITE_OK) ){ sqlite3OsCloseFree(pMaster); sqlite3OsDelete(pVfs, zMaster, 0); - sqlite3_free(zMaster); + sqlite3DbFree(db, zMaster); return rc; } @@ -1382,7 +1384,7 @@ static int vdbeCommit(sqlite3 *db){ } sqlite3OsCloseFree(pMaster); if( rc!=SQLITE_OK ){ - sqlite3_free(zMaster); + sqlite3DbFree(db, zMaster); return rc; } @@ -1391,7 +1393,7 @@ static int vdbeCommit(sqlite3 *db){ ** transaction files are deleted. */ rc = sqlite3OsDelete(pVfs, zMaster, 1); - sqlite3_free(zMaster); + sqlite3DbFree(db, zMaster); zMaster = 0; if( rc ){ return rc; @@ -1633,7 +1635,7 @@ int sqlite3VdbeHalt(Vdbe *p){ rc = xFunc(pBt); if( rc && (p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT) ){ p->rc = rc; - sqlite3_free(p->zErrMsg); + sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; } } @@ -1713,8 +1715,9 @@ int sqlite3VdbeReset(Vdbe *p, int freebuffers){ */ if( p->pc>=0 ){ if( p->zErrMsg ){ - sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,sqlite3_free); + sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,SQLITE_TRANSIENT); db->errCode = p->rc; + sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; }else if( p->rc ){ sqlite3Error(db, p->rc, 0); @@ -1727,7 +1730,8 @@ int sqlite3VdbeReset(Vdbe *p, int freebuffers){ ** called), set the database error in this case as well. */ sqlite3Error(db, p->rc, 0); - sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, sqlite3_free); + sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); + sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; } @@ -1805,13 +1809,15 @@ void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){ */ void sqlite3VdbeDelete(Vdbe *p){ int i; + sqlite3 *db; + if( p==0 ) return; - /* Cleanup(p, 1); */ + db = p->db; if( p->pPrev ){ p->pPrev->pNext = p->pNext; }else{ - assert( p->db->pVdbe==p ); - p->db->pVdbe = p->pNext; + assert( db->pVdbe==p ); + db->pVdbe = p->pNext; } if( p->pNext ){ p->pNext->pPrev = p->pPrev; @@ -1819,23 +1825,23 @@ void sqlite3VdbeDelete(Vdbe *p){ if( p->aOp ){ Op *pOp = p->aOp; for(i=0; inOp; i++, pOp++){ - freeP4(pOp->p4type, pOp->p4.p); + freeP4(db, pOp->p4type, pOp->p4.p); #ifdef SQLITE_DEBUG - sqlite3_free(pOp->zComment); + sqlite3DbFree(db, pOp->zComment); #endif } - sqlite3_free(p->aOp); + sqlite3DbFree(db, p->aOp); } releaseMemArray(p->aVar, p->nVar, 1); - sqlite3_free(p->aLabel); + sqlite3DbFree(db, p->aLabel); if( p->aMem ){ - sqlite3_free(&p->aMem[1]); + sqlite3DbFree(db, &p->aMem[1]); } releaseMemArray(p->aColName, p->nResColumn*COLNAME_N, 1); - sqlite3_free(p->aColName); - sqlite3_free(p->zSql); + sqlite3DbFree(db, p->aColName); + sqlite3DbFree(db, p->zSql); p->magic = VDBE_MAGIC_DEAD; - sqlite3_free(p); + sqlite3DbFree(db, p); } /* @@ -2259,7 +2265,7 @@ void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){ } } if( p->needFree ){ - sqlite3_free(p); + sqlite3DbFree(p->pKeyInfo->db, p); } } } diff --git a/src/vdbeblob.c b/src/vdbeblob.c index e2cfb503dd..746bfe4c37 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -12,7 +12,7 @@ ** ** This file contains code used to implement incremental BLOB I/O. ** -** $Id: vdbeblob.c,v 1.24 2008/07/10 00:32:42 drh Exp $ +** $Id: vdbeblob.c,v 1.25 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" @@ -117,7 +117,7 @@ int sqlite3_blob_open( if( sParse.zErrMsg ){ sqlite3_snprintf(sizeof(zErr), zErr, "%s", sParse.zErrMsg); } - sqlite3_free(sParse.zErrMsg); + sqlite3DbFree(db, sParse.zErrMsg); rc = SQLITE_ERROR; (void)sqlite3SafetyOff(db); sqlite3BtreeLeaveAll(db); @@ -229,7 +229,7 @@ int sqlite3_blob_open( } pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob)); if( db->mallocFailed ){ - sqlite3_free(pBlob); + sqlite3DbFree(db, pBlob); goto blob_open_out; } pBlob->flags = flags; @@ -268,7 +268,7 @@ int sqlite3_blob_close(sqlite3_blob *pBlob){ int rc; rc = sqlite3_finalize(p->pStmt); - sqlite3_free(p); + sqlite3DbFree(p->db, p); return rc; } diff --git a/src/vdbefifo.c b/src/vdbefifo.c index 956321c059..a5e270d8ae 100644 --- a/src/vdbefifo.c +++ b/src/vdbefifo.c @@ -12,7 +12,7 @@ ** This file implements a FIFO queue of rowids used for processing ** UPDATE and DELETE statements. ** -** $Id: vdbefifo.c,v 1.7 2008/06/15 02:51:48 drh Exp $ +** $Id: vdbefifo.c,v 1.8 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" @@ -33,12 +33,12 @@ ** Allocate a new FifoPage and return a pointer to it. Return NULL if ** we run out of memory. Leave space on the page for nEntry entries. */ -static FifoPage *allocateFifoPage(int nEntry){ +static FifoPage *allocateFifoPage(sqlite3 *db, int nEntry){ FifoPage *pPage; if( nEntry>FIFOSIZE_MAX ){ nEntry = FIFOSIZE_MAX; } - pPage = sqlite3Malloc( sizeof(FifoPage) + sizeof(i64)*(nEntry-1) ); + pPage = sqlite3DbMallocRaw(db, sizeof(FifoPage) + sizeof(i64)*(nEntry-1) ); if( pPage ){ pPage->nSlot = nEntry; pPage->iWrite = 0; @@ -51,8 +51,9 @@ static FifoPage *allocateFifoPage(int nEntry){ /* ** Initialize a Fifo structure. */ -void sqlite3VdbeFifoInit(Fifo *pFifo){ +void sqlite3VdbeFifoInit(Fifo *pFifo, sqlite3 *db){ memset(pFifo, 0, sizeof(*pFifo)); + pFifo->db = db; } /* @@ -64,12 +65,13 @@ int sqlite3VdbeFifoPush(Fifo *pFifo, i64 val){ FifoPage *pPage; pPage = pFifo->pLast; if( pPage==0 ){ - pPage = pFifo->pLast = pFifo->pFirst = allocateFifoPage(FIFOSIZE_FIRST); + pPage = pFifo->pLast = pFifo->pFirst = + allocateFifoPage(pFifo->db, FIFOSIZE_FIRST); if( pPage==0 ){ return SQLITE_NOMEM; } }else if( pPage->iWrite>=pPage->nSlot ){ - pPage->pNext = allocateFifoPage(pFifo->nEntry); + pPage->pNext = allocateFifoPage(pFifo->db, pFifo->nEntry); if( pPage->pNext==0 ){ return SQLITE_NOMEM; } @@ -101,7 +103,7 @@ int sqlite3VdbeFifoPop(Fifo *pFifo, i64 *pVal){ pFifo->nEntry--; if( pPage->iRead>=pPage->iWrite ){ pFifo->pFirst = pPage->pNext; - sqlite3_free(pPage); + sqlite3DbFree(pFifo->db, pPage); if( pFifo->nEntry==0 ){ assert( pFifo->pLast==pPage ); pFifo->pLast = 0; @@ -122,7 +124,7 @@ void sqlite3VdbeFifoClear(Fifo *pFifo){ FifoPage *pPage, *pNextPage; for(pPage=pFifo->pFirst; pPage; pPage=pNextPage){ pNextPage = pPage->pNext; - sqlite3_free(pPage); + sqlite3DbFree(pFifo->db, pPage); } - sqlite3VdbeFifoInit(pFifo); + sqlite3VdbeFifoInit(pFifo, pFifo->db); } diff --git a/src/vdbemem.c b/src/vdbemem.c index a8a2129f97..184195c3ba 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -15,7 +15,7 @@ ** only within the VDBE. Interface routines refer to a Mem using the ** name sqlite_value ** -** $Id: vdbemem.c,v 1.118 2008/07/09 16:51:51 drh Exp $ +** $Id: vdbemem.c,v 1.119 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" #include @@ -83,7 +83,7 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){ ); if( n<32 ) n = 32; - if( sqlite3MallocSize(pMem->zMalloc)db, pMem->zMalloc)z==pMem->zMalloc ){ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); if( !pMem->z ){ @@ -91,7 +91,7 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){ } preserve = 0; }else{ - sqlite3_free(pMem->zMalloc); + sqlite3DbFree(pMem->db, pMem->zMalloc); pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); } } @@ -255,7 +255,7 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ ctx.isError = 0; pFunc->xFinalize(&ctx); assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel ); - sqlite3_free(pMem->zMalloc); + sqlite3DbFree(pMem->db, pMem->zMalloc); *pMem = ctx.s; rc = (ctx.isError?SQLITE_ERROR:SQLITE_OK); } @@ -286,7 +286,7 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){ */ void sqlite3VdbeMemRelease(Mem *p){ sqlite3VdbeMemReleaseExternal(p); - sqlite3_free(p->zMalloc); + sqlite3DbFree(p->db, p->zMalloc); p->z = 0; p->zMalloc = 0; p->xDel = 0; @@ -631,11 +631,21 @@ int sqlite3VdbeMemSetStr( return SQLITE_NOMEM; } memcpy(pMem->z, z, nAlloc); + }else if( xDel==SQLITE_DYNAMIC ){ + sqlite3VdbeMemRelease(pMem); + pMem->zMalloc = pMem->z = (char *)z; + pMem->xDel = 0; }else{ sqlite3VdbeMemRelease(pMem); pMem->z = (char *)z; - pMem->xDel = xDel; - flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn); + if( xDel==SQLITE_DYNAMIC ){ + pMem->zMalloc = pMem->z; + pMem->xDel = 0; + flags |= MEM_Dyn; + }else{ + pMem->xDel = xDel; + flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn); + } } pMem->n = nByte; @@ -966,11 +976,11 @@ int sqlite3ValueFromExpr( op = pExpr->op; if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ - zVal = sqlite3StrNDup((char*)pExpr->token.z, pExpr->token.n); + zVal = sqlite3DbStrNDup(db, (char*)pExpr->token.z, pExpr->token.n); pVal = sqlite3ValueNew(db); if( !zVal || !pVal ) goto no_mem; sqlite3Dequote(zVal); - sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, sqlite3_free); + sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){ sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, enc); }else{ @@ -993,7 +1003,7 @@ int sqlite3ValueFromExpr( nVal = pExpr->token.n - 3; zVal = (char*)pExpr->token.z + 2; sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, - 0, sqlite3_free); + 0, SQLITE_DYNAMIC); } #endif @@ -1002,7 +1012,7 @@ int sqlite3ValueFromExpr( no_mem: db->mallocFailed = 1; - sqlite3_free(zVal); + sqlite3DbFree(db, zVal); sqlite3ValueFree(pVal); *ppVal = 0; return SQLITE_NOMEM; @@ -1027,7 +1037,7 @@ void sqlite3ValueSetStr( void sqlite3ValueFree(sqlite3_value *v){ if( !v ) return; sqlite3VdbeMemRelease((Mem *)v); - sqlite3_free(v); + sqlite3DbFree(((Mem*)v)->db, v); } /* diff --git a/src/vtab.c b/src/vtab.c index 2c71215dec..c9ff4e0bdd 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to help implement virtual tables. ** -** $Id: vtab.c,v 1.71 2008/07/23 18:17:32 drh Exp $ +** $Id: vtab.c,v 1.72 2008/07/28 19:34:54 drh Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE #include "sqliteInt.h" @@ -41,7 +41,7 @@ static int createModule( if( pDel && pDel->xDestroy ){ pDel->xDestroy(pDel->pAux); } - sqlite3_free(pDel); + sqlite3DbFree(db, pDel); if( pDel==pMod ){ db->mallocFailed = 1; } @@ -116,17 +116,18 @@ void sqlite3VtabUnlock(sqlite3 *db, sqlite3_vtab *pVtab){ */ void sqlite3VtabClear(Table *p){ sqlite3_vtab *pVtab = p->pVtab; + sqlite3 *db = p->db; if( pVtab ){ assert( p->pMod && p->pMod->pModule ); - sqlite3VtabUnlock(p->pSchema->db, pVtab); + sqlite3VtabUnlock(db, pVtab); p->pVtab = 0; } if( p->azModuleArg ){ int i; for(i=0; inModuleArg; i++){ - sqlite3_free(p->azModuleArg[i]); + sqlite3DbFree(db, p->azModuleArg[i]); } - sqlite3_free(p->azModuleArg); + sqlite3DbFree(db, p->azModuleArg); } } @@ -144,10 +145,10 @@ static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){ if( azModuleArg==0 ){ int j; for(j=0; jazModuleArg[j]); + sqlite3DbFree(db, pTable->azModuleArg[j]); } - sqlite3_free(zArg); - sqlite3_free(pTable->azModuleArg); + sqlite3DbFree(db, zArg); + sqlite3DbFree(db, pTable->azModuleArg); pTable->nModuleArg = 0; }else{ azModuleArg[i] = zArg; @@ -278,7 +279,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ zStmt, pParse->regRowid ); - sqlite3_free(zStmt); + sqlite3DbFree(db, zStmt); v = sqlite3GetVdbe(pParse); sqlite3ChangeCookie(pParse, iDb); @@ -377,7 +378,7 @@ static int vtabCallConstructor( *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); }else { *pzErr = sqlite3MPrintf(db, "%s", zErr); - sqlite3_free(zErr); + sqlite3DbFree(db, zErr); } }else if( db->pVTab ){ const char *zFormat = "vtable constructor did not declare schema: %s"; @@ -388,7 +389,7 @@ static int vtabCallConstructor( rc = rc2; } db->pVTab = 0; - sqlite3_free(zModuleName); + sqlite3DbFree(db, zModuleName); /* If everything went according to plan, loop through the columns ** of the table to see if any of them contain the token "hidden". @@ -457,7 +458,7 @@ int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){ if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "%s", zErr); } - sqlite3_free(zErr); + sqlite3DbFree(db, zErr); } return rc; @@ -493,7 +494,7 @@ static int addToVTrans(sqlite3 *db, sqlite3_vtab *pVtab){ ** ** If an error occurs, *pzErr is set to point an an English language ** description of the error and an SQLITE_XXX error code is returned. -** In this case the caller must call sqlite3_free() on *pzErr. +** In this case the caller must call sqlite3DbFree(db, ) on *pzErr. */ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ int rc = SQLITE_OK; @@ -562,7 +563,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ db->pVTab = 0; } else { sqlite3Error(db, SQLITE_ERROR, zErr); - sqlite3_free(zErr); + sqlite3DbFree(db, zErr); rc = SQLITE_ERROR; } sParse.declareVtab = 0; @@ -632,7 +633,7 @@ static void callFinaliser(sqlite3 *db, int offset){ if( x ) x(pVtab); sqlite3VtabUnlock(db, pVtab); } - sqlite3_free(db->aVTrans); + sqlite3DbFree(db, db->aVTrans); db->nVTrans = 0; db->aVTrans = 0; } @@ -787,7 +788,7 @@ FuncDef *sqlite3VtabOverloadFunction( *z = sqlite3UpperToLower[*z]; } rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg); - sqlite3_free(zLowerName); + sqlite3DbFree(db, zLowerName); sqlite3VtabTransferError(db, rc, pVtab); } if( rc==0 ){ @@ -835,7 +836,7 @@ void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ void sqlite3VtabTransferError(sqlite3 *db, int rc, sqlite3_vtab *pVtab){ if( pVtab->zErrMsg ){ sqlite3Error(db, rc, "%s", pVtab->zErrMsg); - sqlite3_free(pVtab->zErrMsg); + sqlite3DbFree(db, pVtab->zErrMsg); pVtab->zErrMsg = 0; } } diff --git a/src/where.c b/src/where.c index 5971028b58..dac5161b83 100644 --- a/src/where.c +++ b/src/where.c @@ -16,7 +16,7 @@ ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.317 2008/07/12 14:52:20 drh Exp $ +** $Id: where.c,v 1.318 2008/07/28 19:34:54 drh Exp $ */ #include "sqliteInt.h" @@ -92,7 +92,7 @@ struct WhereTerm { /* ** Allowed values of WhereTerm.flags */ -#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(pExpr) */ +#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(db, pExpr) */ #define TERM_VIRTUAL 0x02 /* Added by the optimizer. Do not code */ #define TERM_CODED 0x04 /* This term is already coded */ #define TERM_COPIED 0x08 /* Has a child */ @@ -203,13 +203,14 @@ static void whereClauseInit( static void whereClauseClear(WhereClause *pWC){ int i; WhereTerm *a; + sqlite3 *db = pWC->pParse->db; for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){ if( a->flags & TERM_DYNAMIC ){ - sqlite3ExprDelete(a->pExpr); + sqlite3ExprDelete(db, a->pExpr); } } if( pWC->a!=pWC->aStatic ){ - sqlite3_free(pWC->a); + sqlite3DbFree(db, pWC->a); } } @@ -230,18 +231,18 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, int flags){ int idx; if( pWC->nTerm>=pWC->nSlot ){ WhereTerm *pOld = pWC->a; - pWC->a = sqlite3Malloc( sizeof(pWC->a[0])*pWC->nSlot*2 ); + sqlite3 *db = pWC->pParse->db; + pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); if( pWC->a==0 ){ - pWC->pParse->db->mallocFailed = 1; if( flags & TERM_DYNAMIC ){ - sqlite3ExprDelete(p); + sqlite3ExprDelete(db, p); } pWC->a = pOld; return 0; } memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); if( pOld!=pWC->aStatic ){ - sqlite3_free(pOld); + sqlite3DbFree(db, pOld); } pWC->nSlot *= 2; } @@ -773,7 +774,7 @@ static void exprAnalyze( int idxNew; pDup = sqlite3ExprDup(db, pExpr); if( db->mallocFailed ){ - sqlite3ExprDelete(pDup); + sqlite3ExprDelete(db, pDup); return; } idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC); @@ -889,7 +890,7 @@ static void exprAnalyze( pWC->a[idxNew].iParent = idxTerm; pTerm->nChild = 1; }else{ - sqlite3ExprListDelete(pList); + sqlite3ExprListDelete(db, pList); } } or_not_possible: @@ -1908,14 +1909,15 @@ static int nQPlan = 0; /* Next free slow in _query_plan[] */ static void whereInfoFree(WhereInfo *pWInfo){ if( pWInfo ){ int i; + sqlite3 *db = pWInfo->pParse->db; for(i=0; inLevel; i++){ sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo; if( pInfo ){ assert( pInfo->needToFreeIdxStr==0 ); - sqlite3_free(pInfo); + sqlite3DbFree(db, pInfo); } } - sqlite3_free(pWInfo); + sqlite3DbFree(db, pWInfo); } } @@ -2248,22 +2250,22 @@ WhereInfo *sqlite3WhereBegin( struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom]; zMsg = sqlite3MPrintf(db, "TABLE %s", pItem->zName); if( pItem->zAlias ){ - zMsg = sqlite3MPrintf(db, "%z AS %s", zMsg, pItem->zAlias); + zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias); } if( (pIx = pLevel->pIdx)!=0 ){ - zMsg = sqlite3MPrintf(db, "%z WITH INDEX %s", zMsg, pIx->zName); + zMsg = sqlite3MAppendf(db, zMsg, "%s WITH INDEX %s", zMsg, pIx->zName); }else if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){ - zMsg = sqlite3MPrintf(db, "%z USING PRIMARY KEY", zMsg); + zMsg = sqlite3MAppendf(db, zMsg, "%s USING PRIMARY KEY", zMsg); } #ifndef SQLITE_OMIT_VIRTUALTABLE else if( pLevel->pBestIdx ){ sqlite3_index_info *pBestIdx = pLevel->pBestIdx; - zMsg = sqlite3MPrintf(db, "%z VIRTUAL TABLE INDEX %d:%s", zMsg, + zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg, pBestIdx->idxNum, pBestIdx->idxStr); } #endif if( pLevel->flags & WHERE_ORDERBY ){ - zMsg = sqlite3MPrintf(db, "%z ORDER BY", zMsg); + zMsg = sqlite3MAppendf(db, zMsg, "%s ORDER BY", zMsg); } sqlite3VdbeAddOp4(v, OP_Explain, i, pLevel->iFrom, 0, zMsg, P4_DYNAMIC); } @@ -2779,14 +2781,16 @@ whereBeginNoMem: ** sqlite3WhereBegin() for additional information. */ void sqlite3WhereEnd(WhereInfo *pWInfo){ - Vdbe *v = pWInfo->pParse->pVdbe; + Parse *pParse = pWInfo->pParse; + Vdbe *v = pParse->pVdbe; int i; WhereLevel *pLevel; SrcList *pTabList = pWInfo->pTabList; + sqlite3 *db = pParse->db; /* Generate loop termination code. */ - sqlite3ExprClearColumnCache(pWInfo->pParse, -1); + sqlite3ExprClearColumnCache(pParse, -1); for(i=pTabList->nSrc-1; i>=0; i--){ pLevel = &pWInfo->a[i]; sqlite3VdbeResolveLabel(v, pLevel->cont); @@ -2802,7 +2806,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ sqlite3VdbeAddOp2(v, OP_Next, pIn->iCur, pIn->topAddr); sqlite3VdbeJumpHere(v, pIn->topAddr-1); } - sqlite3_free(pLevel->aInLoop); + sqlite3DbFree(db, pLevel->aInLoop); } sqlite3VdbeResolveLabel(v, pLevel->brk); if( pLevel->iLeftJoin ){ diff --git a/test/memsubsys1.test b/test/memsubsys1.test index 7061798c95..0c0b12b7a6 100644 --- a/test/memsubsys1.test +++ b/test/memsubsys1.test @@ -11,7 +11,7 @@ # # This file contains tests of the memory allocation subsystem # -# $Id: memsubsys1.test,v 1.5 2008/07/25 13:39:08 drh Exp $ +# $Id: memsubsys1.test,v 1.6 2008/07/28 19:34:54 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -26,6 +26,7 @@ proc build_test_db {testname pragmas} { catch {db close} file delete -force test.db test.db-journal sqlite3 db test.db + sqlite3_db_config_lookaside db 0 0 db eval $pragmas db eval { CREATE TABLE t1(x, y); @@ -49,6 +50,7 @@ proc build_test_db {testname pragmas} { # db close sqlite3_shutdown +sqlite3_config_lookaside 0 0 sqlite3_initialize build_test_db memsubsys1-1 {PRAGMA page_size=1024} do_test memsubsys1-1.3 { @@ -224,6 +226,7 @@ db close sqlite3_shutdown sqlite3_config_pagecache 0 0 sqlite3_config_scratch 0 0 +sqlite3_config_lookaside 100 500 sqlite3_initialize autoinstall_test_functions finish_test diff --git a/test/speed1.test b/test/speed1.test index dcee0733a7..ba0d8c1547 100644 --- a/test/speed1.test +++ b/test/speed1.test @@ -11,11 +11,12 @@ # This file implements regression tests for SQLite library. The # focus of this script is measuring executing speed. # -# $Id: speed1.test,v 1.6 2008/07/24 23:34:07 drh Exp $ +# $Id: speed1.test,v 1.7 2008/07/28 19:34:54 drh Exp $ # sqlite3_shutdown sqlite3_config_scratch 29000 1 +sqlite3_config_lookaside 1000 300 set testdir [file dirname $argv0] source $testdir/tester.tcl speed_trial_init speed1 diff --git a/tool/lemon.c b/tool/lemon.c index 94ca549803..155fdbc018 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -3147,7 +3147,7 @@ int *lineno; }else if( sp->destructor ){ cp = sp->destructor; fprintf(out,"{\n"); (*lineno)++; - tplt_linedir(out,sp->destLineno,lemp->outname); (*lineno)++; + tplt_linedir(out,sp->destLineno,lemp->filename); (*lineno)++; }else if( lemp->vardest ){ cp = lemp->vardest; if( cp==0 ) return; diff --git a/tool/lempar.c b/tool/lempar.c index 061331f678..f5fafd4c28 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -273,7 +273,12 @@ void *ParseAlloc(void *(*mallocProc)(size_t)){ ** "yymajor" is the symbol code, and "yypminor" is a pointer to ** the value. */ -static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ +static void yy_destructor( + yyParser *yypParser, /* The parser */ + YYCODETYPE yymajor, /* Type code for object to destroy */ + YYMINORTYPE *yypminor /* The object to be destroyed */ +){ + ParseARG_FETCH; switch( yymajor ){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen @@ -311,7 +316,7 @@ static int yy_pop_parser_stack(yyParser *pParser){ } #endif yymajor = yytos->major; - yy_destructor( yymajor, &yytos->minor); + yy_destructor(pParser, yymajor, &yytos->minor); pParser->yyidx--; return yymajor; } @@ -758,7 +763,7 @@ void Parse( yyTracePrompt,yyTokenName[yymajor]); } #endif - yy_destructor(yymajor,&yyminorunion); + yy_destructor(yypParser, yymajor,&yyminorunion); yymajor = YYNOCODE; }else{ while( @@ -771,7 +776,7 @@ void Parse( yy_pop_parser_stack(yypParser); } if( yypParser->yyidx < 0 || yymajor==0 ){ - yy_destructor(yymajor,&yyminorunion); + yy_destructor(yypParser,yymajor,&yyminorunion); yy_parse_failed(yypParser); yymajor = YYNOCODE; }else if( yymx!=YYERRORSYMBOL ){ @@ -796,7 +801,7 @@ void Parse( yy_syntax_error(yypParser,yymajor,yyminorunion); } yypParser->yyerrcnt = 3; - yy_destructor(yymajor,&yyminorunion); + yy_destructor(yypParser,yymajor,&yyminorunion); if( yyendofinput ){ yy_parse_failed(yypParser); }