Where possible, avoid freeing buffers allocated for vdbe memory cells in case they can be reused. (CVS 4783)

FossilOrigin-Name: 990237e27e417aff3dbf05784b716c21f3761a3a
This commit is contained in:
danielk1977 2008-02-13 18:25:27 +00:00
parent 0f35a6b529
commit a7a8e14bf2
25 changed files with 548 additions and 441 deletions

View File

@ -1,5 +1,5 @@
C When\smaterializing\sa\sview\sfor\san\sUPDATE\sor\sDELETE\smake\suse\sof\sthe\sWHERE\nclause\sto\slimit\sthe\snumber\sof\srows\smaterialized.\s\sTicket\s#2938.\s(CVS\s4782) C Where\spossible,\savoid\sfreeing\sbuffers\sallocated\sfor\svdbe\smemory\scells\sin\scase\sthey\scan\sbe\sreused.\s(CVS\s4783)
D 2008-02-12T16:52:14 D 2008-02-13T18:25:27
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in bc2b5df3e3d0d4b801b824b7ef6dec43812b049b F Makefile.in bc2b5df3e3d0d4b801b824b7ef6dec43812b049b
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -80,7 +80,7 @@ F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc
F src/alter.c b494a50f239a760565ce6220ee316e96956ec054 F src/alter.c b494a50f239a760565ce6220ee316e96956ec054
F src/analyze.c a78ac494668581fe7f54ee63700815bb0ea34261 F src/analyze.c a78ac494668581fe7f54ee63700815bb0ea34261
F src/attach.c 90665c7ef5145e066570f66d7f0f15cdd0a4d14b F src/attach.c e13d62597e8725075b27186817f7e745122af24e
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
F src/btmutex.c 483ced3c52205b04b97df69161fadbf87f4f1ea2 F src/btmutex.c 483ced3c52205b04b97df69161fadbf87f4f1ea2
F src/btree.c 29ea577155f39be65bdec1c7782301ff2ee9eb3f F src/btree.c 29ea577155f39be65bdec1c7782301ff2ee9eb3f
@ -97,24 +97,24 @@ F src/fault.c 049b88b8ba0a1db3240aeaf9695cd08b9a3ba9e1
F src/func.c 8e3d0c59961dc403716767308ee764504179054b F src/func.c 8e3d0c59961dc403716767308ee764504179054b
F src/hash.c 2dc6afe7478a0b739499af360c8863c900ea11a8 F src/hash.c 2dc6afe7478a0b739499af360c8863c900ea11a8
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
F src/insert.c d422fda2d1f02219871cb7e3e4b49c680632450e F src/insert.c b313f5ecadf82dda15b1aa6780b0310eceb9e776
F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66 F src/legacy.c cb1939fdeb91ea88fb44fbd2768a10e14bc44650
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
F src/loadext.c d17a0f760d6866aacf5262f97d8efaaad379cdd7 F src/loadext.c d17a0f760d6866aacf5262f97d8efaaad379cdd7
F src/main.c b4014b71979a58d6aa79549fdf87175ab7bdf1cc F src/main.c b4014b71979a58d6aa79549fdf87175ab7bdf1cc
F src/malloc.c 60e392a4c12c839517f9b0db7b995f825444fb35 F src/malloc.c 60e392a4c12c839517f9b0db7b995f825444fb35
F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
F src/mem1.c 6d1a11864963d249c67e72ad5f6533b040333880 F src/mem1.c b15e107d51bdd4bcf410c18798ee48bee4768d4e
F src/mem2.c 607af52ad7593f34934e7e4fa53a364556853d30 F src/mem2.c ed0cb11ae43a3cc92bfb07172c2801956e94eaba
F src/mem3.c 9d80034bb004c1bddc28d6befe1ddb044d18deab F src/mem3.c cf1bf5b2f9d4d76e465c84c0607f6882d3b1b522
F src/mem4.c 36ecd536a8b7acfe4cbf011353dae6ea68121e40 F src/mem4.c 36ecd536a8b7acfe4cbf011353dae6ea68121e40
F src/mutex.c 3259f62c2429967aee6dc112117a6d2f499ef061 F src/mutex.c 3259f62c2429967aee6dc112117a6d2f499ef061
F src/mutex.h 079fa6fe9da18ceb89e79012c010594c6672addb F src/mutex.h 079fa6fe9da18ceb89e79012c010594c6672addb
F src/mutex_os2.c 19ab15764736f13b94b4f70e53f77547cbddd47a F src/mutex_os2.c 19ab15764736f13b94b4f70e53f77547cbddd47a
F src/mutex_unix.c a6e111947a3cdaa2cda394ed060d7f496fcb4af8 F src/mutex_unix.c a6e111947a3cdaa2cda394ed060d7f496fcb4af8
F src/mutex_w32.c 6e197765f283815496193e78e9548b5d0e53b68e F src/mutex_w32.c 6e197765f283815496193e78e9548b5d0e53b68e
F src/os.c 50c0c1706c35f872db312815aaecc4b5ebcd6a4c F src/os.c 2f2753b8d33f79d169c43d6bb0b25b3c58fd33de
F src/os.h d04706d54a072c7a30ab9e346ad916ef28c842d5 F src/os.h d04706d54a072c7a30ab9e346ad916ef28c842d5
F src/os_common.h 98862f120ca6bf7a48ce8b16f158b77d00bc9d2f F src/os_common.h 98862f120ca6bf7a48ce8b16f158b77d00bc9d2f
F src/os_os2.c bf1cd3d4f42c1b1ab059c12732cd9f7be4e718a6 F src/os_os2.c bf1cd3d4f42c1b1ab059c12732cd9f7be4e718a6
@ -128,27 +128,27 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c 2ed81808091ce42ceb1cf209e4ce87922a0065c8 F src/pager.c 2ed81808091ce42ceb1cf209e4ce87922a0065c8
F src/pager.h 8174615ffd14ccc2cad2b081b919a398fa95e3f9 F src/pager.h 8174615ffd14ccc2cad2b081b919a398fa95e3f9
F src/parse.y 00f2698c8ae84f315be5e3f10b63c94f531fdd6d F src/parse.y 00f2698c8ae84f315be5e3f10b63c94f531fdd6d
F src/pragma.c 2bb8d6882b9a330e041acd05fb6aff5a01bf0a08 F src/pragma.c e3f39f8576234887ecd0c1de43dc51af5855930c
F src/prepare.c 1b0601ca3f97a9d253cc08697484e3045a1678e9 F src/prepare.c 1b0601ca3f97a9d253cc08697484e3045a1678e9
F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
F src/random.c 02ef38b469237482f1ea14a78b2087cfbaec48bd F src/random.c 02ef38b469237482f1ea14a78b2087cfbaec48bd
F src/select.c 394aa3542e8df599dcca77b0e75f7875760a13ad F src/select.c 1d780691071af7d58b83a6b38517c2687dd83c5b
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c ca06cb687c40a8bff6307b5fad41a0e86a0f8558 F src/shell.c ca06cb687c40a8bff6307b5fad41a0e86a0f8558
F src/sqlite.h.in 690736613958e0f462e08ae2a9136fa335214edc F src/sqlite.h.in 690736613958e0f462e08ae2a9136fa335214edc
F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
F src/sqliteInt.h e4ca11fff0cdac38551b75a2a278edb8ad9e1f00 F src/sqliteInt.h 822045362bdddd303a0b17aa09679ba735ffbaa1
F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
F src/table.c 46ccf9b7892a86f57420ae7bac69ecd5e72d26b5 F src/table.c 46ccf9b7892a86f57420ae7bac69ecd5e72d26b5
F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf F src/tclsqlite.c 0d4483e37c6a1e87f80565e50d977df6dd2bf732
F src/test1.c 5363a117741f26e84b85e30757f0f4414331c46f F src/test1.c 28b135491b436b1df6390a8b53834da2f94efca4
F src/test2.c 77b34303883b9d722c65a6879bb0163a400e3789 F src/test2.c 77b34303883b9d722c65a6879bb0163a400e3789
F src/test3.c 4557ee13c6e5921eb28979ff77cdbd913bfde6be F src/test3.c 4557ee13c6e5921eb28979ff77cdbd913bfde6be
F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071 F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4 F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
F src/test6.c f8b34a6ff04937092327798ddf0ab46863535bc5 F src/test6.c f8b34a6ff04937092327798ddf0ab46863535bc5
F src/test7.c acec2256c7c2d279db5a8b5fa1a2a68fcc942c67 F src/test7.c acec2256c7c2d279db5a8b5fa1a2a68fcc942c67
F src/test8.c cab3f576353dfef4877c7cc3b0d0e48acc65c37c F src/test8.c 25e127f0e21f59da24fa33cdbc645851cfb933f1
F src/test9.c 4615ef08750245a2d96aaa7cbe2fb4aff2b57acc F src/test9.c 4615ef08750245a2d96aaa7cbe2fb4aff2b57acc
F src/test_async.c 5f21392d66869a4c87dc9153e40d0dc0e085261f F src/test_async.c 5f21392d66869a4c87dc9153e40d0dc0e085261f
F src/test_autoext.c 855157d97aa28cf84233847548bfacda21807436 F src/test_autoext.c 855157d97aa28cf84233847548bfacda21807436
@ -157,7 +157,7 @@ F src/test_config.c e7db7a46833d0df98ae6c9a11f70dada1bcca249
F src/test_devsym.c fd8884c2269fb7e0db2c52d21ec59d31a33790ba F src/test_devsym.c fd8884c2269fb7e0db2c52d21ec59d31a33790ba
F src/test_hexio.c 1a1cd8324d57585ea86b922f609fa1fbaaf9662d F src/test_hexio.c 1a1cd8324d57585ea86b922f609fa1fbaaf9662d
F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8 F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
F src/test_malloc.c 0bc9d27c09efe0be63d0de5fb6e38a4253cd5551 F src/test_malloc.c f57e6327a9c32dc71fb2c15941f64d4e91461d3b
F src/test_md5.c c107c96637123239c3518b5fbe97a79130f4d32e F src/test_md5.c c107c96637123239c3518b5fbe97a79130f4d32e
F src/test_onefile.c 54282b6796d55d7acc489be83b89b8715e7d3756 F src/test_onefile.c 54282b6796d55d7acc489be83b89b8715e7d3756
F src/test_schema.c 12c9de7661d6294eec2d57afbb52e2af1128084f F src/test_schema.c 12c9de7661d6294eec2d57afbb52e2af1128084f
@ -167,17 +167,17 @@ F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
F src/tokenize.c c4b79fd48ddb709b2b8522b7d93a5a3d98168ca4 F src/tokenize.c c4b79fd48ddb709b2b8522b7d93a5a3d98168ca4
F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3 F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3
F src/update.c 9b3be169cd2a0b065717164aa0f90aa48f34aed1 F src/update.c 9b3be169cd2a0b065717164aa0f90aa48f34aed1
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736 F src/utf.c 32b00d6e19010025e58f2ecb2f921d5e126771b4
F src/util.c c56e41ed4769c1f2b8af9ffde4757a7b4fb08ed1 F src/util.c c56e41ed4769c1f2b8af9ffde4757a7b4fb08ed1
F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
F src/vdbe.c 1049375248b494e626598abffeeb31052c660c78 F src/vdbe.c a172f5134d19ae910134e28987bf7906523c9b6f
F src/vdbe.h 58a7d931ffb704e034b2a725981cfa5bd406fad9 F src/vdbe.h 58a7d931ffb704e034b2a725981cfa5bd406fad9
F src/vdbeInt.h 969d360acc85f7b2069a8169b4f8a3e1fbaccd44 F src/vdbeInt.h 76c81d057a39813de0fda3cad1498655d53ec69d
F src/vdbeapi.c 61b37dbe11baa221baea7f93c01780705d2419ed F src/vdbeapi.c cf9fc963efae3cdf5de08e2a9718b487059c7fc5
F src/vdbeaux.c 771b9ffd7b42cbb4bd029d7a9414a7cb03f924a7 F src/vdbeaux.c 36d4db24659146606a1c755650f2a70cf88eec25
F src/vdbeblob.c 63c750acc7b5012479f508c0e9627372a82cb65d F src/vdbeblob.c 63c750acc7b5012479f508c0e9627372a82cb65d
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
F src/vdbemem.c cee169fb5542cccfd1e8d832ae4538cb69b8917a F src/vdbemem.c e060d04bc6f8cf32c638fddada266b01cad8ee9a
F src/vtab.c dc8947c9c79780b19ee6d6bae4ea624a2a303353 F src/vtab.c dc8947c9c79780b19ee6d6bae4ea624a2a303353
F src/where.c 7ff0ca021cc77086e367ed3b6308fbc6bc9e1a31 F src/where.c 7ff0ca021cc77086e367ed3b6308fbc6bc9e1a31
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
@ -378,7 +378,7 @@ F test/malloc8.test addc27d907fec1af429551b95c72caa47fce2974
F test/malloc9.test 95d7069ad4fa262bf33bc4c5ca0a46f2bb2391cb F test/malloc9.test 95d7069ad4fa262bf33bc4c5ca0a46f2bb2391cb
F test/mallocA.test 5ee8d42ff90e5b1aeee6fb645e73ffcb35bffd21 F test/mallocA.test 5ee8d42ff90e5b1aeee6fb645e73ffcb35bffd21
F test/mallocAll.test 2a2222a5e447be6c6579055a9a26e507e4586f4e F test/mallocAll.test 2a2222a5e447be6c6579055a9a26e507e4586f4e
F test/mallocB.test 82ecf4d3fa6c389cabc747daa2deddfe94af2a74 F test/mallocB.test d4a91e7d9cc916d009e0fec08537b3be299ee514
F test/mallocC.test 9daac0aa8e5b0afa7b0a3fb0cd792f02fe0cc838 F test/mallocC.test 9daac0aa8e5b0afa7b0a3fb0cd792f02fe0cc838
F test/mallocD.test 24c1d07a00e605831d0d627b036bd690b2952416 F test/mallocD.test 24c1d07a00e605831d0d627b036bd690b2952416
F test/mallocE.test e15333c394d7c330c8372a7cdf7b0f7c16573082 F test/mallocE.test e15333c394d7c330c8372a7cdf7b0f7c16573082
@ -412,7 +412,7 @@ F test/pragma.test d9f3d80583b80708aa270e8c5038dee949190d78
F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
F test/printf.test c3405535b418d454e8a52196a0fc592ec9eec58d F test/printf.test c3405535b418d454e8a52196a0fc592ec9eec58d
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x
F test/ptrchng.test 38ae1806833d72d9a81a6121322e274f24937e18 F test/ptrchng.test 1f7bb92398163f1c18d69727c3ab31d90e94b458
F test/quick.test 771a6b3a88fdd0e7e813ce013ceda29037bc9462 F test/quick.test 771a6b3a88fdd0e7e813ce013ceda29037bc9462
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
F test/rdonly.test b34db316525440d3b42c32e83942c02c37d28ef0 F test/rdonly.test b34db316525440d3b42c32e83942c02c37d28ef0
@ -453,7 +453,7 @@ F test/table.test 13b1c2e2fb4727b35ee1fb7641fc469214fd2455
F test/tableapi.test 4546eb710d979db023bfcc16b0c108b1557fcb43 F test/tableapi.test 4546eb710d979db023bfcc16b0c108b1557fcb43
F test/tclsqlite.test 3fac87cb1059c46b8fa8a60b553f4f1adb0fb6d9 F test/tclsqlite.test 3fac87cb1059c46b8fa8a60b553f4f1adb0fb6d9
F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125 F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125
F test/tester.tcl bfad4d2acf0659c6afbf48a98556b0433d2906dc F test/tester.tcl 70ed4c0dda3e2277bac9e0bf38e60df9dc360d08
F test/thread001.test 8fbd9559da0bbdc273e00318c7fd66c162020af7 F test/thread001.test 8fbd9559da0bbdc273e00318c7fd66c162020af7
F test/thread002.test 2c4ad2c386f60f6fe268cd91c769ee35b3c1fd0b F test/thread002.test 2c4ad2c386f60f6fe268cd91c769ee35b3c1fd0b
F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35 F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35
@ -617,7 +617,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
P 607247c27b80520b8c25c489757288b8ea186f9e P 5ab71c3a79cac04cb2c576f83a62218d05571006
R 6e7459c99c887be282a1c6ce2d461da7 R c1dd02f73a73bb7e12988703f2d12663
U drh U danielk1977
Z 584629669827c756e74626290b2a5564 Z 2dff5d02e45b3ba8d57e28cad43b1b4e

View File

@ -1 +1 @@
5ab71c3a79cac04cb2c576f83a62218d05571006 990237e27e417aff3dbf05784b716c21f3761a3a

View File

@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands. ** This file contains code used to implement the ATTACH and DETACH commands.
** **
** $Id: attach.c,v 1.71 2008/02/06 14:11:35 drh Exp $ ** $Id: attach.c,v 1.72 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@ -328,14 +328,14 @@ static void codeAttach(
} }
v = sqlite3GetVdbe(pParse); v = sqlite3GetVdbe(pParse);
regArgs = sqlite3GetTempRange(pParse, 3); regArgs = sqlite3GetTempRange(pParse, 4);
sqlite3ExprCode(pParse, pFilename, regArgs); sqlite3ExprCode(pParse, pFilename, regArgs);
sqlite3ExprCode(pParse, pDbname, regArgs+1); sqlite3ExprCode(pParse, pDbname, regArgs+1);
sqlite3ExprCode(pParse, pKey, regArgs+2); sqlite3ExprCode(pParse, pKey, regArgs+2);
assert( v || db->mallocFailed ); assert( v || db->mallocFailed );
if( v ){ if( v ){
sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-nFunc, regArgs); sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-nFunc, regArgs+3);
sqlite3VdbeChangeP5(v, nFunc); sqlite3VdbeChangeP5(v, nFunc);
pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0); pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0);
sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF); sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF);

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite. ** to handle INSERT statements in SQLite.
** **
** $Id: insert.c,v 1.228 2008/01/25 15:04:50 drh Exp $ ** $Id: insert.c,v 1.229 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@ -218,14 +218,15 @@ static void autoIncEnd(
Vdbe *v = pParse->pVdbe; Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb]; Db *pDb = &pParse->db->aDb[iDb];
int j1; int j1;
int iRec = ++pParse->nMem; /* Memory cell used for record */
assert( v ); assert( v );
sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1);
sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1); sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1);
sqlite3VdbeJumpHere(v, j1); sqlite3VdbeJumpHere(v, j1);
sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, memId-1); sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec);
sqlite3VdbeAddOp3(v, OP_Insert, iCur, memId-1, memId+1); sqlite3VdbeAddOp3(v, OP_Insert, iCur, iRec, memId+1);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
sqlite3VdbeAddOp1(v, OP_Close, iCur); sqlite3VdbeAddOp1(v, OP_Close, iCur);
} }

View File

@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be ** other files are for internal use by SQLite and should not be
** accessed by users of the library. ** accessed by users of the library.
** **
** $Id: legacy.c,v 1.22 2007/08/29 12:31:26 danielk1977 Exp $ ** $Id: legacy.c,v 1.23 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@ -82,6 +82,10 @@ int sqlite3_exec(
if( 0==nCallback ){ if( 0==nCallback ){
for(i=0; i<nCol; i++){ for(i=0; i<nCol; i++){
azCols[i] = (char *)sqlite3_column_name(pStmt, i); azCols[i] = (char *)sqlite3_column_name(pStmt, i);
if( !azCols[i] ){
db->mallocFailed = 1;
goto exec_out;
}
} }
nCallback++; nCallback++;
} }
@ -89,6 +93,10 @@ int sqlite3_exec(
azVals = &azCols[nCol]; azVals = &azCols[nCol];
for(i=0; i<nCol; i++){ for(i=0; i<nCol; i++){
azVals[i] = (char *)sqlite3_column_text(pStmt, i); azVals[i] = (char *)sqlite3_column_text(pStmt, i);
if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){
db->mallocFailed = 1;
goto exec_out;
}
} }
} }
if( xCallback(pArg, nCol, azVals, azCols) ){ if( xCallback(pArg, nCol, azVals, azCols) ){

View File

@ -12,7 +12,7 @@
** This file contains the C functions that implement a memory ** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite. ** allocation subsystem for use by SQLite.
** **
** $Id: mem1.c,v 1.14 2007/11/29 18:36:49 drh Exp $ ** $Id: mem1.c,v 1.15 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
/* /*
@ -189,6 +189,16 @@ void sqlite3_free(void *pPrior){
sqlite3_mutex_leave(mem.mutex); sqlite3_mutex_leave(mem.mutex);
} }
/*
** Return the number of bytes allocated at p.
*/
int sqlite3MallocSize(void *p){
sqlite3_int64 *pInt;
if( !p ) return 0;
pInt = p;
return pInt[-1];
}
/* /*
** Change the size of an existing memory allocation ** Change the size of an existing memory allocation
*/ */

View File

@ -12,7 +12,7 @@
** This file contains the C functions that implement a memory ** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite. ** allocation subsystem for use by SQLite.
** **
** $Id: mem2.c,v 1.19 2008/01/22 21:30:53 drh Exp $ ** $Id: mem2.c,v 1.20 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
/* /*
@ -243,6 +243,18 @@ static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
return p; return p;
} }
/*
** Return the number of bytes currently allocated at address p.
*/
int sqlite3MallocSize(void *p){
struct MemBlockHdr *pHdr;
if( !p ){
return 0;
}
pHdr = sqlite3MemsysGetHeader(p);
return pHdr->iSize;
}
/* /*
** Allocate nByte bytes of memory. ** Allocate nByte bytes of memory.
*/ */
@ -452,5 +464,17 @@ void sqlite3_memdebug_dump(const char *zFilename){
fclose(out); fclose(out);
} }
/*
** Return the number of times sqlite3_malloc() has been called.
*/
int sqlite3_memdebug_malloc_count(){
int i;
int nTotal = 0;
for(i=0; i<NCSIZE; i++){
nTotal += mem.sizeCnt[i];
}
return nTotal;
}
#endif /* SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */ #endif /* SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */

View File

@ -20,7 +20,7 @@
** This version of the memory allocation subsystem is used if ** This version of the memory allocation subsystem is used if
** and only if SQLITE_MEMORY_SIZE is defined. ** and only if SQLITE_MEMORY_SIZE is defined.
** **
** $Id: mem3.c,v 1.8 2007/12/29 13:18:22 drh Exp $ ** $Id: mem3.c,v 1.9 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
/* /*
@ -291,7 +291,7 @@ static void memsys3OutOfMemory(int nByte){
** size returned omits the 8-byte header overhead. This only ** size returned omits the 8-byte header overhead. This only
** works for chunks that are currently checked out. ** works for chunks that are currently checked out.
*/ */
static int memsys3Size(void *p){ int sqlite3MallocSize(void *p){
Mem3Block *pBlock = (Mem3Block*)p; Mem3Block *pBlock = (Mem3Block*)p;
assert( (pBlock[-1].u.hdr.size4x&1)!=0 ); assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
return (pBlock[-1].u.hdr.size4x&~3)*2 - 4; return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
@ -556,7 +556,7 @@ void *sqlite3_realloc(void *pPrior, int nBytes){
return 0; return 0;
} }
assert( mem.mutex!=0 ); assert( mem.mutex!=0 );
nOld = memsys3Size(pPrior); nOld = sqlite3MallocSize(pPrior);
if( nBytes<=nOld && nBytes>=nOld-128 ){ if( nBytes<=nOld && nBytes>=nOld-128 ){
return pPrior; return pPrior;
} }

View File

@ -1,4 +1,4 @@
/* /*
** 2005 November 29 ** 2005 November 29
** **
** The author disclaims copyright to this source code. In place of ** The author disclaims copyright to this source code. In place of

View File

@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** This file contains code used to implement the PRAGMA command. ** This file contains code used to implement the PRAGMA command.
** **
** $Id: pragma.c,v 1.169 2008/01/22 01:48:09 drh Exp $ ** $Id: pragma.c,v 1.170 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@ -894,8 +894,8 @@ void sqlite3Pragma(
if( cnt==0 ) continue; if( cnt==0 ) continue;
/* Make sure sufficient number of registers have been allocated */ /* Make sure sufficient number of registers have been allocated */
if( pParse->nMem < cnt+3 ){ if( pParse->nMem < cnt+4 ){
pParse->nMem = cnt+3; pParse->nMem = cnt+4;
} }
/* Do the b-tree integrity checks */ /* Do the b-tree integrity checks */
@ -905,7 +905,8 @@ void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
P4_DYNAMIC); P4_DYNAMIC);
sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 2); sqlite3VdbeAddOp2(v, OP_Move, 2, 4);
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1); sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
sqlite3VdbeJumpHere(v, addr); sqlite3VdbeJumpHere(v, addr);

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite. ** to handle SELECT statements in SQLite.
** **
** $Id: select.c,v 1.412 2008/02/06 23:52:37 drh Exp $ ** $Id: select.c,v 1.413 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@ -810,8 +810,8 @@ static void generateSortTail(
int j1; int j1;
assert( nColumn==1 ); assert( nColumn==1 );
j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow); j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow);
sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRow, &p->affinity, 1); sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRow); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
sqlite3VdbeJumpHere(v, j1); sqlite3VdbeJumpHere(v, j1);
break; break;
} }

View File

@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** Internal interface definitions for SQLite.
** **
** @(#) $Id: sqliteInt.h,v 1.660 2008/02/12 16:52:14 drh Exp $ ** @(#) $Id: sqliteInt.h,v 1.661 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
#ifndef _SQLITEINT_H_ #ifndef _SQLITEINT_H_
#define _SQLITEINT_H_ #define _SQLITEINT_H_
@ -1683,6 +1683,7 @@ char *sqlite3DbStrDup(sqlite3*,const char*);
char *sqlite3DbStrNDup(sqlite3*,const char*, int); char *sqlite3DbStrNDup(sqlite3*,const char*, int);
void *sqlite3DbReallocOrFree(sqlite3 *, void *, int); void *sqlite3DbReallocOrFree(sqlite3 *, void *, int);
void *sqlite3DbRealloc(sqlite3 *, void *, int); void *sqlite3DbRealloc(sqlite3 *, void *, int);
int sqlite3MallocSize(void *);
char *sqlite3MPrintf(sqlite3*,const char*, ...); char *sqlite3MPrintf(sqlite3*,const char*, ...);
char *sqlite3VMPrintf(sqlite3*,const char*, va_list); char *sqlite3VMPrintf(sqlite3*,const char*, va_list);

View File

@ -12,7 +12,7 @@
** A TCL Interface to SQLite. Append this file to sqlite3.c and ** A TCL Interface to SQLite. Append this file to sqlite3.c and
** compile the whole thing to build a TCL-enabled version of SQLite. ** compile the whole thing to build a TCL-enabled version of SQLite.
** **
** $Id: tclsqlite.c,v 1.207 2007/11/14 06:48:48 danielk1977 Exp $ ** $Id: tclsqlite.c,v 1.208 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
#include "tcl.h" #include "tcl.h"
#include <errno.h> #include <errno.h>
@ -1702,7 +1702,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
switch( sqlite3_column_type(pStmt, i) ){ switch( sqlite3_column_type(pStmt, i) ){
case SQLITE_BLOB: { case SQLITE_BLOB: {
int bytes = sqlite3_column_bytes(pStmt, i); int bytes = sqlite3_column_bytes(pStmt, i);
pVal = Tcl_NewByteArrayObj(sqlite3_column_blob(pStmt, i), bytes); char *zBlob = sqlite3_column_blob(pStmt, i);
if( !zBlob ) bytes = 0;
pVal = Tcl_NewByteArrayObj(zBlob, bytes);
break; break;
} }
case SQLITE_INTEGER: { case SQLITE_INTEGER: {

View File

@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated ** is not included in the SQLite library. It is used for automated
** testing of the SQLite library. ** testing of the SQLite library.
** **
** $Id: test1.c,v 1.287 2008/01/23 14:51:50 drh Exp $ ** $Id: test1.c,v 1.288 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "tcl.h" #include "tcl.h"
@ -954,16 +954,17 @@ static int test_create_function(
/* Use the sqlite3_create_function16() API here. Mainly for fun, but also /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
** because it is not tested anywhere else. */ ** because it is not tested anywhere else. */
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
void *zUtf16;
sqlite3_value *pVal; sqlite3_value *pVal;
sqlite3_mutex_enter(db->mutex); sqlite3_mutex_enter(db->mutex);
pVal = sqlite3ValueNew(db); pVal = sqlite3ValueNew(db);
sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
if( db->mallocFailed ){ if( db->mallocFailed ){
rc = SQLITE_NOMEM; rc = SQLITE_NOMEM;
}else{ }else{
rc = sqlite3_create_function16(db, rc = sqlite3_create_function16(db, zUtf16,
sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
} }
sqlite3ValueFree(pVal); sqlite3ValueFree(pVal);
sqlite3_mutex_leave(db->mutex); sqlite3_mutex_leave(db->mutex);
@ -2152,6 +2153,7 @@ static int test_collate(
rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8, rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
(void *)SQLITE_UTF8, val?test_collate_func:0); (void *)SQLITE_UTF8, val?test_collate_func:0);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
void *zUtf16;
if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
(void *)SQLITE_UTF16LE, val?test_collate_func:0); (void *)SQLITE_UTF16LE, val?test_collate_func:0);
@ -2165,11 +2167,11 @@ static int test_collate(
sqlite3_mutex_enter(db->mutex); sqlite3_mutex_enter(db->mutex);
pVal = sqlite3ValueNew(db); pVal = sqlite3ValueNew(db);
sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC); sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
if( db->mallocFailed ){ if( db->mallocFailed ){
rc = SQLITE_NOMEM; rc = SQLITE_NOMEM;
}else{ }else{
rc = sqlite3_create_collation16(db, rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE,
sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), SQLITE_UTF16BE,
(void *)SQLITE_UTF16BE, val?test_collate_func:0); (void *)SQLITE_UTF16BE, val?test_collate_func:0);
} }
sqlite3ValueFree(pVal); sqlite3ValueFree(pVal);

View File

@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated ** is not included in the SQLite library. It is used for automated
** testing of the SQLite library. ** testing of the SQLite library.
** **
** $Id: test8.c,v 1.59 2008/01/22 21:30:53 drh Exp $ ** $Id: test8.c,v 1.60 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "tcl.h" #include "tcl.h"
@ -160,7 +160,12 @@ static int getColumnNames(
*/ */
nBytes = sizeof(char *) * nCol; nBytes = sizeof(char *) * nCol;
for(ii=0; ii<nCol; ii++){ for(ii=0; ii<nCol; ii++){
nBytes += (strlen(sqlite3_column_name(pStmt, ii)) + 1); const char *zName = sqlite3_column_name(pStmt, ii);
if( !zName ){
rc = SQLITE_NOMEM;
goto out;
}
nBytes += strlen(zName)+1;
} }
aCol = (char **)sqlite3MallocZero(nBytes); aCol = (char **)sqlite3MallocZero(nBytes);
if( !aCol ){ if( !aCol ){
@ -952,11 +957,15 @@ int echoUpdate(
if( bindArgOne ){ if( bindArgOne ){
sqlite3_bind_value(pStmt, 1, apData[1]); sqlite3_bind_value(pStmt, 1, apData[1]);
} }
for(i=2; i<nData; i++){ for(i=2; i<nData && rc==SQLITE_OK; i++){
if( apData[i] ) sqlite3_bind_value(pStmt, i, apData[i]); if( apData[i] ) rc = sqlite3_bind_value(pStmt, i, apData[i]);
}
if( rc==SQLITE_OK ){
sqlite3_step(pStmt);
rc = sqlite3_finalize(pStmt);
}else{
sqlite3_finalize(pStmt);
} }
sqlite3_step(pStmt);
rc = sqlite3_finalize(pStmt);
} }
if( pRowid && rc==SQLITE_OK ){ if( pRowid && rc==SQLITE_OK ){

View File

@ -13,7 +13,7 @@
** This file contains code used to implement test interfaces to the ** This file contains code used to implement test interfaces to the
** memory allocation subsystem. ** memory allocation subsystem.
** **
** $Id: test_malloc.c,v 1.11 2008/01/31 14:43:24 drh Exp $ ** $Id: test_malloc.c,v 1.12 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "tcl.h" #include "tcl.h"
@ -343,6 +343,32 @@ static int test_memdebug_dump(
return TCL_OK; return TCL_OK;
} }
/*
** Usage: sqlite3_memdebug_malloc_count
**
** Return the total number of times malloc() has been called.
*/
static int test_memdebug_malloc_count(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
int nMalloc = -1;
if( objc!=1 ){
Tcl_WrongNumArgs(interp, 1, objv, "");
return TCL_ERROR;
}
#if defined(SQLITE_MEMDEBUG)
{
extern int sqlite3_memdebug_malloc_count();
nMalloc = sqlite3_memdebug_malloc_count();
}
#endif
Tcl_SetObjResult(interp, Tcl_NewIntObj(nMalloc));
return TCL_OK;
}
/* /*
** Usage: sqlite3_memdebug_fail COUNTER ?OPTIONS? ** Usage: sqlite3_memdebug_fail COUNTER ?OPTIONS?
@ -504,6 +530,7 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){
{ "sqlite3_memdebug_fail", test_memdebug_fail }, { "sqlite3_memdebug_fail", test_memdebug_fail },
{ "sqlite3_memdebug_pending", test_memdebug_pending }, { "sqlite3_memdebug_pending", test_memdebug_pending },
{ "sqlite3_memdebug_settitle", test_memdebug_settitle }, { "sqlite3_memdebug_settitle", test_memdebug_settitle },
{ "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count },
}; };
int i; int i;
for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){

View File

@ -12,7 +12,7 @@
** This file contains routines used to translate between UTF-8, ** This file contains routines used to translate between UTF-8,
** UTF-16, UTF-16BE, and UTF-16LE. ** UTF-16, UTF-16BE, and UTF-16LE.
** **
** $Id: utf.c,v 1.59 2007/10/03 08:46:45 danielk1977 Exp $ ** $Id: utf.c,v 1.60 2008/02/13 18:25:27 danielk1977 Exp $
** **
** Notes on UTF-8: ** Notes on UTF-8:
** **
@ -188,7 +188,6 @@ int sqlite3Utf8Read(
** encoding, or if *pMem does not contain a string value. ** encoding, or if *pMem does not contain a string value.
*/ */
int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
unsigned char zShort[NBFS]; /* Temporary short output buffer */
int len; /* Maximum length of output string in bytes */ int len; /* Maximum length of output string in bytes */
unsigned char *zOut; /* Output buffer */ unsigned char *zOut; /* Output buffer */
unsigned char *zIn; /* Input iterator */ unsigned char *zIn; /* Input iterator */
@ -254,19 +253,14 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
/* Set zIn to point at the start of the input buffer and zTerm to point 1 /* Set zIn to point at the start of the input buffer and zTerm to point 1
** byte past the end. ** byte past the end.
** **
** Variable zOut is set to point at the output buffer. This may be space ** Variable zOut is set to point at the output buffer, space obtained
** obtained from sqlite3_malloc(), or Mem.zShort, if it large enough and ** from sqlite3_malloc().
** not in use, or the zShort array on the stack (see above).
*/ */
zIn = (u8*)pMem->z; zIn = (u8*)pMem->z;
zTerm = &zIn[pMem->n]; zTerm = &zIn[pMem->n];
if( len>NBFS ){ zOut = sqlite3DbMallocRaw(pMem->db, len);
zOut = sqlite3DbMallocRaw(pMem->db, len); if( !zOut ){
if( !zOut ){ return SQLITE_NOMEM;
return SQLITE_NOMEM;
}
}else{
zOut = zShort;
} }
z = zOut; z = zOut;
@ -308,15 +302,9 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
sqlite3VdbeMemRelease(pMem); sqlite3VdbeMemRelease(pMem);
pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short); pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
pMem->enc = desiredEnc; pMem->enc = desiredEnc;
if( zOut==zShort ){ pMem->flags |= (MEM_Term|MEM_Dyn);
memcpy(pMem->zShort, zOut, len);
zOut = (u8*)pMem->zShort;
pMem->flags |= (MEM_Term|MEM_Short);
}else{
pMem->flags |= (MEM_Term|MEM_Dyn);
}
pMem->z = (char*)zOut; pMem->z = (char*)zOut;
translate_out: translate_out:
@ -355,24 +343,14 @@ int sqlite3VdbeMemHandleBom(Mem *pMem){
} }
if( bom ){ if( bom ){
/* This function is called as soon as a string is stored in a Mem*, rc = sqlite3VdbeMemMakeWriteable(pMem);
** from within sqlite3VdbeMemSetStr(). At that point it is not possible if( rc==SQLITE_OK ){
** for the string to be stored in Mem.zShort, or for it to be stored pMem->n -= 2;
** in dynamic memory with no destructor. memmove(pMem->z, &pMem->z[2], pMem->n);
*/ pMem->z[pMem->n] = '\0';
assert( !(pMem->flags&MEM_Short) ); pMem->z[pMem->n+1] = '\0';
assert( !(pMem->flags&MEM_Dyn) || pMem->xDel ); pMem->flags |= MEM_Term;
if( pMem->flags & MEM_Dyn ){ pMem->enc = bom;
void (*xDel)(void*) = pMem->xDel;
char *z = pMem->z;
pMem->z = 0;
pMem->xDel = 0;
rc = sqlite3VdbeMemSetStr(pMem, &z[2], pMem->n-2, bom,
SQLITE_TRANSIENT);
xDel(z);
}else{
rc = sqlite3VdbeMemSetStr(pMem, &pMem->z[2], pMem->n-2, bom,
SQLITE_TRANSIENT);
} }
} }
return rc; return rc;

View File

@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing ** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code. ** commenting and indentation practices when changing or adding code.
** **
** $Id: vdbe.c,v 1.708 2008/02/06 14:11:35 drh Exp $ ** $Id: vdbe.c,v 1.709 2008/02/13 18:25:27 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@ -236,9 +236,8 @@ static void applyNumericAffinity(Mem *pRec){
i64 value; i64 value;
sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8); sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8);
if( !realnum && sqlite3Atoi64(pRec->z, &value) ){ if( !realnum && sqlite3Atoi64(pRec->z, &value) ){
sqlite3VdbeMemRelease(pRec);
pRec->u.i = value; pRec->u.i = value;
pRec->flags = MEM_Int; MemSetTypeFlag(pRec, MEM_Int);
}else{ }else{
sqlite3VdbeMemRealify(pRec); sqlite3VdbeMemRealify(pRec);
} }
@ -1000,14 +999,19 @@ case OP_ResultRow: {
** Add the text in register P1 onto the end of the text in ** Add the text in register P1 onto the end of the text in
** register P2 and store the result in register P3. ** register P2 and store the result in register P3.
** If either the P1 or P2 text are NULL then store NULL in P3. ** If either the P1 or P2 text are NULL then store NULL in P3.
**
** P3 = P2 || P1
**
** It is illegal for P1 and P3 to be the same register. Sometimes,
** if P3 is the same register as P2, the implementation is able
** to avoid a memcpy().
*/ */
case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
char *zNew;
i64 nByte; i64 nByte;
assert( pIn1!=pOut );
if( (pIn1->flags | pIn2->flags) & MEM_Null ){ if( (pIn1->flags | pIn2->flags) & MEM_Null ){
Release(pOut); sqlite3VdbeMemSetNull(pOut);
pOut->flags = MEM_Null;
break; break;
} }
ExpandBlob(pIn1); ExpandBlob(pIn1);
@ -1018,20 +1022,19 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
if( nByte>SQLITE_MAX_LENGTH ){ if( nByte>SQLITE_MAX_LENGTH ){
goto too_big; goto too_big;
} }
zNew = sqlite3DbMallocRaw(db, nByte+2); MemSetTypeFlag(pOut, MEM_Str);
if( zNew==0 ){ if( sqlite3VdbeMemGrow(pOut, nByte+2, pOut==pIn2) ){
goto no_mem; goto no_mem;
} }
memcpy(zNew, pIn2->z, pIn2->n); if( pOut!=pIn2 ){
memcpy(&zNew[pIn2->n], pIn1->z, pIn1->n); memcpy(pOut->z, pIn2->z, pIn2->n);
zNew[nByte] = 0; }
zNew[nByte+1] = 0; memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
Release(pOut); pOut->z[nByte] = 0;
pOut->z[nByte+1] = 0;
pOut->flags |= MEM_Term;
pOut->n = nByte; pOut->n = nByte;
pOut->flags = MEM_Str|MEM_Dyn|MEM_Term;
pOut->xDel = 0;
pOut->enc = encoding; pOut->enc = encoding;
pOut->z = zNew;
UPDATE_MAX_BLOBSIZE(pOut); UPDATE_MAX_BLOBSIZE(pOut);
break; break;
} }
@ -1105,9 +1108,8 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
break; break;
} }
} }
Release(pOut);
pOut->u.i = b; pOut->u.i = b;
pOut->flags = MEM_Int; MemSetTypeFlag(pOut, MEM_Int);
}else{ }else{
double a, b; double a, b;
a = sqlite3VdbeRealValue(pIn1); a = sqlite3VdbeRealValue(pIn1);
@ -1133,9 +1135,8 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
if( sqlite3_isnan(b) ){ if( sqlite3_isnan(b) ){
goto arithmetic_result_is_null; goto arithmetic_result_is_null;
} }
Release(pOut);
pOut->r = b; pOut->r = b;
pOut->flags = MEM_Real; MemSetTypeFlag(pOut, MEM_Real);
if( (flags & MEM_Real)==0 ){ if( (flags & MEM_Real)==0 ){
sqlite3VdbeIntegerAffinity(pOut); sqlite3VdbeIntegerAffinity(pOut);
} }
@ -1168,6 +1169,7 @@ case OP_CollSeq: {
** Invoke a user function (P4 is a pointer to a Function structure that ** Invoke a user function (P4 is a pointer to a Function structure that
** defines the function) with P5 arguments taken from register P2 and ** defines the function) with P5 arguments taken from register P2 and
** successors. The result of the function is stored in register P3. ** successors. The result of the function is stored in register P3.
** Register P3 must not be one of the function inputs.
** **
** P1 is a 32-bit bitmask indicating whether or not each argument to the ** P1 is a 32-bit bitmask indicating whether or not each argument to the
** function was determined to be constant at compile time. If the first ** function was determined to be constant at compile time. If the first
@ -1189,6 +1191,7 @@ case OP_Function: {
assert( apVal || n==0 ); assert( apVal || n==0 );
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem) ); assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem) );
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
pArg = &p->aMem[pOp->p2]; pArg = &p->aMem[pOp->p2];
for(i=0; i<n; i++, pArg++){ for(i=0; i<n; i++, pArg++){
apVal[i] = pArg; apVal[i] = pArg;
@ -1205,10 +1208,18 @@ case OP_Function: {
ctx.pFunc = ctx.pVdbeFunc->pFunc; ctx.pFunc = ctx.pVdbeFunc->pFunc;
} }
assert( pOp->p3>0 && pOp->p3<=p->nMem );
pOut = &p->aMem[pOp->p3];
ctx.s.flags = MEM_Null; ctx.s.flags = MEM_Null;
ctx.s.z = 0; ctx.s.db = 0;
ctx.s.xDel = 0;
ctx.s.db = db; /* The output cell may already have a buffer allocated. Move
** the pointer to ctx.s so in case the user-function can use
** the already allocated buffer instead of allocating a new one.
*/
sqlite3VdbeMemMove(&ctx.s, pOut);
MemSetTypeFlag(&ctx.s, MEM_Null);
ctx.isError = 0; ctx.isError = 0;
if( ctx.pFunc->needCollSeq ){ if( ctx.pFunc->needCollSeq ){
assert( pOp>p->aOp ); assert( pOp>p->aOp );
@ -1250,8 +1261,6 @@ case OP_Function: {
/* Copy the result of the function into register P3 */ /* Copy the result of the function into register P3 */
sqlite3VdbeChangeEncoding(&ctx.s, encoding); sqlite3VdbeChangeEncoding(&ctx.s, encoding);
assert( pOp->p3>0 && pOp->p3<=p->nMem );
pOut = &p->aMem[pOp->p3];
sqlite3VdbeMemMove(pOut, &ctx.s); sqlite3VdbeMemMove(pOut, &ctx.s);
if( sqlite3VdbeMemTooBig(pOut) ){ if( sqlite3VdbeMemTooBig(pOut) ){
goto too_big; goto too_big;
@ -1306,9 +1315,8 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
default: assert( pOp->opcode==OP_ShiftRight ); default: assert( pOp->opcode==OP_ShiftRight );
a >>= b; break; a >>= b; break;
} }
Release(pOut);
pOut->u.i = a; pOut->u.i = a;
pOut->flags = MEM_Int; MemSetTypeFlag(pOut, MEM_Int);
break; break;
} }
@ -1350,9 +1358,8 @@ case OP_ForceInt: { /* jump, in1 */
if( pIn1->r>(double)v ) v++; if( pIn1->r>(double)v ) v++;
if( pOp->p3 && pIn1->r==(double)v ) v++; if( pOp->p3 && pIn1->r==(double)v ) v++;
} }
Release(pIn1);
pIn1->u.i = v; pIn1->u.i = v;
pIn1->flags = MEM_Int; MemSetTypeFlag(pIn1, MEM_Int);
break; break;
} }
@ -1373,8 +1380,7 @@ case OP_MustBeInt: { /* jump, in1 */
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
}else{ }else{
Release(pIn1); MemSetTypeFlag(pIn1, MEM_Int);
pIn1->flags = MEM_Int;
} }
break; break;
} }
@ -1411,7 +1417,7 @@ case OP_ToText: { /* same as TK_TO_TEXT, in1 */
pIn1->flags |= (pIn1->flags&MEM_Blob)>>3; pIn1->flags |= (pIn1->flags&MEM_Blob)>>3;
applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
rc = ExpandBlob(pIn1); rc = ExpandBlob(pIn1);
assert( pIn1->flags & MEM_Str ); assert( pIn1->flags & MEM_Str || db->mallocFailed );
pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob); pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob);
UPDATE_MAX_BLOBSIZE(pIn1); UPDATE_MAX_BLOBSIZE(pIn1);
break; break;
@ -1430,10 +1436,9 @@ case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */
if( pIn1->flags & MEM_Null ) break; if( pIn1->flags & MEM_Null ) break;
if( (pIn1->flags & MEM_Blob)==0 ){ if( (pIn1->flags & MEM_Blob)==0 ){
applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
assert( pIn1->flags & MEM_Str ); assert( pIn1->flags & MEM_Str || db->mallocFailed );
pIn1->flags |= MEM_Blob;
} }
pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Str); MemSetTypeFlag(pIn1, MEM_Blob);
UPDATE_MAX_BLOBSIZE(pIn1); UPDATE_MAX_BLOBSIZE(pIn1);
break; break;
} }
@ -1591,8 +1596,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
*/ */
if( pOp->p5 & SQLITE_STOREP2 ){ if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &p->aMem[pOp->p2]; pOut = &p->aMem[pOp->p2];
Release(pOut); MemSetTypeFlag(pOut, MEM_Null);
pOut->flags = MEM_Null;
REGISTER_TRACE(pOp->p2, pOut); REGISTER_TRACE(pOp->p2, pOut);
}else if( pOp->p5 & SQLITE_JUMPIFNULL ){ }else if( pOp->p5 & SQLITE_JUMPIFNULL ){
pc = pOp->p2-1; pc = pOp->p2-1;
@ -1622,8 +1626,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
if( pOp->p5 & SQLITE_STOREP2 ){ if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &p->aMem[pOp->p2]; pOut = &p->aMem[pOp->p2];
Release(pOut); MemSetTypeFlag(pOut, MEM_Int);
pOut->flags = MEM_Int;
pOut->u.i = res; pOut->u.i = res;
REGISTER_TRACE(pOp->p2, pOut); REGISTER_TRACE(pOp->p2, pOut);
}else if( res ){ }else if( res ){
@ -1671,12 +1674,11 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
v1 = or_logic[v1*3+v2]; v1 = or_logic[v1*3+v2];
} }
Release(pOut);
if( v1==2 ){ if( v1==2 ){
pOut->flags = MEM_Null; MemSetTypeFlag(pOut, MEM_Null);
}else{ }else{
pOut->u.i = v1; pOut->u.i = v1;
pOut->flags = MEM_Int; MemSetTypeFlag(pOut, MEM_Int);
} }
break; break;
} }
@ -1691,7 +1693,7 @@ case OP_Not: { /* same as TK_NOT, in1 */
if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */ if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */
sqlite3VdbeMemIntegerify(pIn1); sqlite3VdbeMemIntegerify(pIn1);
pIn1->u.i = !pIn1->u.i; pIn1->u.i = !pIn1->u.i;
assert( pIn1->flags==MEM_Int ); assert( pIn1->flags&MEM_Int );
break; break;
} }
@ -1705,7 +1707,7 @@ case OP_BitNot: { /* same as TK_BITNOT, in1 */
if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */ if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */
sqlite3VdbeMemIntegerify(pIn1); sqlite3VdbeMemIntegerify(pIn1);
pIn1->u.i = ~pIn1->u.i; pIn1->u.i = ~pIn1->u.i;
assert( pIn1->flags==MEM_Int ); assert( pIn1->flags&MEM_Int );
break; break;
} }
@ -1823,10 +1825,11 @@ case OP_Column: {
Mem sMem; /* For storing the record being decoded */ Mem sMem; /* For storing the record being decoded */
sMem.flags = 0; sMem.flags = 0;
sMem.db = 0;
assert( p1<p->nCursor ); assert( p1<p->nCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem ); assert( pOp->p3>0 && pOp->p3<=p->nMem );
pDest = &p->aMem[pOp->p3]; pDest = &p->aMem[pOp->p3];
sqlite3VdbeMemSetNull(pDest); MemSetTypeFlag(pDest, MEM_Null);
/* This block sets the variable payloadSize to be the total number of /* This block sets the variable payloadSize to be the total number of
** bytes in the record. ** bytes in the record.
@ -1877,7 +1880,7 @@ case OP_Column: {
/* If payloadSize is 0, then just store a NULL */ /* If payloadSize is 0, then just store a NULL */
if( payloadSize==0 ){ if( payloadSize==0 ){
assert( pDest->flags==MEM_Null ); assert( pDest->flags&MEM_Null );
goto op_column_out; goto op_column_out;
} }
if( payloadSize>SQLITE_MAX_LENGTH ){ if( payloadSize>SQLITE_MAX_LENGTH ){
@ -1943,6 +1946,8 @@ case OP_Column: {
** acquire the complete header text. ** acquire the complete header text.
*/ */
if( !zRec && avail<offset ){ if( !zRec && avail<offset ){
sMem.flags = 0;
sMem.db = 0;
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, offset, pC->isIndex, &sMem); rc = sqlite3VdbeMemFromBtree(pCrsr, 0, offset, pC->isIndex, &sMem);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
goto op_column_out; goto op_column_out;
@ -1994,22 +1999,30 @@ case OP_Column: {
if( aOffset[p2] ){ if( aOffset[p2] ){
assert( rc==SQLITE_OK ); assert( rc==SQLITE_OK );
if( zRec ){ if( zRec ){
zData = &zRec[aOffset[p2]]; if( pDest->flags&MEM_Dyn ){
sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], &sMem);
sMem.db = db;
sqlite3VdbeMemCopy(pDest, &sMem);
assert( !(sMem.flags&MEM_Dyn) );
}else{
sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], pDest);
}
}else{ }else{
len = sqlite3VdbeSerialTypeLen(aType[p2]); len = sqlite3VdbeSerialTypeLen(aType[p2]);
sqlite3VdbeMemMove(&sMem, pDest);
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex, &sMem); rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex, &sMem);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
goto op_column_out; goto op_column_out;
} }
zData = sMem.z; zData = sMem.z;
sqlite3VdbeSerialGet((u8*)zData, aType[p2], pDest);
} }
sqlite3VdbeSerialGet((u8*)zData, aType[p2], pDest);
pDest->enc = encoding; pDest->enc = encoding;
}else{ }else{
if( pOp->p4type==P4_MEM ){ if( pOp->p4type==P4_MEM ){
sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static); sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
}else{ }else{
assert( pDest->flags==MEM_Null ); assert( pDest->flags&MEM_Null );
} }
} }
@ -2019,16 +2032,14 @@ case OP_Column: {
** This prevents a memory copy. ** This prevents a memory copy.
*/ */
if( (sMem.flags & MEM_Dyn)!=0 ){ if( (sMem.flags & MEM_Dyn)!=0 ){
assert( pDest->flags & MEM_Ephem ); assert( !sMem.xDel );
assert( pDest->flags & (MEM_Str|MEM_Blob) ); assert( !(pDest->flags & MEM_Dyn) );
assert( pDest->z==sMem.z ); assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z );
assert( sMem.flags & MEM_Term ); pDest->flags &= ~(MEM_Ephem|MEM_Static);
pDest->flags &= ~MEM_Ephem;
pDest->flags |= MEM_Dyn|MEM_Term; pDest->flags |= MEM_Dyn|MEM_Term;
pDest->z = sMem.z;
} }
/* pDest->z might be pointing to sMem.zShort[]. Fix that so that we
** can abandon sMem */
rc = sqlite3VdbeMemMakeWriteable(pDest); rc = sqlite3VdbeMemMakeWriteable(pDest);
op_column_out: op_column_out:
@ -2086,7 +2097,6 @@ case OP_MakeRecord: {
char *zAffinity; /* The affinity string for the record */ char *zAffinity; /* The affinity string for the record */
int file_format; /* File format to use for encoding */ int file_format; /* File format to use for encoding */
int i; /* Space used in zNewRecord[] */ int i; /* Space used in zNewRecord[] */
char zTemp[NBFS]; /* Space to hold small records */
nField = pOp->p1; nField = pOp->p1;
zAffinity = pOp->p4.z; zAffinity = pOp->p4.z;
@ -2130,15 +2140,17 @@ case OP_MakeRecord: {
goto too_big; goto too_big;
} }
/* Allocate space for the new record. */ /* Make sure the output register has a buffer large enough to store
if( nByte>sizeof(zTemp) ){ ** the new record. The output register (pOp->p3) is not allowed to
zNewRecord = sqlite3DbMallocRaw(db, nByte); ** be one of the input registers (because the following call to
if( !zNewRecord ){ ** sqlite3VdbeMemGrow() could clobber the value before it is used).
goto no_mem; */
} assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
}else{ pOut = &p->aMem[pOp->p3];
zNewRecord = (u8*)zTemp; if( sqlite3VdbeMemGrow(pOut, nByte, 0) ){
goto no_mem;
} }
zNewRecord = (u8 *)pOut->z;
/* Write the record */ /* Write the record */
i = sqlite3PutVarint(zNewRecord, nHdr); i = sqlite3PutVarint(zNewRecord, nHdr);
@ -2152,20 +2164,9 @@ case OP_MakeRecord: {
assert( i==nByte ); assert( i==nByte );
assert( pOp->p3>0 && pOp->p3<=p->nMem ); assert( pOp->p3>0 && pOp->p3<=p->nMem );
pOut = &p->aMem[pOp->p3];
Release(pOut);
pOut->n = nByte; pOut->n = nByte;
if( nByte<=sizeof(zTemp) ){ pOut->flags = MEM_Blob | MEM_Dyn;
assert( zNewRecord==(unsigned char *)zTemp ); pOut->xDel = 0;
pOut->z = pOut->zShort;
memcpy(pOut->zShort, zTemp, nByte);
pOut->flags = MEM_Blob | MEM_Short;
}else{
assert( zNewRecord!=(unsigned char *)zTemp );
pOut->z = (char*)zNewRecord;
pOut->flags = MEM_Blob | MEM_Dyn;
pOut->xDel = 0;
}
if( nZero ){ if( nZero ){
pOut->u.i = nZero; pOut->u.i = nZero;
pOut->flags |= MEM_Zero; pOut->flags |= MEM_Zero;
@ -2343,7 +2344,7 @@ case OP_ReadCookie: { /* out2-prerelease */
*/ */
rc = sqlite3BtreeGetMeta(db->aDb[iDb].pBt, 1 + iCookie, (u32 *)&iMeta); rc = sqlite3BtreeGetMeta(db->aDb[iDb].pBt, 1 + iCookie, (u32 *)&iMeta);
pOut->u.i = iMeta; pOut->u.i = iMeta;
pOut->flags = MEM_Int; MemSetTypeFlag(pOut, MEM_Int);
break; break;
} }
@ -2896,7 +2897,6 @@ case OP_IsUnique: { /* jump, in3 */
pK = &p->aMem[pOp->p4.i]; pK = &p->aMem[pOp->p4.i];
sqlite3VdbeMemIntegerify(pIn3); sqlite3VdbeMemIntegerify(pIn3);
R = pIn3->u.i; R = pIn3->u.i;
assert( (pIn3->flags & MEM_Dyn)==0 );
assert( i>=0 && i<p->nCursor ); assert( i>=0 && i<p->nCursor );
pCx = p->apCsr[i]; pCx = p->apCsr[i];
assert( pCx!=0 ); assert( pCx!=0 );
@ -2960,7 +2960,7 @@ case OP_IsUnique: { /* jump, in3 */
** a UNIQUE constraint.) ** a UNIQUE constraint.)
*/ */
pIn3->u.i = v; pIn3->u.i = v;
assert( pIn3->flags==MEM_Int ); assert( pIn3->flags&MEM_Int );
} }
break; break;
} }
@ -3021,7 +3021,7 @@ case OP_Sequence: { /* out2-prerelease */
assert( i>=0 && i<p->nCursor ); assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 ); assert( p->apCsr[i]!=0 );
pOut->u.i = p->apCsr[i]->seqCount++; pOut->u.i = p->apCsr[i]->seqCount++;
pOut->flags = MEM_Int; MemSetTypeFlag(pOut, MEM_Int);
break; break;
} }
@ -3174,7 +3174,7 @@ case OP_NewRowid: { /* out2-prerelease */
pC->deferredMoveto = 0; pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE; pC->cacheStatus = CACHE_STALE;
} }
pOut->flags = MEM_Int; MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = v; pOut->u.i = v;
break; break;
} }
@ -3368,13 +3368,15 @@ case OP_ResetCount: {
** If the P1 cursor must be pointing to a valid row (not a NULL row) ** If the P1 cursor must be pointing to a valid row (not a NULL row)
** of a real table, not a pseudo-table. ** of a real table, not a pseudo-table.
*/ */
case OP_RowKey: /* out2-prerelease */ case OP_RowKey:
case OP_RowData: { /* out2-prerelease */ case OP_RowData: {
int i = pOp->p1; int i = pOp->p1;
Cursor *pC; Cursor *pC;
BtCursor *pCrsr; BtCursor *pCrsr;
u32 n; u32 n;
pOut = &p->aMem[pOp->p2];
/* Note that RowKey and RowData are really exactly the same instruction */ /* Note that RowKey and RowData are really exactly the same instruction */
assert( i>=0 && i<p->nCursor ); assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i]; pC = p->apCsr[i];
@ -3401,17 +3403,11 @@ case OP_RowData: { /* out2-prerelease */
goto too_big; goto too_big;
} }
} }
pOut->n = n; if( sqlite3VdbeMemGrow(pOut, n, 0) ){
if( n<=NBFS ){ goto no_mem;
pOut->flags = MEM_Blob | MEM_Short;
pOut->z = pOut->zShort;
}else{
char *z = sqlite3_malloc( n );
if( z==0 ) goto no_mem;
pOut->flags = MEM_Blob | MEM_Dyn;
pOut->xDel = 0;
pOut->z = z;
} }
pOut->n = n;
MemSetTypeFlag(pOut, MEM_Blob);
if( pC->isIndex ){ if( pC->isIndex ){
rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z); rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z);
}else{ }else{
@ -3450,7 +3446,7 @@ case OP_Rowid: { /* out2-prerelease */
v = keyToInt(v); v = keyToInt(v);
} }
pOut->u.i = v; pOut->u.i = v;
pOut->flags = MEM_Int; MemSetTypeFlag(pOut, MEM_Int);
break; break;
} }
@ -3642,8 +3638,9 @@ case OP_IdxInsert: { /* in2 */
/* Opcode: IdxDelete P1 P2 * * * /* Opcode: IdxDelete P1 P2 * * *
** **
** The content of register P2 is an index key built using the either the ** The content of register P2 is an index key built using the
** MakeIdxRec opcode. Removes that entry from the index. ** MakeIdxRec opcode. This opcode removes that entry from the
** index opened by cursor P1.
*/ */
case OP_IdxDelete: { /* in2 */ case OP_IdxDelete: { /* in2 */
int i = pOp->p1; int i = pOp->p1;
@ -3689,7 +3686,7 @@ case OP_IdxRowid: { /* out2-prerelease */
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
goto abort_due_to_error; goto abort_due_to_error;
} }
pOut->flags = MEM_Int; MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = rowid; pOut->u.i = rowid;
} }
} }
@ -3801,7 +3798,7 @@ case OP_Destroy: { /* out2-prerelease */
assert( iCnt==1 ); assert( iCnt==1 );
assert( (p->btreeMask & (1<<iDb))!=0 ); assert( (p->btreeMask & (1<<iDb))!=0 );
rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved); rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
pOut->flags = MEM_Int; MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = iMoved; pOut->u.i = iMoved;
#ifndef SQLITE_OMIT_AUTOVACUUM #ifndef SQLITE_OMIT_AUTOVACUUM
if( rc==SQLITE_OK && iMoved!=0 ){ if( rc==SQLITE_OK && iMoved!=0 ){
@ -3870,7 +3867,7 @@ case OP_CreateTable: { /* out2-prerelease */
rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
pOut->u.i = pgno; pOut->u.i = pgno;
pOut->flags = MEM_Int; MemSetTypeFlag(pOut, MEM_Int);
} }
break; break;
} }
@ -4023,12 +4020,8 @@ case OP_IntegrityCk: {
if( nErr==0 ){ if( nErr==0 ){
assert( z==0 ); assert( z==0 );
}else{ }else{
pIn1->z = z; sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
pIn1->n = strlen(z);
pIn1->flags = MEM_Str | MEM_Dyn | MEM_Term;
pIn1->xDel = 0;
} }
pIn1->enc = SQLITE_UTF8;
UPDATE_MAX_BLOBSIZE(pIn1); UPDATE_MAX_BLOBSIZE(pIn1);
sqlite3VdbeChangeEncoding(pIn1, encoding); sqlite3VdbeChangeEncoding(pIn1, encoding);
sqlite3_free(aRoot); sqlite3_free(aRoot);
@ -4058,8 +4051,7 @@ case OP_FifoRead: { /* jump */
CHECK_FOR_INTERRUPT; CHECK_FOR_INTERRUPT;
assert( pOp->p1>0 && pOp->p1<=p->nMem ); assert( pOp->p1>0 && pOp->p1<=p->nMem );
pOut = &p->aMem[pOp->p1]; pOut = &p->aMem[pOp->p1];
Release(pOut); MemSetTypeFlag(pOut, MEM_Int);
pOut->flags = MEM_Int;
if( sqlite3VdbeFifoPop(&p->sFifo, &pOut->u.i)==SQLITE_DONE ){ if( sqlite3VdbeFifoPop(&p->sFifo, &pOut->u.i)==SQLITE_DONE ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
@ -4137,7 +4129,7 @@ case OP_MemMax: { /* in1, in2 */
** not contain an integer. An assertion fault will result if you try. ** not contain an integer. An assertion fault will result if you try.
*/ */
case OP_IfPos: { /* jump, in1 */ case OP_IfPos: { /* jump, in1 */
assert( pIn1->flags==MEM_Int ); assert( pIn1->flags&MEM_Int );
if( pIn1->u.i>0 ){ if( pIn1->u.i>0 ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
@ -4152,7 +4144,7 @@ case OP_IfPos: { /* jump, in1 */
** not contain an integer. An assertion fault will result if you try. ** not contain an integer. An assertion fault will result if you try.
*/ */
case OP_IfNeg: { /* jump, in1 */ case OP_IfNeg: { /* jump, in1 */
assert( pIn1->flags==MEM_Int ); assert( pIn1->flags&MEM_Int );
if( pIn1->u.i<0 ){ if( pIn1->u.i<0 ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
@ -4167,7 +4159,7 @@ case OP_IfNeg: { /* jump, in1 */
** not contain an integer. An assertion fault will result if you try. ** not contain an integer. An assertion fault will result if you try.
*/ */
case OP_IfZero: { /* jump, in1 */ case OP_IfZero: { /* jump, in1 */
assert( pIn1->flags==MEM_Int ); assert( pIn1->flags&MEM_Int );
if( pIn1->u.i==0 ){ if( pIn1->u.i==0 ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
} }
@ -4502,7 +4494,7 @@ case OP_VRowid: { /* out2-prerelease */
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xRowid(pCur->pVtabCursor, &iRow); rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
pOut->flags = MEM_Int; MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = iRow; pOut->u.i = iRow;
break; break;
} }
@ -4531,8 +4523,15 @@ case OP_VColumn: {
pModule = pCur->pVtabCursor->pVtab->pModule; pModule = pCur->pVtabCursor->pVtab->pModule;
assert( pModule->xColumn ); assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext)); memset(&sContext, 0, sizeof(sContext));
sContext.s.flags = MEM_Null;
sContext.s.db = db; /* The output cell may already have a buffer allocated. Move
** the current contents to sContext.s so in case the user-function
** can use the already allocated buffer instead of allocating a
** new one.
*/
sqlite3VdbeMemMove(&sContext.s, pDest);
MemSetTypeFlag(&sContext.s, MEM_Null);
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2); rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);

View File

@ -94,13 +94,6 @@ struct Cursor {
}; };
typedef struct Cursor Cursor; typedef struct Cursor Cursor;
/*
** Number of bytes of string storage space available to each stack
** layer without having to malloc. NBFS is short for Number of Bytes
** For Strings.
*/
#define NBFS 32
/* /*
** A value for Cursor.cacheValid that means the cache is always invalid. ** A value for Cursor.cacheValid that means the cache is always invalid.
*/ */
@ -130,7 +123,6 @@ struct Mem {
u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */ u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
void (*xDel)(void *); /* If not null, call this function to delete Mem.z */ void (*xDel)(void *); /* If not null, call this function to delete Mem.z */
char zShort[NBFS]; /* Space for short strings */
}; };
/* One or more of the following flags are set to indicate the validOK /* One or more of the following flags are set to indicate the validOK
@ -154,6 +146,9 @@ struct Mem {
#define MEM_Real 0x0008 /* Value is a real number */ #define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Blob 0x0010 /* Value is a BLOB */ #define MEM_Blob 0x0010 /* Value is a BLOB */
#define MemSetTypeFlag(p, f) \
((p)->flags = ((p)->flags&~(MEM_Int|MEM_Real|MEM_Null|MEM_Blob|MEM_Str))|f)
/* Whenever Mem contains a valid string or blob representation, one of /* Whenever Mem contains a valid string or blob representation, one of
** the following flags must be set to determine the memory management ** the following flags must be set to determine the memory management
** policy for Mem.z. The MEM_Term flag tells us whether or not the ** policy for Mem.z. The MEM_Term flag tells us whether or not the
@ -163,7 +158,6 @@ struct Mem {
#define MEM_Dyn 0x0040 /* Need to call sqliteFree() on Mem.z */ #define MEM_Dyn 0x0040 /* Need to call sqliteFree() on Mem.z */
#define MEM_Static 0x0080 /* Mem.z points to a static string */ #define MEM_Static 0x0080 /* Mem.z points to a static string */
#define MEM_Ephem 0x0100 /* Mem.z points to an ephemeral string */ #define MEM_Ephem 0x0100 /* Mem.z points to an ephemeral string */
#define MEM_Short 0x0200 /* Mem.z points to Mem.zShort */
#define MEM_Agg 0x0400 /* Mem.z points to an agg function context */ #define MEM_Agg 0x0400 /* Mem.z points to an agg function context */
#define MEM_Zero 0x0800 /* Mem.i contains count of 0s appended to blob */ #define MEM_Zero 0x0800 /* Mem.i contains count of 0s appended to blob */
@ -398,6 +392,7 @@ void sqlite3VdbeMemRelease(Mem *p);
int sqlite3VdbeMemFinalize(Mem*, FuncDef*); int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
const char *sqlite3OpcodeName(int); const char *sqlite3OpcodeName(int);
int sqlite3VdbeOpcodeHasProperty(int, int); int sqlite3VdbeOpcodeHasProperty(int, int);
int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
#ifndef NDEBUG #ifndef NDEBUG
void sqlite3VdbeMemSanity(Mem*); void sqlite3VdbeMemSanity(Mem*);

View File

@ -944,6 +944,7 @@ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = sqlite3VdbeMemCopy(&p->aVar[i-1], pValue); rc = sqlite3VdbeMemCopy(&p->aVar[i-1], pValue);
} }
rc = sqlite3ApiExit(p->db, rc);
sqlite3_mutex_leave(p->db->mutex); sqlite3_mutex_leave(p->db->mutex);
return rc; return rc;
} }

View File

@ -735,11 +735,15 @@ void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
** Release an array of N Mem elements ** Release an array of N Mem elements
*/ */
static void releaseMemArray(Mem *p, int N){ static void releaseMemArray(Mem *p, int N){
if( p ){ if( p && N ){
sqlite3 *db = p->db;
int malloc_failed = db->mallocFailed;
while( N-->0 ){ while( N-->0 ){
assert( N<2 || p[0].db==p[1].db ); assert( N<2 || p[0].db==p[1].db );
sqlite3VdbeMemSetNull(p++); sqlite3VdbeMemRelease(p);
p++->flags = MEM_Null;
} }
db->mallocFailed = malloc_failed;
} }
} }
@ -786,6 +790,7 @@ int sqlite3VdbeList(
rc = SQLITE_ERROR; rc = SQLITE_ERROR;
sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0); sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0);
}else{ }else{
char *z;
Op *pOp = &p->aOp[i]; Op *pOp = &p->aOp[i];
if( p->explain==1 ){ if( p->explain==1 ){
pMem->flags = MEM_Int; pMem->flags = MEM_Int;
@ -819,18 +824,29 @@ int sqlite3VdbeList(
pMem++; pMem++;
} }
pMem->flags = MEM_Ephem|MEM_Str|MEM_Term; /* P4 */ if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */
pMem->z = displayP4(pOp, pMem->zShort, sizeof(pMem->zShort)); p->db->mallocFailed = 1;
assert( pMem->z!=0 ); return SQLITE_NOMEM;
pMem->n = strlen(pMem->z); }
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
z = displayP4(pOp, pMem->z, 32);
if( z!=pMem->z ){
sqlite3VdbeMemSetStr(pMem, z, -1, SQLITE_UTF8, 0);
}else{
assert( pMem->z!=0 );
pMem->n = strlen(pMem->z);
pMem->enc = SQLITE_UTF8;
}
pMem->type = SQLITE_TEXT; pMem->type = SQLITE_TEXT;
pMem->enc = SQLITE_UTF8;
pMem++; pMem++;
if( p->explain==1 ){ if( p->explain==1 ){
pMem->flags = MEM_Str|MEM_Term|MEM_Short; if( sqlite3VdbeMemGrow(pMem, 32, 0) ){
pMem->n = sprintf(pMem->zShort, "%.2x", pOp->p5); /* P5 */ p->db->mallocFailed = 1;
pMem->z = pMem->zShort; return SQLITE_NOMEM;
}
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
pMem->n = sprintf(pMem->z, "%.2x", pOp->p5); /* P5 */
pMem->type = SQLITE_TEXT; pMem->type = SQLITE_TEXT;
pMem->enc = SQLITE_UTF8; pMem->enc = SQLITE_UTF8;
pMem++; pMem++;
@ -1058,6 +1074,9 @@ static void closeAllCursorsExceptActiveVtabs(Vdbe *p){
static void Cleanup(Vdbe *p){ static void Cleanup(Vdbe *p){
int i; int i;
closeAllCursorsExceptActiveVtabs(p); closeAllCursorsExceptActiveVtabs(p);
for(i=1; i<=p->nMem; i++){
MemSetTypeFlag(&p->aMem[i], MEM_Null);
}
releaseMemArray(&p->aMem[1], p->nMem); releaseMemArray(&p->aMem[1], p->nMem);
sqlite3VdbeFifoClear(&p->sFifo); sqlite3VdbeFifoClear(&p->sFifo);
if( p->contextStack ){ if( p->contextStack ){
@ -2133,8 +2152,10 @@ int sqlite3VdbeRecordCompare(
Mem mem2; Mem mem2;
mem1.enc = pKeyInfo->enc; mem1.enc = pKeyInfo->enc;
mem1.db = pKeyInfo->db; mem1.db = pKeyInfo->db;
mem1.flags = 0;
mem2.enc = pKeyInfo->enc; mem2.enc = pKeyInfo->enc;
mem2.db = pKeyInfo->db; mem2.db = pKeyInfo->db;
mem2.flags = 0;
idx1 = GetVarint(aKey1, szHdr1); idx1 = GetVarint(aKey1, szHdr1);
d1 = szHdr1; d1 = szHdr1;
@ -2159,8 +2180,8 @@ int sqlite3VdbeRecordCompare(
/* Do the comparison /* Do the comparison
*/ */
rc = sqlite3MemCompare(&mem1, &mem2, i<nField ? pKeyInfo->aColl[i] : 0); rc = sqlite3MemCompare(&mem1, &mem2, i<nField ? pKeyInfo->aColl[i] : 0);
if( mem1.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem1); if( mem1.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem1);
if( mem2.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem2); if( mem2.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem2);
if( rc!=0 ){ if( rc!=0 ){
break; break;
} }
@ -2222,6 +2243,8 @@ int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){
if( nCellKey<=0 ){ if( nCellKey<=0 ){
return SQLITE_CORRUPT_BKPT; return SQLITE_CORRUPT_BKPT;
} }
m.flags = 0;
m.db = 0;
rc = sqlite3VdbeMemFromBtree(pCur, 0, nCellKey, 1, &m); rc = sqlite3VdbeMemFromBtree(pCur, 0, nCellKey, 1, &m);
if( rc ){ if( rc ){
return rc; return rc;
@ -2261,6 +2284,8 @@ int sqlite3VdbeIdxKeyCompare(
*res = 0; *res = 0;
return SQLITE_OK; return SQLITE_OK;
} }
m.db = 0;
m.flags = 0;
rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m); rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m);
if( rc ){ if( rc ){
return rc; return rc;

View File

@ -59,33 +59,83 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
#endif #endif
} }
/*
** Make sure pMem->z points to a writable allocation of at least
** n bytes.
**
** If the memory cell currently contains string or blob data
** and the third argument passed to this function is true, the
** current content of the cell is preserved. Otherwise, it may
** be discarded.
**
** This function sets the MEM_Dyn flag and clears any xDel callback.
** It also clears MEM_Ephem and MEM_Static. If the preserve flag is
** not set, Mem.n is zeroed.
*/
int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
int f = pMem->flags;
assert( (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==0
|| (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Dyn
|| (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Ephem
|| (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Static
);
if( ((f&MEM_Dyn)==0 || pMem->xDel || sqlite3MallocSize(pMem->z)<n) ){
/* Allocate the new buffer. The minimum allocation size is 32 bytes. */
char *z = 0;
if( n>0 ){
if( preserve && (f&MEM_Dyn) && !pMem->xDel ){
z = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
pMem->z = 0;
preserve = 0;
}else{
z = sqlite3DbMallocRaw(pMem->db, (n>32?n:32));
}
if( !z ){
return SQLITE_NOMEM;
}
}
/* If the value is currently a string or blob and the preserve flag
** is true, copy the content to the new buffer.
*/
if( pMem->flags&(MEM_Blob|MEM_Str) && preserve ){
int nCopy = (pMem->n>n?n:pMem->n);
memcpy(z, pMem->z, nCopy);
}
/* Release the old buffer. */
sqlite3VdbeMemRelease(pMem);
pMem->z = z;
pMem->flags |= MEM_Dyn;
pMem->flags &= ~(MEM_Ephem|MEM_Static);
pMem->xDel = 0;
}
return SQLITE_OK;
}
/* /*
** Make the given Mem object MEM_Dyn. ** Make the given Mem object MEM_Dyn.
** **
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
*/ */
int sqlite3VdbeMemDynamicify(Mem *pMem){ int sqlite3VdbeMemDynamicify(Mem *pMem){
int n; int f;
u8 *z;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
expandBlob(pMem); expandBlob(pMem);
if( (pMem->flags & (MEM_Ephem|MEM_Static|MEM_Short))==0 ){ f = pMem->flags;
return SQLITE_OK; if( (f&(MEM_Str|MEM_Blob)) && ((f&MEM_Dyn)==0 || pMem->xDel) ){
if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){
return SQLITE_NOMEM;
}
pMem->z[pMem->n] = 0;
pMem->z[pMem->n+1] = 0;
pMem->flags |= MEM_Term;
} }
assert( (pMem->flags & MEM_Dyn)==0 );
n = pMem->n;
assert( pMem->flags & (MEM_Str|MEM_Blob) );
z = sqlite3DbMallocRaw(pMem->db, n+2 );
if( z==0 ){
return SQLITE_NOMEM;
}
pMem->flags |= MEM_Dyn|MEM_Term;
pMem->xDel = 0;
memcpy(z, pMem->z, n );
z[n] = 0;
z[n+1] = 0;
pMem->z = (char*)z;
pMem->flags &= ~(MEM_Ephem|MEM_Static|MEM_Short);
return SQLITE_OK; return SQLITE_OK;
} }
@ -96,24 +146,22 @@ int sqlite3VdbeMemDynamicify(Mem *pMem){
#ifndef SQLITE_OMIT_INCRBLOB #ifndef SQLITE_OMIT_INCRBLOB
int sqlite3VdbeMemExpandBlob(Mem *pMem){ int sqlite3VdbeMemExpandBlob(Mem *pMem){
if( pMem->flags & MEM_Zero ){ if( pMem->flags & MEM_Zero ){
char *pNew;
int nByte; int nByte;
assert( (pMem->flags & MEM_Blob)!=0 ); assert( pMem->flags&MEM_Blob );
nByte = pMem->n + pMem->u.i;
if( nByte<=0 ) nByte = 1;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
pNew = sqlite3DbMallocRaw(pMem->db, nByte);
if( pNew==0 ){ /* Set nByte to the number of bytes required to store the expanded blob. */
nByte = pMem->n + pMem->u.i;
if( nByte<=0 ){
nByte = 1;
}
if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
return SQLITE_NOMEM; return SQLITE_NOMEM;
} }
memcpy(pNew, pMem->z, pMem->n);
memset(&pNew[pMem->n], 0, pMem->u.i); memset(&pMem->z[pMem->n], 0, pMem->u.i);
sqlite3VdbeMemRelease(pMem);
pMem->z = pNew;
pMem->n += pMem->u.i; pMem->n += pMem->u.i;
pMem->u.i = 0; pMem->flags &= ~(MEM_Zero|MEM_Term);
pMem->flags &= ~(MEM_Zero|MEM_Static|MEM_Ephem|MEM_Short|MEM_Term);
pMem->flags |= MEM_Dyn;
} }
return SQLITE_OK; return SQLITE_OK;
} }
@ -127,33 +175,7 @@ int sqlite3VdbeMemExpandBlob(Mem *pMem){
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
*/ */
int sqlite3VdbeMemMakeWriteable(Mem *pMem){ int sqlite3VdbeMemMakeWriteable(Mem *pMem){
int n; return sqlite3VdbeMemDynamicify(pMem);
u8 *z;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
expandBlob(pMem);
if( (pMem->flags & (MEM_Ephem|MEM_Static))==0 ){
return SQLITE_OK;
}
assert( (pMem->flags & MEM_Dyn)==0 );
assert( pMem->flags & (MEM_Str|MEM_Blob) );
if( (n = pMem->n)+2<sizeof(pMem->zShort) ){
z = (u8*)pMem->zShort;
pMem->flags |= MEM_Short|MEM_Term;
}else{
z = sqlite3DbMallocRaw(pMem->db, n+2 );
if( z==0 ){
return SQLITE_NOMEM;
}
pMem->flags |= MEM_Dyn|MEM_Term;
pMem->xDel = 0;
}
memcpy(z, pMem->z, n );
z[n] = 0;
z[n+1] = 0;
pMem->z = (char*)z;
pMem->flags &= ~(MEM_Ephem|MEM_Static);
assert(0==(1&(int)pMem->z));
return SQLITE_OK;
} }
/* /*
@ -164,27 +186,12 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){
if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){ if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){
return SQLITE_OK; /* Nothing to do */ return SQLITE_OK; /* Nothing to do */
} }
if( pMem->flags & (MEM_Static|MEM_Ephem) ){ if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){
return sqlite3VdbeMemMakeWriteable(pMem); return SQLITE_NOMEM;
}else{
char *z;
sqlite3VdbeMemExpandBlob(pMem);
z = sqlite3DbMallocRaw(pMem->db, pMem->n+2);
if( !z ){
return SQLITE_NOMEM;
}
memcpy(z, pMem->z, pMem->n);
z[pMem->n] = 0;
z[pMem->n+1] = 0;
if( pMem->xDel ){
pMem->xDel(pMem->z);
}else{
sqlite3_free(pMem->z);
}
pMem->xDel = 0;
pMem->z = z;
pMem->flags |= MEM_Term;
} }
pMem->z[pMem->n] = 0;
pMem->z[pMem->n+1] = 0;
pMem->flags |= MEM_Term;
return SQLITE_OK; return SQLITE_OK;
} }
@ -204,29 +211,32 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){
int sqlite3VdbeMemStringify(Mem *pMem, int enc){ int sqlite3VdbeMemStringify(Mem *pMem, int enc){
int rc = SQLITE_OK; int rc = SQLITE_OK;
int fg = pMem->flags; int fg = pMem->flags;
char *z = pMem->zShort; const int nByte = 32;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( !(fg&MEM_Zero) ); assert( !(fg&MEM_Zero) );
assert( !(fg&(MEM_Str|MEM_Blob)) ); assert( !(fg&(MEM_Str|MEM_Blob)) );
assert( fg&(MEM_Int|MEM_Real) ); assert( fg&(MEM_Int|MEM_Real) );
/* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8 if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){
return SQLITE_NOMEM;
}
/* For a Real or Integer, use sqlite3_mprintf() to produce the UTF-8
** string representation of the value. Then, if the required encoding ** string representation of the value. Then, if the required encoding
** is UTF-16le or UTF-16be do a translation. ** is UTF-16le or UTF-16be do a translation.
** **
** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16. ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
*/ */
if( fg & MEM_Int ){ if( fg & MEM_Int ){
sqlite3_snprintf(NBFS, z, "%lld", pMem->u.i); sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i);
}else{ }else{
assert( fg & MEM_Real ); assert( fg & MEM_Real );
sqlite3_snprintf(NBFS, z, "%!.15g", pMem->r); sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->r);
} }
pMem->n = strlen(z); pMem->n = strlen(pMem->z);
pMem->z = z;
pMem->enc = SQLITE_UTF8; pMem->enc = SQLITE_UTF8;
pMem->flags |= MEM_Str | MEM_Short | MEM_Term; pMem->flags |= MEM_Str|MEM_Term;
sqlite3VdbeChangeEncoding(pMem, enc); sqlite3VdbeChangeEncoding(pMem, enc);
return rc; return rc;
} }
@ -246,19 +256,15 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
ctx.s.flags = MEM_Null; ctx.s.flags = MEM_Null;
ctx.s.z = pMem->zShort;
ctx.s.db = pMem->db; ctx.s.db = pMem->db;
ctx.pMem = pMem; ctx.pMem = pMem;
ctx.pFunc = pFunc; ctx.pFunc = pFunc;
ctx.isError = 0; ctx.isError = 0;
pFunc->xFinalize(&ctx); pFunc->xFinalize(&ctx);
if( pMem->z && pMem->z!=pMem->zShort ){ if( pMem->z ){
sqlite3_free( pMem->z ); sqlite3_free( pMem->z );
} }
*pMem = ctx.s; *pMem = ctx.s;
if( pMem->flags & MEM_Short ){
pMem->z = pMem->zShort;
}
rc = (ctx.isError?SQLITE_ERROR:SQLITE_OK); rc = (ctx.isError?SQLITE_ERROR:SQLITE_OK);
} }
return rc; return rc;
@ -394,14 +400,17 @@ void sqlite3VdbeIntegerAffinity(Mem *pMem){
} }
} }
static void setTypeFlag(Mem *pMem, int f){
MemSetTypeFlag(pMem, f);
}
/* /*
** Convert pMem to type integer. Invalidate any prior representations. ** Convert pMem to type integer. Invalidate any prior representations.
*/ */
int sqlite3VdbeMemIntegerify(Mem *pMem){ int sqlite3VdbeMemIntegerify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
pMem->u.i = sqlite3VdbeIntValue(pMem); pMem->u.i = sqlite3VdbeIntValue(pMem);
sqlite3VdbeMemRelease(pMem); setTypeFlag(pMem, MEM_Int);
pMem->flags = MEM_Int;
return SQLITE_OK; return SQLITE_OK;
} }
@ -412,8 +421,7 @@ int sqlite3VdbeMemIntegerify(Mem *pMem){
int sqlite3VdbeMemRealify(Mem *pMem){ int sqlite3VdbeMemRealify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
pMem->r = sqlite3VdbeRealValue(pMem); pMem->r = sqlite3VdbeRealValue(pMem);
sqlite3VdbeMemRelease(pMem); setTypeFlag(pMem, MEM_Real);
pMem->flags = MEM_Real;
return SQLITE_OK; return SQLITE_OK;
} }
@ -434,8 +442,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
sqlite3VdbeMemIntegerify(pMem); sqlite3VdbeMemIntegerify(pMem);
}else{ }else{
pMem->r = r1; pMem->r = r1;
pMem->flags = MEM_Real; setTypeFlag(pMem, MEM_Real);
sqlite3VdbeMemRelease(pMem);
} }
return SQLITE_OK; return SQLITE_OK;
} }
@ -444,10 +451,8 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
** Delete any previous value and set the value stored in *pMem to NULL. ** Delete any previous value and set the value stored in *pMem to NULL.
*/ */
void sqlite3VdbeMemSetNull(Mem *pMem){ void sqlite3VdbeMemSetNull(Mem *pMem){
sqlite3VdbeMemRelease(pMem); setTypeFlag(pMem, MEM_Null);
pMem->flags = MEM_Null;
pMem->type = SQLITE_NULL; pMem->type = SQLITE_NULL;
pMem->n = 0;
} }
/* /*
@ -456,12 +461,12 @@ void sqlite3VdbeMemSetNull(Mem *pMem){
*/ */
void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){ void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
sqlite3VdbeMemRelease(pMem); sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Blob|MEM_Zero|MEM_Short; setTypeFlag(pMem, MEM_Blob);
pMem->flags = MEM_Blob|MEM_Zero;
pMem->type = SQLITE_BLOB; pMem->type = SQLITE_BLOB;
pMem->n = 0; pMem->n = 0;
if( n<0 ) n = 0; if( n<0 ) n = 0;
pMem->u.i = n; pMem->u.i = n;
pMem->z = pMem->zShort;
pMem->enc = SQLITE_UTF8; pMem->enc = SQLITE_UTF8;
} }
@ -514,10 +519,10 @@ int sqlite3VdbeMemTooBig(Mem *p){
*/ */
void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
sqlite3VdbeMemRelease(pTo); sqlite3VdbeMemRelease(pTo);
memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort)); memcpy(pTo, pFrom, sizeof(*pFrom));
pTo->xDel = 0; pTo->xDel = 0;
if( pTo->flags & (MEM_Str|MEM_Blob) ){ if( pTo->flags&MEM_Dyn ){
pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short|MEM_Ephem); pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
assert( srcType==MEM_Ephem || srcType==MEM_Static ); assert( srcType==MEM_Ephem || srcType==MEM_Static );
pTo->flags |= srcType; pTo->flags |= srcType;
} }
@ -528,12 +533,46 @@ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
** freed before the copy is made. ** freed before the copy is made.
*/ */
int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
int rc; int rc = SQLITE_OK;
sqlite3VdbeMemShallowCopy(pTo, pFrom, MEM_Ephem); char *zBuf = 0;
if( pTo->flags & MEM_Ephem ){
rc = sqlite3VdbeMemMakeWriteable(pTo); /* If cell pTo currently has a reusable buffer, save a pointer to it
** in local variable zBuf. This function attempts to avoid freeing
** this buffer.
*/
if( pTo->xDel ){
sqlite3VdbeMemRelease(pTo);
}else if( pTo->flags&MEM_Dyn ){
zBuf = pTo->z;
}
/* Copy the contents of *pFrom to *pTo */
memcpy(pTo, pFrom, sizeof(*pFrom));
if( pTo->flags&(MEM_Str|MEM_Blob) && pTo->flags&MEM_Static ){
/* pFrom contained a pointer to a static string. In this case,
** free any dynamically allocated buffer associated with pTo.
*/
sqlite3_free(zBuf);
}else{ }else{
rc = SQLITE_OK; char *zData = pTo->z;
pTo->z = zBuf;
pTo->flags &= ~(MEM_Static|MEM_Ephem);
pTo->flags |= MEM_Dyn;
pTo->xDel = 0;
if( pTo->flags&(MEM_Str|MEM_Blob) ){
if( sqlite3VdbeMemGrow(pTo, pTo->n+2, 0) ){
pTo->n = 0;
rc = SQLITE_NOMEM;
}else{
memcpy(pTo->z, zData, pTo->n);
pTo->z[pTo->n] = '\0';
pTo->z[pTo->n+1] = '\0';
pTo->flags |= MEM_Term;
}
}
} }
return rc; return rc;
} }
@ -552,15 +591,18 @@ void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
sqlite3VdbeMemRelease(pTo); sqlite3VdbeMemRelease(pTo);
} }
memcpy(pTo, pFrom, sizeof(Mem)); memcpy(pTo, pFrom, sizeof(Mem));
if( pFrom->flags & MEM_Short ){
pTo->z = pTo->zShort;
}
pFrom->flags = MEM_Null; pFrom->flags = MEM_Null;
pFrom->xDel = 0; pFrom->xDel = 0;
} }
/* /*
** Change the value of a Mem to be a string or a BLOB. ** Change the value of a Mem to be a string or a BLOB.
**
** The memory management strategy depends on the value of the xDel
** parameter. If the value passed is SQLITE_TRANSIENT, then the
** string is copied into a (possibly existing) buffer managed by the
** Mem structure. Otherwise, any existing buffer is freed and the
** pointer copied.
*/ */
int sqlite3VdbeMemSetStr( int sqlite3VdbeMemSetStr(
Mem *pMem, /* Memory cell to set to string value */ Mem *pMem, /* Memory cell to set to string value */
@ -569,59 +611,56 @@ int sqlite3VdbeMemSetStr(
u8 enc, /* Encoding of z. 0 for BLOBs */ u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */ void (*xDel)(void*) /* Destructor function */
){ ){
int nByte = n; /* New value for pMem->n */
int flags = 0; /* New value for pMem->flags */
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
sqlite3VdbeMemRelease(pMem);
/* If z is a NULL pointer, set pMem to contain an SQL NULL. */
if( !z ){ if( !z ){
pMem->flags = MEM_Null; sqlite3VdbeMemSetNull(pMem);
pMem->type = SQLITE_NULL;
return SQLITE_OK; return SQLITE_OK;
} }
pMem->z = (char *)z;
if( xDel==SQLITE_STATIC ){ flags = (enc==0?MEM_Blob:MEM_Str);
pMem->flags = MEM_Static; if( nByte<0 ){
}else if( xDel==SQLITE_TRANSIENT ){ assert( enc!=0 );
pMem->flags = MEM_Ephem; nByte = ((enc==SQLITE_UTF8)?strlen(z):sqlite3Utf16ByteLen(z, -1));
}else{ flags |= MEM_Term;
pMem->flags = MEM_Dyn;
pMem->xDel = xDel;
} }
pMem->enc = enc; /* The following block sets the new values of Mem.z and Mem.xDel. It
pMem->type = enc==0 ? SQLITE_BLOB : SQLITE_TEXT; ** also sets a flag in local variable "flags" to indicate the memory
pMem->n = n; ** management (one of MEM_Dyn or MEM_Static).
*/
if( xDel==SQLITE_TRANSIENT ){
int nAlloc = nByte;
if( flags&MEM_Term ){
nAlloc += (enc==SQLITE_UTF8?1:2);
}
if( sqlite3VdbeMemGrow(pMem, nAlloc, 0) ){
return SQLITE_NOMEM;
}
memcpy(pMem->z, z, nAlloc);
flags |= MEM_Dyn;
}else{
sqlite3VdbeMemRelease(pMem);
pMem->z = (char *)z;
pMem->xDel = xDel;
flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
}
assert( enc==0 || enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE pMem->n = nByte;
|| enc==SQLITE_UTF16BE ); pMem->flags = flags;
switch( enc ){ pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
case 0: pMem->type = (enc==0 ? SQLITE_BLOB : SQLITE_TEXT);
pMem->flags |= MEM_Blob;
pMem->enc = SQLITE_UTF8;
break;
case SQLITE_UTF8:
pMem->flags |= MEM_Str;
if( n<0 ){
pMem->n = strlen(z);
pMem->flags |= MEM_Term;
}
break;
#ifndef SQLITE_OMIT_UTF16 #ifndef SQLITE_OMIT_UTF16
case SQLITE_UTF16LE: if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
case SQLITE_UTF16BE: return SQLITE_NOMEM;
pMem->flags |= MEM_Str;
if( pMem->n<0 ){
pMem->n = sqlite3Utf16ByteLen(pMem->z,-1);
pMem->flags |= MEM_Term;
}
if( sqlite3VdbeMemHandleBom(pMem) ){
return SQLITE_NOMEM;
}
#endif /* SQLITE_OMIT_UTF16 */
}
if( pMem->flags&MEM_Ephem ){
return sqlite3VdbeMemMakeWriteable(pMem);
} }
#endif
return SQLITE_OK; return SQLITE_OK;
} }
@ -769,6 +808,7 @@ int sqlite3VdbeMemFromBtree(
char *zData; /* Data from the btree layer */ char *zData; /* Data from the btree layer */
int available = 0; /* Number of bytes available on the local btree page */ int available = 0; /* Number of bytes available on the local btree page */
sqlite3 *db; /* Database connection */ sqlite3 *db; /* Database connection */
int rc = SQLITE_OK;
db = sqlite3BtreeCursorDb(pCur); db = sqlite3BtreeCursorDb(pCur);
assert( sqlite3_mutex_held(db->mutex) ); assert( sqlite3_mutex_held(db->mutex) );
@ -779,49 +819,28 @@ int sqlite3VdbeMemFromBtree(
} }
assert( zData!=0 ); assert( zData!=0 );
pMem->db = db; if( offset+amt<=available && ((pMem->flags&MEM_Dyn)==0 || pMem->xDel) ){
pMem->n = amt; sqlite3VdbeMemRelease(pMem);
if( offset+amt<=available ){
pMem->z = &zData[offset]; pMem->z = &zData[offset];
pMem->flags = MEM_Blob|MEM_Ephem; pMem->flags = MEM_Blob|MEM_Ephem;
}else{ }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
int rc; pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
if( amt>NBFS-2 ){
zData = (char *)sqlite3DbMallocRaw(db, amt+2);
if( !zData ){
return SQLITE_NOMEM;
}
pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
pMem->xDel = 0;
}else{
zData = &(pMem->zShort[0]);
pMem->flags = MEM_Blob|MEM_Short|MEM_Term;
}
pMem->z = zData;
pMem->enc = 0; pMem->enc = 0;
pMem->type = SQLITE_BLOB; pMem->type = SQLITE_BLOB;
if( key ){ if( key ){
rc = sqlite3BtreeKey(pCur, offset, amt, zData); rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
}else{ }else{
rc = sqlite3BtreeData(pCur, offset, amt, zData); rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
} }
zData[amt] = 0; pMem->z[amt] = 0;
zData[amt+1] = 0; pMem->z[amt+1] = 0;
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
if( amt>NBFS-2 ){ sqlite3VdbeMemRelease(pMem);
assert( zData!=pMem->zShort );
assert( pMem->flags & MEM_Dyn );
sqlite3_free(zData);
} else {
assert( zData==pMem->zShort );
assert( pMem->flags & MEM_Short );
}
return rc;
} }
} }
pMem->n = amt;
return SQLITE_OK; return rc;
} }
#if 0 #if 0
@ -1019,7 +1038,7 @@ void sqlite3ValueSetStr(
*/ */
void sqlite3ValueFree(sqlite3_value *v){ void sqlite3ValueFree(sqlite3_value *v){
if( !v ) return; if( !v ) return;
sqlite3ValueSetStr(v, 0, 0, SQLITE_UTF8, SQLITE_STATIC); sqlite3VdbeMemRelease((Mem *)v);
sqlite3_free(v); sqlite3_free(v);
} }

View File

@ -13,7 +13,7 @@
# that they have little in common. # that they have little in common.
# #
# #
# $Id: mallocB.test,v 1.7 2008/01/17 20:26:47 drh Exp $ # $Id: mallocB.test,v 1.8 2008/02/13 18:25:27 danielk1977 Exp $
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@ -31,7 +31,7 @@ source $testdir/malloc_common.tcl
do_malloc_test mallocB-1 -sqlbody {SELECT - 456} do_malloc_test mallocB-1 -sqlbody {SELECT - 456}
do_malloc_test mallocB-2 -sqlbody {SELECT - 456.1} do_malloc_test mallocB-2 -sqlbody {SELECT - 456.1}
do_malloc_test mallocB-3 -sqlbody {SELECT random()} do_malloc_test mallocB-3 -sqlbody {SELECT random()}
do_malloc_test mallocB-4 -sqlbody {SELECT zeroblob(1000)} do_malloc_test mallocB-4 -sqlbody {SELECT length(zeroblob(1000))}
ifcapable subquery { ifcapable subquery {
do_malloc_test mallocB-5 -sqlbody {SELECT * FROM (SELECT 1) GROUP BY 1;} do_malloc_test mallocB-5 -sqlbody {SELECT * FROM (SELECT 1) GROUP BY 1;}
} }

View File

@ -21,7 +21,7 @@
# sqlite3_value_bytes() # sqlite3_value_bytes()
# sqlite3_value_bytes16() # sqlite3_value_bytes16()
# #
# $Id: ptrchng.test,v 1.2 2007/09/12 17:01:45 danielk1977 Exp $ # $Id: ptrchng.test,v 1.3 2008/02/13 18:25:27 danielk1977 Exp $
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@ -52,6 +52,8 @@ do_test ptrchng-1.1 {
# For the short entries that fit in the Mem.zBuf[], the pointer should # For the short entries that fit in the Mem.zBuf[], the pointer should
# never change regardless of what type conversions occur. # never change regardless of what type conversions occur.
# #
# UPDATE: No longer true, as Mem.zBuf[] has been removed.
#
do_test ptrchng-2.1 { do_test ptrchng-2.1 {
execsql { execsql {
SELECT pointer_change(y, 'text', 'noop', 'blob') FROM t1 WHERE x=1 SELECT pointer_change(y, 'text', 'noop', 'blob') FROM t1 WHERE x=1
@ -61,18 +63,18 @@ do_test ptrchng-2.2 {
execsql { execsql {
SELECT pointer_change(y, 'blob', 'noop', 'text') FROM t1 WHERE x=1 SELECT pointer_change(y, 'blob', 'noop', 'text') FROM t1 WHERE x=1
} }
} {0} } {1}
ifcapable utf16 { ifcapable utf16 {
do_test ptrchng-2.3 { do_test ptrchng-2.3 {
execsql { execsql {
SELECT pointer_change(y, 'text', 'noop', 'text16') FROM t1 WHERE x=1 SELECT pointer_change(y, 'text', 'noop', 'text16') FROM t1 WHERE x=1
} }
} {0} } {1}
do_test ptrchng-2.4 { do_test ptrchng-2.4 {
execsql { execsql {
SELECT pointer_change(y, 'blob', 'noop', 'text16') FROM t1 WHERE x=1 SELECT pointer_change(y, 'blob', 'noop', 'text16') FROM t1 WHERE x=1
} }
} {0} } {1}
do_test ptrchng-2.5 { do_test ptrchng-2.5 {
execsql { execsql {
SELECT pointer_change(y, 'text16', 'noop', 'blob') FROM t1 WHERE x=1 SELECT pointer_change(y, 'text16', 'noop', 'blob') FROM t1 WHERE x=1
@ -82,7 +84,7 @@ ifcapable utf16 {
execsql { execsql {
SELECT pointer_change(y, 'text16', 'noop', 'text') FROM t1 WHERE x=1 SELECT pointer_change(y, 'text16', 'noop', 'text') FROM t1 WHERE x=1
} }
} {0} } {1}
} }
do_test ptrchng-2.11 { do_test ptrchng-2.11 {
execsql { execsql {
@ -93,18 +95,18 @@ do_test ptrchng-2.12 {
execsql { execsql {
SELECT pointer_change(y, 'blob', 'noop', 'text') FROM t1 WHERE x=3 SELECT pointer_change(y, 'blob', 'noop', 'text') FROM t1 WHERE x=3
} }
} {0} } {1}
ifcapable utf16 { ifcapable utf16 {
do_test ptrchng-2.13 { do_test ptrchng-2.13 {
execsql { execsql {
SELECT pointer_change(y, 'text', 'noop', 'text16') FROM t1 WHERE x=3 SELECT pointer_change(y, 'text', 'noop', 'text16') FROM t1 WHERE x=3
} }
} {0} } {1}
do_test ptrchng-2.14 { do_test ptrchng-2.14 {
execsql { execsql {
SELECT pointer_change(y, 'blob', 'noop', 'text16') FROM t1 WHERE x=3 SELECT pointer_change(y, 'blob', 'noop', 'text16') FROM t1 WHERE x=3
} }
} {0} } {1}
do_test ptrchng-2.15 { do_test ptrchng-2.15 {
execsql { execsql {
SELECT pointer_change(y, 'text16', 'noop', 'blob') FROM t1 WHERE x=3 SELECT pointer_change(y, 'text16', 'noop', 'blob') FROM t1 WHERE x=3
@ -115,7 +117,7 @@ btree_breakpoint
execsql { execsql {
SELECT pointer_change(y, 'text16', 'noop', 'text') FROM t1 WHERE x=3 SELECT pointer_change(y, 'text16', 'noop', 'text') FROM t1 WHERE x=3
} }
} {0} } {1}
} }
# For the long entries that do not fit in the Mem.zBuf[], the pointer # For the long entries that do not fit in the Mem.zBuf[], the pointer
@ -130,7 +132,7 @@ do_test ptrchng-3.2 {
execsql { execsql {
SELECT pointer_change(y, 'blob', 'noop', 'text') FROM t1 WHERE x=2 SELECT pointer_change(y, 'blob', 'noop', 'text') FROM t1 WHERE x=2
} }
} {0} } {1}
ifcapable utf16 { ifcapable utf16 {
do_test ptrchng-3.3 { do_test ptrchng-3.3 {
execsql { execsql {
@ -162,7 +164,7 @@ do_test ptrchng-3.12 {
execsql { execsql {
SELECT pointer_change(y, 'blob', 'noop', 'text') FROM t1 WHERE x=4 SELECT pointer_change(y, 'blob', 'noop', 'text') FROM t1 WHERE x=4
} }
} {0} } {1}
ifcapable utf16 { ifcapable utf16 {
do_test ptrchng-3.13 { do_test ptrchng-3.13 {
execsql { execsql {

View File

@ -11,7 +11,7 @@
# This file implements some common TCL routines used for regression # This file implements some common TCL routines used for regression
# testing the SQLite library # testing the SQLite library
# #
# $Id: tester.tcl,v 1.103 2008/02/08 18:25:30 danielk1977 Exp $ # $Id: tester.tcl,v 1.104 2008/02/13 18:25:27 danielk1977 Exp $
set tcl_precision 15 set tcl_precision 15
@ -227,6 +227,9 @@ proc finalize_testing {} {
} }
puts "Maximum memory usage: [sqlite3_memory_highwater 1] bytes" puts "Maximum memory usage: [sqlite3_memory_highwater 1] bytes"
puts "Current memory usage: [sqlite3_memory_highwater] bytes" puts "Current memory usage: [sqlite3_memory_highwater] bytes"
if {[info commands sqlite3_memdebug_malloc_count] ne ""} {
puts "Number of malloc() : [sqlite3_memdebug_malloc_count] calls"
}
foreach f [glob -nocomplain test.db-*-journal] { foreach f [glob -nocomplain test.db-*-journal] {
file delete -force $f file delete -force $f
} }