From: drh Date: Wed, 29 May 2019 21:18:27 +0000 (+0000) Subject: Much faster implementation of applyNumericAffinity() by avoiding some X-Git-Tag: version-3.29.0~59 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8a3884efae47b8f762fdd7c3b0751ddca8e41243;p=thirdparty%2Fsqlite.git Much faster implementation of applyNumericAffinity() by avoiding some unnecessary calls to sqlite3Atoi64(). FossilOrigin-Name: c1d8a3f65490eef2216f360d708b1746cbaa6dadce42c0950dc8e09b9ab28ee2 --- diff --git a/manifest b/manifest index e176159d4f..78f25db778 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -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 @@ -527,7 +527,7 @@ F src/shell.c.in 6c992809abf20dbb4aad89299d7c15c98ddf2504b23c83ef71eb435ad392cdc 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 @@ -592,15 +592,15 @@ F src/trigger.c bb034c08eca111e66a19cda045903a12547c1be2294b5570d794b869d9c44a73 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 @@ -1829,7 +1829,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 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 diff --git a/manifest.uuid b/manifest.uuid index 9463b5aacc..f9268007f6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f9e85e6c79162081f8f512d22951931a89d157a32b24afdc48b7eb865379abe7 \ No newline at end of file +c1d8a3f65490eef2216f360d708b1746cbaa6dadce42c0950dc8e09b9ab28ee2 \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5518d93ab1..24fabe6276 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4175,6 +4175,7 @@ int sqlite3FixSelect(DbFixer*, Select*); 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*); diff --git a/src/util.c b/src/util.c index a59a2d240e..938b6a9fb2 100644 --- a/src/util.c +++ b/src/util.c @@ -397,8 +397,13 @@ static LONGDOUBLE_TYPE sqlite3Pow10(int E){ ** 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] @@ -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 */ 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 */ @@ -436,7 +441,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ incr = 2; assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); for(i=3-enc; i0 && 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 */ diff --git a/src/vdbe.c b/src/vdbe.c index c8dd618adf..7e1356679a 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -276,6 +276,30 @@ static VdbeCursor *allocateCursor( 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 @@ -293,12 +317,12 @@ static VdbeCursor *allocateCursor( */ 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; diff --git a/src/vdbemem.c b/src/vdbemem.c index ee4a4a3905..e8e85dc9e6 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -697,7 +697,7 @@ int sqlite3VdbeMemRealify(Mem *pMem){ ** 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; }