1
0
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:
drh
2004-05-27 01:53:56 +00:00
parent ea61b2c4fc
commit eb2e176a12
13 changed files with 403 additions and 831 deletions

13
main.mk
View File

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

View File

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

View File

@ -1 +1 @@
74097ecdb0b1e0eec143c5a3f8ca2f0d63d6f38d
dbdd1a7f316e576d0611748ec63c9ef00d4c10db

View File

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

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

View File

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

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

View File

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

View File

@ -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.
*/

View File

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

View File

@ -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;
}
/*

View File

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

View File

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