diff --git a/manifest b/manifest index 7d3ff18c0f..e65112dc53 100644 --- a/manifest +++ b/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----- diff --git a/manifest.uuid b/manifest.uuid index 4df93e6923..031937a730 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0a4528d629018eae0b0f3e173ebda666c2e2d502 \ No newline at end of file +07ee080ec4527fd2191f41231208da66b3f6b955 \ No newline at end of file diff --git a/src/date.c b/src/date.c index 04ffbe23ce..b81049aa65 100644 --- a/src/date.c +++ b/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,8 +563,9 @@ 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 - && (n=(int)r)==r && n>=0 && r<7 ){ + 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); p->validTZ = 0; @@ -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 diff --git a/src/expr.c b/src/expr.c index 2474635218..41be16260f 100644 --- a/src/expr.c +++ b/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{ diff --git a/src/func.c b/src/func.c index 6119e4a956..8b7086f600 100644 --- a/src/func.c +++ b/src/func.c @@ -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); diff --git a/src/pragma.c b/src/pragma.c index 0f3ce3c524..362e77f29e 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -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); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index adf6ce8a28..8515efcc49 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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 **); diff --git a/src/test1.c b/src/test1.c index 8e827f07ba..af83d5cb45 100644 --- a/src/test1.c +++ b/src/test1.c @@ -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; } diff --git a/src/util.c b/src/util.c index 6b30b311ae..4b603b3086 100644 --- a/src/util.c +++ b/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 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 ) 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 ) 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 ) 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 && 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 ) 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='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]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)='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)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); - }else{ - sqlite3AtoF(zUtf8, &pRec->r); - MemSetTypeFlag(pRec, MEM_Real); - } -#ifndef SQLITE_OMIT_UTF16 - if( enc!=SQLITE_UTF8 ){ - sqlite3DbFree(pRec->db, zUtf8); - } -#endif + 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{ + 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); - } + 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 ){ diff --git a/src/vdbemem.c b/src/vdbemem.c index 0b7c70d3bd..598cb9d661 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -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 ); - 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) ){ - MemSetTypeFlag(pMem, MEM_Int); - }else{ - pMem->r = sqlite3VdbeRealValue(pMem); - MemSetTypeFlag(pMem, MEM_Real); - sqlite3VdbeIntegerAffinity(pMem); + 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) ); + 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 diff --git a/test/date.test b/test/date.test index 29b5ed4d1d..9bfec12626 100644 --- a/test/date.test +++ b/test/date.test @@ -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 diff --git a/test/enc4.test b/test/enc4.test new file mode 100644 index 0000000000..de2a1b88d0 --- /dev/null +++ b/test/enc4.test @@ -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 diff --git a/test/expr.test b/test/expr.test index 87ee8ed3ca..140ab8d8b3 100644 --- a/test/expr.test +++ b/test/expr.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'} {r1r2} 0 diff --git a/test/index.test b/test/index.test index a278ac8889..0a41a6de3e 100644 --- a/test/index.test +++ b/test/index.test @@ -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 diff --git a/test/tkt-3998683a16.test b/test/tkt-3998683a16.test new file mode 100644 index 0000000000..919dc23368 --- /dev/null +++ b/test/tkt-3998683a16.test @@ -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 diff --git a/test/tkt-8454a207b9.test b/test/tkt-8454a207b9.test new file mode 100644 index 0000000000..88a8614f82 --- /dev/null +++ b/test/tkt-8454a207b9.test @@ -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