mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-15 11:41:13 +03:00
Merge experimental into trunk: Refactor the text-to-numeric conversion
routines to work without zero-terminators and in UTF16 as well as UTF8. Avoid invalidating strings with doing affinity conversions. FossilOrigin-Name: 07ee080ec4527fd2191f41231208da66b3f6b955
This commit is contained in:
49
manifest
49
manifest
@@ -1,5 +1,8 @@
|
||||
C Add\sfurther\stests\sto\se_createtable.test.
|
||||
D 2010-09-30T18:43:14
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA1
|
||||
|
||||
C Merge\sexperimental\sinto\strunk:\s\sRefactor\sthe\stext-to-numeric\sconversion\nroutines\sto\swork\swithout\szero-terminators\sand\sin\sUTF16\sas\swell\sas\sUTF8.\nAvoid\sinvalidating\sstrings\swith\sdoing\saffinity\sconversions.
|
||||
D 2010-09-30T20:33:40
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in c599a15d268b1db2aeadea19df2adc3bf2eb6bee
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@@ -125,12 +128,12 @@ F src/build.c 00a327120d81ace6267e714ae8010c997d55de5d
|
||||
F src/callback.c a1d1b1c9c85415dff013af033e2fed9c8382d33b
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 4f3aadad62c6c9f0d4e5a96718516ac4e3c598df
|
||||
F src/date.c 5dd8448a0bfea8d31fb14cff487d0c06ff8c8b20
|
||||
F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b
|
||||
F src/delete.c 7ed8a8c8b5f748ece92df173d7e0f7810c899ebd
|
||||
F src/expr.c 1caa723c3ab7a7e35952bc85a6f4a7da3632308f
|
||||
F src/expr.c c5749e45576a58d9de27e6a8462fa84eac0b32fd
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 17950a28f28b23e8ad3feaac5fc88c324d2f600a
|
||||
F src/func.c b5664982355274c264afe90efd7f694d447a594a
|
||||
F src/func.c 2b7cf54d2569c2eba42fe81165d1932b546681a3
|
||||
F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3
|
||||
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
|
||||
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
|
||||
@@ -167,7 +170,7 @@ F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
|
||||
F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
|
||||
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
|
||||
F src/pcache1.c e9578a3beac26f229ee558a4e16c863f2498185f
|
||||
F src/pragma.c 8b24ce00a93de345b6c3bd1e1e2cfba9f63d2325
|
||||
F src/pragma.c 216d12e4546e65ca6cfcd3221e64573889ae8f34
|
||||
F src/prepare.c ce4c35a2b1d5fe916e4a46b70d24a6e997d7c4c6
|
||||
F src/printf.c 8ae5082dd38a1b5456030c3755ec3a392cd51506
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
@@ -177,12 +180,12 @@ F src/select.c cf3013b1953348c7c6ff9636342e87b9fda68466
|
||||
F src/shell.c 8517fc1f9c59ae4007e6cc8b9af91ab231ea2056
|
||||
F src/sqlite.h.in a5b50e1bc4d4d9a3cc95386747220a839d0c40f7
|
||||
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
|
||||
F src/sqliteInt.h ea31c7867d910c1da9b20adb6614e474011fbae0
|
||||
F src/sqliteInt.h c63b0340dfdfde18ff255ddccf004edd2d073288
|
||||
F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44
|
||||
F src/status.c 496913d4e8441195f6f2a75b1c95993a45b9b30b
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c e91019fb6787166abca23a81b16c07fecc2ed751
|
||||
F src/test1.c a0f135000894cb5a3d32d23fd74a83939ca854fa
|
||||
F src/test1.c e8803ee4bf6766f1b9cd8a3fed1559cc05caa306
|
||||
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
|
||||
F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc
|
||||
F src/test4.c 0528360b5025688002a5feb6be906ddce52eaaee
|
||||
@@ -223,15 +226,15 @@ F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
|
||||
F src/trigger.c b8bedb9c0084ceb51a40f54fcca2ce048c8de852
|
||||
F src/update.c 227e6cd512108b84f69421fc6c7aa1b83d60d6e0
|
||||
F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685
|
||||
F src/util.c 5f5f4db4e799224713582bb49124827b16aa8e54
|
||||
F src/util.c cd78524566fe45671863eee78685969a4bfd4e4c
|
||||
F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f
|
||||
F src/vdbe.c 69812aabf486a2d6a5b0960ffd9a47d141442735
|
||||
F src/vdbe.c e1aa917961e69f71c80f46ce231b496d3c841ae1
|
||||
F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2
|
||||
F src/vdbeInt.h 7f4cf1b2b69bef3a432b1f23dfebef57275436b4
|
||||
F src/vdbeapi.c 03cddfa4f85cadf608c0d28ff6b622b7da432446
|
||||
F src/vdbeaux.c de0b06b11a25293e820a49159eca9f1c51a64716
|
||||
F src/vdbeblob.c 258a6010ba7a82b72b327fb24c55790655689256
|
||||
F src/vdbemem.c 8ff4f80a35d51f3690c191ec44778ef4bf949ac0
|
||||
F src/vdbemem.c ef015d9d05fbf3fcce664dadd5b589663878ab50
|
||||
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
|
||||
F src/vtab.c 6c90e3e65b2f026fc54703a8f3c917155f419d87
|
||||
F src/wal.c 7081f148cb52b0cf2280e6384196402dc58130a3
|
||||
@@ -337,7 +340,7 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/createtab.test 199cf68f44e5d9e87a0b8afc7130fdeb4def3272
|
||||
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
|
||||
F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
|
||||
F test/date.test 6354b883f922c38046a8efbad187cc95df6da023
|
||||
F test/date.test a18a2ce81add84b17b06559e82ad7bb91bc6ddff
|
||||
F test/dbstatus.test 175b088308f2ce3f7afb8208f25c10878ee05921
|
||||
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
|
||||
F test/delete.test f7629d9eb245dfca170169cc5c7a735dec34aeb4
|
||||
@@ -362,11 +365,12 @@ F test/e_vacuum.test 057cc29445746fc1d2542984ff0253d511a234bd
|
||||
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
F test/enc2.test 6d91a5286f59add0cfcbb2d0da913b76f2242398
|
||||
F test/enc3.test 5c550d59ff31dccdba5d1a02ae11c7047d77c041
|
||||
F test/enc4.test 4b575ef09e0eff896e73bd24076f96c2aa6a42de
|
||||
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
|
||||
F test/exclusive.test 0ba00fb15aeec1eba3d4b03a271b5081e21c35be
|
||||
F test/exclusive2.test 76e63c05349cb70d09d60b99d2ae625525ff5155
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/expr.test 9f521ae22f00e074959f72ce2e55d46b9ed23f68
|
||||
F test/expr.test 620a636cf7b7d4e5834a0b9d83a4da372e24a7b7
|
||||
F test/fallocate.test 43dc34b8c24be6baffadc3b4401ee15710ce83c6
|
||||
F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e
|
||||
F test/filefmt.test f77c92141960b7933bc6691631d2ad62257ef40a
|
||||
@@ -461,7 +465,7 @@ F test/incrblob_err.test c577c91d4ed9e8336cdb188b15d6ee2a6fe9604e
|
||||
F test/incrvacuum.test 453d1e490d8f5ad2c9b3a54282a0690d6ae56462
|
||||
F test/incrvacuum2.test 9e22a794899c91b7d8c8e12eaacac8df249faafe
|
||||
F test/incrvacuum_ioerr.test 57d2f5777ab13fa03b87b262a4ea1bad5cfc0291
|
||||
F test/index.test cbf301cdb2da43e4eac636c3400c2439af1834ad
|
||||
F test/index.test df7c00c6edd9504ab71c83a9514f1c5ca0fa54d8
|
||||
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
|
||||
F test/index3.test 423a25c789fc8cc51aaf2a4370bbdde2d9e9eed7
|
||||
F test/indexedby.test 5a1180602f2e72c481467bd4cae05dae5dc36f47
|
||||
@@ -660,12 +664,14 @@ F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660
|
||||
F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
|
||||
F test/tkt-31338dca7e.test 5741cd48de500347a437ba1be58c8335e83c5a5e
|
||||
F test/tkt-313723c356.test c47f8a9330523e6f35698bf4489bcb29609b53ac
|
||||
F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
|
||||
F test/tkt-3fe897352e.test 10de1a67bd5c66b238a4c96abe55531b37bb4f00
|
||||
F test/tkt-4a03edc4c8.test 2865e4edbc075b954daa82f8da7cc973033ec76e
|
||||
F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
|
||||
F test/tkt-5ee23731f.test 3581260f2a71e51db94e1506ba6b0f7311d002a9
|
||||
F test/tkt-78e04e52ea.test fb5430c675e708f5cbafdf3e7e5593da5145a527
|
||||
F test/tkt-80e031a00f.test 9a154173461a4dbe2de49cda73963e04842d52f7
|
||||
F test/tkt-8454a207b9.test c583a9f814a82a2b5ba95207f55001c9f0cd816c
|
||||
F test/tkt-94c04eaadb.test be5ea61cb04dfdc047d19b5c5a9e75fa3da67a7f
|
||||
F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67
|
||||
F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
|
||||
@@ -869,7 +875,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P f34dc54d46d05adf1f52db51442195b3285a26b9
|
||||
R 069696d4daf65a8968d092bcd64d11c4
|
||||
U dan
|
||||
Z 1a4ebdd9f70b124e6529c3e98e65ef52
|
||||
P 0a4528d629018eae0b0f3e173ebda666c2e2d502 dd6d61a967e3c0d98b78987f6f7bb9bdf090174e
|
||||
R ad1d113ec850200341f8d4b0b4290fb2
|
||||
U drh
|
||||
Z db01694f0e5febfb397c97bb3dc289ab
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||
|
||||
iD8DBQFMpPQooxKgR168RlERAuYFAJ48UfDVvwv5OeiELuVh1cra3a7+lACeP6IT
|
||||
GYp3aSgYDm2W/VlxdCCZfbs=
|
||||
=i1hI
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
@@ -1 +1 @@
|
||||
0a4528d629018eae0b0f3e173ebda666c2e2d502
|
||||
07ee080ec4527fd2191f41231208da66b3f6b955
|
||||
22
src/date.c
22
src/date.c
@@ -133,12 +133,6 @@ end_getDigits:
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
** Read text from z[] and convert into a floating point number. Return
|
||||
** the number of digits converted.
|
||||
*/
|
||||
#define getValue sqlite3AtoF
|
||||
|
||||
/*
|
||||
** Parse a timezone extension on the end of a date-time.
|
||||
** The extension is of the form:
|
||||
@@ -340,7 +334,7 @@ static int parseDateOrTime(
|
||||
const char *zDate,
|
||||
DateTime *p
|
||||
){
|
||||
int isRealNum; /* Return from sqlite3IsNumber(). Not used */
|
||||
double r;
|
||||
if( parseYyyyMmDd(zDate,p)==0 ){
|
||||
return 0;
|
||||
}else if( parseHhMmSs(zDate, p)==0 ){
|
||||
@@ -348,9 +342,7 @@ static int parseDateOrTime(
|
||||
}else if( sqlite3StrICmp(zDate,"now")==0){
|
||||
setDateTimeToCurrent(context, p);
|
||||
return 0;
|
||||
}else if( sqlite3IsNumber(zDate, &isRealNum, SQLITE_UTF8) ){
|
||||
double r;
|
||||
getValue(zDate, &r);
|
||||
}else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
|
||||
p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
|
||||
p->validJD = 1;
|
||||
return 0;
|
||||
@@ -571,7 +563,8 @@ static int parseModifier(const char *zMod, DateTime *p){
|
||||
** weekday N where 0==Sunday, 1==Monday, and so forth. If the
|
||||
** date is already on the appropriate weekday, this is a no-op.
|
||||
*/
|
||||
if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
|
||||
if( strncmp(z, "weekday ", 8)==0
|
||||
&& sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)
|
||||
&& (n=(int)r)==r && n>=0 && r<7 ){
|
||||
sqlite3_int64 Z;
|
||||
computeYMD_HMS(p);
|
||||
@@ -627,8 +620,11 @@ static int parseModifier(const char *zMod, DateTime *p){
|
||||
case '8':
|
||||
case '9': {
|
||||
double rRounder;
|
||||
n = getValue(z, &r);
|
||||
assert( n>=1 );
|
||||
for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
|
||||
if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
if( z[n]==':' ){
|
||||
/* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
|
||||
** specified number of hours, minutes, seconds, and fractional seconds
|
||||
|
||||
17
src/expr.c
17
src/expr.c
@@ -555,7 +555,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
||||
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
|
||||
** use it as the variable number */
|
||||
i64 i;
|
||||
int bOk = sqlite3Atoi64(&z[1], &i);
|
||||
int bOk = 0==sqlite3Atoi64(&z[1], &i, sqlite3Strlen30(&z[1]), SQLITE_UTF8);
|
||||
pExpr->iColumn = (ynVar)i;
|
||||
testcase( i==0 );
|
||||
testcase( i==1 );
|
||||
@@ -1918,7 +1918,7 @@ static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
|
||||
if( ALWAYS(z!=0) ){
|
||||
double value;
|
||||
char *zV;
|
||||
sqlite3AtoF(z, &value);
|
||||
sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
|
||||
assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
|
||||
if( negateFlag ) value = -value;
|
||||
zV = dup8bytes(v, (char*)&value);
|
||||
@@ -1932,9 +1932,7 @@ static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
|
||||
** Generate an instruction that will put the integer describe by
|
||||
** text z[0..n-1] into register iMem.
|
||||
**
|
||||
** The z[] string will probably not be zero-terminated. But the
|
||||
** z[n] character is guaranteed to be something that does not look
|
||||
** like the continuation of the number.
|
||||
** Expr.u.zToken is always UTF8 and zero-terminated.
|
||||
*/
|
||||
static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
@@ -1943,13 +1941,14 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
|
||||
if( negFlag ) i = -i;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i, iMem);
|
||||
}else{
|
||||
int c;
|
||||
i64 value;
|
||||
const char *z = pExpr->u.zToken;
|
||||
assert( z!=0 );
|
||||
if( sqlite3FitsIn64Bits(z, negFlag) ){
|
||||
i64 value;
|
||||
c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
|
||||
if( c==0 || (c==2 && negFlag) ){
|
||||
char *zV;
|
||||
sqlite3Atoi64(z, &value);
|
||||
if( negFlag ) value = -value;
|
||||
if( negFlag ){ value = -value; }
|
||||
zV = dup8bytes(v, (char*)&value);
|
||||
sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
|
||||
}else{
|
||||
|
||||
@@ -285,7 +285,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
sqlite3AtoF(zBuf, &r);
|
||||
sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
|
||||
sqlite3_free(zBuf);
|
||||
}
|
||||
sqlite3_result_double(context, r);
|
||||
|
||||
@@ -587,7 +587,7 @@ void sqlite3Pragma(
|
||||
Pager *pPager = sqlite3BtreePager(pDb->pBt);
|
||||
i64 iLimit = -2;
|
||||
if( zRight ){
|
||||
sqlite3Atoi64(zRight, &iLimit);
|
||||
sqlite3Atoi64(zRight, &iLimit, 1000000, SQLITE_UTF8);
|
||||
if( iLimit<-1 ) iLimit = -1;
|
||||
}
|
||||
iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
|
||||
|
||||
@@ -2507,7 +2507,6 @@ int sqlite3CantopenError(int);
|
||||
** Internal function prototypes
|
||||
*/
|
||||
int sqlite3StrICmp(const char *, const char *);
|
||||
int sqlite3IsNumber(const char*, int*, u8);
|
||||
int sqlite3Strlen30(const char*);
|
||||
#define sqlite3StrNICmp sqlite3_strnicmp
|
||||
|
||||
@@ -2827,9 +2826,8 @@ int sqlite3FixSelect(DbFixer*, Select*);
|
||||
int sqlite3FixExpr(DbFixer*, Expr*);
|
||||
int sqlite3FixExprList(DbFixer*, ExprList*);
|
||||
int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
|
||||
int sqlite3AtoF(const char *z, double*);
|
||||
int sqlite3AtoF(const char *z, double*, int, u8);
|
||||
int sqlite3GetInt32(const char *, int*);
|
||||
int sqlite3FitsIn64Bits(const char *, int);
|
||||
int sqlite3Utf16ByteLen(const void *pData, int nChar);
|
||||
int sqlite3Utf8CharLen(const char *pData, int nByte);
|
||||
int sqlite3Utf8Read(const u8*, const u8**);
|
||||
@@ -2875,7 +2873,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 sqlite3Atoi64(const char*, i64*, int, u8);
|
||||
void sqlite3Error(sqlite3*, int, const char*,...);
|
||||
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
|
||||
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
|
||||
|
||||
@@ -1235,7 +1235,7 @@ static int sqlite3_mprintf_int64(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for(i=2; i<5; i++){
|
||||
if( !sqlite3Atoi64(argv[i], &a[i-2]) ){
|
||||
if( sqlite3Atoi64(argv[i], &a[i-2], 1000000, SQLITE_UTF8) ){
|
||||
Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
248
src/util.c
248
src/util.c
@@ -238,121 +238,111 @@ int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if z is a pure numeric string. Return FALSE and leave
|
||||
** *realnum unchanged if the string contains any character which is not
|
||||
** part of a number.
|
||||
** The string z[] is an text representation of a real number.
|
||||
** Convert this string to a double and write it into *pResult.
|
||||
**
|
||||
** If the string is pure numeric, set *realnum to TRUE if the string
|
||||
** contains the '.' character or an "E+000" style exponentiation suffix.
|
||||
** Otherwise set *realnum to FALSE. Note that just becaue *realnum is
|
||||
** false does not mean that the number can be successfully converted into
|
||||
** an integer - it might be too big.
|
||||
** The string z[] is length bytes in length (bytes, not characters) and
|
||||
** uses the encoding enc. The string is not necessarily zero-terminated.
|
||||
**
|
||||
** An empty string is considered non-numeric.
|
||||
** 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:
|
||||
**
|
||||
** [+-]digits[E[+-]digits]
|
||||
** [+-]digits.[digits][E[+-]digits]
|
||||
** [+-].digits[E[+-]digits]
|
||||
**
|
||||
** Leading and trailing whitespace is ignored for the purpose of determining
|
||||
** validity.
|
||||
**
|
||||
** If some prefix of the input string is a valid number, this routine
|
||||
** returns FALSE but it still converts the prefix and writes the result
|
||||
** into *pResult.
|
||||
*/
|
||||
int sqlite3IsNumber(const char *z, int *realnum, u8 enc){
|
||||
int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
int incr = (enc==SQLITE_UTF8?1:2);
|
||||
if( enc==SQLITE_UTF16BE ) z++;
|
||||
if( *z=='-' || *z=='+' ) z += incr;
|
||||
if( !sqlite3Isdigit(*z) ){
|
||||
return 0;
|
||||
}
|
||||
z += incr;
|
||||
*realnum = 0;
|
||||
while( sqlite3Isdigit(*z) ){ z += incr; }
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
if( *z=='.' ){
|
||||
z += incr;
|
||||
if( !sqlite3Isdigit(*z) ) return 0;
|
||||
while( sqlite3Isdigit(*z) ){ z += incr; }
|
||||
*realnum = 1;
|
||||
}
|
||||
if( *z=='e' || *z=='E' ){
|
||||
z += incr;
|
||||
if( *z=='+' || *z=='-' ) z += incr;
|
||||
if( !sqlite3Isdigit(*z) ) return 0;
|
||||
while( sqlite3Isdigit(*z) ){ z += incr; }
|
||||
*realnum = 1;
|
||||
}
|
||||
#endif
|
||||
return *z==0;
|
||||
}
|
||||
|
||||
/*
|
||||
** The string z[] is an ASCII representation of a real number.
|
||||
** Convert this string to a double.
|
||||
**
|
||||
** This routine assumes that z[] really is a valid number. If it
|
||||
** is not, the result is undefined.
|
||||
**
|
||||
** This routine is used instead of the library atof() function because
|
||||
** the library atof() might want to use "," as the decimal point instead
|
||||
** of "." depending on how locale is set. But that would cause problems
|
||||
** for SQL. So this routine always uses "." regardless of locale.
|
||||
*/
|
||||
int sqlite3AtoF(const char *z, double *pResult){
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
const char *zBegin = z;
|
||||
const char *zEnd = z + length;
|
||||
/* sign * significand * (10 ^ (esign * exponent)) */
|
||||
int sign = 1; /* sign of significand */
|
||||
i64 s = 0; /* significand */
|
||||
int d = 0; /* adjust exponent for shifting decimal point */
|
||||
int esign = 1; /* sign of exponent */
|
||||
int e = 0; /* exponent */
|
||||
int eValid = 1; /* True exponent is either not used or is well-formed */
|
||||
double result;
|
||||
int nDigits = 0;
|
||||
|
||||
*pResult = 0.0; /* Default return value, in case of an error */
|
||||
|
||||
if( enc==SQLITE_UTF16BE ) z++;
|
||||
|
||||
/* skip leading spaces */
|
||||
while( sqlite3Isspace(*z) ) z++;
|
||||
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
|
||||
if( z>=zEnd ) return 0;
|
||||
|
||||
/* get sign of significand */
|
||||
if( *z=='-' ){
|
||||
sign = -1;
|
||||
z++;
|
||||
z+=incr;
|
||||
}else if( *z=='+' ){
|
||||
z++;
|
||||
z+=incr;
|
||||
}
|
||||
|
||||
/* skip leading zeroes */
|
||||
while( z[0]=='0' ) z++, nDigits++;
|
||||
while( z<zEnd && z[0]=='0' ) z+=incr, nDigits++;
|
||||
|
||||
/* copy max significant digits to significand */
|
||||
while( sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
|
||||
while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
|
||||
s = s*10 + (*z - '0');
|
||||
z++, nDigits++;
|
||||
z+=incr, nDigits++;
|
||||
}
|
||||
|
||||
/* skip non-significant significand digits
|
||||
** (increase exponent by d to shift decimal left) */
|
||||
while( sqlite3Isdigit(*z) ) z++, nDigits++, d++;
|
||||
while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++, d++;
|
||||
if( z>=zEnd ) goto do_atof_calc;
|
||||
|
||||
/* if decimal point is present */
|
||||
if( *z=='.' ){
|
||||
z++;
|
||||
z+=incr;
|
||||
/* copy digits from after decimal to significand
|
||||
** (decrease exponent by d to shift decimal right) */
|
||||
while( sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
|
||||
while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
|
||||
s = s*10 + (*z - '0');
|
||||
z++, nDigits++, d--;
|
||||
z+=incr, nDigits++, d--;
|
||||
}
|
||||
/* skip non-significant digits */
|
||||
while( sqlite3Isdigit(*z) ) z++, nDigits++;
|
||||
while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++;
|
||||
}
|
||||
if( z>=zEnd ) goto do_atof_calc;
|
||||
|
||||
/* if exponent is present */
|
||||
if( *z=='e' || *z=='E' ){
|
||||
z++;
|
||||
z+=incr;
|
||||
eValid = 0;
|
||||
if( z>=zEnd ) goto do_atof_calc;
|
||||
/* get sign of exponent */
|
||||
if( *z=='-' ){
|
||||
esign = -1;
|
||||
z++;
|
||||
z+=incr;
|
||||
}else if( *z=='+' ){
|
||||
z++;
|
||||
z+=incr;
|
||||
}
|
||||
/* copy digits to exponent */
|
||||
while( sqlite3Isdigit(*z) ){
|
||||
while( z<zEnd && sqlite3Isdigit(*z) ){
|
||||
e = e*10 + (*z - '0');
|
||||
z++;
|
||||
z+=incr;
|
||||
eValid = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip trailing spaces */
|
||||
if( nDigits && eValid ){
|
||||
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
|
||||
}
|
||||
|
||||
do_atof_calc:
|
||||
/* adjust exponent by d, and update sign */
|
||||
e = (e*esign) + d;
|
||||
if( e<0 ) {
|
||||
@@ -411,10 +401,10 @@ int sqlite3AtoF(const char *z, double *pResult){
|
||||
/* store the result */
|
||||
*pResult = result;
|
||||
|
||||
/* return number of characters used */
|
||||
return (int)(z - zBegin);
|
||||
/* return true if number and no extra non-whitespace chracters after */
|
||||
return z>=zEnd && nDigits>0 && eValid;
|
||||
#else
|
||||
return sqlite3Atoi64(z, pResult);
|
||||
return !sqlite3Atoi64(z, pResult, length, enc);
|
||||
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
||||
}
|
||||
|
||||
@@ -422,20 +412,26 @@ int sqlite3AtoF(const char *z, double *pResult){
|
||||
** 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.
|
||||
** Note that zNum must contain exactly 19 characters.
|
||||
**
|
||||
** 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")
|
||||
** compare2pow63("9223372036854775800", 1)
|
||||
**
|
||||
** will return -8.
|
||||
*/
|
||||
static int compare2pow63(const char *zNum){
|
||||
int c;
|
||||
c = memcmp(zNum,"922337203685477580",18)*10;
|
||||
static int compare2pow63(const char *zNum, int incr){
|
||||
int c = 0;
|
||||
int i;
|
||||
/* 012345678901234567 */
|
||||
const char *pow63 = "922337203685477580";
|
||||
for(i=0; c==0 && i<18; i++){
|
||||
c = (zNum[i*incr]-pow63[i])*10;
|
||||
}
|
||||
if( c==0 ){
|
||||
c = zNum[18] - '8';
|
||||
c = zNum[18*incr] - '8';
|
||||
testcase( c==(-1) );
|
||||
testcase( c==0 );
|
||||
testcase( c==(+1) );
|
||||
@@ -445,94 +441,60 @@ static int compare2pow63(const char *zNum){
|
||||
|
||||
|
||||
/*
|
||||
** 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.
|
||||
** Convert zNum to a 64-bit signed integer and write
|
||||
** the value of the integer into *pNum.
|
||||
** If zNum is exactly 9223372036854665808, return 2.
|
||||
** This is a special case as the context will determine
|
||||
** if it is too big (used as a negative).
|
||||
** If zNum is not an integer or is an integer that
|
||||
** is too large to be expressed with 64 bits,
|
||||
** then return 1. Otherwise return 0.
|
||||
**
|
||||
** 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.
|
||||
** length is the number of bytes in the string (bytes, not characters).
|
||||
** The string is not necessarily zero-terminated. The encoding is
|
||||
** given by enc.
|
||||
*/
|
||||
int sqlite3Atoi64(const char *zNum, i64 *pNum){
|
||||
int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
|
||||
int incr = (enc==SQLITE_UTF8?1:2);
|
||||
i64 v = 0;
|
||||
int neg;
|
||||
int i, c;
|
||||
int neg = 0; /* assume positive */
|
||||
int i;
|
||||
int c = 0;
|
||||
const char *zStart;
|
||||
while( sqlite3Isspace(*zNum) ) zNum++;
|
||||
const char *zEnd = zNum + length;
|
||||
if( enc==SQLITE_UTF16BE ) zNum++;
|
||||
while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
|
||||
if( zNum>=zEnd ) goto do_atoi_calc;
|
||||
if( *zNum=='-' ){
|
||||
neg = 1;
|
||||
zNum++;
|
||||
zNum+=incr;
|
||||
}else if( *zNum=='+' ){
|
||||
neg = 0;
|
||||
zNum++;
|
||||
}else{
|
||||
neg = 0;
|
||||
zNum+=incr;
|
||||
}
|
||||
do_atoi_calc:
|
||||
zStart = zNum;
|
||||
while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */
|
||||
for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
|
||||
while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */
|
||||
for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
|
||||
v = v*10 + c - '0';
|
||||
}
|
||||
*pNum = neg ? -v : v;
|
||||
testcase( i==18 );
|
||||
testcase( i==19 );
|
||||
testcase( i==20 );
|
||||
if( c!=0 || (i==0 && zStart==zNum) || i>19 ){
|
||||
if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr ){
|
||||
/* 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 */
|
||||
** than 19 digits (thus guaranteeing that it is too large) */
|
||||
return 1;
|
||||
}else if( i<19*incr ){
|
||||
/* Less than 19 digits, so we know that it fits in 64 bits */
|
||||
return 0;
|
||||
}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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The string zNum represents an unsigned integer. The zNum string
|
||||
** consists of one or more digit characters and is terminated by
|
||||
** a zero character. Any stray characters in zNum result in undefined
|
||||
** behavior.
|
||||
**
|
||||
** If the unsigned integer that zNum represents will fit in a
|
||||
** 64-bit signed integer, return TRUE. Otherwise return FALSE.
|
||||
**
|
||||
** If the negFlag parameter is true, that means that zNum really represents
|
||||
** a negative number. (The leading "-" is omitted from zNum.) This
|
||||
** parameter is needed to determine a boundary case. A string
|
||||
** of "9223373036854775808" returns false if negFlag is false or true
|
||||
** if negFlag is true.
|
||||
**
|
||||
** Leading zeros are ignored.
|
||||
*/
|
||||
int sqlite3FitsIn64Bits(const char *zNum, int negFlag){
|
||||
int i;
|
||||
int neg = 0;
|
||||
|
||||
assert( zNum[0]>='0' && zNum[0]<='9' ); /* zNum is an unsigned number */
|
||||
|
||||
if( negFlag ) neg = 1-neg;
|
||||
while( *zNum=='0' ){
|
||||
zNum++; /* Skip leading zeros. Ticket #2454 */
|
||||
}
|
||||
for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); }
|
||||
testcase( i==18 );
|
||||
testcase( i==19 );
|
||||
testcase( i==20 );
|
||||
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;
|
||||
** is 2^63. Return 1 if to large */
|
||||
c=compare2pow63(zNum, incr);
|
||||
if( c==0 && neg==0 ) return 2; /* too big, exactly 9223372036854665808 */
|
||||
return c<neg ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
42
src/vdbe.c
42
src/vdbe.c
@@ -249,31 +249,17 @@ static VdbeCursor *allocateCursor(
|
||||
*/
|
||||
static void applyNumericAffinity(Mem *pRec){
|
||||
if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
|
||||
int realnum;
|
||||
double rValue;
|
||||
i64 iValue;
|
||||
u8 enc = pRec->enc;
|
||||
sqlite3VdbeMemNulTerminate(pRec);
|
||||
if( (pRec->flags&MEM_Str) && sqlite3IsNumber(pRec->z, &realnum, enc) ){
|
||||
i64 value;
|
||||
char *zUtf8 = pRec->z;
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
if( enc!=SQLITE_UTF8 ){
|
||||
assert( pRec->db );
|
||||
zUtf8 = sqlite3Utf16to8(pRec->db, pRec->z, pRec->n, enc);
|
||||
if( !zUtf8 ) return;
|
||||
}
|
||||
#endif
|
||||
if( !realnum && sqlite3Atoi64(zUtf8, &value) ){
|
||||
pRec->u.i = value;
|
||||
MemSetTypeFlag(pRec, MEM_Int);
|
||||
if( (pRec->flags&MEM_Str)==0 ) return;
|
||||
if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
|
||||
if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
|
||||
pRec->u.i = iValue;
|
||||
pRec->flags |= MEM_Int;
|
||||
}else{
|
||||
sqlite3AtoF(zUtf8, &pRec->r);
|
||||
MemSetTypeFlag(pRec, MEM_Real);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
if( enc!=SQLITE_UTF8 ){
|
||||
sqlite3DbFree(pRec->db, zUtf8);
|
||||
}
|
||||
#endif
|
||||
pRec->r = rValue;
|
||||
pRec->flags |= MEM_Real;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1555,7 +1541,6 @@ case OP_MustBeInt: { /* jump, in1 */
|
||||
*/
|
||||
case OP_RealAffinity: { /* in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
memAboutToChange(p, pIn1);
|
||||
if( pIn1->flags & MEM_Int ){
|
||||
sqlite3VdbeMemRealify(pIn1);
|
||||
}
|
||||
@@ -1598,7 +1583,6 @@ case OP_ToText: { /* same as TK_TO_TEXT, in1 */
|
||||
*/
|
||||
case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
memAboutToChange(p, pIn1);
|
||||
if( pIn1->flags & MEM_Null ) break;
|
||||
if( (pIn1->flags & MEM_Blob)==0 ){
|
||||
applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
|
||||
@@ -1623,10 +1607,7 @@ case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */
|
||||
*/
|
||||
case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
memAboutToChange(p, pIn1);
|
||||
if( (pIn1->flags & (MEM_Null|MEM_Int|MEM_Real))==0 ){
|
||||
sqlite3VdbeMemNumerify(pIn1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_CAST */
|
||||
@@ -1642,7 +1623,6 @@ case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */
|
||||
*/
|
||||
case OP_ToInt: { /* same as TK_TO_INT, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
memAboutToChange(p, pIn1);
|
||||
if( (pIn1->flags & MEM_Null)==0 ){
|
||||
sqlite3VdbeMemIntegerify(pIn1);
|
||||
}
|
||||
@@ -1754,8 +1734,6 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
pIn3 = &aMem[pOp->p3];
|
||||
memAboutToChange(p, pIn1);
|
||||
memAboutToChange(p, pIn3);
|
||||
flags1 = pIn1->flags;
|
||||
flags3 = pIn3->flags;
|
||||
if( (pIn1->flags | pIn3->flags)&MEM_Null ){
|
||||
@@ -2378,7 +2356,6 @@ case OP_Affinity: {
|
||||
while( (cAff = *(zAffinity++))!=0 ){
|
||||
assert( pIn1 <= &p->aMem[p->nMem] );
|
||||
assert( memIsValid(pIn1) );
|
||||
memAboutToChange(p, pIn1);
|
||||
ExpandBlob(pIn1);
|
||||
applyAffinity(pIn1, cAff, encoding);
|
||||
pIn1++;
|
||||
@@ -2456,7 +2433,6 @@ case OP_MakeRecord: {
|
||||
for(pRec=pData0; pRec<=pLast; pRec++){
|
||||
assert( memIsValid(pRec) );
|
||||
if( zAffinity ){
|
||||
memAboutToChange(p, pRec);
|
||||
applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
|
||||
}
|
||||
if( pRec->flags&MEM_Zero && pRec->n>0 ){
|
||||
|
||||
@@ -368,13 +368,9 @@ i64 sqlite3VdbeIntValue(Mem *pMem){
|
||||
return doubleToInt64(pMem->r);
|
||||
}else if( flags & (MEM_Str|MEM_Blob) ){
|
||||
i64 value;
|
||||
pMem->flags |= MEM_Str;
|
||||
if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8)
|
||||
|| sqlite3VdbeMemNulTerminate(pMem) ){
|
||||
return 0;
|
||||
}
|
||||
assert( pMem->z );
|
||||
sqlite3Atoi64(pMem->z, &value);
|
||||
assert( pMem->z || pMem->n==0 );
|
||||
testcase( pMem->z==0 );
|
||||
sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
|
||||
return value;
|
||||
}else{
|
||||
return 0;
|
||||
@@ -404,7 +400,7 @@ double sqlite3VdbeRealValue(Mem *pMem){
|
||||
return (double)0;
|
||||
}
|
||||
assert( pMem->z );
|
||||
sqlite3AtoF(pMem->z, &val);
|
||||
sqlite3AtoF(pMem->z, &val, pMem->n, SQLITE_UTF8);
|
||||
return val;
|
||||
}else{
|
||||
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
|
||||
@@ -477,21 +473,19 @@ int sqlite3VdbeMemRealify(Mem *pMem){
|
||||
** as much of the string as we can and ignore the rest.
|
||||
*/
|
||||
int sqlite3VdbeMemNumerify(Mem *pMem){
|
||||
int rc;
|
||||
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 );
|
||||
if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){
|
||||
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
|
||||
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
||||
rc = sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8);
|
||||
if( rc ) return rc;
|
||||
rc = sqlite3VdbeMemNulTerminate(pMem);
|
||||
if( rc ) return rc;
|
||||
if( sqlite3Atoi64(pMem->z, &pMem->u.i) ){
|
||||
if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){
|
||||
MemSetTypeFlag(pMem, MEM_Int);
|
||||
}else{
|
||||
pMem->r = sqlite3VdbeRealValue(pMem);
|
||||
MemSetTypeFlag(pMem, MEM_Real);
|
||||
sqlite3VdbeIntegerAffinity(pMem);
|
||||
}
|
||||
}
|
||||
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
|
||||
pMem->flags &= ~(MEM_Str|MEM_Blob);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -1034,6 +1028,8 @@ int sqlite3ValueFromExpr(
|
||||
int op;
|
||||
char *zVal = 0;
|
||||
sqlite3_value *pVal = 0;
|
||||
int negInt = 1;
|
||||
const char *zNeg = "";
|
||||
|
||||
if( !pExpr ){
|
||||
*ppVal = 0;
|
||||
@@ -1051,13 +1047,24 @@ int sqlite3ValueFromExpr(
|
||||
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
|
||||
#endif
|
||||
|
||||
/* Handle negative integers in a single step. This is needed in the
|
||||
** case when the value is -9223372036854775808.
|
||||
*/
|
||||
if( op==TK_UMINUS
|
||||
&& (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){
|
||||
pExpr = pExpr->pLeft;
|
||||
op = pExpr->op;
|
||||
negInt = -1;
|
||||
zNeg = "-";
|
||||
}
|
||||
|
||||
if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
|
||||
pVal = sqlite3ValueNew(db);
|
||||
if( pVal==0 ) goto no_mem;
|
||||
if( ExprHasProperty(pExpr, EP_IntValue) ){
|
||||
sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue);
|
||||
sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
|
||||
}else{
|
||||
zVal = sqlite3DbStrDup(db, pExpr->u.zToken);
|
||||
zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
|
||||
if( zVal==0 ) goto no_mem;
|
||||
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
|
||||
if( op==TK_FLOAT ) pVal->type = SQLITE_FLOAT;
|
||||
@@ -1067,14 +1074,18 @@ int sqlite3ValueFromExpr(
|
||||
}else{
|
||||
sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
|
||||
}
|
||||
if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str;
|
||||
if( enc!=SQLITE_UTF8 ){
|
||||
sqlite3VdbeChangeEncoding(pVal, enc);
|
||||
}
|
||||
}else if( op==TK_UMINUS ) {
|
||||
/* This branch happens for multiple negative signs. Ex: -(-5) */
|
||||
if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){
|
||||
sqlite3VdbeMemNumerify(pVal);
|
||||
pVal->u.i = -1 * pVal->u.i;
|
||||
/* (double)-1 In case of SQLITE_OMIT_FLOATING_POINT... */
|
||||
pVal->r = (double)-1 * pVal->r;
|
||||
sqlite3ValueApplyAffinity(pVal, affinity, enc);
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_BLOB_LITERAL
|
||||
|
||||
@@ -84,7 +84,7 @@ for {set i 0} {$i<1000} {incr i} {
|
||||
datetest 2.3 {date('2003-10-22','weekday 0')} 2003-10-26
|
||||
datetest 2.4 {date('2003-10-22','weekday 1')} 2003-10-27
|
||||
datetest 2.4a {date('2003-10-22','weekday 1')} 2003-10-27
|
||||
datetest 2.4b {date('2003-10-22','weekday 1x')} 2003-10-27
|
||||
datetest 2.4b {date('2003-10-22','weekday 1x')} NULL
|
||||
datetest 2.4c {date('2003-10-22','weekday -1')} NULL
|
||||
datetest 2.4d {date('2003-10-22','weakday 1x')} NULL
|
||||
datetest 2.4e {date('2003-10-22','weekday ')} NULL
|
||||
|
||||
139
test/enc4.test
Normal file
139
test/enc4.test
Normal file
@@ -0,0 +1,139 @@
|
||||
# 2010 Sept 29
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The focus of
|
||||
# this file is testing the SQLite routines used for converting between the
|
||||
# various suported unicode encodings (UTF-8, UTF-16, UTF-16le and
|
||||
# UTF-16be).
|
||||
#
|
||||
# $Id: enc4.test,v 1.0 2010/09/29 08:29:32 shaneh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# If UTF16 support is disabled, ignore the tests in this file
|
||||
#
|
||||
ifcapable {!utf16} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
db close
|
||||
|
||||
# The three unicode encodings understood by SQLite.
|
||||
set encodings [list UTF-8 UTF-16le UTF-16be]
|
||||
|
||||
# initial value to use in SELECT
|
||||
set inits [list 1 1.0 1. 1e0]
|
||||
|
||||
# vals
|
||||
set vals [list\
|
||||
"922337203685477580792233720368547758079223372036854775807"\
|
||||
"100000000000000000000000000000000000000000000000000000000"\
|
||||
"1.0000000000000000000000000000000000000000000000000000000"\
|
||||
]
|
||||
|
||||
set i 1
|
||||
foreach enc $encodings {
|
||||
|
||||
file delete -force test.db
|
||||
sqlite3 db test.db
|
||||
db eval "PRAGMA encoding = \"$enc\""
|
||||
|
||||
do_test enc4-$i.1 {
|
||||
db eval {PRAGMA encoding}
|
||||
} $enc
|
||||
|
||||
set j 1
|
||||
foreach init $inits {
|
||||
|
||||
do_test enc4-$i.$j.2 {
|
||||
set S [sqlite3_prepare_v2 db "SELECT $init+?" -1 dummy]
|
||||
sqlite3_expired $S
|
||||
} {0}
|
||||
|
||||
set k 1
|
||||
foreach val $vals {
|
||||
for {set x 1} {$x<18} {incr x} {
|
||||
set part [expr $init + [string range $val 0 [expr $x-1]]]
|
||||
regsub {e\+0} $part {e+} part
|
||||
regsub {^1e} $part {1.0e} part
|
||||
|
||||
do_test enc4-$i.$j.$k.3.$x {
|
||||
sqlite3_reset $S
|
||||
sqlite3_bind_text $S 1 $val $x
|
||||
sqlite3_step $S
|
||||
sqlite3_column_text $S 0
|
||||
} [list $part]
|
||||
|
||||
do_test enc4-$i.$j.$k.4.$x {
|
||||
sqlite3_reset $S
|
||||
sqlite3_bind_text16 $S 1 [encoding convertto unicode $val] [expr $x*2]
|
||||
sqlite3_step $S
|
||||
sqlite3_column_text $S 0
|
||||
} [list $part]
|
||||
}
|
||||
|
||||
incr k
|
||||
}
|
||||
|
||||
do_test enc4-$i.$j.5 {
|
||||
sqlite3_finalize $S
|
||||
} {SQLITE_OK}
|
||||
|
||||
incr j
|
||||
}
|
||||
|
||||
db close
|
||||
incr i
|
||||
}
|
||||
|
||||
file delete -force test.db
|
||||
sqlite3 db test.db
|
||||
|
||||
do_test enc4-4.1 {
|
||||
db eval "select 1+1."
|
||||
} {2.0}
|
||||
|
||||
do_test enc4-4.2.1 {
|
||||
set S [sqlite3_prepare_v2 db "SELECT 1+1." -1 dummy]
|
||||
sqlite3_step $S
|
||||
sqlite3_column_text $S 0
|
||||
} {2.0}
|
||||
|
||||
do_test enc4-4.2.2 {
|
||||
sqlite3_finalize $S
|
||||
} {SQLITE_OK}
|
||||
|
||||
do_test enc4-4.3.1 {
|
||||
set S [sqlite3_prepare_v2 db "SELECT 1+?" -1 dummy]
|
||||
sqlite3_bind_text $S 1 "1." 2
|
||||
sqlite3_step $S
|
||||
sqlite3_column_text $S 0
|
||||
} {2.0}
|
||||
|
||||
do_test enc4-4.3.2 {
|
||||
sqlite3_finalize $S
|
||||
} {SQLITE_OK}
|
||||
|
||||
do_test enc4-4.4.1 {
|
||||
set S [sqlite3_prepare_v2 db "SELECT 1+?" -1 dummy]
|
||||
sqlite3_bind_text $S 1 "1.0" 2
|
||||
sqlite3_step $S
|
||||
sqlite3_column_text $S 0
|
||||
} {2.0}
|
||||
|
||||
do_test enc4-4.4.2 {
|
||||
sqlite3_finalize $S
|
||||
} {SQLITE_OK}
|
||||
|
||||
db close
|
||||
|
||||
finish_test
|
||||
@@ -290,7 +290,7 @@ ifcapable floatingpoint {
|
||||
test_expr expr-4.14 {r1='abc', r2='Bbc'} {r1>r2} 1
|
||||
test_expr expr-4.15 {r1='0', r2='0.0'} {r1==r2} 1
|
||||
test_expr expr-4.16 {r1='0.000', r2='0.0'} {r1==r2} 1
|
||||
test_expr expr-4.17 {r1=' 0.000', r2=' 0.0'} {r1==r2} 0
|
||||
test_expr expr-4.17 {r1=' 0.000', r2=' 0.0'} {r1==r2} 1
|
||||
test_expr expr-4.18 {r1='0.0', r2='abc'} {r1<r2} 1
|
||||
test_expr expr-4.19 {r1='0.0', r2='abc'} {r1==r2} 0
|
||||
test_expr expr-4.20 {r1='0.0', r2='abc'} {r1>r2} 0
|
||||
|
||||
@@ -532,10 +532,19 @@ do_test index-15.2 {
|
||||
INSERT INTO t1 VALUES('+',9);
|
||||
INSERT INTO t1 VALUES('+12347.E+02',10);
|
||||
INSERT INTO t1 VALUES('+12347E+02',11);
|
||||
SELECT b FROM t1 ORDER BY a;
|
||||
INSERT INTO t1 VALUES('+.125E+04',12);
|
||||
INSERT INTO t1 VALUES('-.125E+04',13);
|
||||
INSERT INTO t1 VALUES('.125E+0',14);
|
||||
INSERT INTO t1 VALUES('.125',15);
|
||||
SELECT b FROM t1 ORDER BY a, b;
|
||||
}
|
||||
} {8 5 2 1 3 6 11 9 10 4 7}
|
||||
integrity_check index-15.1
|
||||
} {13 14 15 12 8 5 2 1 3 6 10 11 9 4 7}
|
||||
do_test index-15.3 {
|
||||
execsql {
|
||||
SELECT b FROM t1 WHERE typeof(a) IN ('integer','real') ORDER BY b;
|
||||
}
|
||||
} {1 2 3 5 6 8 10 11 12 13 14 15}
|
||||
integrity_check index-15.4
|
||||
|
||||
# The following tests - index-16.* - test that when a table definition
|
||||
# includes qualifications that specify the same constraint twice only a
|
||||
|
||||
46
test/tkt-3998683a16.test
Normal file
46
test/tkt-3998683a16.test
Normal file
@@ -0,0 +1,46 @@
|
||||
# 2010 September 30
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file implements regression tests for SQLite library. Specifically,
|
||||
# it tests that ticket [3998683a16a7076e08f5585c1f4816414c8c653a] where in
|
||||
# floating point values with a decimal point at the beginning or end
|
||||
# of the mantissa are used.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_test tkt-3998683a16.1 {
|
||||
db eval {
|
||||
CREATE TABLE t1(x, y REAL);
|
||||
INSERT INTO t1 VALUES(1, '1.0');
|
||||
INSERT INTO t1 VALUES(2, '.125');
|
||||
INSERT INTO t1 VALUES(3, '123.');
|
||||
INSERT INTO t1 VALUES(4, '123.e+2');
|
||||
INSERT INTO t1 VALUES(5, '.125e+3');
|
||||
INSERT INTO t1 VALUES(6, '123e4');
|
||||
INSERT INTO t1 VALUES(11, ' 1.0');
|
||||
INSERT INTO t1 VALUES(12, ' .125');
|
||||
INSERT INTO t1 VALUES(13, ' 123.');
|
||||
INSERT INTO t1 VALUES(14, ' 123.e+2');
|
||||
INSERT INTO t1 VALUES(15, ' .125e+3');
|
||||
INSERT INTO t1 VALUES(16, ' 123e4');
|
||||
INSERT INTO t1 VALUES(21, '1.0 ');
|
||||
INSERT INTO t1 VALUES(22, '.125 ');
|
||||
INSERT INTO t1 VALUES(23, '123. ');
|
||||
INSERT INTO t1 VALUES(24, '123.e+2 ');
|
||||
INSERT INTO t1 VALUES(25, '.125e+3 ');
|
||||
INSERT INTO t1 VALUES(26, '123e4 ');
|
||||
SELECT x FROM t1 WHERE typeof(y)=='real' ORDER BY x;
|
||||
}
|
||||
} {1 2 3 4 5 6 11 12 13 14 15 16 21 22 23 24 25 26}
|
||||
|
||||
finish_test
|
||||
67
test/tkt-8454a207b9.test
Normal file
67
test/tkt-8454a207b9.test
Normal file
@@ -0,0 +1,67 @@
|
||||
# 2010 September 30
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file implements regression tests for SQLite library. Specifically,
|
||||
# it tests that ticket [8454a207b9fd2243c4c6b7a73f67ea0315717c1a]. Verify
|
||||
# that a negative default value on an added text column actually comes
|
||||
# out negative.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_test tkt-8454a207b9.1 {
|
||||
db eval {
|
||||
CREATE TABLE t1(a);
|
||||
INSERT INTO t1 VALUES(1);
|
||||
ALTER TABLE t1 ADD COLUMN b TEXT DEFAULT -123.0;
|
||||
SELECT b, typeof(b) FROM t1;
|
||||
}
|
||||
} {-123.0 text}
|
||||
do_test tkt-8454a207b9.2 {
|
||||
db eval {
|
||||
ALTER TABLE t1 ADD COLUMN c TEXT DEFAULT -123.5;
|
||||
SELECT c, typeof(c) FROM t1;
|
||||
}
|
||||
} {-123.5 text}
|
||||
do_test tkt-8454a207b9.3 {
|
||||
db eval {
|
||||
ALTER TABLE t1 ADD COLUMN d TEXT DEFAULT -'hello';
|
||||
SELECT d, typeof(d) FROM t1;
|
||||
}
|
||||
} {0 text}
|
||||
do_test tkt-8454a207b9.4 {
|
||||
db eval {
|
||||
ALTER TABLE t1 ADD COLUMN e DEFAULT -123.0;
|
||||
SELECT e, typeof(e) FROM t1;
|
||||
}
|
||||
} {-123 integer}
|
||||
do_test tkt-8454a207b9.5 {
|
||||
db eval {
|
||||
ALTER TABLE t1 ADD COLUMN f DEFAULT -123.5;
|
||||
SELECT f, typeof(f) FROM t1;
|
||||
}
|
||||
} {-123.5 real}
|
||||
do_test tkt-8454a207b9.6 {
|
||||
db eval {
|
||||
ALTER TABLE t1 ADD COLUMN g DEFAULT -9223372036854775808;
|
||||
SELECT g, typeof(g) FROM t1;
|
||||
}
|
||||
} {-9223372036854775808 integer}
|
||||
do_test tkt-8454a207b9.7 {
|
||||
db eval {
|
||||
ALTER TABLE t1 ADD COLUMN h DEFAULT 9223372036854775807;
|
||||
SELECT h, typeof(h) FROM t1;
|
||||
}
|
||||
} {9223372036854775807 integer}
|
||||
|
||||
|
||||
finish_test
|
||||
Reference in New Issue
Block a user