]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Where possible, avoid freeing buffers allocated for vdbe memory cells in case they...
authordanielk1977 <danielk1977@noemail.net>
Wed, 13 Feb 2008 18:25:27 +0000 (18:25 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Wed, 13 Feb 2008 18:25:27 +0000 (18:25 +0000)
FossilOrigin-Name: 990237e27e417aff3dbf05784b716c21f3761a3a

25 files changed:
manifest
manifest.uuid
src/attach.c
src/insert.c
src/legacy.c
src/mem1.c
src/mem2.c
src/mem3.c
src/os.c
src/pragma.c
src/select.c
src/sqliteInt.h
src/tclsqlite.c
src/test1.c
src/test8.c
src/test_malloc.c
src/utf.c
src/vdbe.c
src/vdbeInt.h
src/vdbeapi.c
src/vdbeaux.c
src/vdbemem.c
test/mallocB.test
test/ptrchng.test
test/tester.tcl

index fc1ff17d92658b05be6c978b3292a1affef36c53..d87aedc6ca4467a47902090f2b1f38c87a53d805 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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)
-D 2008-02-12T16:52:14
+C Where\spossible,\savoid\sfreeing\sbuffers\sallocated\sfor\svdbe\smemory\scells\sin\scase\sthey\scan\sbe\sreused.\s(CVS\s4783)
+D 2008-02-13T18:25:27
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in bc2b5df3e3d0d4b801b824b7ef6dec43812b049b
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -80,7 +80,7 @@ F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
 F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc
 F src/alter.c b494a50f239a760565ce6220ee316e96956ec054
 F src/analyze.c a78ac494668581fe7f54ee63700815bb0ea34261
-F src/attach.c 90665c7ef5145e066570f66d7f0f15cdd0a4d14b
+F src/attach.c e13d62597e8725075b27186817f7e745122af24e
 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
 F src/btmutex.c 483ced3c52205b04b97df69161fadbf87f4f1ea2
 F src/btree.c 29ea577155f39be65bdec1c7782301ff2ee9eb3f
@@ -97,24 +97,24 @@ F src/fault.c 049b88b8ba0a1db3240aeaf9695cd08b9a3ba9e1
 F src/func.c 8e3d0c59961dc403716767308ee764504179054b
 F src/hash.c 2dc6afe7478a0b739499af360c8863c900ea11a8
 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
-F src/insert.c d422fda2d1f02219871cb7e3e4b49c680632450e
+F src/insert.c b313f5ecadf82dda15b1aa6780b0310eceb9e776
 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
-F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
+F src/legacy.c cb1939fdeb91ea88fb44fbd2768a10e14bc44650
 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
 F src/loadext.c d17a0f760d6866aacf5262f97d8efaaad379cdd7
 F src/main.c b4014b71979a58d6aa79549fdf87175ab7bdf1cc
 F src/malloc.c 60e392a4c12c839517f9b0db7b995f825444fb35
 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
-F src/mem1.c 6d1a11864963d249c67e72ad5f6533b040333880
-F src/mem2.c 607af52ad7593f34934e7e4fa53a364556853d30
-F src/mem3.c 9d80034bb004c1bddc28d6befe1ddb044d18deab
+F src/mem1.c b15e107d51bdd4bcf410c18798ee48bee4768d4e
+F src/mem2.c ed0cb11ae43a3cc92bfb07172c2801956e94eaba
+F src/mem3.c cf1bf5b2f9d4d76e465c84c0607f6882d3b1b522
 F src/mem4.c 36ecd536a8b7acfe4cbf011353dae6ea68121e40
 F src/mutex.c 3259f62c2429967aee6dc112117a6d2f499ef061
 F src/mutex.h 079fa6fe9da18ceb89e79012c010594c6672addb
 F src/mutex_os2.c 19ab15764736f13b94b4f70e53f77547cbddd47a
 F src/mutex_unix.c a6e111947a3cdaa2cda394ed060d7f496fcb4af8
 F src/mutex_w32.c 6e197765f283815496193e78e9548b5d0e53b68e
-F src/os.c 50c0c1706c35f872db312815aaecc4b5ebcd6a4c
+F src/os.c 2f2753b8d33f79d169c43d6bb0b25b3c58fd33de
 F src/os.h d04706d54a072c7a30ab9e346ad916ef28c842d5
 F src/os_common.h 98862f120ca6bf7a48ce8b16f158b77d00bc9d2f
 F src/os_os2.c bf1cd3d4f42c1b1ab059c12732cd9f7be4e718a6
@@ -128,27 +128,27 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
 F src/pager.c 2ed81808091ce42ceb1cf209e4ce87922a0065c8
 F src/pager.h 8174615ffd14ccc2cad2b081b919a398fa95e3f9
 F src/parse.y 00f2698c8ae84f315be5e3f10b63c94f531fdd6d
-F src/pragma.c 2bb8d6882b9a330e041acd05fb6aff5a01bf0a08
+F src/pragma.c e3f39f8576234887ecd0c1de43dc51af5855930c
 F src/prepare.c 1b0601ca3f97a9d253cc08697484e3045a1678e9
 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
 F src/random.c 02ef38b469237482f1ea14a78b2087cfbaec48bd
-F src/select.c 394aa3542e8df599dcca77b0e75f7875760a13ad
+F src/select.c 1d780691071af7d58b83a6b38517c2687dd83c5b
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c ca06cb687c40a8bff6307b5fad41a0e86a0f8558
 F src/sqlite.h.in 690736613958e0f462e08ae2a9136fa335214edc
 F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
-F src/sqliteInt.h e4ca11fff0cdac38551b75a2a278edb8ad9e1f00
+F src/sqliteInt.h 822045362bdddd303a0b17aa09679ba735ffbaa1
 F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
 F src/table.c 46ccf9b7892a86f57420ae7bac69ecd5e72d26b5
-F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
-F src/test1.c 5363a117741f26e84b85e30757f0f4414331c46f
+F src/tclsqlite.c 0d4483e37c6a1e87f80565e50d977df6dd2bf732
+F src/test1.c 28b135491b436b1df6390a8b53834da2f94efca4
 F src/test2.c 77b34303883b9d722c65a6879bb0163a400e3789
 F src/test3.c 4557ee13c6e5921eb28979ff77cdbd913bfde6be
 F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
 F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
 F src/test6.c f8b34a6ff04937092327798ddf0ab46863535bc5
 F src/test7.c acec2256c7c2d279db5a8b5fa1a2a68fcc942c67
-F src/test8.c cab3f576353dfef4877c7cc3b0d0e48acc65c37c
+F src/test8.c 25e127f0e21f59da24fa33cdbc645851cfb933f1
 F src/test9.c 4615ef08750245a2d96aaa7cbe2fb4aff2b57acc
 F src/test_async.c 5f21392d66869a4c87dc9153e40d0dc0e085261f
 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_hexio.c 1a1cd8324d57585ea86b922f609fa1fbaaf9662d
 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_onefile.c 54282b6796d55d7acc489be83b89b8715e7d3756
 F src/test_schema.c 12c9de7661d6294eec2d57afbb52e2af1128084f
@@ -167,17 +167,17 @@ F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
 F src/tokenize.c c4b79fd48ddb709b2b8522b7d93a5a3d98168ca4
 F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3
 F src/update.c 9b3be169cd2a0b065717164aa0f90aa48f34aed1
-F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
+F src/utf.c 32b00d6e19010025e58f2ecb2f921d5e126771b4
 F src/util.c c56e41ed4769c1f2b8af9ffde4757a7b4fb08ed1
 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
-F src/vdbe.c 1049375248b494e626598abffeeb31052c660c78
+F src/vdbe.c a172f5134d19ae910134e28987bf7906523c9b6f
 F src/vdbe.h 58a7d931ffb704e034b2a725981cfa5bd406fad9
-F src/vdbeInt.h 969d360acc85f7b2069a8169b4f8a3e1fbaccd44
-F src/vdbeapi.c 61b37dbe11baa221baea7f93c01780705d2419ed
-F src/vdbeaux.c 771b9ffd7b42cbb4bd029d7a9414a7cb03f924a7
+F src/vdbeInt.h 76c81d057a39813de0fda3cad1498655d53ec69d
+F src/vdbeapi.c cf9fc963efae3cdf5de08e2a9718b487059c7fc5
+F src/vdbeaux.c 36d4db24659146606a1c755650f2a70cf88eec25
 F src/vdbeblob.c 63c750acc7b5012479f508c0e9627372a82cb65d
 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
-F src/vdbemem.c cee169fb5542cccfd1e8d832ae4538cb69b8917a
+F src/vdbemem.c e060d04bc6f8cf32c638fddada266b01cad8ee9a
 F src/vtab.c dc8947c9c79780b19ee6d6bae4ea624a2a303353
 F src/where.c 7ff0ca021cc77086e367ed3b6308fbc6bc9e1a31
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
@@ -378,7 +378,7 @@ F test/malloc8.test addc27d907fec1af429551b95c72caa47fce2974
 F test/malloc9.test 95d7069ad4fa262bf33bc4c5ca0a46f2bb2391cb
 F test/mallocA.test 5ee8d42ff90e5b1aeee6fb645e73ffcb35bffd21
 F test/mallocAll.test 2a2222a5e447be6c6579055a9a26e507e4586f4e
-F test/mallocB.test 82ecf4d3fa6c389cabc747daa2deddfe94af2a74
+F test/mallocB.test d4a91e7d9cc916d009e0fec08537b3be299ee514
 F test/mallocC.test 9daac0aa8e5b0afa7b0a3fb0cd792f02fe0cc838
 F test/mallocD.test 24c1d07a00e605831d0d627b036bd690b2952416
 F test/mallocE.test e15333c394d7c330c8372a7cdf7b0f7c16573082
@@ -412,7 +412,7 @@ F test/pragma.test d9f3d80583b80708aa270e8c5038dee949190d78
 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
 F test/printf.test c3405535b418d454e8a52196a0fc592ec9eec58d
 F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x
-F test/ptrchng.test 38ae1806833d72d9a81a6121322e274f24937e18
+F test/ptrchng.test 1f7bb92398163f1c18d69727c3ab31d90e94b458
 F test/quick.test 771a6b3a88fdd0e7e813ce013ceda29037bc9462
 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
 F test/rdonly.test b34db316525440d3b42c32e83942c02c37d28ef0
@@ -453,7 +453,7 @@ F test/table.test 13b1c2e2fb4727b35ee1fb7641fc469214fd2455
 F test/tableapi.test 4546eb710d979db023bfcc16b0c108b1557fcb43
 F test/tclsqlite.test 3fac87cb1059c46b8fa8a60b553f4f1adb0fb6d9
 F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125
-F test/tester.tcl bfad4d2acf0659c6afbf48a98556b0433d2906dc
+F test/tester.tcl 70ed4c0dda3e2277bac9e0bf38e60df9dc360d08
 F test/thread001.test 8fbd9559da0bbdc273e00318c7fd66c162020af7
 F test/thread002.test 2c4ad2c386f60f6fe268cd91c769ee35b3c1fd0b
 F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35
@@ -617,7 +617,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 607247c27b80520b8c25c489757288b8ea186f9e
-R 6e7459c99c887be282a1c6ce2d461da7
-U drh
-Z 584629669827c756e74626290b2a5564
+P 5ab71c3a79cac04cb2c576f83a62218d05571006
+R c1dd02f73a73bb7e12988703f2d12663
+U danielk1977
+Z 2dff5d02e45b3ba8d57e28cad43b1b4e
index 1db4f72be5da67130b3b46216a72d6f391b1fff6..6137d5bb895042e5d3e1770a7655468f28c85293 100644 (file)
@@ -1 +1 @@
-5ab71c3a79cac04cb2c576f83a62218d05571006
\ No newline at end of file
+990237e27e417aff3dbf05784b716c21f3761a3a
\ No newline at end of file
index 67a34b7b0842c30fff78f0eb17823d75f05b1b60..905b1b052d180343d22e3ffd583c37a4088ed04a 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** 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"
 
@@ -328,14 +328,14 @@ static void codeAttach(
   }
 
   v = sqlite3GetVdbe(pParse);
-  regArgs = sqlite3GetTempRange(pParse, 3);
+  regArgs = sqlite3GetTempRange(pParse, 4);
   sqlite3ExprCode(pParse, pFilename, regArgs);
   sqlite3ExprCode(pParse, pDbname, regArgs+1);
   sqlite3ExprCode(pParse, pKey, regArgs+2);
 
   assert( v || db->mallocFailed );
   if( v ){
-    sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-nFunc, regArgs);
+    sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-nFunc, regArgs+3);
     sqlite3VdbeChangeP5(v, nFunc);
     pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0);
     sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF);
index 07b069c6fec8d39f4448b73ab8f81fd9882345e1..9d1673b799a60fe6abc630e0e81d45a3e8e9ebd4 100644 (file)
@@ -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.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"
 
@@ -218,14 +218,15 @@ static void autoIncEnd(
     Vdbe *v = pParse->pVdbe;
     Db *pDb = &pParse->db->aDb[iDb];
     int j1;
+    int iRec = ++pParse->nMem;    /* Memory cell used for record */
 
     assert( v );
     sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
     j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1);
     sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1);
     sqlite3VdbeJumpHere(v, j1);
-    sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, memId-1);
-    sqlite3VdbeAddOp3(v, OP_Insert, iCur, memId-1, memId+1);
+    sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec);
+    sqlite3VdbeAddOp3(v, OP_Insert, iCur, iRec, memId+1);
     sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
     sqlite3VdbeAddOp1(v, OP_Close, iCur);
   }
index c004b89e1d5615add5fa1a36ec01cdb1312a87fc..c1d1accd1ba33751dd33fe11d06b4c272978c684 100644 (file)
@@ -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.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"
@@ -82,6 +82,10 @@ int sqlite3_exec(
         if( 0==nCallback ){
           for(i=0; i<nCol; i++){
             azCols[i] = (char *)sqlite3_column_name(pStmt, i);
+            if( !azCols[i] ){
+              db->mallocFailed = 1;
+              goto exec_out;
+            }
           }
           nCallback++;
         }
@@ -89,6 +93,10 @@ int sqlite3_exec(
           azVals = &azCols[nCol];
           for(i=0; i<nCol; 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) ){
index 60ffc913824be1f3ff2764f340a941dca12c7aa9..33c4902d96b5e1827ba7fa33ddeed27fe8491d82 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains the C functions that implement a memory
 ** 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);  
 }
 
+/*
+** 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
 */
index 0c99c63e5863ffeab35c41d3be29acb1699171e9..807b72011782445a45c53d7e4a8ecc1408ba2b6c 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains the C functions that implement a memory
 ** 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 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.
 */
@@ -452,5 +464,17 @@ void sqlite3_memdebug_dump(const char *zFilename){
   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 */
index 0d98372a5e2fb5a62de7de60246d040696da6ea0..05b35ad891b1f337b47798d2283fc249078e916c 100644 (file)
@@ -20,7 +20,7 @@
 ** This version of the memory allocation subsystem is used if
 ** 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
 ** works for chunks that are currently checked out.
 */
-static int memsys3Size(void *p){
+int sqlite3MallocSize(void *p){
   Mem3Block *pBlock = (Mem3Block*)p;
   assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
   return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
@@ -556,7 +556,7 @@ void *sqlite3_realloc(void *pPrior, int nBytes){
     return 0;
   }
   assert( mem.mutex!=0 );
-  nOld = memsys3Size(pPrior);
+  nOld = sqlite3MallocSize(pPrior);
   if( nBytes<=nOld && nBytes>=nOld-128 ){
     return pPrior;
   }
index 57e2d0fdd0bfbe6fdd5a0aa61ed91652a083ccda..f5397641d0adafa67d4b30346c9bf5d7b18fbe70 100644 (file)
--- a/src/os.c
+++ b/src/os.c
@@ -1,4 +1,4 @@
- /*
+/*
 ** 2005 November 29
 **
 ** The author disclaims copyright to this source code.  In place of
index dc7db612bbcacb3c06b574ddb393913f6a1a71db..4019ca77a77054f180e1f78aca08521252ad2a18 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** 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 <ctype.h>
@@ -894,8 +894,8 @@ void sqlite3Pragma(
       if( cnt==0 ) continue;
 
       /* Make sure sufficient number of registers have been allocated */
-      if( pParse->nMem < cnt+3 ){
-        pParse->nMem = cnt+3;
+      if( pParse->nMem < cnt+4 ){
+        pParse->nMem = cnt+4;
       }
 
       /* Do the b-tree integrity checks */
@@ -905,7 +905,8 @@ void sqlite3Pragma(
       sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
          sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
          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);
       sqlite3VdbeJumpHere(v, addr);
 
index 590f6e6850b3198b2b8346051435f22aafc30aad..a6ecc6fc8fa1017782ec701c2658cf1fd1600f07 100644 (file)
@@ -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.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"
 
@@ -810,8 +810,8 @@ static void generateSortTail(
       int j1;
       assert( nColumn==1 );
       j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow);
-      sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRow, &p->affinity, 1);
-      sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRow);
+      sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1);
+      sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
       sqlite3VdbeJumpHere(v, j1);
       break;
     }
index f9087f7c92b0efdf666d003f79491d20ed6dc6fa..8a3e6a3232916ff1c20518132e4392dfa1e01005 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** 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_
 #define _SQLITEINT_H_
@@ -1683,6 +1683,7 @@ char *sqlite3DbStrDup(sqlite3*,const char*);
 char *sqlite3DbStrNDup(sqlite3*,const char*, int);
 void *sqlite3DbReallocOrFree(sqlite3 *, void *, int);
 void *sqlite3DbRealloc(sqlite3 *, void *, int);
+int sqlite3MallocSize(void *);
 
 char *sqlite3MPrintf(sqlite3*,const char*, ...);
 char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
index a151bb6acf912a79ca5e526dcc2d27e6f5f5b890..ebb8c0f7cd2653a2c0af74aae8fe4ec9b253b171 100644 (file)
@@ -12,7 +12,7 @@
 ** A TCL Interface to SQLite.  Append this file to sqlite3.c and
 ** 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 <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) ){
             case SQLITE_BLOB: {
               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;
             }
             case SQLITE_INTEGER: {
index 5fb8fa7790e2876bd69d0e4c0e307125e1108c44..adb9797819cb29ac780dca0ed80b1f8e605b9e55 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test1.c,v 1.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 "tcl.h"
@@ -954,16 +954,17 @@ static int test_create_function(
   /* Use the sqlite3_create_function16() API here. Mainly for fun, but also 
   ** because it is not tested anywhere else. */
   if( rc==SQLITE_OK ){
+    void *zUtf16;
     sqlite3_value *pVal;
     sqlite3_mutex_enter(db->mutex);
     pVal = sqlite3ValueNew(db);
     sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
+    zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
     if( db->mallocFailed ){
       rc = SQLITE_NOMEM;
     }else{
-      rc = sqlite3_create_function16(db, 
-              sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
-              1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
+      rc = sqlite3_create_function16(db, zUtf16, 
+                1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
     }
     sqlite3ValueFree(pVal);
     sqlite3_mutex_leave(db->mutex);
@@ -2152,6 +2153,7 @@ static int test_collate(
   rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8, 
           (void *)SQLITE_UTF8, val?test_collate_func:0);
   if( rc==SQLITE_OK ){
+    void *zUtf16;
     if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
     rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, 
             (void *)SQLITE_UTF16LE, val?test_collate_func:0);
@@ -2165,11 +2167,11 @@ static int test_collate(
     sqlite3_mutex_enter(db->mutex);
     pVal = sqlite3ValueNew(db);
     sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
+    zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
     if( db->mallocFailed ){
       rc = SQLITE_NOMEM;
     }else{
-      rc = sqlite3_create_collation16(db, 
-          sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), SQLITE_UTF16BE, 
+      rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE, 
           (void *)SQLITE_UTF16BE, val?test_collate_func:0);
     }
     sqlite3ValueFree(pVal);
index 944ac686ef4b6d2eed727daabce68198ff99ef59..8c49571afa206707b0db8d3add2929ca34d20341 100644 (file)
@@ -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.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 "tcl.h"
@@ -160,7 +160,12 @@ static int getColumnNames(
     */
     nBytes = sizeof(char *) * nCol;
     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);
     if( !aCol ){
@@ -952,11 +957,15 @@ int echoUpdate(
     if( bindArgOne ){
       sqlite3_bind_value(pStmt, 1, apData[1]);
     }
-    for(i=2; i<nData; i++){
-      if( apData[i] ) sqlite3_bind_value(pStmt, i, apData[i]);
+    for(i=2; i<nData && rc==SQLITE_OK; 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 ){
index d581ea3bf91bf4b112e5d79c365794fb182e3e19..df35b207d0fcdc20e95e446130a9dbfb6e6d8266 100644 (file)
@@ -13,7 +13,7 @@
 ** This file contains code used to implement test interfaces to the
 ** 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 "tcl.h"
@@ -343,6 +343,32 @@ static int test_memdebug_dump(
   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?
@@ -504,6 +530,7 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){
      { "sqlite3_memdebug_fail",      test_memdebug_fail            },
      { "sqlite3_memdebug_pending",   test_memdebug_pending         },
      { "sqlite3_memdebug_settitle",  test_memdebug_settitle        },
+     { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count },
   };
   int i;
   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
index b6b313316fcce66820f8e50ca512c18c8fbc89eb..3580b6dfab1faf8179b2c8a2025338d0acb007da 100644 (file)
--- a/src/utf.c
+++ b/src/utf.c
@@ -12,7 +12,7 @@
 ** This file contains routines used to translate between UTF-8, 
 ** UTF-16, UTF-16BE, and UTF-16LE.
 **
-** $Id: utf.c,v 1.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:
 **
@@ -188,7 +188,6 @@ int sqlite3Utf8Read(
 ** encoding, or if *pMem does not contain a string value.
 */
 int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
-  unsigned char zShort[NBFS]; /* Temporary short output buffer */
   int len;                    /* Maximum length of output string in bytes */
   unsigned char *zOut;                  /* Output buffer */
   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
   ** byte past the end.
   **
-  ** Variable zOut is set to point at the output buffer. This may be space
-  ** obtained from sqlite3_malloc(), or Mem.zShort, if it large enough and
-  ** not in use, or the zShort array on the stack (see above).
+  ** Variable zOut is set to point at the output buffer, space obtained
+  ** from sqlite3_malloc().
   */
   zIn = (u8*)pMem->z;
   zTerm = &zIn[pMem->n];
-  if( len>NBFS ){
-    zOut = sqlite3DbMallocRaw(pMem->db, len);
-    if( !zOut ){
-      return SQLITE_NOMEM;
-    }
-  }else{
-    zOut = zShort;
+  zOut = sqlite3DbMallocRaw(pMem->db, len);
+  if( !zOut ){
+    return SQLITE_NOMEM;
   }
   z = zOut;
 
@@ -308,15 +302,9 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
   assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
 
   sqlite3VdbeMemRelease(pMem);
-  pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short);
+  pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
   pMem->enc = desiredEnc;
-  if( zOut==zShort ){
-    memcpy(pMem->zShort, zOut, len);
-    zOut = (u8*)pMem->zShort;
-    pMem->flags |= (MEM_Term|MEM_Short);
-  }else{
-    pMem->flags |= (MEM_Term|MEM_Dyn);
-  }
+  pMem->flags |= (MEM_Term|MEM_Dyn);
   pMem->z = (char*)zOut;
 
 translate_out:
@@ -355,24 +343,14 @@ int sqlite3VdbeMemHandleBom(Mem *pMem){
   }
   
   if( bom ){
-    /* This function is called as soon as a string is stored in a Mem*,
-    ** from within sqlite3VdbeMemSetStr(). At that point it is not possible
-    ** for the string to be stored in Mem.zShort, or for it to be stored
-    ** in dynamic memory with no destructor.
-    */
-    assert( !(pMem->flags&MEM_Short) );
-    assert( !(pMem->flags&MEM_Dyn) || pMem->xDel );
-    if( pMem->flags & MEM_Dyn ){
-      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);
+    rc = sqlite3VdbeMemMakeWriteable(pMem);
+    if( rc==SQLITE_OK ){
+      pMem->n -= 2;
+      memmove(pMem->z, &pMem->z[2], pMem->n);
+      pMem->z[pMem->n] = '\0';
+      pMem->z[pMem->n+1] = '\0';
+      pMem->flags |= MEM_Term;
+      pMem->enc = bom;
     }
   }
   return rc;
index 2901752a18cc339f2ab54f3960888ae38f897256..8bcff572a36f65b572e879f8f3f12bdb51a713c1 100644 (file)
@@ -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.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 <ctype.h>
@@ -236,9 +236,8 @@ static void applyNumericAffinity(Mem *pRec){
       i64 value;
       sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8);
       if( !realnum && sqlite3Atoi64(pRec->z, &value) ){
-        sqlite3VdbeMemRelease(pRec);
         pRec->u.i = value;
-        pRec->flags = MEM_Int;
+        MemSetTypeFlag(pRec, MEM_Int);
       }else{
         sqlite3VdbeMemRealify(pRec);
       }
@@ -1000,14 +999,19 @@ case OP_ResultRow: {
 ** Add the text in register P1 onto the end of the text in
 ** register P2 and store the result in register 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 */
-  char *zNew;
   i64 nByte;
 
+  assert( pIn1!=pOut );
   if( (pIn1->flags | pIn2->flags) & MEM_Null ){
-    Release(pOut);
-    pOut->flags = MEM_Null;
+    sqlite3VdbeMemSetNull(pOut);
     break;
   }
   ExpandBlob(pIn1);
@@ -1018,20 +1022,19 @@ case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
   if( nByte>SQLITE_MAX_LENGTH ){
     goto too_big;
   }
-  zNew = sqlite3DbMallocRaw(db, nByte+2);
-  if( zNew==0 ){
+  MemSetTypeFlag(pOut, MEM_Str);
+  if( sqlite3VdbeMemGrow(pOut, nByte+2, pOut==pIn2) ){
     goto no_mem;
   }
-  memcpy(zNew, pIn2->z, pIn2->n);
-  memcpy(&zNew[pIn2->n], pIn1->z, pIn1->n);
-  zNew[nByte] = 0;
-  zNew[nByte+1] = 0;
-  Release(pOut);
+  if( pOut!=pIn2 ){
+    memcpy(pOut->z, pIn2->z, pIn2->n);
+  }
+  memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
+  pOut->z[nByte] = 0;
+  pOut->z[nByte+1] = 0;
+  pOut->flags |= MEM_Term;
   pOut->n = nByte;
-  pOut->flags = MEM_Str|MEM_Dyn|MEM_Term;
-  pOut->xDel = 0;
   pOut->enc = encoding;
-  pOut->z = zNew;
   UPDATE_MAX_BLOBSIZE(pOut);
   break;
 }
@@ -1105,9 +1108,8 @@ case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
         break;
       }
     }
-    Release(pOut);
     pOut->u.i = b;
-    pOut->flags = MEM_Int;
+    MemSetTypeFlag(pOut, MEM_Int);
   }else{
     double a, b;
     a = sqlite3VdbeRealValue(pIn1);
@@ -1133,9 +1135,8 @@ case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
     if( sqlite3_isnan(b) ){
       goto arithmetic_result_is_null;
     }
-    Release(pOut);
     pOut->r = b;
-    pOut->flags = MEM_Real;
+    MemSetTypeFlag(pOut, MEM_Real);
     if( (flags & MEM_Real)==0 ){
       sqlite3VdbeIntegerAffinity(pOut);
     }
@@ -1168,6 +1169,7 @@ case OP_CollSeq: {
 ** Invoke a user function (P4 is a pointer to a Function structure that
 ** defines the function) with P5 arguments taken from register P2 and
 ** 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 
 ** function was determined to be constant at compile time. If the first
@@ -1189,6 +1191,7 @@ case OP_Function: {
   assert( apVal || n==0 );
 
   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];
   for(i=0; i<n; i++, pArg++){
     apVal[i] = pArg;
@@ -1205,10 +1208,18 @@ case OP_Function: {
     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.z = 0;
-  ctx.s.xDel = 0;
-  ctx.s.db = db;
+  ctx.s.db = 0;
+
+  /* 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;
   if( ctx.pFunc->needCollSeq ){
     assert( pOp>p->aOp );
@@ -1250,8 +1261,6 @@ case OP_Function: {
 
   /* Copy the result of the function into register P3 */
   sqlite3VdbeChangeEncoding(&ctx.s, encoding);
-  assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  pOut = &p->aMem[pOp->p3];
   sqlite3VdbeMemMove(pOut, &ctx.s);
   if( sqlite3VdbeMemTooBig(pOut) ){
     goto too_big;
@@ -1306,9 +1315,8 @@ case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
     default:  assert( pOp->opcode==OP_ShiftRight );
                          a >>= b;    break;
   }
-  Release(pOut);
   pOut->u.i = a;
-  pOut->flags = MEM_Int;
+  MemSetTypeFlag(pOut, MEM_Int);
   break;
 }
 
@@ -1350,9 +1358,8 @@ case OP_ForceInt: {            /* jump, in1 */
     if( pIn1->r>(double)v ) v++;
     if( pOp->p3 && pIn1->r==(double)v ) v++;
   }
-  Release(pIn1);
   pIn1->u.i = v;
-  pIn1->flags = MEM_Int;
+  MemSetTypeFlag(pIn1, MEM_Int);
   break;
 }
 
@@ -1373,8 +1380,7 @@ case OP_MustBeInt: {            /* jump, in1 */
       pc = pOp->p2 - 1;
     }
   }else{
-    Release(pIn1);
-    pIn1->flags = MEM_Int;
+    MemSetTypeFlag(pIn1, MEM_Int);
   }
   break;
 }
@@ -1411,7 +1417,7 @@ case OP_ToText: {                  /* same as TK_TO_TEXT, in1 */
   pIn1->flags |= (pIn1->flags&MEM_Blob)>>3;
   applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
   rc = ExpandBlob(pIn1);
-  assert( pIn1->flags & MEM_Str );
+  assert( pIn1->flags & MEM_Str || db->mallocFailed );
   pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob);
   UPDATE_MAX_BLOBSIZE(pIn1);
   break;
@@ -1430,10 +1436,9 @@ case OP_ToBlob: {                  /* same as TK_TO_BLOB, in1 */
   if( pIn1->flags & MEM_Null ) break;
   if( (pIn1->flags & MEM_Blob)==0 ){
     applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
-    assert( pIn1->flags & MEM_Str );
-    pIn1->flags |= MEM_Blob;
+    assert( pIn1->flags & MEM_Str || db->mallocFailed );
   }
-  pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Str);
+  MemSetTypeFlag(pIn1, MEM_Blob);
   UPDATE_MAX_BLOBSIZE(pIn1);
   break;
 }
@@ -1591,8 +1596,7 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
       */
       if( pOp->p5 & SQLITE_STOREP2 ){
         pOut = &p->aMem[pOp->p2];
-        Release(pOut);
-        pOut->flags = MEM_Null;
+        MemSetTypeFlag(pOut, MEM_Null);
         REGISTER_TRACE(pOp->p2, pOut);
       }else if( pOp->p5 & SQLITE_JUMPIFNULL ){
         pc = pOp->p2-1;
@@ -1622,8 +1626,7 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
 
   if( pOp->p5 & SQLITE_STOREP2 ){
     pOut = &p->aMem[pOp->p2];
-    Release(pOut);
-    pOut->flags = MEM_Int;
+    MemSetTypeFlag(pOut, MEM_Int);
     pOut->u.i = res;
     REGISTER_TRACE(pOp->p2, pOut);
   }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 };
     v1 = or_logic[v1*3+v2];
   }
-  Release(pOut);
   if( v1==2 ){
-    pOut->flags = MEM_Null;
+    MemSetTypeFlag(pOut, MEM_Null);
   }else{
     pOut->u.i = v1;
-    pOut->flags = MEM_Int;
+    MemSetTypeFlag(pOut, MEM_Int);
   }
   break;
 }
@@ -1691,7 +1693,7 @@ case OP_Not: {                /* same as TK_NOT, in1 */
   if( pIn1->flags & MEM_Null ) break;  /* Do nothing to NULLs */
   sqlite3VdbeMemIntegerify(pIn1);
   pIn1->u.i = !pIn1->u.i;
-  assert( pIn1->flags==MEM_Int );
+  assert( pIn1->flags&MEM_Int );
   break;
 }
 
@@ -1705,7 +1707,7 @@ case OP_BitNot: {             /* same as TK_BITNOT, in1 */
   if( pIn1->flags & MEM_Null ) break;  /* Do nothing to NULLs */
   sqlite3VdbeMemIntegerify(pIn1);
   pIn1->u.i = ~pIn1->u.i;
-  assert( pIn1->flags==MEM_Int );
+  assert( pIn1->flags&MEM_Int );
   break;
 }
 
@@ -1823,10 +1825,11 @@ case OP_Column: {
   Mem sMem;          /* For storing the record being decoded */
 
   sMem.flags = 0;
+  sMem.db = 0;
   assert( p1<p->nCursor );
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
   pDest = &p->aMem[pOp->p3];
-  sqlite3VdbeMemSetNull(pDest);
+  MemSetTypeFlag(pDest, MEM_Null);
 
   /* This block sets the variable payloadSize to be the total number of
   ** bytes in the record.
@@ -1877,7 +1880,7 @@ case OP_Column: {
 
   /* If payloadSize is 0, then just store a NULL */
   if( payloadSize==0 ){
-    assert( pDest->flags==MEM_Null );
+    assert( pDest->flags&MEM_Null );
     goto op_column_out;
   }
   if( payloadSize>SQLITE_MAX_LENGTH ){
@@ -1943,6 +1946,8 @@ case OP_Column: {
     ** acquire the complete header text.
     */
     if( !zRec && avail<offset ){
+      sMem.flags = 0;
+      sMem.db = 0;
       rc = sqlite3VdbeMemFromBtree(pCrsr, 0, offset, pC->isIndex, &sMem);
       if( rc!=SQLITE_OK ){
         goto op_column_out;
@@ -1994,22 +1999,30 @@ case OP_Column: {
   if( aOffset[p2] ){
     assert( rc==SQLITE_OK );
     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{
       len = sqlite3VdbeSerialTypeLen(aType[p2]);
+      sqlite3VdbeMemMove(&sMem, pDest);
       rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex, &sMem);
       if( rc!=SQLITE_OK ){
         goto op_column_out;
       }
       zData = sMem.z;
+      sqlite3VdbeSerialGet((u8*)zData, aType[p2], pDest);
     }
-    sqlite3VdbeSerialGet((u8*)zData, aType[p2], pDest);
     pDest->enc = encoding;
   }else{
     if( pOp->p4type==P4_MEM ){
       sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
     }else{
-      assert( pDest->flags==MEM_Null );
+      assert( pDest->flags&MEM_Null );
     }
   }
 
@@ -2019,16 +2032,14 @@ case OP_Column: {
   ** This prevents a memory copy.
   */
   if( (sMem.flags & MEM_Dyn)!=0 ){
-    assert( pDest->flags & MEM_Ephem );
-    assert( pDest->flags & (MEM_Str|MEM_Blob) );
-    assert( pDest->z==sMem.z );
-    assert( sMem.flags & MEM_Term );
-    pDest->flags &= ~MEM_Ephem;
+    assert( !sMem.xDel );
+    assert( !(pDest->flags & MEM_Dyn) );
+    assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z );
+    pDest->flags &= ~(MEM_Ephem|MEM_Static);
     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);
 
 op_column_out:
@@ -2086,7 +2097,6 @@ case OP_MakeRecord: {
   char *zAffinity;       /* The affinity string for the record */
   int file_format;       /* File format to use for encoding */
   int i;                 /* Space used in zNewRecord[] */
-  char zTemp[NBFS];      /* Space to hold small records */
 
   nField = pOp->p1;
   zAffinity = pOp->p4.z;
@@ -2130,15 +2140,17 @@ case OP_MakeRecord: {
     goto too_big;
   }
 
-  /* Allocate space for the new record. */
-  if( nByte>sizeof(zTemp) ){
-    zNewRecord = sqlite3DbMallocRaw(db, nByte);
-    if( !zNewRecord ){
-      goto no_mem;
-    }
-  }else{
-    zNewRecord = (u8*)zTemp;
+  /* Make sure the output register has a buffer large enough to store 
+  ** the new record. The output register (pOp->p3) is not allowed to
+  ** be one of the input registers (because the following call to
+  ** sqlite3VdbeMemGrow() could clobber the value before it is used).
+  */
+  assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
+  pOut = &p->aMem[pOp->p3];
+  if( sqlite3VdbeMemGrow(pOut, nByte, 0) ){
+    goto no_mem;
   }
+  zNewRecord = (u8 *)pOut->z;
 
   /* Write the record */
   i = sqlite3PutVarint(zNewRecord, nHdr);
@@ -2152,20 +2164,9 @@ case OP_MakeRecord: {
   assert( i==nByte );
 
   assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  pOut = &p->aMem[pOp->p3];
-  Release(pOut);
   pOut->n = nByte;
-  if( nByte<=sizeof(zTemp) ){
-    assert( zNewRecord==(unsigned char *)zTemp );
-    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;
-  }
+  pOut->flags = MEM_Blob | MEM_Dyn;
+  pOut->xDel = 0;
   if( nZero ){
     pOut->u.i = nZero;
     pOut->flags |= MEM_Zero;
@@ -2343,7 +2344,7 @@ case OP_ReadCookie: {               /* out2-prerelease */
   */
   rc = sqlite3BtreeGetMeta(db->aDb[iDb].pBt, 1 + iCookie, (u32 *)&iMeta);
   pOut->u.i = iMeta;
-  pOut->flags = MEM_Int;
+  MemSetTypeFlag(pOut, MEM_Int);
   break;
 }
 
@@ -2896,7 +2897,6 @@ case OP_IsUnique: {        /* jump, in3 */
   pK = &p->aMem[pOp->p4.i];
   sqlite3VdbeMemIntegerify(pIn3);
   R = pIn3->u.i;
-  assert( (pIn3->flags & MEM_Dyn)==0 );
   assert( i>=0 && i<p->nCursor );
   pCx = p->apCsr[i];
   assert( pCx!=0 );
@@ -2960,7 +2960,7 @@ case OP_IsUnique: {        /* jump, in3 */
     ** a UNIQUE constraint.)
     */
     pIn3->u.i = v;
-    assert( pIn3->flags==MEM_Int );
+    assert( pIn3->flags&MEM_Int );
   }
   break;
 }
@@ -3021,7 +3021,7 @@ case OP_Sequence: {           /* out2-prerelease */
   assert( i>=0 && i<p->nCursor );
   assert( p->apCsr[i]!=0 );
   pOut->u.i = p->apCsr[i]->seqCount++;
-  pOut->flags = MEM_Int;
+  MemSetTypeFlag(pOut, MEM_Int);
   break;
 }
 
@@ -3174,7 +3174,7 @@ case OP_NewRowid: {           /* out2-prerelease */
     pC->deferredMoveto = 0;
     pC->cacheStatus = CACHE_STALE;
   }
-  pOut->flags = MEM_Int;
+  MemSetTypeFlag(pOut, MEM_Int);
   pOut->u.i = v;
   break;
 }
@@ -3368,13 +3368,15 @@ case OP_ResetCount: {
 ** If the P1 cursor must be pointing to a valid row (not a NULL row)
 ** of a real table, not a pseudo-table.
 */
-case OP_RowKey:             /* out2-prerelease */
-case OP_RowData: {          /* out2-prerelease */
+case OP_RowKey:
+case OP_RowData: {
   int i = pOp->p1;
   Cursor *pC;
   BtCursor *pCrsr;
   u32 n;
 
+  pOut = &p->aMem[pOp->p2];
+
   /* Note that RowKey and RowData are really exactly the same instruction */
   assert( i>=0 && i<p->nCursor );
   pC = p->apCsr[i];
@@ -3401,17 +3403,11 @@ case OP_RowData: {          /* out2-prerelease */
       goto too_big;
     }
   }
-  pOut->n = n;
-  if( n<=NBFS ){
-    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;
+  if( sqlite3VdbeMemGrow(pOut, n, 0) ){
+    goto no_mem;
   }
+  pOut->n = n;
+  MemSetTypeFlag(pOut, MEM_Blob);
   if( pC->isIndex ){
     rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z);
   }else{
@@ -3450,7 +3446,7 @@ case OP_Rowid: {                 /* out2-prerelease */
     v = keyToInt(v);
   }
   pOut->u.i = v;
-  pOut->flags = MEM_Int;
+  MemSetTypeFlag(pOut, MEM_Int);
   break;
 }
 
@@ -3642,8 +3638,9 @@ case OP_IdxInsert: {        /* in2 */
 
 /* Opcode: IdxDelete P1 P2 * * *
 **
-** The content of register P2 is an index key built using the either the
-** MakeIdxRec opcode.  Removes that entry from the index.
+** The content of register P2 is an index key built using the 
+** MakeIdxRec opcode. This opcode removes that entry from the 
+** index opened by cursor P1.
 */
 case OP_IdxDelete: {        /* in2 */
   int i = pOp->p1;
@@ -3689,7 +3686,7 @@ case OP_IdxRowid: {              /* out2-prerelease */
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
-      pOut->flags = MEM_Int;
+      MemSetTypeFlag(pOut, MEM_Int);
       pOut->u.i = rowid;
     }
   }
@@ -3801,7 +3798,7 @@ case OP_Destroy: {     /* out2-prerelease */
     assert( iCnt==1 );
     assert( (p->btreeMask & (1<<iDb))!=0 );
     rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
-    pOut->flags = MEM_Int;
+    MemSetTypeFlag(pOut, MEM_Int);
     pOut->u.i = iMoved;
 #ifndef SQLITE_OMIT_AUTOVACUUM
     if( rc==SQLITE_OK && iMoved!=0 ){
@@ -3870,7 +3867,7 @@ case OP_CreateTable: {          /* out2-prerelease */
   rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
   if( rc==SQLITE_OK ){
     pOut->u.i = pgno;
-    pOut->flags = MEM_Int;
+    MemSetTypeFlag(pOut, MEM_Int);
   }
   break;
 }
@@ -4023,12 +4020,8 @@ case OP_IntegrityCk: {
   if( nErr==0 ){
     assert( z==0 );
   }else{
-    pIn1->z = z;
-    pIn1->n = strlen(z);
-    pIn1->flags = MEM_Str | MEM_Dyn | MEM_Term;
-    pIn1->xDel = 0;
+    sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
   }
-  pIn1->enc = SQLITE_UTF8;
   UPDATE_MAX_BLOBSIZE(pIn1);
   sqlite3VdbeChangeEncoding(pIn1, encoding);
   sqlite3_free(aRoot);
@@ -4058,8 +4051,7 @@ case OP_FifoRead: {         /* jump */
   CHECK_FOR_INTERRUPT;
   assert( pOp->p1>0 && pOp->p1<=p->nMem );
   pOut = &p->aMem[pOp->p1];
-  Release(pOut);
-  pOut->flags = MEM_Int;
+  MemSetTypeFlag(pOut, MEM_Int);
   if( sqlite3VdbeFifoPop(&p->sFifo, &pOut->u.i)==SQLITE_DONE ){
     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.
 */
 case OP_IfPos: {        /* jump, in1 */
-  assert( pIn1->flags==MEM_Int );
+  assert( pIn1->flags&MEM_Int );
   if( pIn1->u.i>0 ){
      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.
 */
 case OP_IfNeg: {        /* jump, in1 */
-  assert( pIn1->flags==MEM_Int );
+  assert( pIn1->flags&MEM_Int );
   if( pIn1->u.i<0 ){
      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.
 */
 case OP_IfZero: {        /* jump, in1 */
-  assert( pIn1->flags==MEM_Int );
+  assert( pIn1->flags&MEM_Int );
   if( pIn1->u.i==0 ){
      pc = pOp->p2 - 1;
   }
@@ -4502,7 +4494,7 @@ case OP_VRowid: {             /* out2-prerelease */
   if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
   rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
   if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
-  pOut->flags = MEM_Int;
+  MemSetTypeFlag(pOut, MEM_Int);
   pOut->u.i = iRow;
   break;
 }
@@ -4531,8 +4523,15 @@ case OP_VColumn: {
   pModule = pCur->pVtabCursor->pVtab->pModule;
   assert( pModule->xColumn );
   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;
   rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
 
index 407ed49c92bf58aab2496b80c68dc701db3a9b86..ca9c39f07996e76cfb9ddd667c1e36e861d3beae 100644 (file)
@@ -94,13 +94,6 @@ struct 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.
 */
@@ -130,7 +123,6 @@ struct Mem {
   u8  type;           /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */
   u8  enc;            /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
   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
@@ -154,6 +146,9 @@ struct Mem {
 #define MEM_Real      0x0008   /* Value is a real number */
 #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
 ** 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
@@ -163,7 +158,6 @@ struct Mem {
 #define MEM_Dyn       0x0040   /* Need to call sqliteFree() on Mem.z */
 #define MEM_Static    0x0080   /* Mem.z points to a static 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_Zero      0x0800   /* Mem.i contains count of 0s appended to blob */
 
@@ -398,6 +392,7 @@ void sqlite3VdbeMemRelease(Mem *p);
 int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
 const char *sqlite3OpcodeName(int);
 int sqlite3VdbeOpcodeHasProperty(int, int);
+int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
 
 #ifndef NDEBUG
   void sqlite3VdbeMemSanity(Mem*);
index e756c705152ff335b3af1abf2abccf598355ddfd..8b4283d944479b0f168f4a1b9c03fc71c261eb1f 100644 (file)
@@ -944,6 +944,7 @@ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
   if( rc==SQLITE_OK ){
     rc = sqlite3VdbeMemCopy(&p->aVar[i-1], pValue);
   }
+  rc = sqlite3ApiExit(p->db, rc);
   sqlite3_mutex_leave(p->db->mutex);
   return rc;
 }
index c15207b9bed216f7f79214eeb4cd16266f426327..ca368b6ec3929ac4bf0d2452356436057c5290ae 100644 (file)
@@ -735,11 +735,15 @@ void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
 ** Release an array of N Mem elements
 */
 static void releaseMemArray(Mem *p, int N){
-  if( p ){
+  if( p && N ){
+    sqlite3 *db = p->db;
+    int malloc_failed = db->mallocFailed;
     while( N-->0 ){
       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;
     sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0);
   }else{
+    char *z;
     Op *pOp = &p->aOp[i];
     if( p->explain==1 ){
       pMem->flags = MEM_Int;
@@ -819,18 +824,29 @@ int sqlite3VdbeList(
       pMem++;
     }
 
-    pMem->flags = MEM_Ephem|MEM_Str|MEM_Term;     /* P4 */
-    pMem->z = displayP4(pOp, pMem->zShort, sizeof(pMem->zShort));
-    assert( pMem->z!=0 );
-    pMem->n = strlen(pMem->z);
+    if( sqlite3VdbeMemGrow(pMem, 32, 0) ){            /* P4 */
+      p->db->mallocFailed = 1;
+      return SQLITE_NOMEM;
+    }
+    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->enc = SQLITE_UTF8;
     pMem++;
 
     if( p->explain==1 ){
-      pMem->flags = MEM_Str|MEM_Term|MEM_Short;
-      pMem->n = sprintf(pMem->zShort, "%.2x", pOp->p5);   /* P5 */
-      pMem->z = pMem->zShort;
+      if( sqlite3VdbeMemGrow(pMem, 32, 0) ){
+        p->db->mallocFailed = 1;
+        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->enc = SQLITE_UTF8;
       pMem++;
@@ -1058,6 +1074,9 @@ static void closeAllCursorsExceptActiveVtabs(Vdbe *p){
 static void Cleanup(Vdbe *p){
   int i;
   closeAllCursorsExceptActiveVtabs(p);
+  for(i=1; i<=p->nMem; i++){
+    MemSetTypeFlag(&p->aMem[i], MEM_Null);
+  }
   releaseMemArray(&p->aMem[1], p->nMem);
   sqlite3VdbeFifoClear(&p->sFifo);
   if( p->contextStack ){
@@ -2133,8 +2152,10 @@ int sqlite3VdbeRecordCompare(
   Mem mem2;
   mem1.enc = pKeyInfo->enc;
   mem1.db = pKeyInfo->db;
+  mem1.flags = 0;
   mem2.enc = pKeyInfo->enc;
   mem2.db = pKeyInfo->db;
+  mem2.flags = 0;
   
   idx1 = GetVarint(aKey1, szHdr1);
   d1 = szHdr1;
@@ -2159,8 +2180,8 @@ int sqlite3VdbeRecordCompare(
     /* Do the comparison
     */
     rc = sqlite3MemCompare(&mem1, &mem2, i<nField ? pKeyInfo->aColl[i] : 0);
-    if( mem1.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem1);
-    if( mem2.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem2);
+    if( mem1.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem1);
+    if( mem2.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem2);
     if( rc!=0 ){
       break;
     }
@@ -2222,6 +2243,8 @@ int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){
   if( nCellKey<=0 ){
     return SQLITE_CORRUPT_BKPT;
   }
+  m.flags = 0;
+  m.db = 0;
   rc = sqlite3VdbeMemFromBtree(pCur, 0, nCellKey, 1, &m);
   if( rc ){
     return rc;
@@ -2261,6 +2284,8 @@ int sqlite3VdbeIdxKeyCompare(
     *res = 0;
     return SQLITE_OK;
   }
+  m.db = 0;
+  m.flags = 0;
   rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m);
   if( rc ){
     return rc;
index fa407b671c505796304f82eaf64f4c776f912ffd..d620aa2e55230eb2f351cba16fc1f9720ccb1481 100644 (file)
@@ -59,33 +59,83 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
 #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.
 **
 ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
 */
 int sqlite3VdbeMemDynamicify(Mem *pMem){
-  int n;
-  u8 *z;
+  int f;
   assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
   expandBlob(pMem);
-  if( (pMem->flags & (MEM_Ephem|MEM_Static|MEM_Short))==0 ){
-    return SQLITE_OK;
-  }
-  assert( (pMem->flags & MEM_Dyn)==0 );
-  n = pMem->n;
-  assert( pMem->flags & (MEM_Str|MEM_Blob) );
-  z = sqlite3DbMallocRaw(pMem->db, n+2 );
-  if( z==0 ){
-    return SQLITE_NOMEM;
+  f = pMem->flags;
+  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;
   }
-  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;
 }
 
@@ -96,24 +146,22 @@ int sqlite3VdbeMemDynamicify(Mem *pMem){
 #ifndef SQLITE_OMIT_INCRBLOB
 int sqlite3VdbeMemExpandBlob(Mem *pMem){
   if( pMem->flags & MEM_Zero ){
-    char *pNew;
     int nByte;
-    assert( (pMem->flags & MEM_Blob)!=0 );
-    nByte = pMem->n + pMem->u.i;
-    if( nByte<=0 ) nByte = 1;
+    assert( pMem->flags&MEM_Blob );
     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;
     }
-    memcpy(pNew, pMem->z, pMem->n);
-    memset(&pNew[pMem->n], 0, pMem->u.i);
-    sqlite3VdbeMemRelease(pMem);
-    pMem->z = pNew;
+
+    memset(&pMem->z[pMem->n], 0, pMem->u.i);
     pMem->n += pMem->u.i;
-    pMem->u.i = 0;
-    pMem->flags &= ~(MEM_Zero|MEM_Static|MEM_Ephem|MEM_Short|MEM_Term);
-    pMem->flags |= MEM_Dyn;
+    pMem->flags &= ~(MEM_Zero|MEM_Term);
   }
   return SQLITE_OK;
 }
@@ -127,33 +175,7 @@ int sqlite3VdbeMemExpandBlob(Mem *pMem){
 ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
 */
 int sqlite3VdbeMemMakeWriteable(Mem *pMem){
-  int n;
-  u8 *z;
-  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
-  expandBlob(pMem);
-  if( (pMem->flags & (MEM_Ephem|MEM_Static))==0 ){
-    return SQLITE_OK;
-  }
-  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;
+  return sqlite3VdbeMemDynamicify(pMem);
 }
 
 /*
@@ -164,27 +186,12 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){
   if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){
     return SQLITE_OK;   /* Nothing to do */
   }
-  if( pMem->flags & (MEM_Static|MEM_Ephem) ){
-    return sqlite3VdbeMemMakeWriteable(pMem);
-  }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;
+  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;
   return SQLITE_OK;
 }
 
@@ -204,29 +211,32 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){
 int sqlite3VdbeMemStringify(Mem *pMem, int enc){
   int rc = SQLITE_OK;
   int fg = pMem->flags;
-  char *z = pMem->zShort;
+  const int nByte = 32;
 
   assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
   assert( !(fg&MEM_Zero) );
   assert( !(fg&(MEM_Str|MEM_Blob)) );
   assert( fg&(MEM_Int|MEM_Real) );
 
-  /* 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
   ** is UTF-16le or UTF-16be do a translation.
   ** 
   ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
   */
   if( fg & MEM_Int ){
-    sqlite3_snprintf(NBFS, z, "%lld", pMem->u.i);
+    sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i);
   }else{
     assert( fg & MEM_Real );
-    sqlite3_snprintf(NBFS, z, "%!.15g", pMem->r);
+    sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->r);
   }
-  pMem->n = strlen(z);
-  pMem->z = z;
+  pMem->n = strlen(pMem->z);
   pMem->enc = SQLITE_UTF8;
-  pMem->flags |= MEM_Str | MEM_Short | MEM_Term;
+  pMem->flags |= MEM_Str|MEM_Term;
   sqlite3VdbeChangeEncoding(pMem, enc);
   return rc;
 }
@@ -246,19 +256,15 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
     assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
     assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
     ctx.s.flags = MEM_Null;
-    ctx.s.z = pMem->zShort;
     ctx.s.db = pMem->db;
     ctx.pMem = pMem;
     ctx.pFunc = pFunc;
     ctx.isError = 0;
     pFunc->xFinalize(&ctx);
-    if( pMem->z && pMem->z!=pMem->zShort ){
+    if( pMem->z ){
       sqlite3_free( pMem->z );
     }
     *pMem = ctx.s;
-    if( pMem->flags & MEM_Short ){
-      pMem->z = pMem->zShort;
-    }
     rc = (ctx.isError?SQLITE_ERROR:SQLITE_OK);
   }
   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.
 */
 int sqlite3VdbeMemIntegerify(Mem *pMem){
   assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
   pMem->u.i = sqlite3VdbeIntValue(pMem);
-  sqlite3VdbeMemRelease(pMem);
-  pMem->flags = MEM_Int;
+  setTypeFlag(pMem, MEM_Int);
   return SQLITE_OK;
 }
 
@@ -412,8 +421,7 @@ int sqlite3VdbeMemIntegerify(Mem *pMem){
 int sqlite3VdbeMemRealify(Mem *pMem){
   assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
   pMem->r = sqlite3VdbeRealValue(pMem);
-  sqlite3VdbeMemRelease(pMem);
-  pMem->flags = MEM_Real;
+  setTypeFlag(pMem, MEM_Real);
   return SQLITE_OK;
 }
 
@@ -434,8 +442,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
     sqlite3VdbeMemIntegerify(pMem);
   }else{
     pMem->r = r1;
-    pMem->flags = MEM_Real;
-    sqlite3VdbeMemRelease(pMem);
+    setTypeFlag(pMem, MEM_Real);
   }
   return SQLITE_OK;
 }
@@ -444,10 +451,8 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
 ** Delete any previous value and set the value stored in *pMem to NULL.
 */
 void sqlite3VdbeMemSetNull(Mem *pMem){
-  sqlite3VdbeMemRelease(pMem);
-  pMem->flags = MEM_Null;
+  setTypeFlag(pMem, MEM_Null);
   pMem->type = SQLITE_NULL;
-  pMem->n = 0;
 }
 
 /*
@@ -456,12 +461,12 @@ void sqlite3VdbeMemSetNull(Mem *pMem){
 */
 void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
   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->n = 0;
   if( n<0 ) n = 0;
   pMem->u.i = n;
-  pMem->z = pMem->zShort;
   pMem->enc = SQLITE_UTF8;
 }
 
@@ -514,10 +519,10 @@ int sqlite3VdbeMemTooBig(Mem *p){
 */
 void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
   sqlite3VdbeMemRelease(pTo);
-  memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort));
+  memcpy(pTo, pFrom, sizeof(*pFrom));
   pTo->xDel = 0;
-  if( pTo->flags & (MEM_Str|MEM_Blob) ){
-    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short|MEM_Ephem);
+  if( pTo->flags&MEM_Dyn ){
+    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
     assert( srcType==MEM_Ephem || srcType==MEM_Static );
     pTo->flags |= srcType;
   }
@@ -528,12 +533,46 @@ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
 ** freed before the copy is made.
 */
 int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
-  int rc;
-  sqlite3VdbeMemShallowCopy(pTo, pFrom, MEM_Ephem);
-  if( pTo->flags & MEM_Ephem ){
-    rc = sqlite3VdbeMemMakeWriteable(pTo);
+  int rc = SQLITE_OK;
+  char *zBuf = 0;
+
+  /* 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{
-    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;
 }
@@ -552,15 +591,18 @@ void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
     sqlite3VdbeMemRelease(pTo);
   }
   memcpy(pTo, pFrom, sizeof(Mem));
-  if( pFrom->flags & MEM_Short ){
-    pTo->z = pTo->zShort;
-  }
   pFrom->flags = MEM_Null;
   pFrom->xDel = 0;
 }
 
 /*
 ** 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(
   Mem *pMem,          /* Memory cell to set to string value */
@@ -569,59 +611,56 @@ int sqlite3VdbeMemSetStr(
   u8 enc,             /* Encoding of z.  0 for BLOBs */
   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) );
-  sqlite3VdbeMemRelease(pMem);
+
+  /* If z is a NULL pointer, set pMem to contain an SQL NULL. */
   if( !z ){
-    pMem->flags = MEM_Null;
-    pMem->type = SQLITE_NULL;
+    sqlite3VdbeMemSetNull(pMem);
     return SQLITE_OK;
   }
-  pMem->z = (char *)z;
-  if( xDel==SQLITE_STATIC ){
-    pMem->flags = MEM_Static;
-  }else if( xDel==SQLITE_TRANSIENT ){
-    pMem->flags = MEM_Ephem;
+
+  flags = (enc==0?MEM_Blob:MEM_Str);
+  if( nByte<0 ){
+    assert( enc!=0 );
+    nByte = ((enc==SQLITE_UTF8)?strlen(z):sqlite3Utf16ByteLen(z, -1));
+    flags |= MEM_Term;
+  }
+
+  /* The following block sets the new values of Mem.z and Mem.xDel. It
+  ** also sets a flag in local variable "flags" to indicate the memory
+  ** 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{
-    pMem->flags = MEM_Dyn;
+    sqlite3VdbeMemRelease(pMem);
+    pMem->z = (char *)z;
     pMem->xDel = xDel;
+    flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
   }
 
-  pMem->enc = enc;
-  pMem->type = enc==0 ? SQLITE_BLOB : SQLITE_TEXT;
-  pMem->n = n;
-
-  assert( enc==0 || enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE 
-      || enc==SQLITE_UTF16BE );
-  switch( enc ){
-    case 0:
-      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;
+  pMem->n = nByte;
+  pMem->flags = flags;
+  pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
+  pMem->type = (enc==0 ? SQLITE_BLOB : SQLITE_TEXT);
 
 #ifndef SQLITE_OMIT_UTF16
-    case SQLITE_UTF16LE:
-    case SQLITE_UTF16BE:
-      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);
+  if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
+    return SQLITE_NOMEM;
   }
+#endif
+
   return SQLITE_OK;
 }
 
@@ -769,6 +808,7 @@ int sqlite3VdbeMemFromBtree(
   char *zData;       /* Data from the btree layer */
   int available = 0; /* Number of bytes available on the local btree page */
   sqlite3 *db;       /* Database connection */
+  int rc = SQLITE_OK;
 
   db = sqlite3BtreeCursorDb(pCur);
   assert( sqlite3_mutex_held(db->mutex) );
@@ -779,49 +819,28 @@ int sqlite3VdbeMemFromBtree(
   }
   assert( zData!=0 );
 
-  pMem->db = db;
-  pMem->n = amt;
-  if( offset+amt<=available ){
+  if( offset+amt<=available && ((pMem->flags&MEM_Dyn)==0 || pMem->xDel) ){
+    sqlite3VdbeMemRelease(pMem);
     pMem->z = &zData[offset];
     pMem->flags = MEM_Blob|MEM_Ephem;
-  }else{
-    int rc;
-    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;
+  }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
+    pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
     pMem->enc = 0;
     pMem->type = SQLITE_BLOB;
-
     if( key ){
-      rc = sqlite3BtreeKey(pCur, offset, amt, zData);
+      rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
     }else{
-      rc = sqlite3BtreeData(pCur, offset, amt, zData);
+      rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
     }
-    zData[amt] = 0;
-    zData[amt+1] = 0;
+    pMem->z[amt] = 0;
+    pMem->z[amt+1] = 0;
     if( rc!=SQLITE_OK ){
-      if( amt>NBFS-2 ){
-        assert( zData!=pMem->zShort );
-        assert( pMem->flags & MEM_Dyn );
-        sqlite3_free(zData);
-      } else {
-        assert( zData==pMem->zShort );
-        assert( pMem->flags & MEM_Short );
-      }
-      return rc;
+      sqlite3VdbeMemRelease(pMem);
     }
   }
+  pMem->n = amt;
 
-  return SQLITE_OK;
+  return rc;
 }
 
 #if 0
@@ -1019,7 +1038,7 @@ void sqlite3ValueSetStr(
 */
 void sqlite3ValueFree(sqlite3_value *v){
   if( !v ) return;
-  sqlite3ValueSetStr(v, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
+  sqlite3VdbeMemRelease((Mem *)v);
   sqlite3_free(v);
 }
 
index 90888579f3cacf56a1fe84a98c5c93ddceb5c76a..72e89c9362eac3f7d635d5012ea5441571e39d21 100644 (file)
@@ -13,7 +13,7 @@
 # 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]
 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-2 -sqlbody {SELECT - 456.1}
 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 {
   do_malloc_test mallocB-5 -sqlbody {SELECT * FROM (SELECT 1) GROUP BY 1;}
 }
index 69bc1935136bd194a5bc045621016361498c4905..406f2e252182ba32b1423b6a68c7a264d2a8458f 100644 (file)
@@ -21,7 +21,7 @@
 #     sqlite3_value_bytes()
 #     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]
 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
 # never change regardless of what type conversions occur.
 #
+# UPDATE: No longer true, as Mem.zBuf[] has been removed.
+#
 do_test ptrchng-2.1 {
   execsql {
     SELECT pointer_change(y, 'text', 'noop', 'blob') FROM t1 WHERE x=1
@@ -61,18 +63,18 @@ do_test ptrchng-2.2 {
   execsql {
     SELECT pointer_change(y, 'blob', 'noop', 'text') FROM t1 WHERE x=1
   }
-} {0}
+} {1}
 ifcapable utf16 {
   do_test ptrchng-2.3 {
     execsql {
       SELECT pointer_change(y, 'text', 'noop', 'text16') FROM t1 WHERE x=1
     }
-  } {0}
+  } {1}
   do_test ptrchng-2.4 {
     execsql {
       SELECT pointer_change(y, 'blob', 'noop', 'text16') FROM t1 WHERE x=1
     }
-  } {0}
+  } {1}
   do_test ptrchng-2.5 {
     execsql {
       SELECT pointer_change(y, 'text16', 'noop', 'blob') FROM t1 WHERE x=1
@@ -82,7 +84,7 @@ ifcapable utf16 {
     execsql {
       SELECT pointer_change(y, 'text16', 'noop', 'text') FROM t1 WHERE x=1
     }
-  } {0}
+  } {1}
 }
 do_test ptrchng-2.11 {
   execsql {
@@ -93,18 +95,18 @@ do_test ptrchng-2.12 {
   execsql {
     SELECT pointer_change(y, 'blob', 'noop', 'text') FROM t1 WHERE x=3
   }
-} {0}
+} {1}
 ifcapable utf16 {
   do_test ptrchng-2.13 {
     execsql {
       SELECT pointer_change(y, 'text', 'noop', 'text16') FROM t1 WHERE x=3
     }
-  } {0}
+  } {1}
   do_test ptrchng-2.14 {
     execsql {
       SELECT pointer_change(y, 'blob', 'noop', 'text16') FROM t1 WHERE x=3
     }
-  } {0}
+  } {1}
   do_test ptrchng-2.15 {
     execsql {
       SELECT pointer_change(y, 'text16', 'noop', 'blob') FROM t1 WHERE x=3
@@ -115,7 +117,7 @@ btree_breakpoint
     execsql {
       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
@@ -130,7 +132,7 @@ do_test ptrchng-3.2 {
   execsql {
     SELECT pointer_change(y, 'blob', 'noop', 'text') FROM t1 WHERE x=2
   }
-} {0}
+} {1}
 ifcapable utf16 {
   do_test ptrchng-3.3 {
     execsql {
@@ -162,7 +164,7 @@ do_test ptrchng-3.12 {
   execsql {
     SELECT pointer_change(y, 'blob', 'noop', 'text') FROM t1 WHERE x=4
   }
-} {0}
+} {1}
 ifcapable utf16 {
   do_test ptrchng-3.13 {
     execsql {
index 618026b00f1efc5887ea44038de6c90f53a2e59f..e0c2a50c9aaedc93b51996296b933ccf04b0aadd 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements some common TCL routines used for regression
 # 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
@@ -227,6 +227,9 @@ proc finalize_testing {} {
   }
   puts "Maximum memory usage: [sqlite3_memory_highwater 1] 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] {
     file delete -force $f
   }