diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 24 | ||||
-rw-r--r-- | src/date.c | 10 | ||||
-rw-r--r-- | src/expr.c | 30 | ||||
-rw-r--r-- | src/func.c | 91 | ||||
-rw-r--r-- | src/parse.y | 58 | ||||
-rw-r--r-- | src/sqliteInt.h | 7 | ||||
-rw-r--r-- | src/test1.c | 8 | ||||
-rw-r--r-- | src/util.c | 9 | ||||
-rw-r--r-- | src/vdbe.c | 92 | ||||
-rw-r--r-- | src/vdbemem.c | 5 |
10 files changed, 201 insertions, 133 deletions
diff --git a/src/build.c b/src/build.c index e0a6e5953..d9d5bb43b 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.328 2005/06/24 03:53:06 drh Exp $ +** $Id: build.c,v 1.329 2005/06/25 18:42:14 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -902,11 +902,11 @@ void sqlite3AddNotNull(Parse *pParse, int onError){ ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. */ -static char sqlite3AffinityType(const char *zType, int nType){ +char sqlite3AffinityType(const Token *pType){ u32 h = 0; char aff = SQLITE_AFF_NUMERIC; - const unsigned char *zIn = zType; - const unsigned char *zEnd = (zIn+nType); + const unsigned char *zIn = pType->z; + const unsigned char *zEnd = &pType->z[pType->n]; while( zIn!=zEnd ){ h = (h<<8) + sqlite3UpperToLower[*zIn]; @@ -938,21 +938,17 @@ static char sqlite3AffinityType(const char *zType, int nType){ ** that contains the typename of the column and store that string ** in zType. */ -void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){ +void sqlite3AddColumnType(Parse *pParse, Token *pType){ Table *p; - int i, j; - int n; - char *z; - const unsigned char *zIn; - + int i; Column *pCol; + if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; if( i<0 ) return; pCol = &p->aCol[i]; - zIn = pFirst->z; - n = pLast->n + (pLast->z - zIn); assert( pCol->zType==0 ); +#if 0 z = pCol->zType = sqliteMallocRaw(n+1); if( z==0 ) return; for(i=j=0; i<n; i++){ @@ -961,7 +957,9 @@ void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){ z[j++] = c; } z[j] = 0; - pCol->affinity = sqlite3AffinityType(z, n); +#endif + pCol->zType = sqlite3NameFromToken(pType); + pCol->affinity = sqlite3AffinityType(pType); } /* diff --git a/src/date.c b/src/date.c index 520756916..35c0bf64a 100644 --- a/src/date.c +++ b/src/date.c @@ -16,7 +16,7 @@ ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.44 2005/03/21 00:43:44 drh Exp $ +** $Id: date.c,v 1.45 2005/06/25 18:42:14 drh Exp $ ** ** NOTES: ** @@ -124,11 +124,7 @@ static int getDigits(const char *zDate, ...){ ** Read text from z[] and convert into a floating point number. Return ** the number of digits converted. */ -static int getValue(const char *z, double *pR){ - const char *zEnd; - *pR = sqlite3AtoF(z, &zEnd); - return zEnd - z; -} +#define getValue sqlite3AtoF /* ** Parse a timezone extension on the end of a date-time. @@ -320,7 +316,7 @@ static int parseDateOrTime(const char *zDate, DateTime *p){ p->validJD = 1; return 0; }else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){ - p->rJD = sqlite3AtoF(zDate, 0); + getValue(zDate, &p->rJD); p->validJD = 1; return 0; } diff --git a/src/expr.c b/src/expr.c index 4f21800e5..efac97766 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.207 2005/06/22 08:48:06 drh Exp $ +** $Id: expr.c,v 1.208 2005/06/25 18:42:14 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -34,12 +34,18 @@ ** SELECT * FROM t1 WHERE (select a from t1); */ char sqlite3ExprAffinity(Expr *pExpr){ - if( pExpr->op==TK_AS ){ + int op = pExpr->op; + if( op==TK_AS ){ return sqlite3ExprAffinity(pExpr->pLeft); } - if( pExpr->op==TK_SELECT ){ + if( op==TK_SELECT ){ return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].pExpr); } +#ifndef SQLITE_OMIT_CAST + if( op==TK_CAST ){ + return sqlite3AffinityType(&pExpr->token); + } +#endif return pExpr->affinity; } @@ -51,7 +57,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ CollSeq *pColl = 0; if( pExpr ){ pColl = pExpr->pColl; - if( pExpr->op==TK_AS && !pColl ){ + if( (pExpr->op==TK_AS || pExpr->op==TK_CAST) && !pColl ){ return sqlite3ExprCollSeq(pParse, pExpr->pLeft); } } @@ -1427,6 +1433,22 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iTable, 0); break; } +#ifndef SQLITE_OMIT_CAST + case TK_CAST: { + /* Expressions of the form: CAST(pLeft AS token) */ + int aff, op; + sqlite3ExprCode(pParse, pExpr->pLeft); + aff = sqlite3AffinityType(&pExpr->token); + switch( aff ){ + case SQLITE_AFF_INTEGER: op = OP_ToInt; break; + case SQLITE_AFF_NUMERIC: op = OP_ToNumeric; break; + case SQLITE_AFF_TEXT: op = OP_ToText; break; + case SQLITE_AFF_NONE: op = OP_ToBlob; break; + } + sqlite3VdbeAddOp(v, op, 0, 0); + break; + } +#endif /* SQLITE_OMIT_CAST */ case TK_LT: case TK_LE: case TK_GT: diff --git a/src/func.c b/src/func.c index d13ba437c..7e8feadc0 100644 --- a/src/func.c +++ b/src/func.c @@ -16,7 +16,7 @@ ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.99 2005/06/22 10:53:59 drh Exp $ +** $Id: func.c,v 1.100 2005/06/25 18:42:14 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -78,92 +78,6 @@ static void typeofFunc( sqlite3_result_text(context, z, -1, SQLITE_STATIC); } -/* -** Convert the argument to a numeric type. -*/ -static void numericFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const char *z = 0; - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_NULL: { - sqlite3_result_int(context, 0); - break; - } - case SQLITE_INTEGER: - case SQLITE_FLOAT: { - sqlite3_result_value(context, argv[0]); - break; - } - case SQLITE_TEXT: - case SQLITE_BLOB: { - z = sqlite3_value_text(argv[0]); - while( *z && *z!='.' ){ z++; } - if( *z ){ - sqlite3_result_double(context, sqlite3_value_double(argv[0])); - }else{ - sqlite3_result_int64(context, sqlite3_value_int64(argv[0])); - } - break; - } - } -} - -/* -** Convert the argument to TEXT -*/ -static void textFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_NULL: { - sqlite3_result_text(context, "", 0, SQLITE_STATIC); - break; - } - case SQLITE_BLOB: - case SQLITE_INTEGER: - case SQLITE_FLOAT: { - sqlite3_result_text(context, sqlite3_value_text(argv[0]), - sqlite3_value_bytes(argv[0]), SQLITE_TRANSIENT); - break; - } - case SQLITE_TEXT: { - sqlite3_result_value(context, argv[0]); - break; - } - } -} - -/* -** Convert the argument to TEXT -*/ -static void blobFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_NULL: { - sqlite3_result_blob(context, "", 0, SQLITE_STATIC); - break; - } - case SQLITE_TEXT: - case SQLITE_INTEGER: - case SQLITE_FLOAT: { - sqlite3_result_blob(context, sqlite3_value_text(argv[0]), - sqlite3_value_bytes(argv[0]), SQLITE_TRANSIENT); - break; - } - case SQLITE_BLOB: { - sqlite3_result_value(context, argv[0]); - break; - } - } -} /* ** Implementation of the length() function @@ -1058,9 +972,6 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid }, { "changes", 0, 1, SQLITE_UTF8, 0, changes }, { "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes }, - { "text", 1, 0, SQLITE_UTF8, 0, textFunc }, - { "numeric", 1, 0, SQLITE_UTF8, 0, numericFunc }, - { "blob", 1, 0, SQLITE_UTF8, 0, blobFunc }, #ifdef SQLITE_SOUNDEX { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, #endif diff --git a/src/parse.y b/src/parse.y index 1f7c8af33..bcb0014a3 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,12 +14,23 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.172 2005/05/23 17:26:51 drh Exp $ +** @(#) $Id: parse.y,v 1.173 2005/06/25 18:42:14 drh Exp $ */ + +// All token codes are small integers with #defines that begin with "TK_" %token_prefix TK_ + +// The type of the data attached to each token is Token. This is also the +// default type for non-terminals. +// %token_type {Token} %default_type {Token} + +// The generated parser function takes a 4th argument as follows: %extra_argument {Parse *pParse} + +// This code runs whenever there is a syntax error +// %syntax_error { if( pParse->zErrMsg==0 ){ if( TOKEN.z[0] ){ @@ -29,7 +40,14 @@ } } } + +// The name of the generated procedure that implements the parser +// is as follows: %name sqlite3Parser + +// The following text is included near the beginning of the C source +// code file that implements the parser. +// %include { #include "sqliteInt.h" #include "parse.h" @@ -126,9 +144,10 @@ create_table_args ::= AS select(S). { columnlist ::= columnlist COMMA column. columnlist ::= column. -// About the only information used for a column is the name of the -// column. The type is always just "text". But the code will accept -// an elaborate typename. Perhaps someday we'll do something with it. +// A "column" is a complete description of a single column in a +// CREATE TABLE statement. This includes the column name, its +// datatype, and other keywords such as PRIMARY KEY, UNIQUE, REFERENCES, +// NOT NULL and so forth. // column(A) ::= columnid(X) type carglist. { A.z = X.z; @@ -151,7 +170,7 @@ id(A) ::= ID(X). {A = X;} // This obviates the need for the "id" nonterminal. // %fallback ID - ABORT AFTER ASC ATTACH BEFORE BEGIN CASCADE CONFLICT + ABORT AFTER ASC ATTACH BEFORE BEGIN CASCADE CAST CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH KEY OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT @@ -198,17 +217,32 @@ nm(A) ::= ID(X). {A = X;} nm(A) ::= STRING(X). {A = X;} nm(A) ::= JOIN_KW(X). {A = X;} +// A typetoken is really one or more tokens that form a type name such +// as can be found after the column name in a CREATE TABLE statement. +// Multiple tokens are concatenated to form the value of the typetoken. +// +%type typetoken {Token} type ::= . -type ::= typename(X). {sqlite3AddColumnType(pParse,&X,&X);} -type ::= typename(X) LP signed RP(Y). {sqlite3AddColumnType(pParse,&X,&Y);} -type ::= typename(X) LP signed COMMA signed RP(Y). - {sqlite3AddColumnType(pParse,&X,&Y);} +type ::= typetoken(X). {sqlite3AddColumnType(pParse,&X);} +typetoken(A) ::= typename(X). {A = X;} +typetoken(A) ::= typename(X) LP signed RP(Y). { + A.z = X.z; + A.n = &Y.z[Y.n] - X.z; +} +typetoken(A) ::= typename(X) LP signed COMMA signed RP(Y). { + A.z = X.z; + A.n = &Y.z[Y.n] - X.z; +} %type typename {Token} typename(A) ::= ids(X). {A = X;} typename(A) ::= typename(X) ids(Y). {A.z=X.z; A.n=Y.n+(Y.z-X.z);} %type signed {int} signed(A) ::= plus_num(X). { A = atoi(X.z); } signed(A) ::= minus_num(X). { A = -atoi(X.z); } + +// "carglist" is a list of additional constraints that come after the +// column name and column type in a CREATE TABLE statement. +// carglist ::= carglist carg. carglist ::= . carg ::= CONSTRAINT nm ccons. @@ -619,6 +653,12 @@ expr(A) ::= VARIABLE(X). { Expr *pExpr = A = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); sqlite3ExprAssignVarNumber(pParse, pExpr); } +%ifndef SQLITE_OMIT_CAST +expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). { + A = sqlite3Expr(TK_CAST, E, 0, &T); + sqlite3ExprSpan(A,&X,&Y); +} +%endif // SQLITE_OMIT_CAST expr(A) ::= ID(X) LP exprlist(Y) RP(E). { A = sqlite3ExprFunction(Y, &X); sqlite3ExprSpan(A,&X,&E); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 966090dc0..cac864c43 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.387 2005/06/12 21:35:52 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.388 2005/06/25 18:42:14 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1369,7 +1369,7 @@ void sqlite3StartTable(Parse*,Token*,Token*,Token*,int,int); void sqlite3AddColumn(Parse*,Token*); void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int); -void sqlite3AddColumnType(Parse*,Token*,Token*); +void sqlite3AddColumnType(Parse*,Token*); void sqlite3AddDefaultValue(Parse*,Expr*); void sqlite3AddCollateType(Parse*, const char*, int); void sqlite3EndTable(Parse*,Token*,Token*,Select*); @@ -1508,7 +1508,7 @@ int sqlite3FixSelect(DbFixer*, Select*); int sqlite3FixExpr(DbFixer*, Expr*); int sqlite3FixExprList(DbFixer*, ExprList*); int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); -double sqlite3AtoF(const char *z, const char **); +int sqlite3AtoF(const char *z, double*); char *sqlite3_snprintf(int,char*,const char*,...); int sqlite3GetInt32(const char *, int*); int sqlite3FitsIn64Bits(const char *); @@ -1563,6 +1563,7 @@ void sqlite3AlterFinishAddColumn(Parse *, Token *); void sqlite3AlterBeginAddColumn(Parse *, SrcList *); const char *sqlite3TestErrorName(int); CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char *, int); +char sqlite3AffinityType(const Token*); #ifdef SQLITE_SSE #include "sseInt.h" diff --git a/src/test1.c b/src/test1.c index 73159910f..dd7e06cd9 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.144 2005/06/12 22:01:43 drh Exp $ +** $Id: test1.c,v 1.145 2005/06/25 18:42:14 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -2794,6 +2794,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_OMIT_CAST + Tcl_SetVar2(interp, "sqlite_options", "cast", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "cast", "1", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_COMPLETE Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY); #else diff --git a/src/util.c b/src/util.c index 23794123e..80fc41da2 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.137 2005/06/14 16:04:06 drh Exp $ +** $Id: util.c,v 1.138 2005/06/25 18:42:15 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> @@ -565,8 +565,9 @@ int sqlite3IsNumber(const char *z, int *realnum, u8 enc){ ** of "." depending on how locale is set. But that would cause problems ** for SQL. So this routine always uses "." regardless of locale. */ -double sqlite3AtoF(const char *z, const char **pzEnd){ +int sqlite3AtoF(const char *z, double *pResult){ int sign = 1; + const char *zBegin = z; LONGDOUBLE_TYPE v1 = 0.0; if( *z=='-' ){ sign = -1; @@ -613,8 +614,8 @@ double sqlite3AtoF(const char *z, const char **pzEnd){ v1 *= scale; } } - if( pzEnd ) *pzEnd = z; - return sign<0 ? -v1 : v1; + *pResult = sign<0 ? -v1 : v1; + return z - zBegin; } /* diff --git a/src/vdbe.c b/src/vdbe.c index 4d0124153..15305116c 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.471 2005/06/24 03:53:06 drh Exp $ +** $Id: vdbe.c,v 1.472 2005/06/25 18:42:15 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -1379,6 +1379,94 @@ case OP_MustBeInt: { /* no-push */ break; } +#ifndef SQLITE_OMIT_CAST +/* Opcode: ToInt * * * +** +** Force the value on the top of the stack to be an integer. If +** The value is currently a real number, drop its fractional part. +** If the value is text or blob, try to convert it to an integer using the +** equivalent of atoi() and store 0 if no such conversion is possible. +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_ToInt: { /* no-push */ + assert( pTos>=p->aStack ); + if( pTos->flags & MEM_Null ) break; + assert( MEM_Str==(MEM_Blob>>3) ); + pTos->flags |= (pTos->flags&MEM_Blob)>>3; + applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc); + sqlite3VdbeMemIntegerify(pTos); + break; +} + +/* Opcode: ToNumeric * * * +** +** Force the value on the top of the stack to be numeric (either an +** integer or a floating-point number. +** If the value is text or blob, try to convert it to an using the +** equivalent of atoi() or atof() and store 0 if no such conversion +** is possible. +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_ToNumeric: { /* no-push */ + assert( pTos>=p->aStack ); + if( pTos->flags & MEM_Null ) break; + assert( MEM_Str==(MEM_Blob>>3) ); + pTos->flags |= (pTos->flags&MEM_Blob)>>3; + applyAffinity(pTos, SQLITE_AFF_NUMERIC, db->enc); + if( (pTos->flags & (MEM_Int|MEM_Real))==0 ){ + sqlite3VdbeMemRealify(pTos); + }else{ + sqlite3VdbeMemRelease(pTos); + } + assert( (pTos->flags & MEM_Dyn)==0 ); + pTos->flags &= (MEM_Int|MEM_Real); + break; +} + +/* Opcode: ToText * * * +** +** Force the value on the top of the stack to be text. +** If the value is numeric, convert it to an using the +** equivalent of printf(). Blob values are unchanged and +** are afterwards simply interpreted as text. +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_ToText: { /* no-push */ + assert( pTos>=p->aStack ); + if( pTos->flags & MEM_Null ) break; + assert( MEM_Str==(MEM_Blob>>3) ); + pTos->flags |= (pTos->flags&MEM_Blob)>>3; + applyAffinity(pTos, SQLITE_AFF_TEXT, db->enc); + assert( pTos->flags & MEM_Str ); + pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Blob); + break; +} + +/* Opcode: ToBlob * * * +** +** Force the value on the top of the stack to be a BLOB. +** If the value is numeric, convert it to a string first. +** Strings are simply reinterpreted as blobs with no change +** to the underlying data. +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_ToBlob: { /* no-push */ + assert( pTos>=p->aStack ); + if( pTos->flags & MEM_Null ) break; + if( (pTos->flags & MEM_Blob)==0 ){ + applyAffinity(pTos, SQLITE_AFF_TEXT, db->enc); + assert( pTos->flags & MEM_Str ); + pTos->flags |= MEM_Blob; + } + pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Str); + break; +} +#endif /* SQLITE_OMIT_CAST */ + /* Opcode: Eq P1 P2 P3 ** ** Pop the top two elements from the stack. If they are equal, then @@ -2154,6 +2242,7 @@ case OP_MakeRecord: { pTos->flags = MEM_Blob | MEM_Dyn; pTos->xDel = 0; } + pTos->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */ /* If a NULL was encountered and jumpIfNull is non-zero, take the jump. */ if( jumpIfNull && containsNull ){ @@ -3289,6 +3378,7 @@ case OP_RowData: { }else{ pTos->flags = MEM_Null; } + pTos->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ break; } diff --git a/src/vdbemem.c b/src/vdbemem.c index f08671f24..37113b90d 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -256,12 +256,14 @@ double sqlite3VdbeRealValue(Mem *pMem){ }else if( pMem->flags & MEM_Int ){ return (double)pMem->i; }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ + double val = 0.0; if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) || sqlite3VdbeMemNulTerminate(pMem) ){ return SQLITE_NOMEM; } assert( pMem->z ); - return sqlite3AtoF(pMem->z, 0); + sqlite3AtoF(pMem->z, &val); + return val; }else{ return 0.0; } @@ -406,6 +408,7 @@ int sqlite3VdbeMemSetStr( switch( enc ){ case 0: pMem->flags |= MEM_Blob; + pMem->enc = SQLITE_UTF8; break; case SQLITE_UTF8: |