Rework the string to integer conversion logic to address tickets
#2344 and #2454. (CVS 4123) FossilOrigin-Name: 5b3a490649ab88c168e3e5bf2efbc7f61b1b954d
This commit is contained in:
parent
c9cf6e3d31
commit
217f49093c
24
manifest
24
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sfor\s#2445.\sA\sbug\sin\sthe\slookupName()\slogic\sthat\scould\scause\sa\scrash\swhen\sa\sWHERE\sclause\sused\san\salias\sto\srefer\sto\san\sexpression\sin\sthe\sresult-set\sof\sthe\sSELECT,\sand\sthat\sexpression\swas\sitself\sa\sreference\sto\sa\stable\scolumn.\s(CVS\s4122)
|
||||
D 2007-06-25T16:29:34
|
||||
C Rework\sthe\sstring\sto\sinteger\sconversion\slogic\sto\saddress\stickets\n#2344\sand\s#2454.\s(CVS\s4123)
|
||||
D 2007-06-25T17:28:01
|
||||
F Makefile.in 7f7485a4cc039476a42e534b3f26ec90e2f9753e
|
||||
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
@ -109,11 +109,11 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||
F src/shell.c 4b0fc3c76a9f23a1c963e01703c0fbbca1b5c34d
|
||||
F src/sqlite.h.in 6f290b660b2e7c3359968bb4b344ec31a1178746
|
||||
F src/sqlite3ext.h 95575e0d175a0271fe2c3232c0d11e8720ed6887
|
||||
F src/sqliteInt.h 6503239d26b1943227031aa005320ef09b9b92b7
|
||||
F src/sqliteInt.h 475c538baf1105c00ae50c3564dbd20159418f9b
|
||||
F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa
|
||||
F src/table.c a8de75bcedf84d4060d804264b067ab3b1a3561d
|
||||
F src/tclsqlite.c 4bffe56752d2c24ade23340e46a91fd92c316e08
|
||||
F src/test1.c a83c097ee1353e8982745ee1b78612fea7425602
|
||||
F src/test1.c 9017dab5bfe2b22e9bc8e81ba999a8ae22c61976
|
||||
F src/test2.c 24458b17ab2f3c90cbc1c8446bd7ffe69be62f88
|
||||
F src/test3.c a280931fb40222b7c90da45eea926459beee8904
|
||||
F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
|
||||
@ -136,16 +136,16 @@ F src/tokenize.c 6cef9e6fc454d789a32c5b509ccb193a2b01977b
|
||||
F src/trigger.c 420192efe3e6f03addf7897c60c3c8bf913d3493
|
||||
F src/update.c 6b10becb6235ea314ed245fbfbf8b38755e3166e
|
||||
F src/utf.c 01b2aba02b10d12903e9e1ff897215c9faf6b662
|
||||
F src/util.c 80cdf6b68d03b8f0ab3237a390842e039cff66c6
|
||||
F src/util.c f58a68d062608eeed6d8229bb22a61b87e530d68
|
||||
F src/vacuum.c 8bd895d29e7074e78d4e80f948e35ddc9cf2beef
|
||||
F src/vdbe.c 81714b7df6c7769ab300446e070fc0a5bb2ece86
|
||||
F src/vdbe.c 251e0121040768fd801920cfecbcb159a891d4af
|
||||
F src/vdbe.h 001c5b257567c1d3de7feb2203aac71d0d7b16a3
|
||||
F src/vdbeInt.h 7d2bf163d6d4e815724a457f2216dd8e38c3955c
|
||||
F src/vdbeapi.c 7930b9a188ab385287ca3eb3840af7225cb43549
|
||||
F src/vdbeaux.c c580d3605edc2c24ba9bd26fa7aa8b4fff10daa4
|
||||
F src/vdbeblob.c 96f3572fdc45eda5be06e6372b612bc30742d9f0
|
||||
F src/vdbefifo.c 3ca8049c561d5d67cbcb94dc909ae9bb68c0bf8f
|
||||
F src/vdbemem.c ca4d3994507cb0a9504820293af69f5c778b4abd
|
||||
F src/vdbemem.c 327944e70cd807c81705e0d81f9417e89f2c563c
|
||||
F src/vtab.c 51d43cda45d25e6f3a15d19fe32992b7756e74db
|
||||
F src/where.c 12387641659605318ae03d87f0687f223dfc9568
|
||||
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
||||
@ -226,7 +226,7 @@ F test/enc3.test 9331988b9d72decec96995c90637e87b00d747a5
|
||||
F test/exclusive.test 5bc520ba366ae3d242420af025ab64d465b04706
|
||||
F test/exclusive2.test 3496656375dc88e97d704c2d5d2c93d626cb7104
|
||||
F test/exclusive3.test 0e49c35b7e7cb8e7280b4ce3f0359d30b207d2ff
|
||||
F test/expr.test 93931366f660dc84ba36eaf390f670b27d2c03e8
|
||||
F test/expr.test a4dc0855b86ba0daeef47f3dd4cf394eda2bd0ac
|
||||
F test/filefmt.test 053b622009fbbb74dd37921ffad374d852c13cd8
|
||||
F test/fkey1.test dcb4f28eb22d5141f15161d6bdca9a4f58c95729
|
||||
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
|
||||
@ -515,7 +515,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P 02b23c4394da7efb82e9318146f10818b0f68b1f
|
||||
R 0b7987f665943fbbfc4744c2a66803b3
|
||||
U danielk1977
|
||||
Z 03cd9b4e47591553bbb663ee352448e0
|
||||
P 044ca1c72a8f4632dc2e6a94690d164d3560ee38
|
||||
R 31842549475179d1d10a54116c67cbde
|
||||
U drh
|
||||
Z dd5bcce4a9040dd3c1d7c52ab375cdda
|
||||
|
@ -1 +1 @@
|
||||
044ca1c72a8f4632dc2e6a94690d164d3560ee38
|
||||
5b3a490649ab88c168e3e5bf2efbc7f61b1b954d
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.575 2007/06/22 15:21:16 danielk1977 Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.576 2007/06/25 17:28:01 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@ -1835,7 +1835,7 @@ void sqlite3TableAffinityStr(Vdbe *, Table *);
|
||||
char sqlite3CompareAffinity(Expr *pExpr, char aff2);
|
||||
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
|
||||
char sqlite3ExprAffinity(Expr *pExpr);
|
||||
int sqlite3Atoi64(const char*, i64*);
|
||||
int sqlite3_atoi64(const char*, i64*);
|
||||
void sqlite3Error(sqlite3*, int, const char*,...);
|
||||
void *sqlite3HexToBlob(const char *z);
|
||||
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
|
||||
|
@ -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.256 2007/06/15 20:29:20 drh Exp $
|
||||
** $Id: test1.c,v 1.257 2007/06/25 17:28:02 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
@ -1082,7 +1082,7 @@ static int sqlite3_mprintf_int(
|
||||
*/
|
||||
static int sqlite3GetInt64(const char *zNum, i64 *pValue){
|
||||
if( sqlite3FitsIn64Bits(zNum) ){
|
||||
sqlite3Atoi64(zNum, pValue);
|
||||
sqlite3_atoi64(zNum, pValue);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
128
src/util.c
128
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.205 2007/05/16 17:50:46 danielk1977 Exp $
|
||||
** $Id: util.c,v 1.206 2007/06/25 17:28:02 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@ -299,18 +299,40 @@ int sqlite3AtoF(const char *z, double *pResult){
|
||||
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
||||
}
|
||||
|
||||
/*
|
||||
** Compare the 19-character string zNum against the text representation
|
||||
** value 2^63: 9223372036854775808. Return negative, zero, or positive
|
||||
** if zNum is less than, equal to, or greater than the string.
|
||||
**
|
||||
** Unlike memcmp() this routine is guaranteed to return the difference
|
||||
** in the values of the last digit if the only difference is in the
|
||||
** last digit. So, for example,
|
||||
**
|
||||
** compare2pow63("9223372036854775800")
|
||||
**
|
||||
** will return -8.
|
||||
*/
|
||||
static int compare2pow63(const char *zNum){
|
||||
int c;
|
||||
c = memcmp(zNum,"922337203685477580",18);
|
||||
if( c==0 ){
|
||||
c = zNum[18] - '8';
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Return TRUE if zNum is a 64-bit signed integer and write
|
||||
** the value of the integer into *pNum. If zNum is not an integer
|
||||
** or is an integer that is too large to be expressed with 64 bits,
|
||||
** then return false. If n>0 and the integer is string is not
|
||||
** exactly n bytes long, return false.
|
||||
** then return false.
|
||||
**
|
||||
** When this routine was originally written it dealt with only
|
||||
** 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){
|
||||
int sqlite3_atoi64(const char *zNum, i64 *pNum){
|
||||
i64 v = 0;
|
||||
int neg;
|
||||
int i, c;
|
||||
@ -324,42 +346,24 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum){
|
||||
}else{
|
||||
neg = 0;
|
||||
}
|
||||
while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */
|
||||
for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
|
||||
v = v*10 + c - '0';
|
||||
}
|
||||
*pNum = neg ? -v : v;
|
||||
return c==0 && i>0 &&
|
||||
(i<19 || (i==19 && memcmp(zNum,"9223372036854775807",19)<=0));
|
||||
}
|
||||
|
||||
/*
|
||||
** The string zNum represents an integer. There might be some other
|
||||
** information following the integer too, but that part is ignored.
|
||||
** If the integer that the prefix of zNum represents will fit in a
|
||||
** 32-bit signed integer, return TRUE. Otherwise return FALSE.
|
||||
**
|
||||
** This routine returns FALSE for the string -2147483648 even that
|
||||
** that number will in fact fit in a 32-bit integer. But positive
|
||||
** 2147483648 will not fit in 32 bits. So it seems safer to return
|
||||
** false.
|
||||
*/
|
||||
static int sqlite3FitsIn32Bits(const char *zNum){
|
||||
int i, c;
|
||||
if( *zNum=='-' || *zNum=='+' ) zNum++;
|
||||
for(i=0; (c=zNum[i])>='0' && c<='9'; i++){}
|
||||
return i<10 || (i==10 && memcmp(zNum,"2147483647",10)<=0);
|
||||
}
|
||||
|
||||
/*
|
||||
** If zNum represents an integer that will fit in 32-bits, then set
|
||||
** *pValue to that integer and return true. Otherwise return false.
|
||||
*/
|
||||
int sqlite3GetInt32(const char *zNum, int *pValue){
|
||||
if( sqlite3FitsIn32Bits(zNum) ){
|
||||
*pValue = atoi(zNum);
|
||||
if( c!=0 || i==0 || i>19 ){
|
||||
/* zNum is empty or contains non-numeric text or is longer
|
||||
** than 19 digits (thus guaranting that it is too large) */
|
||||
return 0;
|
||||
}else if( i<19 ){
|
||||
/* Less than 19 digits, so we know that it fits in 64 bits */
|
||||
return 1;
|
||||
}else{
|
||||
/* 19-digit numbers must be no larger than 9223372036854775807 if positive
|
||||
** or 9223372036854775808 if negative. Note that 9223372036854665808
|
||||
** is 2^63. */
|
||||
return compare2pow63(zNum)<neg;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -375,11 +379,63 @@ int sqlite3GetInt32(const char *zNum, int *pValue){
|
||||
*/
|
||||
int sqlite3FitsIn64Bits(const char *zNum){
|
||||
int i, c;
|
||||
if( *zNum=='-' || *zNum=='+' ) zNum++;
|
||||
int neg = 0;
|
||||
if( *zNum=='-' ){
|
||||
neg = 1;
|
||||
zNum++;
|
||||
}else if( *zNum=='+' ){
|
||||
zNum++;
|
||||
}
|
||||
while( *zNum=='0' ){
|
||||
zNum++; /* Skip leading zeros. Ticket #2454 */
|
||||
}
|
||||
for(i=0; (c=zNum[i])>='0' && c<='9'; i++){}
|
||||
return i<19 || (i==19 && memcmp(zNum,"9223372036854775807",19)<=0);
|
||||
if( i<19 ){
|
||||
/* Guaranteed to fit if less than 19 digits */
|
||||
return 1;
|
||||
}else if( i>19 ){
|
||||
/* Guaranteed to be too big if greater than 19 digits */
|
||||
return 0;
|
||||
}else{
|
||||
/* Compare against 2^63. */
|
||||
return compare2pow63(zNum)<neg;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If zNum represents an integer that will fit in 32-bits, then set
|
||||
** *pValue to that integer and return true. Otherwise return false.
|
||||
**
|
||||
** Any non-numeric characters that following zNum are ignored.
|
||||
** This is different from sqlite3_atoi64() which requires the
|
||||
** input number to be zero-terminated.
|
||||
*/
|
||||
int sqlite3GetInt32(const char *zNum, int *pValue){
|
||||
sqlite_int64 v = 0;
|
||||
int i, c;
|
||||
int neg = 0;
|
||||
if( zNum[0]=='-' ){
|
||||
neg = 1;
|
||||
zNum++;
|
||||
}else if( zNum[0]=='+' ){
|
||||
zNum++;
|
||||
}
|
||||
while( zNum[0]=='0' ) zNum++;
|
||||
for(i=0; i<10 && (c = zNum[i] - '0')>=0 && c<=9; i++){
|
||||
v = v*10 + c;
|
||||
}
|
||||
if( i>9 ){
|
||||
return 0;
|
||||
}
|
||||
if( v-neg>2147483647 ){
|
||||
return 0;
|
||||
}
|
||||
if( neg ){
|
||||
v = -v;
|
||||
}
|
||||
*pValue = (int)v;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to make sure we have a valid db pointer. This test is not
|
||||
|
@ -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.630 2007/06/24 16:11:03 danielk1977 Exp $
|
||||
** $Id: vdbe.c,v 1.631 2007/06/25 17:28:02 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@ -227,7 +227,7 @@ static void applyNumericAffinity(Mem *pRec){
|
||||
&& sqlite3IsNumber(pRec->z, &realnum, pRec->enc) ){
|
||||
i64 value;
|
||||
sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8);
|
||||
if( !realnum && sqlite3Atoi64(pRec->z, &value) ){
|
||||
if( !realnum && sqlite3_atoi64(pRec->z, &value) ){
|
||||
sqlite3VdbeMemRelease(pRec);
|
||||
pRec->u.i = value;
|
||||
pRec->flags = MEM_Int;
|
||||
|
@ -307,7 +307,7 @@ i64 sqlite3VdbeIntValue(Mem *pMem){
|
||||
return 0;
|
||||
}
|
||||
assert( pMem->z );
|
||||
sqlite3Atoi64(pMem->z, &value);
|
||||
sqlite3_atoi64(pMem->z, &value);
|
||||
return value;
|
||||
}else{
|
||||
return 0;
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing expressions.
|
||||
#
|
||||
# $Id: expr.test,v 1.55 2007/05/10 17:23:12 drh Exp $
|
||||
# $Id: expr.test,v 1.56 2007/06/25 17:28:02 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -136,8 +136,8 @@ test_expr expr-1.101 {i1=0, i2=''} {i1=i2} 0
|
||||
test_expr expr-1.102 {i1=40, i2=1} {i2<<i1} 1099511627776
|
||||
|
||||
test_expr expr-1.103 {i1=0} {(-2147483648.0 % -1)} 0.0
|
||||
test_expr expr-1.104 {i1=0} {(-9223372036854775808 % -1)} 0.0
|
||||
test_expr expr-1.105 {i1=0} {(-9223372036854775808 / -1)>1} 1
|
||||
test_expr expr-1.104 {i1=0} {(-9223372036854775808.0 % -1)} 0.0
|
||||
test_expr expr-1.105 {i1=0} {(-9223372036854775808.0 / -1)>1} 1
|
||||
|
||||
test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
|
||||
test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
|
||||
@ -639,10 +639,37 @@ do_test expr-11.1 {
|
||||
execsql {SELECT typeof(9223372036854775807)}
|
||||
} {integer}
|
||||
do_test expr-11.2 {
|
||||
execsql {SELECT typeof(00000009223372036854775807)}
|
||||
} {integer}
|
||||
do_test expr-11.3 {
|
||||
execsql {SELECT typeof(+9223372036854775807)}
|
||||
} {integer}
|
||||
do_test expr-11.4 {
|
||||
execsql {SELECT typeof(+000000009223372036854775807)}
|
||||
} {integer}
|
||||
do_test expr-11.5 {
|
||||
execsql {SELECT typeof(9223372036854775808)}
|
||||
} {real}
|
||||
do_test expr-11.3 {
|
||||
execsql {SELECT typeof(92233720368547758070)}
|
||||
do_test expr-11.6 {
|
||||
execsql {SELECT typeof(00000009223372036854775808)}
|
||||
} {real}
|
||||
do_test expr-11.7 {
|
||||
execsql {SELECT typeof(+9223372036854775808)}
|
||||
} {real}
|
||||
do_test expr-11.8 {
|
||||
execsql {SELECT typeof(+0000009223372036854775808)}
|
||||
} {real}
|
||||
do_test expr-11.11 {
|
||||
execsql {SELECT typeof(-9223372036854775808)}
|
||||
} {integer}
|
||||
do_test expr-11.12 {
|
||||
execsql {SELECT typeof(-00000009223372036854775808)}
|
||||
} {integer}
|
||||
do_test expr-11.13 {
|
||||
execsql {SELECT typeof(-9223372036854775809)}
|
||||
} {real}
|
||||
do_test expr-11.14 {
|
||||
execsql {SELECT typeof(-00000009223372036854775809)}
|
||||
} {real}
|
||||
|
||||
# These two statements used to leak memory (because of missing %destructor
|
||||
|
Loading…
x
Reference in New Issue
Block a user