mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
More MEM changes in the vdbe.c. Still will not compile. (CVS 1469)
FossilOrigin-Name: dbdd1a7f316e576d0611748ec63c9ef00d4c10db
This commit is contained in:
13
main.mk
13
main.mk
@ -58,8 +58,9 @@ LIBOBJ = attach.o auth.o btree.o build.o copy.o date.o delete.o \
|
||||
expr.o func.o hash.o insert.o \
|
||||
main.o opcodes.o os_mac.o os_unix.o os_win.o \
|
||||
pager.o parse.o pragma.o printf.o random.o \
|
||||
select.o table.o tokenize.o trigger.o update.o util.o \
|
||||
vacuum.o vdbe.o vdbeaux.o where.o tclsqlite.o utf.o legacy.o
|
||||
select.o table.o tokenize.o trigger.o update.o util.o vacuum.o \
|
||||
vdbe.o vdbeapi.o vdbeaux.o vdbemem.o \
|
||||
where.o tclsqlite.o utf.o legacy.o
|
||||
|
||||
# All of the source code files.
|
||||
#
|
||||
@ -102,7 +103,9 @@ SRC = \
|
||||
$(TOP)/src/vacuum.c \
|
||||
$(TOP)/src/vdbe.c \
|
||||
$(TOP)/src/vdbe.h \
|
||||
$(TOP)/src/vdbeapi.c \
|
||||
$(TOP)/src/vdbeaux.c \
|
||||
$(TOP)/src/vdbemem.c \
|
||||
$(TOP)/src/vdbeInt.h \
|
||||
$(TOP)/src/where.c
|
||||
|
||||
@ -327,9 +330,15 @@ vacuum.o: $(TOP)/src/vacuum.c $(HDR)
|
||||
vdbe.o: $(TOP)/src/vdbe.c $(VDBEHDR)
|
||||
$(TCCX) -c $(TOP)/src/vdbe.c
|
||||
|
||||
vdbeapi.o: $(TOP)/src/vdbeapi.c $(VDBEHDR)
|
||||
$(TCCX) -c $(TOP)/src/vdbeapi.c
|
||||
|
||||
vdbeaux.o: $(TOP)/src/vdbeaux.c $(VDBEHDR)
|
||||
$(TCCX) -c $(TOP)/src/vdbeaux.c
|
||||
|
||||
vdbemem.o: $(TOP)/src/vdbemem.c $(VDBEHDR)
|
||||
$(TCCX) -c $(TOP)/src/vdbemem.c
|
||||
|
||||
where.o: $(TOP)/src/where.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/where.c
|
||||
|
||||
|
34
manifest
34
manifest
@ -1,5 +1,5 @@
|
||||
C More\stest\scases\sfor\sthe\snew\squery\sAPI.\s(CVS\s1468)
|
||||
D 2004-05-27T01:49:51
|
||||
C More\sMEM\schanges\sin\sthe\svdbe.c.\s\sStill\swill\snot\scompile.\s(CVS\s1469)
|
||||
D 2004-05-27T01:53:56
|
||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
@ -16,7 +16,7 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
|
||||
F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
||||
F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
|
||||
F main.mk bbbe8057c8fac1ec03af0a41f2fac5390dd30386
|
||||
F main.mk 466f12b816527d5bb1cf5dac4f23da77a02f99ad
|
||||
F publish.sh 1cd5c982388560fa91eedf6a338e210f713b35c8
|
||||
F spec.template a38492f1c1dd349fc24cb0565e08afc53045304b
|
||||
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
|
||||
@ -56,7 +56,7 @@ F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
||||
F src/select.c e90e2a147273cdcdb1ee9e14574ab28f04382e63
|
||||
F src/shell.c ed4d237b3e52a0a42512bfcc53530e46de20c28f
|
||||
F src/sqlite.h.in 68e165dc4dc2d477c95c76b9ede13eed5fbaabf4
|
||||
F src/sqliteInt.h 6b0d8d856c4af325eb5a00d1c32d89aacf432875
|
||||
F src/sqliteInt.h dbf4fd06e89cdab13f4f1129d76bf79a38ec2b39
|
||||
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
|
||||
F src/tclsqlite.c 86daf7bf6ba715bf0f0c7a47beb1d947a15cb868
|
||||
F src/test1.c ff7cc8729c320aec038e7d9d116bed9eabd642d0
|
||||
@ -67,15 +67,15 @@ F src/test5.c 9a1f15133f6955f067c5246e564723b5f23ff221
|
||||
F src/tokenize.c e7536dd31205d5afb76c1bdc832dea009c7a3847
|
||||
F src/trigger.c 11afe9abfba13a2ba142944c797c952e162d117f
|
||||
F src/update.c 96461bcf4e946697e83c09c77c7e61b545a2f66e
|
||||
F src/utf.c 1d38da85bffb928fb0d9f301e7db913a6df486ce
|
||||
F src/util.c 4c0adcbc9ce6678dd046931253e45d623c6d279f
|
||||
F src/utf.c 73d70f2764cb34b072e2d7b0f0c23c389cfc1baa
|
||||
F src/util.c caef24dcf3d7dfb7ac747ed36c080d95457fac71
|
||||
F src/vacuum.c 8734f89742f246abd91dbd3e087fc153bddbfbad
|
||||
F src/vdbe.c 4419d3b7e4d56b0c1d973ebf4de40ee5045e612e
|
||||
F src/vdbe.c 06f02181b5fe39b99cb98714bf36e95005e03ef7
|
||||
F src/vdbe.h e73f890e0f2a6c42b183d7d6937947930fe4fdeb
|
||||
F src/vdbeInt.h 8647afb4c3889c827a4c0aa310a54c5ec0ebc934
|
||||
F src/vdbeapi.c 36d4c78bc765dc89cac07ff975b26256e0ac90fc
|
||||
F src/vdbeaux.c 677317be4021eadce96365b16d9deeda9e565bef
|
||||
F src/vdbemem.c c92c41c80c333b3cd405a08ebfd014d02a9f7b8c
|
||||
F src/vdbeInt.h d62f70eb935bf056d9eb7dfb9783393274685e1d
|
||||
F src/vdbeapi.c 56b7de7af5800fbbf79fd953da95ee61c379a387
|
||||
F src/vdbeaux.c de2d82e4cf5815595ae74bd5f663042428efb6a8
|
||||
F src/vdbemem.c 3474db5cdb19a8aa1b1e8e78189e1e8cda2394aa
|
||||
F src/where.c efe5d25fe18cd7381722457898cd863e84097a0c
|
||||
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
|
||||
F test/attach.test cb9b884344e6cfa5e165965d5b1adea679a24c83
|
||||
@ -83,7 +83,7 @@ F test/attach2.test 5472d442bb2ef1ee587e0ae7472bb68b52509a38
|
||||
F test/auth.test 5c4d95cdaf539c0c236e20ce1f71a93e7dde9185
|
||||
F test/bigfile.test ea904b853ce2d703b16c5ce90e2b54951bc1ae81
|
||||
F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
|
||||
F test/bind.test 44097e9a885ac851934c2e9b74d2fec36659bca5
|
||||
F test/bind.test ef1efd5cf63b27c11acda9a1c0c7403960f12400
|
||||
F test/btree.test 08e4093c78d2bc1d54e27266f8d17fed14751125
|
||||
F test/btree2.test aa4a6d05b1ea90b1acaf83ba89039dd302a88635
|
||||
F test/btree4.test 3797b4305694c7af6828675b0f4b1424b8ca30e4
|
||||
@ -97,7 +97,7 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/date.test aed5030482ebc02bd8d386c6c86a29f694ab068d
|
||||
F test/delete.test 92256384f1801760180ded129f7427884cf28886
|
||||
F test/enc.test a55481d45ff493804e8d88357feb4642fc50a6b2
|
||||
F test/enc2.test f80bcf14a286f34e54378b9b044c5d93b7679bc1
|
||||
F test/enc2.test 669f46b4e298a22fb515cb52c55eb8dca57d8b4a
|
||||
F test/expr.test 8b62f3fcac64fbd5c3d43d7a7984245743dcbe65
|
||||
F test/fkey1.test d65c824459916249bee501532d6154ddab0b5db7
|
||||
F test/format3.test 149cc166c97923fa60def047e90dd3fb32bba916
|
||||
@ -205,7 +205,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
||||
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||
P d72adf0c522b442d5e1663862bdd639c282d4495
|
||||
R 2ba0c044593753a501ecb5b9d1ce6722
|
||||
U danielk1977
|
||||
Z 64c9fdf3b1584f065ec0b7238e3a9f4f
|
||||
P 74097ecdb0b1e0eec143c5a3f8ca2f0d63d6f38d
|
||||
R 98aa4ae2a65faf4f8c17b075955c2246
|
||||
U drh
|
||||
Z eb27f7bb480c5083f24dd280c1f9cf51
|
||||
|
@ -1 +1 @@
|
||||
74097ecdb0b1e0eec143c5a3f8ca2f0d63d6f38d
|
||||
dbdd1a7f316e576d0611748ec63c9ef00d4c10db
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.253 2004/05/26 16:54:45 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.254 2004/05/27 01:53:56 drh Exp $
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "sqlite.h"
|
||||
@ -1347,7 +1347,7 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2);
|
||||
char const *sqlite3AffinityString(char affinity);
|
||||
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
|
||||
char sqlite3ExprAffinity(Expr *pExpr);
|
||||
int sqlite3atoi64(const char*, i64*, u8);
|
||||
int sqlite3atoi64(const char*, i64*);
|
||||
void sqlite3Error(sqlite *, int, const char*,...);
|
||||
int sqlite3utfTranslate(const void *, int , u8 , void **, int *, u8);
|
||||
u8 sqlite3UtfReadBom(const void *zData, int nData);
|
||||
|
14
src/utf.c
14
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.10 2004/05/24 12:39:02 danielk1977 Exp $
|
||||
** $Id: utf.c,v 1.11 2004/05/27 01:53:56 drh Exp $
|
||||
**
|
||||
** Notes on UTF-8:
|
||||
**
|
||||
@ -579,12 +579,10 @@ void sqlite3utf16to16be(void *pData, int N){
|
||||
** result is returned in dynamically allocated memory.
|
||||
*/
|
||||
int sqlite3utfTranslate(
|
||||
const void *zData,
|
||||
int nData,
|
||||
u8 enc1,
|
||||
void **zOut,
|
||||
int *nOut,
|
||||
u8 enc2
|
||||
const void *zData, int nData, /* Input string */
|
||||
u8 enc1, /* Encoding of zData */
|
||||
void **zOut, int *nOut, /* Output string */
|
||||
u8 enc2 /* Desired encoding of output */
|
||||
){
|
||||
assert( enc1==TEXT_Utf8 || enc1==TEXT_Utf16le || enc1==TEXT_Utf16be );
|
||||
assert( enc2==TEXT_Utf8 || enc2==TEXT_Utf16le || enc2==TEXT_Utf16be );
|
||||
@ -608,5 +606,3 @@ int sqlite3utfTranslate(
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
14
src/util.c
14
src/util.c
@ -14,7 +14,7 @@
|
||||
** This file contains functions for allocating memory, comparing
|
||||
** strings, and stuff like that.
|
||||
**
|
||||
** $Id: util.c,v 1.88 2004/05/24 07:04:26 danielk1977 Exp $
|
||||
** $Id: util.c,v 1.89 2004/05/27 01:53:56 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <stdarg.h>
|
||||
@ -665,27 +665,23 @@ double sqlite3AtoF(const char *z, const char **pzEnd){
|
||||
** 32-bit numbers. At that time, it was much faster than the
|
||||
** atoi() library routine in RedHat 7.2.
|
||||
*/
|
||||
int sqlite3atoi64(const char *zNum, i64 *pNum, u8 enc){
|
||||
int sqlite3atoi64(const char *zNum, i64 *pNum){
|
||||
i64 v = 0;
|
||||
int neg;
|
||||
int i, c;
|
||||
int incr = (enc==TEXT_Utf8?1:2);
|
||||
if( enc==TEXT_Utf16be ) zNum++;
|
||||
if( *zNum=='-' ){
|
||||
neg = 1;
|
||||
zNum += incr;
|
||||
zNum++;
|
||||
}else if( *zNum=='+' ){
|
||||
neg = 0;
|
||||
zNum += incr;
|
||||
zNum++;
|
||||
}else{
|
||||
neg = 0;
|
||||
}
|
||||
for(i=0; (c=zNum[i])>='0' && c<='9'; i += incr){
|
||||
for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
|
||||
v = v*10 + c - '0';
|
||||
}
|
||||
*pNum = neg ? -v : v;
|
||||
|
||||
/* FIX ME: Handle overflow of strings in UTF-16 here */
|
||||
return c==0 && i>0 &&
|
||||
(i<19 || (i==19 && memcmp(zNum,"9223372036854775807",19)<=0));
|
||||
}
|
||||
|
219
src/vdbe.c
219
src/vdbe.c
@ -43,7 +43,7 @@
|
||||
** in this file for details. If in doubt, do not deviate from existing
|
||||
** commenting and indentation practices when changing or adding code.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.336 2004/05/26 23:25:31 drh Exp $
|
||||
** $Id: vdbe.c,v 1.337 2004/05/27 01:53:56 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@ -69,105 +69,18 @@ int sqlite3_search_count = 0;
|
||||
*/
|
||||
int sqlite3_interrupt_count = 0;
|
||||
|
||||
/*
|
||||
** This macro takes a single parameter, a pointer to a Mem structure.
|
||||
** It returns the string encoding for the Mem structure, one of TEXT_Utf8
|
||||
** TEXT_Utf16le or TEXT_Utf16be.
|
||||
*/
|
||||
#define MemEnc(p) ( \
|
||||
((p)->flags&MEM_Utf16le)?TEXT_Utf16le: \
|
||||
((p)->flags&MEM_Utf16be)?TEXT_Utf16be:TEXT_Utf8) )
|
||||
|
||||
/*
|
||||
** Release the memory associated with the given stack level. This
|
||||
** leaves the Mem.flags field in an inconsistent state.
|
||||
*/
|
||||
#define Release(P) if((P)->flags&MEM_Dyn){ sqliteFree((P)->z); }
|
||||
|
||||
/*
|
||||
** Parmameter "flags" is the value of the flags for a string Mem object.
|
||||
** Return one of TEXT_Utf8, TEXT_Utf16le or TEXT_Utf16be, depending
|
||||
** on the encoding indicated by the flags value.
|
||||
*/
|
||||
static u8 flagsToEnc(int flags){
|
||||
if( flags&MEM_Utf8 ){
|
||||
assert( !(flags&(MEM_Utf16be|MEM_Utf16le)) );
|
||||
return TEXT_Utf8;
|
||||
}
|
||||
if( flags&MEM_Utf16le ){
|
||||
assert( !(flags&(MEM_Utf8|MEM_Utf16be)) );
|
||||
return TEXT_Utf16le;
|
||||
}
|
||||
assert( flags&MEM_Utf16be );
|
||||
assert( !(flags&(MEM_Utf8|MEM_Utf16le)) );
|
||||
return TEXT_Utf16be;
|
||||
}
|
||||
|
||||
/*
|
||||
** Parameter "enc" is one of TEXT_Utf8, TEXT_Utf16le or TEXT_Utf16be.
|
||||
** Return the corresponding MEM_Utf* value.
|
||||
*/
|
||||
static int encToFlags(u8 enc){
|
||||
switch( enc ){
|
||||
case TEXT_Utf8: return MEM_Utf8;
|
||||
case TEXT_Utf16be: return MEM_Utf16be;
|
||||
case TEXT_Utf16le: return MEM_Utf16le;
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the encoding flags of memory cell "pMem" to the correct values
|
||||
** for the database encoding "enc" (one of TEXT_Utf8, TEXT_Utf16le or
|
||||
** TEXT_Utf16be).
|
||||
*/
|
||||
#define SetEncodingFlags(pMem, enc) ((pMem)->flags = \
|
||||
((pMem->flags & ~(MEM_Utf8|MEM_Utf16le|MEM_Utf16be))) | encToFlags(enc))
|
||||
static int SetEncoding(Mem*, int);
|
||||
|
||||
/*
|
||||
** Convert the given stack entity into a string if it isn't one
|
||||
** already. Return non-zero if a malloc() fails.
|
||||
*/
|
||||
#define Stringify(P, enc) \
|
||||
(!((P)->flags&(MEM_Str|MEM_Blob)) && hardStringify(P, enc))
|
||||
static int hardStringify(Mem *pStack, u8 enc){
|
||||
int rc = SQLITE_OK;
|
||||
int fg = pStack->flags;
|
||||
|
||||
assert( !(fg&(MEM_Str|MEM_Blob)) );
|
||||
assert( fg&(MEM_Int|MEM_Real|MEM_Null) );
|
||||
|
||||
if( fg & MEM_Null ){
|
||||
/* A NULL value is converted to a zero length string */
|
||||
pStack->zShort[0] = 0;
|
||||
pStack->zShort[1] = 0;
|
||||
pStack->flags = MEM_Str | MEM_Short | MEM_Term;
|
||||
pStack->z = pStack->zShort;
|
||||
pStack->n = (enc==TEXT_Utf8?1:2);
|
||||
}else{
|
||||
/* For a Real or Integer, use sqlite3_snprintf() 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_Real ){
|
||||
sqlite3_snprintf(NBFS, pStack->zShort, "%.15g", pStack->r);
|
||||
}else if( fg & MEM_Int ){
|
||||
sqlite3_snprintf(NBFS, pStack->zShort, "%lld", pStack->i);
|
||||
}
|
||||
pStack->n = strlen(pStack->zShort) + 1;
|
||||
pStack->z = pStack->zShort;
|
||||
pStack->flags = MEM_Str | MEM_Short | MEM_Term;
|
||||
|
||||
/* Flip the string to UTF-16 if required */
|
||||
SetEncodingFlags(pStack, TEXT_Utf8);
|
||||
rc = SetEncoding(pStack, encToFlags(enc)|MEM_Term);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
(!((P)->flags&(MEM_Str|MEM_Blob)) && sqlite3VdbeMemStringify(P,enc))
|
||||
|
||||
/*
|
||||
** Convert the given stack entity into a string that has been obtained
|
||||
@ -176,22 +89,8 @@ static int hardStringify(Mem *pStack, u8 enc){
|
||||
** will fit but this routine always mallocs for space.
|
||||
** Return non-zero if we run out of memory.
|
||||
*/
|
||||
#define Dynamicify(P, enc) \
|
||||
(((P)->flags & MEM_Dyn)==0 ? hardDynamicify(P, enc):0)
|
||||
static int hardDynamicify(Mem *pStack, u8 enc){
|
||||
int fg = pStack->flags;
|
||||
char *z;
|
||||
if( (fg & MEM_Str)==0 ){
|
||||
hardStringify(pStack, enc);
|
||||
}
|
||||
assert( (fg & MEM_Dyn)==0 );
|
||||
z = sqliteMallocRaw( pStack->n );
|
||||
if( z==0 ) return 1;
|
||||
memcpy(z, pStack->z, pStack->n);
|
||||
pStack->z = z;
|
||||
pStack->flags |= MEM_Dyn;
|
||||
return 0;
|
||||
}
|
||||
#define Dynamicify(P,enc) sqlite3VdbeMemDynamicify(P)
|
||||
|
||||
|
||||
/*
|
||||
** An ephemeral string value (signified by the MEM_Ephem flag) contains
|
||||
@ -205,18 +104,8 @@ static int hardDynamicify(Mem *pStack, u8 enc){
|
||||
** converts an MEM_Ephem string into an MEM_Dyn string.
|
||||
*/
|
||||
#define Deephemeralize(P) \
|
||||
if( ((P)->flags&MEM_Ephem)!=0 && hardDeephem(P) ){ goto no_mem;}
|
||||
static int hardDeephem(Mem *pStack){
|
||||
char *z;
|
||||
assert( (pStack->flags & MEM_Ephem)!=0 );
|
||||
z = sqliteMallocRaw( pStack->n );
|
||||
if( z==0 ) return 1;
|
||||
memcpy(z, pStack->z, pStack->n);
|
||||
pStack->z = z;
|
||||
pStack->flags &= ~MEM_Ephem;
|
||||
pStack->flags |= MEM_Dyn;
|
||||
return 0;
|
||||
}
|
||||
if( ((P)->flags&MEM_Ephem)!=0 \
|
||||
&& sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
|
||||
|
||||
/*
|
||||
** Convert the given stack entity into a integer if it isn't one
|
||||
@ -226,19 +115,7 @@ static int hardDeephem(Mem *pStack){
|
||||
** NULLs are converted into 0.
|
||||
*/
|
||||
#define Integerify(P, enc) \
|
||||
if(((P)->flags&MEM_Int)==0){ hardIntegerify(P, enc); }
|
||||
static void hardIntegerify(Mem *pStack, u8 enc){
|
||||
pStack->i = 0;
|
||||
if( pStack->flags & MEM_Real ){
|
||||
pStack->i = (int)pStack->r;
|
||||
Release(pStack);
|
||||
}else if( pStack->flags & MEM_Str ){
|
||||
if( pStack->z ){
|
||||
sqlite3atoi64(pStack->z, &pStack->i, enc);
|
||||
}
|
||||
}
|
||||
pStack->flags = MEM_Int;
|
||||
}
|
||||
if((P)->flags!=MEM_Int){ sqlite3VdbeMemIntegerify(P); }
|
||||
|
||||
/*
|
||||
** Get a valid Real representation for the given stack element.
|
||||
@ -246,21 +123,8 @@ static void hardIntegerify(Mem *pStack, u8 enc){
|
||||
** Any prior string or integer representation is retained.
|
||||
** NULLs are converted into 0.0.
|
||||
*/
|
||||
#define Realify(P,enc) if(((P)->flags&MEM_Real)==0){ hardRealify(P,enc); }
|
||||
static void hardRealify(Mem *pStack, u8 enc){
|
||||
if( pStack->flags & MEM_Str ){
|
||||
SetEncodingFlags(pStack, enc);
|
||||
SetEncoding(pStack, MEM_Utf8|MEM_Term);
|
||||
pStack->r = sqlite3AtoF(pStack->z, 0);
|
||||
}else if( pStack->flags & MEM_Int ){
|
||||
pStack->r = pStack->i;
|
||||
}else{
|
||||
pStack->r = 0.0;
|
||||
}
|
||||
/* pStack->flags |= MEM_Real; */
|
||||
pStack->flags = MEM_Real;
|
||||
}
|
||||
|
||||
#define Realify(P,enc) \
|
||||
if(((P)->flags&MEM_Real)==0){ sqlite3VdbeMemRealify(P); }
|
||||
|
||||
|
||||
/*
|
||||
@ -1158,29 +1022,26 @@ case OP_Concat: {
|
||||
int nField;
|
||||
int i, j;
|
||||
Mem *pTerm;
|
||||
Mem zSep; /* Memory cell containing the seperator string, if any */
|
||||
int termLen; /* Bytes in the terminator character for this encoding */
|
||||
|
||||
termLen = (db->enc==TEXT_Utf8?1:2);
|
||||
Mem mSep; /* Memory cell containing the seperator string, if any */
|
||||
|
||||
/* FIX ME: Eventually, P3 will be in database native encoding. But for
|
||||
** now it is always UTF-8. So set up zSep to hold the native encoding of
|
||||
** P3.
|
||||
*/
|
||||
if( pOp->p3 ){
|
||||
zSep.z = pOp->p3;
|
||||
zSep.n = strlen(zSep.z)+1;
|
||||
zSep.flags = MEM_Str|MEM_Static|MEM_Utf8|MEM_Term;
|
||||
SetEncoding(&zSep, encToFlags(db->enc)|MEM_Term);
|
||||
mSep.z = pOp->p3;
|
||||
mSep.n = strlen(mSep.z);
|
||||
mSep.flags = MEM_Str|MEM_Static|MEM_Term;
|
||||
mSep.enc = TEXT_Utf8;
|
||||
sqlite3VdbeChangeEncoding(&mSep, db->enc);
|
||||
}else{
|
||||
zSep.flags = MEM_Null;
|
||||
zSep.n = 0;
|
||||
mSep.flags = MEM_Null;
|
||||
}
|
||||
|
||||
/* Loop through the stack elements to see how long the result will be. */
|
||||
nField = pOp->p1;
|
||||
pTerm = &pTos[1-nField];
|
||||
nByte = termLen + (nField-1)*(zSep.n - ((zSep.flags&MEM_Term)?termLen:0));
|
||||
nByte = (nField-1)*mSep.n;
|
||||
for(i=0; i<nField; i++, pTerm++){
|
||||
assert( pOp->p2==0 || (pTerm->flags&MEM_Str) );
|
||||
if( pTerm->flags&MEM_Null ){
|
||||
@ -1188,7 +1049,7 @@ case OP_Concat: {
|
||||
break;
|
||||
}
|
||||
Stringify(pTerm, db->enc);
|
||||
nByte += (pTerm->n - ((pTerm->flags&MEM_Term)?termLen:0));
|
||||
nByte += pTerm->n;
|
||||
}
|
||||
|
||||
if( nByte<0 ){
|
||||
@ -1205,33 +1066,32 @@ case OP_Concat: {
|
||||
/* Otherwise malloc() space for the result and concatenate all the
|
||||
** stack values.
|
||||
*/
|
||||
zNew = sqliteMallocRaw( nByte );
|
||||
zNew = sqliteMallocRaw( nByte+2 );
|
||||
if( zNew==0 ) goto no_mem;
|
||||
j = 0;
|
||||
pTerm = &pTos[1-nField];
|
||||
for(i=j=0; i<nField; i++, pTerm++){
|
||||
int n = pTerm->n-((pTerm->flags&MEM_Term)?termLen:0);
|
||||
int n = pTerm->n;
|
||||
assert( pTerm->flags & MEM_Str );
|
||||
memcpy(&zNew[j], pTerm->z, n);
|
||||
j += n;
|
||||
if( i<nField-1 && !(zSep.flags|MEM_Null) ){
|
||||
n = zSep.n-((zSep.flags&MEM_Term)?termLen:0);
|
||||
memcpy(&zNew[j], zSep.z, n);
|
||||
j += n;
|
||||
if( i<nField-1 && !(mSep.flags|MEM_Null) ){
|
||||
memcpy(&zNew[j], mSep.z, mSep.n);
|
||||
j += mSep.n;
|
||||
}
|
||||
}
|
||||
zNew[j++] = 0;
|
||||
if( termLen==2 ){
|
||||
zNew[j++] = 0;
|
||||
}
|
||||
assert( j==nByte );
|
||||
zNew[j] = 0;
|
||||
zNew[j+1] = 0;
|
||||
assert( j==nByte-1 );
|
||||
|
||||
if( pOp->p2==0 ){
|
||||
popStack(&pTos, nField);
|
||||
}
|
||||
pTos++;
|
||||
pTos->n = nByte;
|
||||
pTos->flags = MEM_Str|MEM_Dyn|MEM_Term|encToFlags(db->enc);
|
||||
pTos->n = j;
|
||||
pTos->flags = MEM_Str|MEM_Dyn|MEM_Term
|
||||
pTos->enc = db->enc;
|
||||
pTos->type = SQLITE3_TEXT;
|
||||
pTos->z = zNew;
|
||||
}
|
||||
break;
|
||||
@ -1553,12 +1413,16 @@ case OP_MustBeInt: {
|
||||
pTos->i = i;
|
||||
}else if( pTos->flags & MEM_Str ){
|
||||
i64 v;
|
||||
if( !sqlite3atoi64(pTos->z, &v, db->enc) ){
|
||||
if( sqlite3VdbeChangeEncoding(pTos, TEXT_Utf8)
|
||||
|| sqlite3VdbeNulTerminate(pTos) ){
|
||||
goto no_mem;
|
||||
}
|
||||
if( !sqlite3atoi64(pTos->z, &v) ){
|
||||
double r;
|
||||
if( !sqlite3IsNumber(pTos->z, 0, db->enc) ){
|
||||
if( !sqlite3IsNumber(pTos->z, 0, TEXT_Utf8) ){
|
||||
goto mismatch;
|
||||
}
|
||||
Realify(pTos, db->enc);
|
||||
Realify(pTos, TEXT_Utf8);
|
||||
v = (int)pTos->r;
|
||||
r = (double)v;
|
||||
if( r!=pTos->r ){
|
||||
@ -1571,6 +1435,7 @@ case OP_MustBeInt: {
|
||||
}
|
||||
Release(pTos);
|
||||
pTos->flags = MEM_Int;
|
||||
pTos->type = SQLITE3_INTEGER;
|
||||
break;
|
||||
|
||||
mismatch:
|
||||
@ -4385,11 +4250,9 @@ case OP_SortNext: {
|
||||
pTos++;
|
||||
pTos->z = pSorter->pData;
|
||||
pTos->n = pSorter->nData;
|
||||
/* FIX ME: I don't understand this. What does the sorter return?
|
||||
** I thought it would be the commented out flags.
|
||||
*/
|
||||
/* pTos->flags = MEM_Blob|MEM_Dyn; */
|
||||
pTos->flags = MEM_Str|MEM_Dyn|MEM_Utf8|MEM_Term;
|
||||
pTos->flags = MEM_Blob|MEM_Dyn|MEM_Term;
|
||||
pTos->enc = 0;
|
||||
pTos->type = SQLITE3_BLOB;
|
||||
sqliteFree(pSorter->zKey);
|
||||
sqliteFree(pSorter);
|
||||
}else{
|
||||
|
@ -356,3 +356,10 @@ int sqlite3VdbeSetEncoding(Mem *, u8);
|
||||
int sqlite3VdbeMemCopy(Mem*, const Mem*);
|
||||
int sqlite3VdbeMemNulTerminate(Mem *);
|
||||
int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, int);
|
||||
int sqlite3VdbeMemSetInt64(Mem*, long long int);
|
||||
int sqlite3VdbeMemSetDouble(Mem*, double);
|
||||
int sqlite3VdbeMemMakeWriteable(Mem*);
|
||||
int sqlite3VdbeMemDynamicify(Mem*);
|
||||
int sqlite3VdbeMemStringify(Mem*);
|
||||
int sqlite3VdbeMemIntegerify(Mem*);
|
||||
int sqlite3VdbeMemRealify(Mem*);
|
||||
|
@ -198,6 +198,50 @@ int sqlite3_step(sqlite3_stmt *pStmt){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Extract the user data from a sqlite3_context structure and return a
|
||||
** pointer to it.
|
||||
*/
|
||||
void *sqlite3_user_data(sqlite3_context *p){
|
||||
assert( p && p->pFunc );
|
||||
return p->pFunc->pUserData;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate or return the aggregate context for a user function. A new
|
||||
** context is allocated on the first call. Subsequent calls return the
|
||||
** same context that was returned on prior calls.
|
||||
**
|
||||
** This routine is defined here in vdbe.c because it depends on knowing
|
||||
** the internals of the sqlite3_context structure which is only defined in
|
||||
** this source file.
|
||||
*/
|
||||
void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
|
||||
assert( p && p->pFunc && p->pFunc->xStep );
|
||||
if( p->pAgg==0 ){
|
||||
if( nByte<=NBFS ){
|
||||
p->pAgg = (void*)p->s.z;
|
||||
memset(p->pAgg, 0, nByte);
|
||||
}else{
|
||||
p->pAgg = sqliteMalloc( nByte );
|
||||
}
|
||||
}
|
||||
return p->pAgg;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of times the Step function of a aggregate has been
|
||||
** called.
|
||||
**
|
||||
** This routine is defined here in vdbe.c because it depends on knowing
|
||||
** the internals of the sqlite3_context structure which is only defined in
|
||||
** this source file.
|
||||
*/
|
||||
int sqlite3_aggregate_count(sqlite3_context *p){
|
||||
assert( p && p->pFunc && p->pFunc->xStep );
|
||||
return p->cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of columns in the result set for the statement pStmt.
|
||||
*/
|
||||
|
458
src/vdbeaux.c
458
src/vdbeaux.c
@ -424,50 +424,6 @@ VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
|
||||
return &p->aOp[addr];
|
||||
}
|
||||
|
||||
/*
|
||||
** Extract the user data from a sqlite3_context structure and return a
|
||||
** pointer to it.
|
||||
*/
|
||||
void *sqlite3_user_data(sqlite3_context *p){
|
||||
assert( p && p->pFunc );
|
||||
return p->pFunc->pUserData;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate or return the aggregate context for a user function. A new
|
||||
** context is allocated on the first call. Subsequent calls return the
|
||||
** same context that was returned on prior calls.
|
||||
**
|
||||
** This routine is defined here in vdbe.c because it depends on knowing
|
||||
** the internals of the sqlite3_context structure which is only defined in
|
||||
** this source file.
|
||||
*/
|
||||
void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
|
||||
assert( p && p->pFunc && p->pFunc->xStep );
|
||||
if( p->pAgg==0 ){
|
||||
if( nByte<=NBFS ){
|
||||
p->pAgg = (void*)p->s.z;
|
||||
memset(p->pAgg, 0, nByte);
|
||||
}else{
|
||||
p->pAgg = sqliteMalloc( nByte );
|
||||
}
|
||||
}
|
||||
return p->pAgg;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of times the Step function of a aggregate has been
|
||||
** called.
|
||||
**
|
||||
** This routine is defined here in vdbe.c because it depends on knowing
|
||||
** the internals of the sqlite3_context structure which is only defined in
|
||||
** this source file.
|
||||
*/
|
||||
int sqlite3_aggregate_count(sqlite3_context *p){
|
||||
assert( p && p->pFunc && p->pFunc->xStep );
|
||||
return p->cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute a string that describes the P3 parameter for an opcode.
|
||||
** Use zTemp for any required temporary buffer space.
|
||||
@ -613,23 +569,36 @@ int sqlite3VdbeList(
|
||||
sqlite3SetString(&p->zErrMsg, sqlite3_error_string(p->rc), (char*)0);
|
||||
}else{
|
||||
Op *pOp = &p->aOp[i];
|
||||
p->aStack[0].flags = MEM_Int;
|
||||
p->aStack[0].i = i; /* Program counter */
|
||||
p->aStack[1].flags = MEM_Static|MEM_Str|MEM_Utf8|MEM_Term;
|
||||
p->aStack[1].z = sqlite3OpcodeNames[pOp->opcode]; /* Opcode */
|
||||
p->aStack[2].flags = MEM_Int;
|
||||
p->aStack[2].i = pOp->p1; /* P1 */
|
||||
p->aStack[3].flags = MEM_Int;
|
||||
p->aStack[3].i = pOp->p2; /* P2 */
|
||||
p->aStack[4].flags = MEM_Str|MEM_Utf8|MEM_Term; /* P3 */
|
||||
p->aStack[4].z = displayP3(pOp, p->aStack[4].zShort, NBFS);
|
||||
if( p->aStack[4].z==p->aStack[4].zShort ){
|
||||
p->aStack[4].flags |= MEM_Short;
|
||||
}else{
|
||||
p->aStack[4].flags |= MEM_Static;
|
||||
}
|
||||
Mem *pMem = p->aStack;
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->type = SQLITE3_INT;
|
||||
pMem->i = i; /* Program counter */
|
||||
pMem++;
|
||||
|
||||
pMem->flags = MEM_Static|MEM_Str|MEM_Term;
|
||||
pMem->z = sqlite3OpcodeNames[pOp->opcode]; /* Opcode */
|
||||
pMem->n = strlen(pMem->z);
|
||||
pMem->type = SQLITE3_TEXT;
|
||||
pMem->enc = TEXT_Utf8;
|
||||
pMem++;
|
||||
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->i = pOp->p1; /* P1 */
|
||||
pMem->type = SQLITE3_INT;
|
||||
pMem++;
|
||||
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->i = pOp->p2; /* P2 */
|
||||
pMem->type = SQLITE_INT;
|
||||
pMem++;
|
||||
|
||||
pMem->flags = MEM_Short|MEM_Str|MEM_Term; /* P3 */
|
||||
pMem->z = displayP3(pOp, pMem->zShort, sizeof(pMem->zShort));
|
||||
pMem->type = SQLITE_TEXT;
|
||||
pMem->enc = TEXT_Utf8;
|
||||
|
||||
p->nResColumn = 5;
|
||||
p->pTos = &p->aStack[4];
|
||||
p->pTos = pMem;
|
||||
p->rc = SQLITE_OK;
|
||||
p->resOnStack = 1;
|
||||
rc = SQLITE_ROW;
|
||||
@ -1184,15 +1153,6 @@ u64 sqlite3VdbeSerialType(Mem *pMem){
|
||||
if( flags&MEM_Str ){
|
||||
int n = pMem->n;
|
||||
assert( n>=0 );
|
||||
if( pMem->flags&MEM_Term ){
|
||||
/* If the nul terminated flag is set we have to subtract something
|
||||
** from the serial-type. Depending on the encoding there could be
|
||||
** one or two 0x00 bytes at the end of the string. Check for these
|
||||
** and subtract 2 from serial_
|
||||
*/
|
||||
if( n>0 && !pMem->z[n-1] ) n--;
|
||||
if( n>0 && !pMem->z[n-1] ) n--;
|
||||
}
|
||||
return ((n*2) + 13);
|
||||
}
|
||||
if( flags&MEM_Blob ){
|
||||
@ -1279,6 +1239,7 @@ int sqlite3VdbeSerialGet(
|
||||
/* NULL */
|
||||
if( serial_type==6 ){
|
||||
pMem->flags = MEM_Null;
|
||||
pMem->type = SQLITE3_NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1297,9 +1258,11 @@ int sqlite3VdbeSerialGet(
|
||||
if( serial_type==5 ){
|
||||
pMem->flags = MEM_Real;
|
||||
pMem->r = *(double*)&v;
|
||||
pMem->type = SQLITE3_FLOAT;
|
||||
}else{
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->i = *(i64*)&v;
|
||||
pMem->type = SQLITE3_INTEGER;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
@ -1308,136 +1271,16 @@ int sqlite3VdbeSerialGet(
|
||||
assert( serial_type>=12 );
|
||||
len = sqlite3VdbeSerialTypeLen(serial_type);
|
||||
if( serial_type&0x01 ){
|
||||
switch( enc ){
|
||||
case TEXT_Utf8:
|
||||
pMem->flags = MEM_Str|MEM_Utf8|MEM_Term;
|
||||
break;
|
||||
case TEXT_Utf16le:
|
||||
pMem->flags = MEM_Str|MEM_Utf16le|MEM_Term;
|
||||
break;
|
||||
case TEXT_Utf16be:
|
||||
pMem->flags = MEM_Str|MEM_Utf16be|MEM_Term;
|
||||
break;
|
||||
assert(0);
|
||||
}
|
||||
pMem->n = len+(enc==TEXT_Utf8?1:2);
|
||||
pMem->flags = MEM_Str | MEM_Ephem;
|
||||
pMem->n = len;
|
||||
}else{
|
||||
pMem->flags = MEM_Blob;
|
||||
pMem->flags = MEM_Blob | MEM_Ephem;
|
||||
pMem->n = len;
|
||||
}
|
||||
|
||||
if( (pMem->n)>NBFS ){
|
||||
pMem->z = sqliteMallocRaw( pMem->n );
|
||||
if( !pMem->z ){
|
||||
return -1;
|
||||
}
|
||||
pMem->flags |= MEM_Dyn;
|
||||
}else{
|
||||
pMem->z = pMem->zShort;
|
||||
pMem->flags |= MEM_Short;
|
||||
}
|
||||
|
||||
memcpy(pMem->z, buf, len);
|
||||
if( pMem->flags&MEM_Str ){
|
||||
pMem->z[len] = '\0';
|
||||
if( enc!=TEXT_Utf8 ){
|
||||
pMem->z[len+1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3VdbeMemMakeWriteable(pMem);
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compare the values contained by the two memory cells, returning
|
||||
** negative, zero or positive if pMem1 is less than, equal to, or greater
|
||||
** than pMem2. Sorting order is NULL's first, followed by numbers (integers
|
||||
** and reals) sorted numerically, followed by text ordered by the collating
|
||||
** sequence pColl and finally blob's ordered by memcmp().
|
||||
**
|
||||
** Two NULL values are considered equal by this function.
|
||||
*/
|
||||
int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
|
||||
int rc;
|
||||
int f1, f2;
|
||||
int combined_flags;
|
||||
|
||||
/* Interchange pMem1 and pMem2 if the collating sequence specifies
|
||||
** DESC order.
|
||||
*/
|
||||
f1 = pMem1->flags;
|
||||
f2 = pMem2->flags;
|
||||
combined_flags = f1|f2;
|
||||
|
||||
/* If one value is NULL, it is less than the other. If both values
|
||||
** are NULL, return 0.
|
||||
*/
|
||||
if( combined_flags&MEM_Null ){
|
||||
return (f2&MEM_Null) - (f1&MEM_Null);
|
||||
}
|
||||
|
||||
/* If one value is a number and the other is not, the number is less.
|
||||
** If both are numbers, compare as reals if one is a real, or as integers
|
||||
** if both values are integers.
|
||||
*/
|
||||
if( combined_flags&(MEM_Int|MEM_Real) ){
|
||||
if( !(f1&(MEM_Int|MEM_Real)) ){
|
||||
return 1;
|
||||
}
|
||||
if( !(f2&(MEM_Int|MEM_Real)) ){
|
||||
return -1;
|
||||
}
|
||||
if( (f1 & f2 & MEM_Int)==0 ){
|
||||
double r1, r2;
|
||||
if( (f1&MEM_Real)==0 ){
|
||||
r1 = pMem1->i;
|
||||
}else{
|
||||
r1 = pMem1->r;
|
||||
}
|
||||
if( (f2&MEM_Real)==0 ){
|
||||
r2 = pMem2->i;
|
||||
}else{
|
||||
r2 = pMem2->r;
|
||||
}
|
||||
if( r1<r2 ) return -1;
|
||||
if( r1>r2 ) return 1;
|
||||
return 0;
|
||||
}else{
|
||||
assert( f1&MEM_Int );
|
||||
assert( f2&MEM_Int );
|
||||
if( pMem1->i < pMem2->i ) return -1;
|
||||
if( pMem1->i > pMem2->i ) return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If one value is a string and the other is a blob, the string is less.
|
||||
** If both are strings, compare using the collating functions.
|
||||
*/
|
||||
if( combined_flags&MEM_Str ){
|
||||
if( (f1 & MEM_Str)==0 ){
|
||||
return 1;
|
||||
}
|
||||
if( (f2 & MEM_Str)==0 ){
|
||||
return -1;
|
||||
}
|
||||
if( pColl && pColl->xCmp ){
|
||||
return pColl->xCmp(pColl->pUser, pMem1->n, pMem1->z, pMem2->n, pMem2->z);
|
||||
}else{
|
||||
/* If no collating sequence is defined, fall through into the
|
||||
** blob case below and use memcmp() for the comparison. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Both values must be blobs. Compare using memcmp().
|
||||
*/
|
||||
rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
|
||||
if( rc==0 ){
|
||||
rc = pMem1->n - pMem2->n;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** The following is the comparison function for (non-integer)
|
||||
** keys in the btrees. This function returns negative, zero, or
|
||||
@ -1703,232 +1546,3 @@ int sqlite3VdbeIdxKeyCompare(
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Parameter "enc" is one of TEXT_Utf8, TEXT_Utf16le or TEXT_Utf16be.
|
||||
** Return the corresponding MEM_Utf* value.
|
||||
*/
|
||||
static int encToFlags(u8 enc){
|
||||
switch( enc ){
|
||||
case TEXT_Utf8: return MEM_Utf8;
|
||||
case TEXT_Utf16be: return MEM_Utf16be;
|
||||
case TEXT_Utf16le: return MEM_Utf16le;
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
static u8 flagsToEnc(int flags){
|
||||
switch( flags&(MEM_Utf8|MEM_Utf16be|MEM_Utf16le) ){
|
||||
case MEM_Utf8: return TEXT_Utf8;
|
||||
case MEM_Utf16le: return TEXT_Utf16le;
|
||||
case MEM_Utf16be: return TEXT_Utf16be;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete any previous value and set the value stored in *pMem to NULL.
|
||||
*/
|
||||
void sqlite3VdbeMemSetNull(Mem *pMem){
|
||||
if( pMem->flags&MEM_Dyn ){
|
||||
sqliteFree(pMem->z);
|
||||
}
|
||||
pMem->flags = MEM_Null;
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete any previous value and set the value stored in *pMem to val,
|
||||
** manifest type INTEGER.
|
||||
*/
|
||||
void sqlite3VdbeMemSetInt(Mem *pMem, i64 val){
|
||||
MemSetNull(pMem);
|
||||
pMem->i = val;
|
||||
pMem->flags = MEM_Int;
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete any previous value and set the value stored in *pMem to val,
|
||||
** manifest type REAL.
|
||||
*/
|
||||
void sqlite3VdbeMemSetReal(Mem *pMem, double val){
|
||||
MemSetNull(pMem);
|
||||
pMem->r = val;
|
||||
pMem->flags = MEM_Real;
|
||||
}
|
||||
|
||||
/*
|
||||
** Copy the contents of memory cell pFrom into pTo.
|
||||
*/
|
||||
int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
|
||||
if( pTo->flags&MEM_Dyn ){
|
||||
sqliteFree(pTo->z);
|
||||
}
|
||||
|
||||
memcpy(pTo, pFrom, sizeof(*pFrom));
|
||||
if( pTo->flags&MEM_Short ){
|
||||
pTo->z = pTo->zShort;
|
||||
}
|
||||
else if( pTo->flags&(MEM_Ephem|MEM_Dyn) ){
|
||||
pTo->flags = pTo->flags&(~(MEM_Static|MEM_Ephem|MEM_Short|MEM_Dyn));
|
||||
if( pTo->n>NBFS ){
|
||||
pTo->z = sqliteMalloc(pTo->n);
|
||||
if( !pTo->z ) return SQLITE_NOMEM;
|
||||
pTo->flags |= MEM_Dyn;
|
||||
}else{
|
||||
pTo->z = pTo->zShort;
|
||||
pTo->flags |= MEM_Short;
|
||||
}
|
||||
memcpy(pTo->z, pFrom->z, pTo->n);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
int sqlite3VdbeMemSetStr(
|
||||
Mem *pMem, /* Memory cell to set to string value */
|
||||
const char *z, /* String pointer */
|
||||
int n, /* Bytes in string, or negative */
|
||||
u8 enc, /* Encoding of z */
|
||||
int eCopy /* True if this function should make a copy of z */
|
||||
){
|
||||
Mem tmp;
|
||||
|
||||
if( !z ){
|
||||
/* If z is NULL, just set *pMem to contain NULL. */
|
||||
MemSetNull(pMem);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
tmp.z = (char *)z;
|
||||
if( eCopy ){
|
||||
tmp.flags = MEM_Ephem|MEM_Str;
|
||||
}else{
|
||||
tmp.flags = MEM_Static|MEM_Str;
|
||||
}
|
||||
tmp.flags |= encToFlags(enc);
|
||||
tmp.n = n;
|
||||
switch( enc ){
|
||||
case 0:
|
||||
tmp.flags |= MEM_Blob;
|
||||
break;
|
||||
|
||||
case TEXT_Utf8:
|
||||
tmp.flags |= MEM_Utf8;
|
||||
if( n<0 ) tmp.n = strlen(z)+1;
|
||||
tmp.flags |= ((tmp.z[tmp.n-1])?0:MEM_Term);
|
||||
break;
|
||||
|
||||
case TEXT_Utf16le:
|
||||
case TEXT_Utf16be:
|
||||
tmp.flags |= (enc==TEXT_Utf16le?MEM_Utf16le:MEM_Utf16be);
|
||||
if( n<0 ) tmp.n = sqlite3utf16ByteLen(z,-1)+1;
|
||||
tmp.flags |= ((tmp.z[tmp.n-1]||tmp.z[tmp.n-2])?0:MEM_Term);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return sqlite3VdbeMemCopy(pMem, &tmp);
|
||||
}
|
||||
|
||||
int sqlite3VdbeMemNulTerminate(Mem *pMem){
|
||||
int nulTermLen;
|
||||
int f = pMem->flags;
|
||||
|
||||
assert( pMem->flags&MEM_Str && !pMem->flags&MEM_Term );
|
||||
assert( flagsToEnc(pMem->flags) );
|
||||
|
||||
nulTermLen = (flagsToEnc(f)==TEXT_Utf8?1:2);
|
||||
|
||||
if( pMem->n+nulTermLen<=NBFS ){
|
||||
/* If the string plus the nul terminator will fit in the Mem.zShort
|
||||
** buffer, and it is not already stored there, copy it there.
|
||||
*/
|
||||
if( !(f&MEM_Short) ){
|
||||
memcpy(pMem->z, pMem->zShort, pMem->n);
|
||||
if( f&MEM_Dyn ){
|
||||
sqliteFree(pMem->z);
|
||||
}
|
||||
pMem->z = pMem->zShort;
|
||||
pMem->flags &= ~(MEM_Static|MEM_Ephem|MEM_Dyn);
|
||||
pMem->flags |= MEM_Short;
|
||||
}
|
||||
}else{
|
||||
/* Otherwise we have to malloc for memory. If the string is already
|
||||
** dynamic, use sqliteRealloc(). Otherwise sqliteMalloc() enough
|
||||
** space for the string and the nul terminator, and copy the string
|
||||
** data there.
|
||||
*/
|
||||
if( f&MEM_Dyn ){
|
||||
pMem->z = (char *)sqliteRealloc(pMem->z, pMem->n+nulTermLen);
|
||||
if( !pMem->z ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
}else{
|
||||
char *z = (char *)sqliteMalloc(pMem->n+nulTermLen);
|
||||
memcpy(z, pMem->z, pMem->n);
|
||||
pMem->z = z;
|
||||
pMem->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short);
|
||||
pMem->flags |= MEM_Dyn;
|
||||
}
|
||||
}
|
||||
|
||||
/* pMem->z now points at the string data, with enough space at the end
|
||||
** to insert the nul nul terminator. pMem->n has not yet been updated.
|
||||
*/
|
||||
memcpy(&pMem->z[pMem->n], "\0\0", nulTermLen);
|
||||
pMem->n += nulTermLen;
|
||||
pMem->flags |= MEM_Term;
|
||||
}
|
||||
|
||||
/*
|
||||
** The following ten routines, named sqlite3_result_*(), are used to
|
||||
** return values or errors from user-defined functions and aggregate
|
||||
** operations. They are commented in the header file sqlite.h (sqlite.h.in)
|
||||
*/
|
||||
void sqlite3_result(sqlite3_context *pCtx, sqlite3_value *pValue){
|
||||
sqlite3VdbeMemCopy(&pCtx->s, pValue);
|
||||
}
|
||||
void sqlite3_result_int32(sqlite3_context *pCtx, int iVal){
|
||||
MemSetInt(&pCtx->s, iVal);
|
||||
}
|
||||
void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){
|
||||
MemSetInt(&pCtx->s, iVal);
|
||||
}
|
||||
void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
|
||||
MemSetReal(&pCtx->s, rVal);
|
||||
}
|
||||
void sqlite3_result_null(sqlite3_context *pCtx){
|
||||
MemSetNull(&pCtx->s);
|
||||
}
|
||||
void sqlite3_result_text(
|
||||
sqlite3_context *pCtx,
|
||||
const char *z,
|
||||
int n,
|
||||
int eCopy
|
||||
){
|
||||
MemSetStr(&pCtx->s, z, n, TEXT_Utf8, eCopy);
|
||||
}
|
||||
void sqlite3_result_text16(
|
||||
sqlite3_context *pCtx,
|
||||
const void *z,
|
||||
int n,
|
||||
int eCopy
|
||||
){
|
||||
MemSetStr(&pCtx->s, z, n, TEXT_Utf16, eCopy);
|
||||
}
|
||||
void sqlite3_result_blob(
|
||||
sqlite3_context *pCtx,
|
||||
const void *z,
|
||||
int n,
|
||||
int eCopy
|
||||
){
|
||||
assert( n>0 );
|
||||
MemSetStr(&pCtx->s, z, n, 0, eCopy);
|
||||
}
|
||||
void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
|
||||
pCtx->isError = 1;
|
||||
MemSetStr(&pCtx->s, z, n, TEXT_Utf8, 1);
|
||||
}
|
||||
void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
|
||||
pCtx->isError = 1;
|
||||
MemSetStr(&pCtx->s, z, n, TEXT_Utf16, 1);
|
||||
}
|
||||
|
375
src/vdbemem.c
375
src/vdbemem.c
@ -20,49 +20,37 @@
|
||||
#include <ctype.h>
|
||||
#include "vdbeInt.h"
|
||||
|
||||
/*
|
||||
** Given a Mem.flags value, return TEXT_Utf8, TEXT_Utf16le, or TEXT_Utf16be
|
||||
** as appropriate.
|
||||
*/
|
||||
#define flagsToEnc(F) \
|
||||
(((F)&MEM_Utf8)?TEXT_Utf8: \
|
||||
((F)&MEM_Utf16be)?TEXT_Utf16be:TEXT_Utf16le)
|
||||
|
||||
/*
|
||||
** If pMem is a string object, this routine sets the encoding of the string
|
||||
** (to one of UTF-8 or UTF16) and whether or not the string is
|
||||
** nul-terminated. If pMem is not a string object, then this routine is
|
||||
** a no-op.
|
||||
**
|
||||
** The second argument, "flags" consists of one of MEM_Utf8, MEM_Utf16le
|
||||
** or MEM_Utf16be, possible ORed with MEM_Term. If necessary this function
|
||||
** manipulates the value stored by pMem so that it matches the flags passed
|
||||
** in "flags".
|
||||
** The second argument, "desiredEnc" is one of TEXT_Utf8, TEXT_Utf16le
|
||||
** or TEXT_Utf16be. This routine changes the encoding of pMem to match
|
||||
** desiredEnc.
|
||||
**
|
||||
** SQLITE_OK is returned if the conversion is successful (or not required).
|
||||
** SQLITE_NOMEM may be returned if a malloc() fails during conversion
|
||||
** between formats.
|
||||
*/
|
||||
int sqlite3VdbeSetEncoding(Mem *pMem, int flags){
|
||||
u8 enc1; /* Current string encoding (TEXT_Utf* value) */
|
||||
u8 enc2; /* Required string encoding (TEXT_Utf* value) */
|
||||
int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
|
||||
u8 oldEnd; /*
|
||||
|
||||
/* If this is not a string, do nothing. */
|
||||
if( !(pMem->flags&MEM_Str) ){
|
||||
/* If this is not a string, or if it is a string but the encoding is
|
||||
** already correct, do nothing. */
|
||||
if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
enc1 = flagsToEnc(pMem->flags);
|
||||
enc2 = flagsToEnc(flags);
|
||||
|
||||
if( enc1!=enc2 ){
|
||||
if( enc1==TEXT_Utf8 || enc2==TEXT_Utf8 ){
|
||||
if( pMem->enc==TEXT_Utf8 || desiredEnd==TEXT_Utf8 ){
|
||||
/* If the current encoding does not match the desired encoding, then
|
||||
** we will need to do some translation between encodings.
|
||||
*/
|
||||
char *z;
|
||||
int n;
|
||||
int rc = sqlite3utfTranslate(pMem->z,pMem->n,enc1,(void **)&z,&n,enc2);
|
||||
int rc = sqlite3utfTranslate(pMem->z, pMem->n, pMem->enc,
|
||||
(void **)&z, &n, desiredEnd);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
@ -73,78 +61,192 @@ int sqlite3VdbeSetEncoding(Mem *pMem, int flags){
|
||||
*/
|
||||
pMem->z = z;
|
||||
pMem->n = n;
|
||||
pMem->flags = (MEM_Str | MEM_Dyn | MEM_Term | flags);
|
||||
pMem->flags &= ~(MEM_Ephem | MEM_Short | MEM_Static);
|
||||
pMem->flags |= MEM_Str | MEM_Dyn | MEM_Term;
|
||||
}else{
|
||||
/* Must be translating between UTF-16le and UTF-16be. */
|
||||
int i;
|
||||
if( pMem->flags&MEM_Static ){
|
||||
Dynamicify(pMem, enc1);
|
||||
}
|
||||
for(i=0; i<pMem->n; i+=2){
|
||||
char c = pMem->z[i];
|
||||
pMem->z[i] = pMem->z[i+1];
|
||||
pMem->z[i+1] = c;
|
||||
}
|
||||
SetEncodingFlags(pMem, enc2);
|
||||
u8 *pFrom, *pTo;
|
||||
sqlite3VdbeMemMakeWritable(pMem);
|
||||
for(i=0, pFrom=pMem->z, pTo=&pMem->z[1]; i<pMem->n; i+=2, pFrom++, pTo++){
|
||||
u8 temp = *pFrom;
|
||||
*pFrom = *pTo;
|
||||
*pTo = temp;
|
||||
}
|
||||
}
|
||||
|
||||
if( (flags&MEM_Term) && !(pMem->flags&MEM_Term) ){
|
||||
/* If we did not do any translation, but currently the string is
|
||||
** not nul terminated (and is required to be), then we add the
|
||||
** nul terminator now. We never have to do this if we translated
|
||||
** the encoding of the string, as the translation functions return
|
||||
** nul terminated values.
|
||||
*/
|
||||
int f = pMem->flags;
|
||||
int nulTermLen = 2; /* The number of 0x00 bytes to append */
|
||||
if( enc2==MEM_Utf8 ){
|
||||
nulTermLen = 1;
|
||||
}
|
||||
|
||||
if( pMem->n+nulTermLen<=NBFS ){
|
||||
/* If the string plus the nul terminator will fit in the Mem.zShort
|
||||
** buffer, and it is not already stored there, copy it there.
|
||||
*/
|
||||
if( !(f&MEM_Short) ){
|
||||
memcpy(pMem->z, pMem->zShort, pMem->n);
|
||||
if( f&MEM_Dyn ){
|
||||
sqliteFree(pMem->z);
|
||||
}
|
||||
pMem->z = pMem->zShort;
|
||||
pMem->flags &= ~(MEM_Static|MEM_Ephem|MEM_Dyn);
|
||||
pMem->flags |= MEM_Short;
|
||||
}
|
||||
}else{
|
||||
/* Otherwise we have to malloc for memory. If the string is already
|
||||
** dynamic, use sqliteRealloc(). Otherwise sqliteMalloc() enough
|
||||
** space for the string and the nul terminator, and copy the string
|
||||
** data there.
|
||||
*/
|
||||
if( f&MEM_Dyn ){
|
||||
pMem->z = (char *)sqliteRealloc(pMem->z, pMem->n+nulTermLen);
|
||||
if( !pMem->z ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
}else{
|
||||
char *z = (char *)sqliteMallocRaw(pMem->n+nulTermLen);
|
||||
memcpy(z, pMem->z, pMem->n);
|
||||
pMem->z = z;
|
||||
pMem->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short);
|
||||
pMem->flags |= MEM_Dyn;
|
||||
}
|
||||
}
|
||||
|
||||
/* pMem->z now points at the string data, with enough space at the end
|
||||
** to insert the nul nul terminator. pMem->n has not yet been updated.
|
||||
*/
|
||||
memcpy(&pMem->z[pMem->n], "\0\0", nulTermLen);
|
||||
pMem->n += nulTermLen;
|
||||
pMem->flags |= MEM_Term;
|
||||
}
|
||||
pMem->enc = desiredEnc;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Make the given Mem object MEM_Dyn.
|
||||
**
|
||||
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
|
||||
*/
|
||||
int sqlite3VdbeMemMakeDynamicify(Mem *pMem){
|
||||
int n;
|
||||
u8 *z;
|
||||
if( (pMem->flags & (MEM_Ephem|MEM_Static|MEM_Short))==0 ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
assert( (pMem->flags & MEM_Dyn)==0 );
|
||||
assert( pMem->flags & (MEM_Str|MEM_Blob) );
|
||||
z = sqliteMallocRaw( n+2 )
|
||||
if( z==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pMem->flags |= MEM_Dyn|MEM_Term;
|
||||
memcpy(z, pMem->z, n );
|
||||
z[n] = 0;
|
||||
z[n+1] = 0;
|
||||
pMem->z = z;
|
||||
pMem->flags &= ~(MEM_Ephem|MEM_Static|MEM_Short);
|
||||
}
|
||||
|
||||
/*
|
||||
** Make the given Mem object either MEM_Short or MEM_Dyn so that bytes
|
||||
** of the Mem.z[] array can be modified.
|
||||
**
|
||||
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
|
||||
*/
|
||||
int sqlite3VdbeMemMakeWritable(Mem *pMem){
|
||||
int n;
|
||||
u8 *z;
|
||||
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 = pMem->zShort;
|
||||
pMem->flags |= MEM_Short|MEM_Term;
|
||||
}else{
|
||||
z = sqliteMallocRaw( n+2 )
|
||||
if( z==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pMem->flags |= MEM_Dyn|MEM_Term;
|
||||
}
|
||||
memcpy(z, pMem->z, n );
|
||||
z[n] = 0;
|
||||
z[n+1] = 0;
|
||||
pMem->z = z;
|
||||
pMem->flags &= ~(MEM_Ephem|MEM_Static);
|
||||
}
|
||||
|
||||
/*
|
||||
** Make sure the given Mem is \u0000 terminated.
|
||||
*/
|
||||
int sqlite3VdbeMemNulTerminate(Mem *pMem){
|
||||
if( (pMem->flags & MEM_Term)!=0 || pMem->flags & (MEM_Str|MEM_Blob))==0 ){
|
||||
return SQLITE_OK; /* Nothing to do */
|
||||
}
|
||||
/* Only static or ephemeral strings can be unterminated */
|
||||
assert( (pMem->flags & (MEM_Static|MEM_Ephem))!=0 );
|
||||
sqlite3VdbeMemMakeWriteable(pMem);
|
||||
}
|
||||
|
||||
/*
|
||||
** Add MEM_Str to the set of representations for the given Mem.
|
||||
** A NULL is converted into an empty string. Numbers are converted
|
||||
** using sqlite3_snprintf(). Converting a BLOB to a string is a
|
||||
** no-op.
|
||||
**
|
||||
** Existing representations MEM_Int and MEM_Real are *not* invalidated.
|
||||
** But MEM_Null is.
|
||||
*/
|
||||
int sqlite3VdbeMemStringify(Mem *pMem, int enc){
|
||||
int rc = SQLITE_OK;
|
||||
int fg = pMem->flags;
|
||||
|
||||
assert( !(fg&(MEM_Str|MEM_Blob)) );
|
||||
assert( fg&(MEM_Int|MEM_Real|MEM_Null) );
|
||||
|
||||
if( fg & MEM_Null ){
|
||||
/* A NULL value is converted to a zero length string */
|
||||
u8 *z = pMem->zShort;
|
||||
z[0] = 0;
|
||||
z[1] = 0;
|
||||
pMem->flags = MEM_Str | MEM_Short | MEM_Term;
|
||||
pMem->z = z;
|
||||
pMem->n = 0;
|
||||
pMem->enc = enc;
|
||||
}else{
|
||||
/* For a Real or Integer, use sqlite3_snprintf() 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.
|
||||
*/
|
||||
u8 *z = pMem->zShort;
|
||||
if( fg & MEM_Real ){
|
||||
sqlite3_snprintf(NBFS, z, "%.15g", pMem->r);
|
||||
}else{
|
||||
assert( fg & MEM_Int );
|
||||
sqlite3_snprintf(NBFS, z, "%lld", pMem->i);
|
||||
}
|
||||
pMem->n = strlen(z);
|
||||
pMem->z = n;
|
||||
pMem->enc = TEXT_Utf8;
|
||||
pMem->flags |= MEM_Str | MEM_Short | MEM_Term;
|
||||
sqlite3VdbeMemChangeEncoding(pMem, enc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert the Mem to have representation MEM_Int only. All
|
||||
** prior representations are invalidated. NULL is converted into 0.
|
||||
*/
|
||||
int sqlite3VdbeMemIntegerify(Mem *pMem){
|
||||
if( pMem->flags & MEM_Int ){
|
||||
/* Do nothing */
|
||||
}else if( pMem->flags & MEM_Real ){
|
||||
pMem->i = (i64)pMem->r;
|
||||
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
|
||||
if( sqlite3VdbeChangeEncoding(pMem, TEXT_Utf8)
|
||||
|| sqlite3VdbeNulTerminate(pMem) ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
assert( pMem->z );
|
||||
sqlite3atoi64(pMem->z, &pMem->i);
|
||||
}else{
|
||||
pMem->i = 0;
|
||||
}
|
||||
Release(pMem);
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->type = SQLITE3_INTEGER;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add MEM_Real to the set of representations for pMem. Prior
|
||||
** prior representations other than MEM_Null retained. NULL is
|
||||
** converted into 0.0.
|
||||
*/
|
||||
int sqlite3VdbeMemRealify(Mem *pMem){
|
||||
if( pMem->flags & MEM_Int ){
|
||||
pMem->r = pMem->r;
|
||||
pMem->flags |= MEM_Real;
|
||||
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
|
||||
if( sqlite3VdbeChangeEncoding(pMem, TEXT_Utf8)
|
||||
|| sqlite3VdbeNulTerminate(pMem) ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
assert( pMem->z );
|
||||
pMem->r = sqlite3AtoF(pMem->z, 0);
|
||||
Release(pMem);
|
||||
pMem->flags = MEM_Real;
|
||||
pMem->type = SQLITE3_INTEGER;
|
||||
}else{
|
||||
pMem->r = 0.0;
|
||||
pMem->flags = MEM_Real;
|
||||
pMem->type = SQLITE3_INTEGER;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Release any memory held by the Mem
|
||||
*/
|
||||
static void releaseMem(Mem *p){
|
||||
if( p->flags & MEM_Dyn ){
|
||||
sqliteFree(p);
|
||||
@ -157,26 +259,29 @@ static void releaseMem(Mem *p){
|
||||
void sqlite3VdbeMemSetNull(Mem *pMem){
|
||||
releaseMem(pMem);
|
||||
pMem->flags = MEM_Null;
|
||||
pMem->type = SQLITE3_NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete any previous value and set the value stored in *pMem to val,
|
||||
** manifest type INTEGER.
|
||||
*/
|
||||
void sqlite3VdbeMemSetInt(Mem *pMem, i64 val){
|
||||
void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
|
||||
releaseMem(pMem);
|
||||
pMem->i = val;
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->type = SQLITE3_INTEGER;
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete any previous value and set the value stored in *pMem to val,
|
||||
** manifest type REAL.
|
||||
*/
|
||||
void sqlite3VdbeMemSetReal(Mem *pMem, double val){
|
||||
void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
|
||||
releaseMem(pMem);
|
||||
pMem->r = val;
|
||||
pMem->flags = MEM_Real;
|
||||
pMem->type = SQLITE3_FLOAT;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -184,36 +289,31 @@ void sqlite3VdbeMemSetReal(Mem *pMem, double val){
|
||||
*/
|
||||
int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
|
||||
releaseMem(pTo);
|
||||
memcpy(pTo, pFrom, sizeof(*pFrom));
|
||||
if( pTo->flags&MEM_Short ){
|
||||
pTo->z = pTo->zShort;
|
||||
}else if( pTo->flags&(MEM_Ephem|MEM_Dyn) ){
|
||||
pTo->flags = pTo->flags&(~(MEM_Static|MEM_Ephem|MEM_Short|MEM_Dyn));
|
||||
if( pTo->n>NBFS ){
|
||||
pTo->z = sqliteMalloc(pTo->n);
|
||||
if( !pTo->z ) return SQLITE_NOMEM;
|
||||
pTo->flags |= MEM_Dyn;
|
||||
}else{
|
||||
pTo->z = pTo->zShort;
|
||||
pTo->flags |= MEM_Short;
|
||||
}
|
||||
memcpy(pTo->z, pFrom->z, pTo->n);
|
||||
memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort));
|
||||
if( pTo->flags & (MEM_Str|MEM_Blob) ){
|
||||
pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
|
||||
pTo->flags |= MEM_Ephem;
|
||||
sqlite3VdbeMemMakeWriteable(pTo);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the value of a Mem to be a string or a BLOB.
|
||||
*/
|
||||
int sqlite3VdbeMemSetStr(
|
||||
Mem *pMem, /* Memory cell to set to string value */
|
||||
const char *z, /* String pointer */
|
||||
int n, /* Bytes in string, or negative */
|
||||
u8 enc, /* Encoding of z */
|
||||
u8 enc, /* Encoding of z. 0 for BLOBs */
|
||||
int eCopy /* True if this function should make a copy of z */
|
||||
){
|
||||
Mem tmp;
|
||||
|
||||
releaseMem(pMem);
|
||||
if( !z ){
|
||||
/* If z is NULL, just set *pMem to contain NULL. */
|
||||
pMem->flags = MEM_Null;
|
||||
pMem->type = SQLITE3_NULL;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@ -223,7 +323,8 @@ int sqlite3VdbeMemSetStr(
|
||||
}else{
|
||||
pMem->flags = MEM_Static|MEM_Str;
|
||||
}
|
||||
pMem->flags |= encToFlags(enc);
|
||||
pMem->enc = enc;
|
||||
pMem->type = enc==0 ? SQLITE3_BLOB : SQLITE3_TEXT;
|
||||
pMem->n = n;
|
||||
switch( enc ){
|
||||
case 0:
|
||||
@ -231,22 +332,16 @@ int sqlite3VdbeMemSetStr(
|
||||
break;
|
||||
|
||||
case TEXT_Utf8:
|
||||
pMem->flags |= MEM_Utf8;
|
||||
if( n<0 ){
|
||||
pMem->n = strlen(z)+1;
|
||||
pMem->flags |= MEM_Term;
|
||||
}else if( z[pMem->n-1]==0 ){
|
||||
pMem->n = strlen(z);
|
||||
pMem->flags |= MEM_Term;
|
||||
}
|
||||
break;
|
||||
|
||||
case TEXT_Utf16le:
|
||||
case TEXT_Utf16be:
|
||||
pMem->flags |= (enc==TEXT_Utf16le?MEM_Utf16le:MEM_Utf16be);
|
||||
if( n<0 ){
|
||||
pMem->n = sqlite3utf16ByteLen(z,-1)+1;
|
||||
pMem->flags |= MEM_Term;
|
||||
}else if( z[pMem->n-1]==0 && z[pMem->n-2]==0 ){
|
||||
pMem->n = sqlite3utf16ByteLen(z,-1);
|
||||
pMem->flags |= MEM_Term;
|
||||
}
|
||||
break;
|
||||
@ -254,57 +349,9 @@ int sqlite3VdbeMemSetStr(
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
Deephemeralize(pMem);
|
||||
if( eCopy ){
|
||||
sqlite3VdbeMemMakeWriteable(pMem);
|
||||
}
|
||||
|
||||
int sqlite3VdbeMemNulTerminate(Mem *pMem){
|
||||
int nulTermLen;
|
||||
int f = pMem->flags;
|
||||
|
||||
assert( pMem->flags&MEM_Str && !pMem->flags&MEM_Term );
|
||||
assert( flagsToEnc(pMem->flags) );
|
||||
|
||||
nulTermLen = (flagsToEnc(f)==TEXT_Utf8?1:2);
|
||||
|
||||
if( pMem->n+nulTermLen<=NBFS ){
|
||||
/* If the string plus the nul terminator will fit in the Mem.zShort
|
||||
** buffer, and it is not already stored there, copy it there.
|
||||
*/
|
||||
if( !(f&MEM_Short) ){
|
||||
memcpy(pMem->z, pMem->zShort, pMem->n);
|
||||
if( f&MEM_Dyn ){
|
||||
sqliteFree(pMem->z);
|
||||
}
|
||||
pMem->z = pMem->zShort;
|
||||
pMem->flags &= ~(MEM_Static|MEM_Ephem|MEM_Dyn);
|
||||
pMem->flags |= MEM_Short;
|
||||
}
|
||||
}else{
|
||||
/* Otherwise we have to malloc for memory. If the string is already
|
||||
** dynamic, use sqliteRealloc(). Otherwise sqliteMalloc() enough
|
||||
** space for the string and the nul terminator, and copy the string
|
||||
** data there.
|
||||
*/
|
||||
if( f&MEM_Dyn ){
|
||||
pMem->z = (char *)sqliteRealloc(pMem->z, pMem->n+nulTermLen);
|
||||
if( !pMem->z ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
}else{
|
||||
char *z = (char *)sqliteMalloc(pMem->n+nulTermLen);
|
||||
memcpy(z, pMem->z, pMem->n);
|
||||
pMem->z = z;
|
||||
pMem->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short);
|
||||
pMem->flags |= MEM_Dyn;
|
||||
}
|
||||
}
|
||||
|
||||
/* pMem->z now points at the string data, with enough space at the end
|
||||
** to insert the nul nul terminator. pMem->n has not yet been updated.
|
||||
*/
|
||||
memcpy(&pMem->z[pMem->n], "\0\0", nulTermLen);
|
||||
pMem->n += nulTermLen;
|
||||
pMem->flags |= MEM_Term;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script testing the sqlite_bind API.
|
||||
#
|
||||
# $Id: bind.test,v 1.9 2004/05/26 10:11:07 danielk1977 Exp $
|
||||
# $Id: bind.test,v 1.10 2004/05/27 01:53:56 drh Exp $
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
@ -28,7 +28,7 @@ proc sqlite_step {stmt N VALS COLS} {
|
||||
lappend cols [sqlite3_column_name $stmt $i]
|
||||
}
|
||||
for {set i 0} {$i < [sqlite3_data_count $stmt]} {incr i} {
|
||||
lappend vals [sqlite3_column_data $stmt $i]
|
||||
lappend vals [sqlite3_column_text $stmt $i]
|
||||
}
|
||||
|
||||
return $rc
|
||||
|
@ -13,7 +13,7 @@
|
||||
# various suported unicode encodings (UTF-8, UTF-16, UTF-16le and
|
||||
# UTF-16be).
|
||||
#
|
||||
# $Id: enc2.test,v 1.2 2004/05/26 10:11:07 danielk1977 Exp $
|
||||
# $Id: enc2.test,v 1.3 2004/05/27 01:53:56 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -91,12 +91,12 @@ do_test $t.6 {
|
||||
do_test $t.7 {
|
||||
set STMT [sqlite3_prepare $DB "SELECT a FROM t1 WHERE c>3;" -1 TAIL]
|
||||
sqlite3_step $STMT
|
||||
sqlite3_column_data $STMT 0
|
||||
sqlite3_column_text $STMT 0
|
||||
} {four}
|
||||
|
||||
do_test $t.8 {
|
||||
sqlite3_step $STMT
|
||||
utf8 [sqlite3_column_data16 $STMT 0]
|
||||
utf8 [sqlite3_column_text16 $STMT 0]
|
||||
} {five}
|
||||
|
||||
do_test $t.9 {
|
||||
@ -123,7 +123,3 @@ foreach enc $encodings {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user