mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-14 00:22:38 +03:00
Remove the blob(), text() and numeric() functions added in (2524) and
replace them with the standard CAST operator. Ticket #1287. (CVS 2527) FossilOrigin-Name: 17631785f9ee8ab280c82677eb53886912e085bc
This commit is contained in:
24
src/build.c
24
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
10
src/date.c
10
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;
|
||||
}
|
||||
|
||||
30
src/expr.c
30
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:
|
||||
|
||||
91
src/func.c
91
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
|
||||
|
||||
58
src/parse.y
58
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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
92
src/vdbe.c
92
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user