]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Rework the string to integer conversion logic to address tickets
authordrh <drh@noemail.net>
Mon, 25 Jun 2007 17:28:00 +0000 (17:28 +0000)
committerdrh <drh@noemail.net>
Mon, 25 Jun 2007 17:28:00 +0000 (17:28 +0000)
#2344 and #2454. (CVS 4123)

FossilOrigin-Name: 5b3a490649ab88c168e3e5bf2efbc7f61b1b954d

manifest
manifest.uuid
src/sqliteInt.h
src/test1.c
src/util.c
src/vdbe.c
src/vdbemem.c
test/expr.test

index 55306c99361e5f27395941a1a08daa236f9e6f4a..6612b70ecfb85163c7dd6684da8d538156dc6aa3 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sfor\s#2445.\sA\sbug\sin\sthe\slookupName()\slogic\sthat\scould\scause\sa\scrash\swhen\sa\sWHERE\sclause\sused\san\salias\sto\srefer\sto\san\sexpression\sin\sthe\sresult-set\sof\sthe\sSELECT,\sand\sthat\sexpression\swas\sitself\sa\sreference\sto\sa\stable\scolumn.\s(CVS\s4122)
-D 2007-06-25T16:29:34
+C Rework\sthe\sstring\sto\sinteger\sconversion\slogic\sto\saddress\stickets\n#2344\sand\s#2454.\s(CVS\s4123)
+D 2007-06-25T17:28:01
 F Makefile.in 7f7485a4cc039476a42e534b3f26ec90e2f9753e
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -109,11 +109,11 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c 4b0fc3c76a9f23a1c963e01703c0fbbca1b5c34d
 F src/sqlite.h.in 6f290b660b2e7c3359968bb4b344ec31a1178746
 F src/sqlite3ext.h 95575e0d175a0271fe2c3232c0d11e8720ed6887
-F src/sqliteInt.h 6503239d26b1943227031aa005320ef09b9b92b7
+F src/sqliteInt.h 475c538baf1105c00ae50c3564dbd20159418f9b
 F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa
 F src/table.c a8de75bcedf84d4060d804264b067ab3b1a3561d
 F src/tclsqlite.c 4bffe56752d2c24ade23340e46a91fd92c316e08
-F src/test1.c a83c097ee1353e8982745ee1b78612fea7425602
+F src/test1.c 9017dab5bfe2b22e9bc8e81ba999a8ae22c61976
 F src/test2.c 24458b17ab2f3c90cbc1c8446bd7ffe69be62f88
 F src/test3.c a280931fb40222b7c90da45eea926459beee8904
 F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
@@ -136,16 +136,16 @@ F src/tokenize.c 6cef9e6fc454d789a32c5b509ccb193a2b01977b
 F src/trigger.c 420192efe3e6f03addf7897c60c3c8bf913d3493
 F src/update.c 6b10becb6235ea314ed245fbfbf8b38755e3166e
 F src/utf.c 01b2aba02b10d12903e9e1ff897215c9faf6b662
-F src/util.c 80cdf6b68d03b8f0ab3237a390842e039cff66c6
+F src/util.c f58a68d062608eeed6d8229bb22a61b87e530d68
 F src/vacuum.c 8bd895d29e7074e78d4e80f948e35ddc9cf2beef
-F src/vdbe.c 81714b7df6c7769ab300446e070fc0a5bb2ece86
+F src/vdbe.c 251e0121040768fd801920cfecbcb159a891d4af
 F src/vdbe.h 001c5b257567c1d3de7feb2203aac71d0d7b16a3
 F src/vdbeInt.h 7d2bf163d6d4e815724a457f2216dd8e38c3955c
 F src/vdbeapi.c 7930b9a188ab385287ca3eb3840af7225cb43549
 F src/vdbeaux.c c580d3605edc2c24ba9bd26fa7aa8b4fff10daa4
 F src/vdbeblob.c 96f3572fdc45eda5be06e6372b612bc30742d9f0
 F src/vdbefifo.c 3ca8049c561d5d67cbcb94dc909ae9bb68c0bf8f
-F src/vdbemem.c ca4d3994507cb0a9504820293af69f5c778b4abd
+F src/vdbemem.c 327944e70cd807c81705e0d81f9417e89f2c563c
 F src/vtab.c 51d43cda45d25e6f3a15d19fe32992b7756e74db
 F src/where.c 12387641659605318ae03d87f0687f223dfc9568
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
@@ -226,7 +226,7 @@ F test/enc3.test 9331988b9d72decec96995c90637e87b00d747a5
 F test/exclusive.test 5bc520ba366ae3d242420af025ab64d465b04706
 F test/exclusive2.test 3496656375dc88e97d704c2d5d2c93d626cb7104
 F test/exclusive3.test 0e49c35b7e7cb8e7280b4ce3f0359d30b207d2ff
-F test/expr.test 93931366f660dc84ba36eaf390f670b27d2c03e8
+F test/expr.test a4dc0855b86ba0daeef47f3dd4cf394eda2bd0ac
 F test/filefmt.test 053b622009fbbb74dd37921ffad374d852c13cd8
 F test/fkey1.test dcb4f28eb22d5141f15161d6bdca9a4f58c95729
 F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
@@ -515,7 +515,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 02b23c4394da7efb82e9318146f10818b0f68b1f
-R 0b7987f665943fbbfc4744c2a66803b3
-U danielk1977
-Z 03cd9b4e47591553bbb663ee352448e0
+P 044ca1c72a8f4632dc2e6a94690d164d3560ee38
+R 31842549475179d1d10a54116c67cbde
+U drh
+Z dd5bcce4a9040dd3c1d7c52ab375cdda
index ce2aaf39433441a25e85a1cb3dcde8ef782514ce..1845cf3fc8ffdc4ec6ce7290b62ab8f572f56534 100644 (file)
@@ -1 +1 @@
-044ca1c72a8f4632dc2e6a94690d164d3560ee38
\ No newline at end of file
+5b3a490649ab88c168e3e5bf2efbc7f61b1b954d
\ No newline at end of file
index 5fd36747112e2867f4f28540186aacf38cd68ce0..6bdd22ef3da270fcd2f410a8bb1f9ab4bf6aa80b 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.575 2007/06/22 15:21:16 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.576 2007/06/25 17:28:01 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1835,7 +1835,7 @@ void sqlite3TableAffinityStr(Vdbe *, Table *);
 char sqlite3CompareAffinity(Expr *pExpr, char aff2);
 int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
 char sqlite3ExprAffinity(Expr *pExpr);
-int sqlite3Atoi64(const char*, i64*);
+int sqlite3_atoi64(const char*, i64*);
 void sqlite3Error(sqlite3*, int, const char*,...);
 void *sqlite3HexToBlob(const char *z);
 int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
index 1454cd64e394dfa270906db177d1c94e7b87e303..dcb7290f7b3ea00bf2ff557bf708b5ef92277c42 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test1.c,v 1.256 2007/06/15 20:29:20 drh Exp $
+** $Id: test1.c,v 1.257 2007/06/25 17:28:02 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -1082,7 +1082,7 @@ static int sqlite3_mprintf_int(
 */
 static int sqlite3GetInt64(const char *zNum, i64 *pValue){
   if( sqlite3FitsIn64Bits(zNum) ){
-    sqlite3Atoi64(zNum, pValue);
+    sqlite3_atoi64(zNum, pValue);
     return 1;
   }
   return 0;
index a5fb28f6e0c74eaa77a41d126226833d6cf797c0..13429f998b58914058825e66c6cc1844ad3a0f96 100644 (file)
@@ -14,7 +14,7 @@
 ** This file contains functions for allocating memory, comparing
 ** strings, and stuff like that.
 **
-** $Id: util.c,v 1.205 2007/05/16 17:50:46 danielk1977 Exp $
+** $Id: util.c,v 1.206 2007/06/25 17:28:02 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -299,18 +299,40 @@ int sqlite3AtoF(const char *z, double *pResult){
 #endif /* SQLITE_OMIT_FLOATING_POINT */
 }
 
+/*
+** Compare the 19-character string zNum against the text representation
+** value 2^63:  9223372036854775808.  Return negative, zero, or positive
+** if zNum is less than, equal to, or greater than the string.
+**
+** Unlike memcmp() this routine is guaranteed to return the difference
+** in the values of the last digit if the only difference is in the
+** last digit.  So, for example,
+**
+**      compare2pow63("9223372036854775800")
+**
+** will return -8.
+*/
+static int compare2pow63(const char *zNum){
+  int c;
+  c = memcmp(zNum,"922337203685477580",18);
+  if( c==0 ){
+    c = zNum[18] - '8';
+  }
+  return c;
+}
+
+
 /*
 ** Return TRUE if zNum is a 64-bit signed integer and write
 ** the value of the integer into *pNum.  If zNum is not an integer
 ** or is an integer that is too large to be expressed with 64 bits,
-** then return false.  If n>0 and the integer is string is not
-** exactly n bytes long, return false.
+** then return false.
 **
 ** When this routine was originally written it dealt with only
 ** 32-bit numbers.  At that time, it was much faster than the
 ** atoi() library routine in RedHat 7.2.
 */
-int sqlite3Atoi64(const char *zNum, i64 *pNum){
+int sqlite3_atoi64(const char *zNum, i64 *pNum){
   i64 v = 0;
   int neg;
   int i, c;
@@ -324,42 +346,24 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum){
   }else{
     neg = 0;
   }
+  while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */
   for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
     v = v*10 + c - '0';
   }
   *pNum = neg ? -v : v;
-  return c==0 && i>0 && 
-      (i<19 || (i==19 && memcmp(zNum,"9223372036854775807",19)<=0));
-}
-
-/*
-** The string zNum represents an integer.  There might be some other
-** information following the integer too, but that part is ignored.
-** If the integer that the prefix of zNum represents will fit in a
-** 32-bit signed integer, return TRUE.  Otherwise return FALSE.
-**
-** This routine returns FALSE for the string -2147483648 even that
-** that number will in fact fit in a 32-bit integer.  But positive
-** 2147483648 will not fit in 32 bits.  So it seems safer to return
-** false.
-*/
-static int sqlite3FitsIn32Bits(const char *zNum){
-  int i, c;
-  if( *zNum=='-' || *zNum=='+' ) zNum++;
-  for(i=0; (c=zNum[i])>='0' && c<='9'; i++){}
-  return i<10 || (i==10 && memcmp(zNum,"2147483647",10)<=0);
-}
-
-/*
-** If zNum represents an integer that will fit in 32-bits, then set
-** *pValue to that integer and return true.  Otherwise return false.
-*/
-int sqlite3GetInt32(const char *zNum, int *pValue){
-  if( sqlite3FitsIn32Bits(zNum) ){
-    *pValue = atoi(zNum);
+  if( c!=0 || i==0 || i>19 ){
+    /* zNum is empty or contains non-numeric text or is longer
+    ** than 19 digits (thus guaranting that it is too large) */
+    return 0;
+  }else if( i<19 ){
+    /* Less than 19 digits, so we know that it fits in 64 bits */
     return 1;
+  }else{
+    /* 19-digit numbers must be no larger than 9223372036854775807 if positive
+    ** or 9223372036854775808 if negative.  Note that 9223372036854665808
+    ** is 2^63. */
+    return compare2pow63(zNum)<neg;
   }
-  return 0;
 }
 
 /*
@@ -375,11 +379,63 @@ int sqlite3GetInt32(const char *zNum, int *pValue){
 */
 int sqlite3FitsIn64Bits(const char *zNum){
   int i, c;
-  if( *zNum=='-' || *zNum=='+' ) zNum++;
+  int neg = 0;
+  if( *zNum=='-' ){
+    neg = 1;
+    zNum++;
+  }else if( *zNum=='+' ){
+    zNum++;
+  }
+  while( *zNum=='0' ){
+    zNum++;   /* Skip leading zeros.  Ticket #2454 */
+  }
   for(i=0; (c=zNum[i])>='0' && c<='9'; i++){}
-  return i<19 || (i==19 && memcmp(zNum,"9223372036854775807",19)<=0);
+  if( i<19 ){
+    /* Guaranteed to fit if less than 19 digits */
+    return 1;
+  }else if( i>19 ){
+    /* Guaranteed to be too big if greater than 19 digits */
+    return 0;
+  }else{
+    /* Compare against 2^63. */
+    return compare2pow63(zNum)<neg;
+  }
 }
 
+/*
+** If zNum represents an integer that will fit in 32-bits, then set
+** *pValue to that integer and return true.  Otherwise return false.
+**
+** Any non-numeric characters that following zNum are ignored.
+** This is different from sqlite3_atoi64() which requires the
+** input number to be zero-terminated.
+*/
+int sqlite3GetInt32(const char *zNum, int *pValue){
+  sqlite_int64 v = 0;
+  int i, c;
+  int neg = 0;
+  if( zNum[0]=='-' ){
+    neg = 1;
+    zNum++;
+  }else if( zNum[0]=='+' ){
+    zNum++;
+  }
+  while( zNum[0]=='0' ) zNum++;
+  for(i=0; i<10 && (c = zNum[i] - '0')>=0 && c<=9; i++){
+    v = v*10 + c;
+  }
+  if( i>9 ){
+    return 0;
+  }
+  if( v-neg>2147483647 ){
+    return 0;
+  }
+  if( neg ){
+    v = -v;
+  }
+  *pValue = (int)v;
+  return 1;
+}
 
 /*
 ** Check to make sure we have a valid db pointer.  This test is not
index 32bea5ad8bf67483f9a4fd8ae63822aed6f36ec7..964356ae70574aa37076df2511f7a48749a06a7a 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.630 2007/06/24 16:11:03 danielk1977 Exp $
+** $Id: vdbe.c,v 1.631 2007/06/25 17:28:02 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -227,7 +227,7 @@ static void applyNumericAffinity(Mem *pRec){
          && sqlite3IsNumber(pRec->z, &realnum, pRec->enc) ){
       i64 value;
       sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8);
-      if( !realnum && sqlite3Atoi64(pRec->z, &value) ){
+      if( !realnum && sqlite3_atoi64(pRec->z, &value) ){
         sqlite3VdbeMemRelease(pRec);
         pRec->u.i = value;
         pRec->flags = MEM_Int;
index f05e05cce99bf15d54c5c7010e01be5aa37f09de..3615f3d6911d9d34737cd71743d76349023f8dc1 100644 (file)
@@ -307,7 +307,7 @@ i64 sqlite3VdbeIntValue(Mem *pMem){
       return 0;
     }
     assert( pMem->z );
-    sqlite3Atoi64(pMem->z, &value);
+    sqlite3_atoi64(pMem->z, &value);
     return value;
   }else{
     return 0;
index 8d89a0d68471f3668e6b7d14113db78d7d992132..e6a057b90f4239975ce80601ee59f5bf9e025b12 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is testing expressions.
 #
-# $Id: expr.test,v 1.55 2007/05/10 17:23:12 drh Exp $
+# $Id: expr.test,v 1.56 2007/06/25 17:28:02 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -136,8 +136,8 @@ test_expr expr-1.101 {i1=0, i2=''} {i1=i2} 0
 test_expr expr-1.102 {i1=40, i2=1} {i2<<i1} 1099511627776
 
 test_expr expr-1.103 {i1=0} {(-2147483648.0 % -1)} 0.0
-test_expr expr-1.104 {i1=0} {(-9223372036854775808 % -1)} 0.0
-test_expr expr-1.105 {i1=0} {(-9223372036854775808 / -1)>1} 1
+test_expr expr-1.104 {i1=0} {(-9223372036854775808.0 % -1)} 0.0
+test_expr expr-1.105 {i1=0} {(-9223372036854775808.0 / -1)>1} 1
 
 test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
 test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
@@ -639,10 +639,37 @@ do_test expr-11.1 {
   execsql {SELECT typeof(9223372036854775807)}
 } {integer}
 do_test expr-11.2 {
+  execsql {SELECT typeof(00000009223372036854775807)}
+} {integer}
+do_test expr-11.3 {
+  execsql {SELECT typeof(+9223372036854775807)}
+} {integer}
+do_test expr-11.4 {
+  execsql {SELECT typeof(+000000009223372036854775807)}
+} {integer}
+do_test expr-11.5 {
   execsql {SELECT typeof(9223372036854775808)}
 } {real}
-do_test expr-11.3 {
-  execsql {SELECT typeof(92233720368547758070)}
+do_test expr-11.6 {
+  execsql {SELECT typeof(00000009223372036854775808)}
+} {real}
+do_test expr-11.7 {
+  execsql {SELECT typeof(+9223372036854775808)}
+} {real}
+do_test expr-11.8 {
+  execsql {SELECT typeof(+0000009223372036854775808)}
+} {real}
+do_test expr-11.11 {
+  execsql {SELECT typeof(-9223372036854775808)}
+} {integer}
+do_test expr-11.12 {
+  execsql {SELECT typeof(-00000009223372036854775808)}
+} {integer}
+do_test expr-11.13 {
+  execsql {SELECT typeof(-9223372036854775809)}
+} {real}
+do_test expr-11.14 {
+  execsql {SELECT typeof(-00000009223372036854775809)}
 } {real}
 
 # These two statements used to leak memory (because of missing %destructor