]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Much faster implementation of applyNumericAffinity() by avoiding some
authordrh <drh@noemail.net>
Wed, 29 May 2019 21:18:27 +0000 (21:18 +0000)
committerdrh <drh@noemail.net>
Wed, 29 May 2019 21:18:27 +0000 (21:18 +0000)
unnecessary calls to sqlite3Atoi64().

FossilOrigin-Name: c1d8a3f65490eef2216f360d708b1746cbaa6dadce42c0950dc8e09b9ab28ee2

manifest
manifest.uuid
src/sqliteInt.h
src/util.c
src/vdbe.c
src/vdbemem.c

index e176159d4f84a9d7b32537318a9b3e1cb5c7f001..78f25db778cf6cd668a946dd369f4a01db063164 100644 (file)
--- 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
index 9463b5aacc66aa3cd376f366feb89cd971f1af45..f9268007f694dd13af54d00a95b3221d9b6404e9 100644 (file)
@@ -1 +1 @@
-f9e85e6c79162081f8f512d22951931a89d157a32b24afdc48b7eb865379abe7
\ No newline at end of file
+c1d8a3f65490eef2216f360d708b1746cbaa6dadce42c0950dc8e09b9ab28ee2
\ No newline at end of file
index 5518d93ab13277bfa88ef7b6ebfe1377cd9de677..24fabe6276d144bdfe67a2e55d958a939f85a62d 100644 (file)
@@ -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*);
index a59a2d240ecebe68c0dd73bddfcb0843e126512d..938b6a9fb2ae480e5fad353d9182af59c8aeb74f 100644 (file)
@@ -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; i<length && z[i]==0; i+=2){}
-    nonNum = i<length;
+    if( i<length ) eType = -100;
     zEnd = &z[i^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( *z=='.' ){
     z+=incr;
+    eType++;
     /* copy digits from after decimal to significand
     ** (decrease exponent by d to shift decimal right) */
     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' ){
     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
@@ -583,7 +590,7 @@ do_atof_calc:
   *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 */
index c8dd618adf6859d0b6ecfe041d71708013ef1e6d..7e1356679aff544acdd16e58b9c3723f9499fe67 100644 (file)
@@ -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;
index ee4a4a3905876c25fa737a55d968faa4e3b3ffcb..e8e85dc9e60029434d7d2ec75feca2d26d1dffb5 100644 (file)
@@ -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;
 }