1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-11 01:42:22 +03:00

Much faster implementation of applyNumericAffinity() by avoiding some

unnecessary calls to sqlite3Atoi64().

FossilOrigin-Name: c1d8a3f65490eef2216f360d708b1746cbaa6dadce42c0950dc8e09b9ab28ee2
This commit is contained in:
drh
2019-05-29 21:18:27 +00:00
parent b0968b6b14
commit 8a3884efae
6 changed files with 52 additions and 20 deletions

View File

@@ -1,5 +1,5 @@
C Add\san\sassert()\sas\san\sadditional\stest\sfor\sfix\sin\scheck-in\s[523b42371122d9e1b3]. C Much\sfaster\simplementation\sof\sapplyNumericAffinity()\sby\savoiding\ssome\nunnecessary\scalls\sto\ssqlite3Atoi64().
D 2019-05-29T18:33:59.635 D 2019-05-29T21:18:27.160
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -527,7 +527,7 @@ F src/shell.c.in 6c992809abf20dbb4aad89299d7c15c98ddf2504b23c83ef71eb435ad392cdc
F src/sqlite.h.in d19c873a17c2effd4417f687fad942b6cc0ab0c64535f669cc2f22a5b05db23b F src/sqlite.h.in d19c873a17c2effd4417f687fad942b6cc0ab0c64535f669cc2f22a5b05db23b
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9ecc93b8493bd20c0c07d52e2ac0ed8bab9b549c7f7955b59869597b650dd8b5 F src/sqlite3ext.h 9ecc93b8493bd20c0c07d52e2ac0ed8bab9b549c7f7955b59869597b650dd8b5
F src/sqliteInt.h 1ba98b4b8742f9b04ae3db1df36a607d4cf6591f3f6f6507f33d9e136fe2c136 F src/sqliteInt.h 0769cc94ac573aea0cc293b4f4e12d9cc1fb7549cece32ff6ff781214ced474c
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -592,15 +592,15 @@ F src/trigger.c bb034c08eca111e66a19cda045903a12547c1be2294b5570d794b869d9c44a73
F src/update.c 3cb9150d2cf661d938e2f1b1749945f3faa767f88febdb739ab1793bbf895ff2 F src/update.c 3cb9150d2cf661d938e2f1b1749945f3faa767f88febdb739ab1793bbf895ff2
F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507 F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507
F src/util.c 2f07256354b58053c20045fa5b3d4bc3884dfa4d393a66c983cfea115d8253dc F src/util.c e278abeb8c82fc84dac998f2f2cf16ef7740333cae9335ce270b9af75e0505a0
F src/vacuum.c 82dcec9e7b1afa980288718ad11bc499651c722d7b9f32933c4d694d91cb6ebf F src/vacuum.c 82dcec9e7b1afa980288718ad11bc499651c722d7b9f32933c4d694d91cb6ebf
F src/vdbe.c 0380e94736e0b5a0717460d1d3546ae4b1338d0fe7ea07674633d1fd9a5fc42b F src/vdbe.c e6fb674eda4aa32c50d53eb09210c9ed802866cb4d1dc0d6187301b55e4a82b7
F src/vdbe.h 712bca562eaed1c25506b9faf9680bdc75fc42e2f4a1cd518d883fa79c7a4237 F src/vdbe.h 712bca562eaed1c25506b9faf9680bdc75fc42e2f4a1cd518d883fa79c7a4237
F src/vdbeInt.h 3ba14553508d66f58753952d6dd287dce4ec735de02c6440858b4891aed51c17 F src/vdbeInt.h 3ba14553508d66f58753952d6dd287dce4ec735de02c6440858b4891aed51c17
F src/vdbeapi.c f9161e5c77f512fbb80091ce8af621d19c9556bda5e734cffaac1198407400da F src/vdbeapi.c f9161e5c77f512fbb80091ce8af621d19c9556bda5e734cffaac1198407400da
F src/vdbeaux.c afe8d7858ad7a7cd67b16d0df396f5c672309722c7855d33cd10adb7ce076b4b F src/vdbeaux.c afe8d7858ad7a7cd67b16d0df396f5c672309722c7855d33cd10adb7ce076b4b
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
F src/vdbemem.c e9a0aa2feb93356333bcd94491c25bac041e63e3d87e4caac67fde742dd2deba F src/vdbemem.c 5ecfa992b496c8e46227f1ff2ebae30c7b7a6bc098229c89a8ff49cf27249d69
F src/vdbesort.c 66592d478dbb46f19aed0b42222325eadb84deb40a90eebe25c6e7c1d8468f47 F src/vdbesort.c 66592d478dbb46f19aed0b42222325eadb84deb40a90eebe25c6e7c1d8468f47
F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143f0 F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143f0
F src/vtab.c 1fa256c6ddad7a81e2a4dc080d015d4b0a7135767717d311298e47f6fca64bb3 F src/vtab.c 1fa256c6ddad7a81e2a4dc080d015d4b0a7135767717d311298e47f6fca64bb3
@@ -1829,7 +1829,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 523b42371122d9e1b3185425745f1490138bff7f7cc941ee26ee81df7ade5bf4 P f9e85e6c79162081f8f512d22951931a89d157a32b24afdc48b7eb865379abe7
R 02ac4619c1cd7611d095b6b080f57f2d R a653c2e9383493624b2d8a6c82e92a37
U drh U drh
Z c74bccf839be69c4d3d35a14f921375f Z 02644c99894a777c23667de1b2c8f4f7

View File

@@ -1 +1 @@
f9e85e6c79162081f8f512d22951931a89d157a32b24afdc48b7eb865379abe7 c1d8a3f65490eef2216f360d708b1746cbaa6dadce42c0950dc8e09b9ab28ee2

View File

@@ -4175,6 +4175,7 @@ int sqlite3FixSelect(DbFixer*, Select*);
int sqlite3FixExpr(DbFixer*, Expr*); int sqlite3FixExpr(DbFixer*, Expr*);
int sqlite3FixExprList(DbFixer*, ExprList*); int sqlite3FixExprList(DbFixer*, ExprList*);
int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
int sqlite3RealSameAsInt(double,sqlite3_int64);
int sqlite3AtoF(const char *z, double*, int, u8); int sqlite3AtoF(const char *z, double*, int, u8);
int sqlite3GetInt32(const char *, int*); int sqlite3GetInt32(const char *, int*);
int sqlite3Atoi(const char*); int sqlite3Atoi(const char*);

View File

@@ -397,8 +397,13 @@ static LONGDOUBLE_TYPE sqlite3Pow10(int E){
** uses the encoding enc. The string is not necessarily zero-terminated. ** 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 ** 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 ** if the string is empty or contains extraneous text. More specifically
** are in one of these formats: ** 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[E[+-]digits]
** [+-]digits.[digits][E[+-]digits] ** [+-]digits.[digits][E[+-]digits]
@@ -424,7 +429,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
int eValid = 1; /* True exponent is either not used or is well-formed */ int eValid = 1; /* True exponent is either not used or is well-formed */
double result; double result;
int nDigit = 0; /* Number of digits processed */ 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 ); assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */ *pResult = 0.0; /* Default return value, in case of an error */
@@ -436,7 +441,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
incr = 2; incr = 2;
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
for(i=3-enc; i<length && z[i]==0; i+=2){} for(i=3-enc; i<length && z[i]==0; i+=2){}
nonNum = i<length; if( i<length ) eType = -100;
zEnd = &z[i^1]; zEnd = &z[i^1];
z += (enc&1); z += (enc&1);
} }
@@ -468,6 +473,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
/* if decimal point is present */ /* if decimal point is present */
if( *z=='.' ){ if( *z=='.' ){
z+=incr; z+=incr;
eType++;
/* copy digits from after decimal to significand /* copy digits from after decimal to significand
** (decrease exponent by d to shift decimal right) */ ** (decrease exponent by d to shift decimal right) */
while( z<zEnd && sqlite3Isdigit(*z) ){ while( z<zEnd && sqlite3Isdigit(*z) ){
@@ -485,6 +491,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
if( *z=='e' || *z=='E' ){ if( *z=='e' || *z=='E' ){
z+=incr; z+=incr;
eValid = 0; eValid = 0;
eType++;
/* This branch is needed to avoid a (harmless) buffer overread. The /* This branch is needed to avoid a (harmless) buffer overread. The
** special comment alerts the mutation tester that the correct answer ** special comment alerts the mutation tester that the correct answer
@@ -583,7 +590,7 @@ do_atof_calc:
*pResult = result; *pResult = result;
/* return true if number and no extra non-whitespace chracters after */ /* 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 #else
return !sqlite3Atoi64(z, pResult, length, enc); return !sqlite3Atoi64(z, pResult, length, enc);
#endif /* SQLITE_OMIT_FLOATING_POINT */ #endif /* SQLITE_OMIT_FLOATING_POINT */

View File

@@ -276,6 +276,30 @@ static VdbeCursor *allocateCursor(
return pCx; 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 ** Try to convert a value into a numeric representation if we can
** do so without loss of information. In other words, if the string ** do so without loss of information. In other words, if the string
@@ -293,12 +317,12 @@ static VdbeCursor *allocateCursor(
*/ */
static void applyNumericAffinity(Mem *pRec, int bTryForInt){ static void applyNumericAffinity(Mem *pRec, int bTryForInt){
double rValue; double rValue;
i64 iValue;
u8 enc = pRec->enc; u8 enc = pRec->enc;
int rc;
assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str ); assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str );
if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return; rc = sqlite3AtoF(pRec->z, &rValue, pRec->n, enc);
if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){ if( rc==0 ) return;
pRec->u.i = iValue; if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){
pRec->flags |= MEM_Int; pRec->flags |= MEM_Int;
}else{ }else{
pRec->u.r = rValue; pRec->u.r = rValue;

View File

@@ -697,7 +697,7 @@ int sqlite3VdbeMemRealify(Mem *pMem){
** comparison of "r1==(double)i" you sometimes get an answer of false even ** 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. ** 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; double r2 = (double)i;
return memcmp(&r1, &r2, sizeof(r1))==0; return memcmp(&r1, &r2, sizeof(r1))==0;
} }