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.
#
$(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
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
-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
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
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
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
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
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
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
-74097ecdb0b1e0eec143c5a3f8ca2f0d63d6f38d
\ No newline at end of file
+dbdd1a7f316e576d0611748ec63c9ef00d4c10db
\ No newline at end of file
*************************************************************************
** 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"
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);
** 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:
**
** 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 );
}
return SQLITE_OK;
}
-
-
** 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>
** 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));
}
** 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"
*/
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
** 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
** 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
** 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.
** 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); }
/*
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 ){
break;
}
Stringify(pTerm, db->enc);
- nByte += (pTerm->n - ((pTerm->flags&MEM_Term)?termLen:0));
+ nByte += pTerm->n;
}
if( nByte<0 ){
/* 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;
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 ){
}
Release(pTos);
pTos->flags = MEM_Int;
+ pTos->type = SQLITE3_INTEGER;
break;
mismatch:
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{
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*);
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.
*/
/*
** Add an opcode that includes the p3 value.
*/
-int sqlite3VdbeOp3(Vdbe *p, int op, int p1, int p2, const char *zP3, int p3type){
+int sqlite3VdbeOp3(Vdbe *p, int op, int p1, int p2, const char *zP3,int p3type){
int addr = sqlite3VdbeAddOp(p, op, p1, p2);
sqlite3VdbeChangeP3(p, addr, zP3, p3type);
return 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.
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;
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 ){
/* NULL */
if( serial_type==6 ){
pMem->flags = MEM_Null;
+ pMem->type = SQLITE3_NULL;
return 0;
}
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;
}
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);
- }else{
- pMem->flags = MEM_Blob;
+ pMem->flags = MEM_Str | 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';
- }
+ pMem->flags = MEM_Blob | MEM_Ephem;
+ pMem->n = len;
}
-
+ 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
}
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);
-}
#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 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);
- if( rc!=SQLITE_OK ){
- return rc;
- }
+ 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, pMem->enc,
+ (void **)&z, &n, desiredEnd);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
- /* Result of sqlite3utfTranslate is currently always dynamically
- ** allocated and nul terminated. This might be altered as a performance
- ** enhancement later.
- */
- pMem->z = z;
- pMem->n = n;
- pMem->flags = (MEM_Str | MEM_Dyn | MEM_Term | flags);
- }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);
+ /* Result of sqlite3utfTranslate is currently always dynamically
+ ** allocated and nul terminated. This might be altered as a performance
+ ** enhancement later.
+ */
+ pMem->z = z;
+ pMem->n = n;
+ 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;
+ 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;
}
}
+ pMem->enc = desiredEnc;
+ return SQLITE_OK;
+}
- 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;
+/*
+** 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);
+}
- 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;
- }
+/*
+** 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{
- /* 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;
- }
+ 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;
+}
- /* 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;
+/*
+** 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;
}
- return SQLITE_OK;
+ 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);
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;
}
/*
*/
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;
}
}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:
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;
default:
assert(0);
}
- Deephemeralize(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;
- }
+ if( eCopy ){
+ sqlite3VdbeMemMakeWriteable(pMem);
}
-
- /* 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;
}
/*
# 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]
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
# 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
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 {
}
finish_test
-
-
-
-