diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/parse.y | 6 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 | ||||
-rw-r--r-- | src/tokenize.c | 27 | ||||
-rw-r--r-- | src/util.c | 21 |
4 files changed, 50 insertions, 7 deletions
diff --git a/src/parse.y b/src/parse.y index 19491192e..b0d03a04e 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1923,6 +1923,12 @@ filter_clause(A) ::= FILTER LP WHERE expr(X) RP. { A = X; } SPAN /* The span operator */ ERROR /* An expression containing an error */ . + +term(A) ::= QNUMBER(X). { + A=tokenExpr(pParse,@X,X); + sqlite3DequoteNumber(A); +} + /* There must be no more than 255 tokens defined above. If this grammar ** is extended with new rules and tokens, they must either be so few in ** number that TK_SPAN is no more than 255, or else the new tokens must diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 79a36e060..c4aaf9d20 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -609,6 +609,8 @@ # define SQLITE_OMIT_ALTERTABLE #endif +#define SQLITE_DIGIT_SEPARATOR '_' + /* ** Return true (non-zero) if the input is an integer that is too large ** to fit in 32-bits. This macro is used inside of various testcase() @@ -4792,6 +4794,7 @@ int sqlite3ErrorToParser(sqlite3*,int); void sqlite3Dequote(char*); void sqlite3DequoteExpr(Expr*); void sqlite3DequoteToken(Token*); +void sqlite3DequoteNumber(Expr*); void sqlite3TokenInit(Token*,char*); int sqlite3KeywordCode(const unsigned char*, int); int sqlite3RunParser(Parse*, const char*); diff --git a/src/tokenize.c b/src/tokenize.c index f4d013dee..ae1f6da3f 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -441,21 +441,34 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ return i; } #endif - for(i=0; sqlite3Isdigit(z[i]); i++){} + for(i=0; 1; i++){ + if( sqlite3Isdigit(z[i])==0 ){ + if( z[i]==SQLITE_DIGIT_SEPARATOR ){ *tokenType = TK_QNUMBER; } + else{ break; } + } + } #ifndef SQLITE_OMIT_FLOATING_POINT if( z[i]=='.' ){ - i++; - while( sqlite3Isdigit(z[i]) ){ i++; } - *tokenType = TK_FLOAT; + if( *tokenType==TK_INTEGER ) *tokenType = TK_FLOAT; + for(i++; 1; i++){ + if( sqlite3Isdigit(z[i])==0 ){ + if( z[i]==SQLITE_DIGIT_SEPARATOR ){ *tokenType = TK_QNUMBER; } + else{ break; } + } + } } if( (z[i]=='e' || z[i]=='E') && ( sqlite3Isdigit(z[i+1]) || ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2])) ) ){ - i += 2; - while( sqlite3Isdigit(z[i]) ){ i++; } - *tokenType = TK_FLOAT; + if( *tokenType==TK_INTEGER ) *tokenType = TK_FLOAT; + for(i+=2; 1; i++){ + if( sqlite3Isdigit(z[i])==0 ){ + if( z[i]==SQLITE_DIGIT_SEPARATOR ){ *tokenType = TK_QNUMBER; } + else{ break; } + } + } } #endif while( IdChar(z[i]) ){ diff --git a/src/util.c b/src/util.c index 207b901ba..24eff14e9 100644 --- a/src/util.c +++ b/src/util.c @@ -312,6 +312,27 @@ void sqlite3DequoteExpr(Expr *p){ } /* +** Expression p is a QINTEGER or QFLOAT (quoted integer or float). Dequote +** the value in p->u.zToken and set the type to INTEGER or FLOAT. "Quoted" +** integers or floats are those that contain '_' characters that must +** be removed before further processing. +*/ +void sqlite3DequoteNumber(Expr *p){ + if( p ){ + const char *pIn = p->u.zToken; + char *pOut = p->u.zToken; + assert( p->op==TK_QNUMBER ); + p->op = TK_INTEGER; + do { + if( *pIn!=SQLITE_DIGIT_SEPARATOR ){ + *pOut++ = *pIn; + if( *pIn=='e' || *pIn=='E' || *pIn=='.' ) p->op = TK_FLOAT; + } + }while( *pIn++ ); + } +} + +/* ** If the input token p is quoted, try to adjust the token to remove ** the quotes. This is not always possible: ** |