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:
drh 2005-06-25 18:42:14 +00:00
parent 7f057c9166
commit 487e262f44
16 changed files with 414 additions and 283 deletions

View File

@ -1,5 +1,5 @@
C NULL\svalues\sin\sa\srow\sof\sa\sunique\sindex\scause\sthe\srow\sto\sbe\sdistinct.\nTicket\s#1301.\s\sMore\stesting\sand\soptimization\sneeds\sto\sbe\sdone\son\sthis\nbefore\sclosing\sthe\sticket.\s(CVS\s2526)
D 2005-06-24T03:53:06
C Remove\sthe\sblob(),\stext()\sand\snumeric()\sfunctions\sadded\sin\s(2524)\sand\r\nreplace\sthem\swith\sthe\sstandard\sCAST\soperator.\r\nTicket\s#1287.\s(CVS\s2527)
D 2005-06-25T18:42:14
F Makefile.in 64a6635ef44a98325e0cffe8d67669920a3dad47
F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@ -32,13 +32,13 @@ F src/attach.c 3615dbe960cbee4aa5ea300b8a213dad36527b0f
F src/auth.c 18c5a0befe20f3a58a41e3ddd78f372faeeefe1f
F src/btree.c a167f412cf5b269bffba925ac55a1c0a2f749e29
F src/btree.h 41a71ce027db9ddee72cb43df2316bbe3a1d92af
F src/build.c 3b64205934761976857ed3fe884854eb4c3b856a
F src/build.c f2f12fcb4455e247e6fabc46d7168eb42f7194df
F src/callback.c 0910b611e0c158f107ee3ff86f8a371654971e2b
F src/date.c 2134ef4388256e8247405178df8a61bd60dc180a
F src/date.c 7444b0900a28da77e57e3337a636873cff0ae940
F src/delete.c 9bb19ede439cf325bc6d6f5995b6393fb85b5162
F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
F src/expr.c 4d6e26da200e0d08233df52fd8d07916d24a6926
F src/func.c 301b81af2e831b2e929f0ba252739c32a0c756e5
F src/expr.c 8d4f5e3d06107e1932b534a45bea848aad6b8612
F src/func.c cbdf7256400ac7d5f020d131261bb2bd41bb631f
F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
F src/insert.c d61752504f8a67e28a3bd45288051a587ba899cd
@ -55,7 +55,7 @@ F src/os_win.c fe7b99cfcfb61d9bf54493ddf5857885a657fb89
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c 841a2cdddd4275de36cda26ed9dc54ae942660ce
F src/pager.h 0d9153d6269d60d04af3dd84a0cc0a96253cf4a4
F src/parse.y 72cd7553f05fbc7b63ea9476108d0da6237f2818
F src/parse.y 562246a70c5e4a6bf1ed203119db0843bc926c11
F src/pragma.c dea86dad2f0e872b29632ae9fba526e539a4ddd8
F src/prepare.c d53602d2f8e097225ae7c76ec764ae68f759ba47
F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
@ -63,10 +63,10 @@ F src/random.c 90adff4e73a3b249eb4f1fc2a6ff9cf78c7233a4
F src/select.c 28b752e58955c7920711fbdbfdcd369a2bd09448
F src/shell.c 25b3217d7c64e6497225439d261a253a23efff26
F src/sqlite.h.in e06d5774e9cfa5962376ae988300a9f114a3e3d7
F src/sqliteInt.h c620e07e0c7e6e09d8623d165427f0f1f659aad5
F src/sqliteInt.h 2135a5bab820af868bf308f51cdf1adbcb3a85b7
F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
F src/tclsqlite.c af0f002d9d6ab4f7f32b9bee5b57665946e76ad9
F src/test1.c 5956d1c61b89d84c2b2ab01f065b1cd878917213
F src/test1.c 96314a056763107646223779bcb2b987944944dd
F src/test2.c 716c1809dba8e5be6093703e9cada99d627542dc
F src/test3.c 683e1e3819152ffd35da2f201e507228921148d0
F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
@ -75,14 +75,14 @@ F src/tokenize.c 57ec9926612fb9e325b57a141303573bc20c79bf
F src/trigger.c f51dec15921629591cb98bf2e350018e268b109a
F src/update.c e96c7b342cd8903c672162f4cf84d2c737943347
F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c
F src/util.c 1cdce9ae9fd17307e00848d63e3bc3300ca7c9fc
F src/util.c 54d5b4d56f0d14d4ff60881b145d1d3d664bb623
F src/vacuum.c 829d9e1a6d7c094b80e0899686670932eafd768c
F src/vdbe.c 5c1f7ccd6a75aa2cf211a9864ff511e15e86957c
F src/vdbe.c 56e892e351eb3ed634c3c239e4ad5c03aecfc2bf
F src/vdbe.h 75e466d84d362b0c4498978a9d6b1e6bd32ecf3b
F src/vdbeInt.h 4312faf41630a6c215924b6c7c2f39ebb1af8ffb
F src/vdbeapi.c 5025a9163107e0a4964212d16e1c4defa13dc5c2
F src/vdbeaux.c 38332d91887817a2146f46b58fff2a8a88ed0278
F src/vdbemem.c 48a64ae95a9edc6e8d940300dad15d70d1670398
F src/vdbemem.c da8e8d6f29dd1323f782f000d7cd120027c9ff03
F src/where.c 3a9a2258ab3364655e9ea215ad5ae7bf41813f54
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3
@ -112,6 +112,7 @@ F test/btree7.test a6d3b842db22af97dd14b989e90a2fd96066b72f
F test/capi2.test f897209386fb21cfdc9267595e0c667ebaca9164
F test/capi3.test 4d848cc55ad6e5f68cf2712716e9fc1fa55d7635
F test/capi3b.test 5b6a66f9f295f79f443b5d3f33187fa5ef6cf336
F test/cast.test 5c5ebb3edadb04eb0bb172d0e48d52642480e004
F test/collate1.test f79736d2ebf5492167ee4d1f4ab4c09dda776b03
F test/collate2.test 224a632ba04907c049804b08162efd234aa7871f
F test/collate3.test 51362bdfb43a72bd2b087d90b2623b0695538e7a
@ -132,7 +133,7 @@ F test/enc2.test d1ab077b84f4d3099246915422b1ab6b81481e0a
F test/enc3.test f6a5f0b7b7f3a88f030d3143729b87cd5c86d837
F test/expr.test 54d9d1cc05eb731fa62daa70f2d7163f8a03c54d
F test/fkey1.test 81bb13caaa78f58d7d191d7f535529f7c91d821a
F test/func.test f5f9f2bd3f1121ae82eb4d6b3f48b8c52f597895
F test/func.test b062105b45cf8fb5b386ba137180c0f439eea0c9
F test/hook.test f8605cde4c77b2c6a4a73723bf6c507796a64dda
F test/in.test ed134f8d477a6280297ced1646de83cccf8f196d
F test/index.test 51e01a0928b4b61228917ddd8c6c0e2466547f6f
@ -225,7 +226,7 @@ F tool/lempar.c f0c30abcae762a7d1eb37cd88b2232ab8dd625fb
F tool/memleak.awk 4e7690a51bf3ed757e611273d43fe3f65b510133
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
F tool/memleak3.tcl 009da0ea82dc5893edca76cf1a21fb7260e9412e
F tool/mkkeywordhash.c 596389943f516bf6eaddd46659e7b87b16ea7c33
F tool/mkkeywordhash.c e4ba5010348303b1dbab41326191e7f37f8a036f
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
@ -264,7 +265,7 @@ F www/faq.tcl 49f31a703f74c71ce66da646aaf18b07a5042672
F www/fileformat.tcl 900c95b9633abc3dcfc384d9ddd8eb4876793059
F www/formatchng.tcl 053ddb73646701353a5b1c9ca6274d5900739b45
F www/index.tcl 9527f4eed69739cf5f81b3d75e0478d1c84d0a8a
F www/lang.tcl 727b4769fbad2727b0f867acaeb8706d554edb35
F www/lang.tcl be57d5f23a46b8afa3753b38f65ea22d26499b80
F www/lockingv3.tcl f59b19d6c8920a931f096699d6faaf61c05db55f
F www/mingw.tcl d96b451568c5d28545fefe0c80bee3431c73f69c
F www/nulls.tcl ec35193f92485b87b90a994a01d0171b58823fcf
@ -281,7 +282,7 @@ F www/tclsqlite.tcl 425be741b8ae664f55cb1ef2371aab0a75109cf9
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
F www/whentouse.tcl 528299b8316726dbcc5548e9aa0648c8b1bd055b
P bcf62dc7a1e8e7a3180138cf9b8944eb8fbd5490
R fa67143595d3d7217f6f8facb2f20078
P 06a71b162b032fc5b56d18919a784d4ee94dde7c
R 232a3463ca338974c39f0662b7bf2007
U drh
Z 382ef1453175c5aaab493342b42488e6
Z 47d0af1509bc0a39043a3f760e0ac13b

View File

@ -1 +1 @@
06a71b162b032fc5b56d18919a784d4ee94dde7c
17631785f9ee8ab280c82677eb53886912e085bc

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

184
test/cast.test Normal file
View File

@ -0,0 +1,184 @@
# 2001 September 15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the CAST operator.
#
# $Id: cast.test,v 1.1 2005/06/25 18:42:16 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Only run these tests if the build includes the CAST operator
ifcapable !cast {
finish_test
return
}
# Tests for the CAST( AS blob), CAST( AS text) and CAST( AS numeric) built-ins
#
do_test cast-1.1 {
execsql {SELECT x'616263'}
} abc
do_test cast-1.2 {
execsql {SELECT typeof(x'616263')}
} blob
do_test cast-1.3 {
execsql {SELECT CAST(x'616263' AS text)}
} abc
do_test cast-1.4 {
execsql {SELECT typeof(CAST(x'616263' AS text))}
} text
do_test cast-1.5 {
execsql {SELECT CAST(x'616263' AS numeric)}
} 0.0
do_test cast-1.6 {
execsql {SELECT typeof(CAST(x'616263' AS numeric))}
} real
do_test cast-1.7 {
execsql {SELECT CAST(x'616263' AS blob)}
} abc
do_test cast-1.8 {
execsql {SELECT typeof(CAST(x'616263' AS blob))}
} blob
do_test cast-1.9 {
execsql {SELECT CAST(x'616263' AS integer)}
} 0
do_test cast-1.10 {
execsql {SELECT typeof(CAST(x'616263' AS integer))}
} integer
do_test cast-1.11 {
execsql {SELECT null}
} {{}}
do_test cast-1.12 {
execsql {SELECT typeof(NULL)}
} null
do_test cast-1.13 {
execsql {SELECT CAST(NULL AS text)}
} {{}}
do_test cast-1.14 {
execsql {SELECT typeof(CAST(NULL AS text))}
} null
do_test cast-1.15 {
execsql {SELECT CAST(NULL AS numeric)}
} {{}}
do_test cast-1.16 {
execsql {SELECT typeof(CAST(NULL AS numeric))}
} null
do_test cast-1.17 {
execsql {SELECT CAST(NULL AS blob)}
} {{}}
do_test cast-1.18 {
execsql {SELECT typeof(CAST(NULL AS blob))}
} null
do_test cast-1.19 {
execsql {SELECT CAST(NULL AS integer)}
} {{}}
do_test cast-1.20 {
execsql {SELECT typeof(CAST(NULL AS integer))}
} null
do_test cast-1.21 {
execsql {SELECT 123}
} {123}
do_test cast-1.22 {
execsql {SELECT typeof(123)}
} integer
do_test cast-1.23 {
execsql {SELECT CAST(123 AS text)}
} {123}
do_test cast-1.24 {
execsql {SELECT typeof(CAST(123 AS text))}
} text
do_test cast-1.25 {
execsql {SELECT CAST(123 AS numeric)}
} 123
do_test cast-1.26 {
execsql {SELECT typeof(CAST(123 AS numeric))}
} integer
do_test cast-1.27 {
execsql {SELECT CAST(123 AS blob)}
} {123}
do_test cast-1.28 {
execsql {SELECT typeof(CAST(123 AS blob))}
} blob
do_test cast-1.29 {
execsql {SELECT CAST(123 AS integer)}
} {123}
do_test cast-1.30 {
execsql {SELECT typeof(CAST(123 AS integer))}
} integer
do_test cast-1.31 {
execsql {SELECT 123.456}
} {123.456}
do_test cast-1.32 {
execsql {SELECT typeof(123.456)}
} real
do_test cast-1.33 {
execsql {SELECT CAST(123.456 AS text)}
} {123.456}
do_test cast-1.34 {
execsql {SELECT typeof(CAST(123.456 AS text))}
} text
do_test cast-1.35 {
execsql {SELECT CAST(123.456 AS numeric)}
} 123.456
do_test cast-1.36 {
execsql {SELECT typeof(CAST(123.456 AS numeric))}
} real
do_test cast-1.37 {
execsql {SELECT CAST(123.456 AS blob)}
} {123.456}
do_test cast-1.38 {
execsql {SELECT typeof(CAST(123.456 AS blob))}
} blob
do_test cast-1.39 {
execsql {SELECT CAST(123.456 AS integer)}
} {123}
do_test cast-1.38 {
execsql {SELECT typeof(CAST(123.456 AS integer))}
} integer
do_test cast-1.41 {
execsql {SELECT '123abc'}
} {123abc}
do_test cast-1.42 {
execsql {SELECT typeof('123abc')}
} text
do_test cast-1.43 {
execsql {SELECT CAST('123abc' AS text)}
} {123abc}
do_test cast-1.44 {
execsql {SELECT typeof(CAST('123abc' AS text))}
} text
do_test cast-1.45 {
execsql {SELECT CAST('123abc' AS numeric)}
} 123.0
do_test cast-1.46 {
execsql {SELECT typeof(CAST('123abc' AS numeric))}
} real
do_test cast-1.47 {
execsql {SELECT CAST('123abc' AS blob)}
} {123abc}
do_test cast-1.48 {
execsql {SELECT typeof(CAST('123abc' AS blob))}
} blob
do_test cast-1.49 {
execsql {SELECT CAST('123abc' AS integer)}
} 123
do_test cast-1.50 {
execsql {SELECT typeof(CAST('123abc' AS integer))}
} integer
do_test cast-1.51 {
execsql {SELECT CAST('123.5abc' AS numeric)}
} 123.5
do_test cast-1.53 {
execsql {SELECT CAST('123.5abc' AS integer)}
} 123
finish_test

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing built-in functions.
#
# $Id: func.test,v 1.35 2005/06/22 10:53:59 drh Exp $
# $Id: func.test,v 1.36 2005/06/25 18:42:16 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -485,134 +485,6 @@ do_test func-16.1 {
}
} {X'616263' NULL}
# Tests for the blob(), text() and numeric() built-ins
#
do_test func-17.1 {
execsql {SELECT x'616263'}
} abc
do_test func-17.2 {
execsql {SELECT typeof(x'616263')}
} blob
do_test func-17.3 {
execsql {SELECT text(x'616263')}
} abc
do_test func-17.4 {
execsql {SELECT typeof(text(x'616263'))}
} text
do_test func-17.5 {
execsql {SELECT numeric(x'616263')}
} 0
do_test func-17.6 {
execsql {SELECT typeof(numeric(x'616263'))}
} integer
do_test func-17.7 {
execsql {SELECT blob(x'616263')}
} abc
do_test func-17.8 {
execsql {SELECT typeof(blob(x'616263'))}
} blob
do_test func-17.11 {
execsql {SELECT null}
} {{}}
do_test func-17.12 {
execsql {SELECT typeof(NULL)}
} null
do_test func-17.13 {
execsql {SELECT text(NULL)}
} {{}}
do_test func-17.14 {
execsql {SELECT typeof(text(NULL))}
} text
do_test func-17.15 {
execsql {SELECT numeric(NULL)}
} 0
do_test func-17.16 {
execsql {SELECT typeof(numeric(NULL))}
} integer
do_test func-17.17 {
execsql {SELECT blob(NULL)}
} {{}}
do_test func-17.18 {
execsql {SELECT typeof(blob(NULL))}
} blob
do_test func-17.21 {
execsql {SELECT 123}
} {123}
do_test func-17.22 {
execsql {SELECT typeof(123)}
} integer
do_test func-17.23 {
execsql {SELECT text(123)}
} {123}
do_test func-17.24 {
execsql {SELECT typeof(text(123))}
} text
do_test func-17.25 {
execsql {SELECT numeric(123)}
} 123
do_test func-17.26 {
execsql {SELECT typeof(numeric(123))}
} integer
do_test func-17.27 {
execsql {SELECT blob(123)}
} {123}
do_test func-17.28 {
execsql {SELECT typeof(blob(123))}
} blob
do_test func-17.31 {
execsql {SELECT 123.456}
} {123.456}
do_test func-17.32 {
execsql {SELECT typeof(123.456)}
} real
do_test func-17.33 {
execsql {SELECT text(123.456)}
} {123.456}
do_test func-17.34 {
execsql {SELECT typeof(text(123.456))}
} text
do_test func-17.35 {
execsql {SELECT numeric(123.456)}
} 123.456
do_test func-17.36 {
execsql {SELECT typeof(numeric(123.456))}
} real
do_test func-17.37 {
execsql {SELECT blob(123.456)}
} {123.456}
do_test func-17.38 {
execsql {SELECT typeof(blob(123.456))}
} blob
do_test func-17.41 {
execsql {SELECT '123abc'}
} {123abc}
do_test func-17.42 {
execsql {SELECT typeof('123abc')}
} text
do_test func-17.43 {
execsql {SELECT text('123abc')}
} {123abc}
do_test func-17.44 {
execsql {SELECT typeof(text('123abc'))}
} text
do_test func-17.45 {
execsql {SELECT numeric('123abc')}
} 123
do_test func-17.46 {
execsql {SELECT typeof(numeric('123abc'))}
} integer
do_test func-17.47 {
execsql {SELECT blob('123abc')}
} {123abc}
do_test func-17.48 {
execsql {SELECT typeof(blob('123abc'))}
} blob
do_test func-17.49 {
execsql {SELECT numeric('123.5abc')}
} 123.5
do_test func-17.49b {
execsql {SELECT typeof(numeric('123.5abc'))}
} real
finish_test

View File

@ -95,6 +95,11 @@ struct Keyword {
#else
# define VIEW 16384
#endif
#ifdef SQLITE_OMIT_CAST
# define CAST 0
#else
# define CAST 32768
#endif
/*
@ -117,6 +122,7 @@ static Keyword aKeywordTable[] = {
{ "BY", "TK_BY", ALWAYS },
{ "CASCADE", "TK_CASCADE", FKEY },
{ "CASE", "TK_CASE", ALWAYS },
{ "CAST", "TK_CAST", CAST },
{ "CHECK", "TK_CHECK", ALWAYS },
{ "COLLATE", "TK_COLLATE", ALWAYS },
{ "COLUMN", "TK_COLUMNKW", ALTER },

View File

@ -1,7 +1,7 @@
#
# Run this Tcl script to generate the lang-*.html files.
#
set rcsid {$Id: lang.tcl,v 1.90 2005/05/10 16:11:41 drh Exp $}
set rcsid {$Id: lang.tcl,v 1.91 2005/06/25 18:42:16 drh Exp $}
source common.tcl
if {[llength $argv]>0} {
@ -1099,7 +1099,7 @@ all arguments are NULL then NULL is returned. There must be at least
<a href="capi3ref.html#sqlite3_create_function">sqlite3_create_function()</a>
interface can
be used to override this function and thereby change the operation
of the <a href="#glob">GLOB</a> operator.</td>
of the <a href="#globFunc">GLOB</a> operator.</td>
</tr>
<tr>