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:
18
manifest
18
manifest
@@ -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
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
f9e85e6c79162081f8f512d22951931a89d157a32b24afdc48b7eb865379abe7
|
c1d8a3f65490eef2216f360d708b1746cbaa6dadce42c0950dc8e09b9ab28ee2
|
||||||
@@ -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*);
|
||||||
|
|||||||
17
src/util.c
17
src/util.c
@@ -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 */
|
||||||
|
|||||||
32
src/vdbe.c
32
src/vdbe.c
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user