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)
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

View File

@ -1 +1 @@
5ab71c3a79cac04cb2c576f83a62218d05571006
990237e27e417aff3dbf05784b716c21f3761a3a

View 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);

View 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);
}

View 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) ){

View 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
*/

View 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 */

View 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;
}

View File

@ -1,4 +1,4 @@
/*
/*
** 2005 November 29
**
** 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.
**
** $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);

View 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;
}

View 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);

View 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: {

View 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);

View 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 ){

View 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++){

View File

@ -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;

View 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);

View 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*);

View 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;
}

View 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;

View 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;
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;
}
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;
}
@ -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;
}else{
pMem->flags = MEM_Dyn;
pMem->xDel = xDel;
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;
}
pMem->enc = enc;
pMem->type = enc==0 ? SQLITE_BLOB : SQLITE_TEXT;
pMem->n = n;
/* 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{
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
|| 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);
}

View 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;}
}

View 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 {

View 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
}