-C Add\san\sassert()\sas\san\sadditional\stest\sfor\sfix\sin\scheck-in\s[523b42371122d9e1b3].
-D 2019-05-29T18:33:59.635
+C Much\sfaster\simplementation\sof\sapplyNumericAffinity()\sby\savoiding\ssome\nunnecessary\scalls\sto\ssqlite3Atoi64().
+D 2019-05-29T21:18:27.160
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/sqlite.h.in d19c873a17c2effd4417f687fad942b6cc0ab0c64535f669cc2f22a5b05db23b
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9ecc93b8493bd20c0c07d52e2ac0ed8bab9b549c7f7955b59869597b650dd8b5
-F src/sqliteInt.h 1ba98b4b8742f9b04ae3db1df36a607d4cf6591f3f6f6507f33d9e136fe2c136
+F src/sqliteInt.h 0769cc94ac573aea0cc293b4f4e12d9cc1fb7549cece32ff6ff781214ced474c
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/update.c 3cb9150d2cf661d938e2f1b1749945f3faa767f88febdb739ab1793bbf895ff2
F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507
-F src/util.c 2f07256354b58053c20045fa5b3d4bc3884dfa4d393a66c983cfea115d8253dc
+F src/util.c e278abeb8c82fc84dac998f2f2cf16ef7740333cae9335ce270b9af75e0505a0
F src/vacuum.c 82dcec9e7b1afa980288718ad11bc499651c722d7b9f32933c4d694d91cb6ebf
-F src/vdbe.c 0380e94736e0b5a0717460d1d3546ae4b1338d0fe7ea07674633d1fd9a5fc42b
+F src/vdbe.c e6fb674eda4aa32c50d53eb09210c9ed802866cb4d1dc0d6187301b55e4a82b7
F src/vdbe.h 712bca562eaed1c25506b9faf9680bdc75fc42e2f4a1cd518d883fa79c7a4237
F src/vdbeInt.h 3ba14553508d66f58753952d6dd287dce4ec735de02c6440858b4891aed51c17
F src/vdbeapi.c f9161e5c77f512fbb80091ce8af621d19c9556bda5e734cffaac1198407400da
F src/vdbeaux.c afe8d7858ad7a7cd67b16d0df396f5c672309722c7855d33cd10adb7ce076b4b
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
-F src/vdbemem.c e9a0aa2feb93356333bcd94491c25bac041e63e3d87e4caac67fde742dd2deba
+F src/vdbemem.c 5ecfa992b496c8e46227f1ff2ebae30c7b7a6bc098229c89a8ff49cf27249d69
F src/vdbesort.c 66592d478dbb46f19aed0b42222325eadb84deb40a90eebe25c6e7c1d8468f47
F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143f0
F src/vtab.c 1fa256c6ddad7a81e2a4dc080d015d4b0a7135767717d311298e47f6fca64bb3
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 523b42371122d9e1b3185425745f1490138bff7f7cc941ee26ee81df7ade5bf4
-R 02ac4619c1cd7611d095b6b080f57f2d
+P f9e85e6c79162081f8f512d22951931a89d157a32b24afdc48b7eb865379abe7
+R a653c2e9383493624b2d8a6c82e92a37
U drh
-Z c74bccf839be69c4d3d35a14f921375f
+Z 02644c99894a777c23667de1b2c8f4f7
-f9e85e6c79162081f8f512d22951931a89d157a32b24afdc48b7eb865379abe7
\ No newline at end of file
+c1d8a3f65490eef2216f360d708b1746cbaa6dadce42c0950dc8e09b9ab28ee2
\ No newline at end of file
int sqlite3FixExpr(DbFixer*, Expr*);
int sqlite3FixExprList(DbFixer*, ExprList*);
int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
+int sqlite3RealSameAsInt(double,sqlite3_int64);
int sqlite3AtoF(const char *z, double*, int, u8);
int sqlite3GetInt32(const char *, int*);
int sqlite3Atoi(const char*);
** uses the encoding enc. The string is not necessarily zero-terminated.
**
** Return TRUE if the result is a valid real number (or integer) and FALSE
-** if the string is empty or contains extraneous text. Valid numbers
-** are in one of these formats:
+** if the string is empty or contains extraneous text. More specifically
+** return
+** 1 => The input string is a pure integer
+** 2 or more => The input has a decimal point or eNNN clause
+** 0 => The input string is not a valid number
+**
+** Valid numbers are in one of these formats:
**
** [+-]digits[E[+-]digits]
** [+-]digits.[digits][E[+-]digits]
int eValid = 1; /* True exponent is either not used or is well-formed */
double result;
int nDigit = 0; /* Number of digits processed */
- int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
+ int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */
incr = 2;
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
for(i=3-enc; i<length && z[i]==0; i+=2){}
- nonNum = i<length;
+ if( i<length ) eType = -100;
zEnd = &z[i^1];
z += (enc&1);
}
/* if decimal point is present */
if( *z=='.' ){
z+=incr;
+ eType++;
/* copy digits from after decimal to significand
** (decrease exponent by d to shift decimal right) */
while( z<zEnd && sqlite3Isdigit(*z) ){
if( *z=='e' || *z=='E' ){
z+=incr;
eValid = 0;
+ eType++;
/* This branch is needed to avoid a (harmless) buffer overread. The
** special comment alerts the mutation tester that the correct answer
*pResult = result;
/* return true if number and no extra non-whitespace chracters after */
- return z==zEnd && nDigit>0 && eValid && nonNum==0;
+ return z==zEnd && nDigit>0 && eValid && eType>0 ? eType : 0;
#else
return !sqlite3Atoi64(z, pResult, length, enc);
#endif /* SQLITE_OMIT_FLOATING_POINT */
return pCx;
}
+/*
+** The string in pRec is known to look like an integer and to have a
+** floating point value of rValue. Return true and set *piValue to the
+** integer value if the string is in range to be an integer. Otherwise,
+** return false.
+*/
+static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){
+ i64 iValue = (double)rValue;
+ if( sqlite3RealSameAsInt(rValue,iValue) ){
+ testcase( iValue<-2251799813685248 );
+ testcase( iValue==-2251799813685248 );
+ testcase( iValue==-2251799813685247 );
+ testcase( iValue>-2251799813685247 && iValue<+2251799813685247 );
+ testcase( iValue==+2251799813685247 );
+ testcase( iValue==+2251799813685248 );
+ testcase( iValue>+2251799813685248 );
+ if( iValue > -2251799813685248 && iValue < 2251799813685248 ){
+ *piValue = iValue;
+ return 1;
+ }
+ }
+ return 0==sqlite3Atoi64(pRec->z, piValue, pRec->n, pRec->enc);
+}
+
/*
** Try to convert a value into a numeric representation if we can
** do so without loss of information. In other words, if the string
*/
static void applyNumericAffinity(Mem *pRec, int bTryForInt){
double rValue;
- i64 iValue;
u8 enc = pRec->enc;
+ int rc;
assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str );
- if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
- if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
- pRec->u.i = iValue;
+ rc = sqlite3AtoF(pRec->z, &rValue, pRec->n, enc);
+ if( rc==0 ) return;
+ if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){
pRec->flags |= MEM_Int;
}else{
pRec->u.r = rValue;
** comparison of "r1==(double)i" you sometimes get an answer of false even
** though the r1 and (double)i values are bit-for-bit the same.
*/
-static int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){
+int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){
double r2 = (double)i;
return memcmp(&r1, &r2, sizeof(r1))==0;
}