Improved resolution of large integer values in "CAST(x AS NUMERIC)".

FossilOrigin-Name: 7f2bd4ff45fba29528c18cac6da983bd9b164303525d3965056f5b40f85dc83f
This commit is contained in:
drh 2017-09-20 10:47:10 +00:00
parent 9a243e69c2
commit 84d4f1a328
8 changed files with 91 additions and 38 deletions

View File

@ -1,5 +1,5 @@
C Updates\sto\sthe\s"lemon.html"\sdocument\sreceived\sfrom\sAndy\sGoth.
D 2017-09-20T09:09:34.192
C Improved\sresolution\sof\slarge\sinteger\svalues\sin\s"CAST(x\sAS\sNUMERIC)".
D 2017-09-20T10:47:10.365
F Makefile.in 4bc36d913c2e3e2d326d588d72f618ac9788b2fd4b7efda61102611a6495c3ff
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 6033b51b6aea702ea059f6ab2d47b1d3cef648695f787247dd4fb395fe60673f
@ -411,7 +411,7 @@ F src/ctime.c ff1be3eed7bdd75aaca61ca8dc848f7c9f850ef2fb9cb56f2734e922a098f9c0
F src/date.c 48f743d88bbe88f848532d333cca84f26e52a4f217e86f86be7fc1b919c33d74
F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720
F src/delete.c 21a5f1812fdb599e9f7afb9f650bdabab60a3afd51d7e94e539c982f647b0023
F src/expr.c 38a225057f5b7d6a2bc403d7a5d3a67f59ee57b73fe7c546221e3c53202a3731
F src/expr.c 82fedd57c8ce9e7dc16a003ad4cd863308787d5b5cbd0f83263b37805a56319c
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 5ff2c895fe087756d8085dc1a9bc229b5670e2a65c3929dd87c71e43649af333
F src/func.c b4d259af627e3cd9510cf08db37f0bcc88b1887c735169c74490c3739d5cf5c6
@ -423,7 +423,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c d2d1bf12d2b5382450620d7cede84c7ffe57e6a89fa9a908f1aba68df2731cd9
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
F src/loadext.c 20865b183bb8a3723d59cf1efffc3c50217eb452c1021d077b908c94da26b0b2
F src/main.c 34a58563358fe40979186124d1a3614b9a00c833124d7ebfa8e5d604ed1d2521
F src/main.c 1c2307a9f7e3183232a2d049881026fe43bf25659857cc11a9a44898accd3200
F src/malloc.c a02c9e69bc76bee0f639416b947a946412890b606301454727feadcb313536d6
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@ -524,15 +524,15 @@ F src/treeview.c 2ee4a5dada213d5ab08a742af5c876cee6f1aaae65f10a61923f3fb63846afe
F src/trigger.c 48e0f7ed6749ce4d50a695e09e20ce9cf84ecabf2691852c965a51e0b620eccc
F src/update.c 5404be9e840717323a69209190cdbc9d0d34adaedaaf1d1a1069babf2c4171c0
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
F src/util.c ece10cb34b4a62cbb3aab8d711b67e93a2765e0b81d0f72458cb801a3ac60703
F src/util.c 5168013cfd937a695d23cce8c67cb07a3dda242d4cb812530ba1148b88e0f159
F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739
F src/vdbe.c 0a0ef7f0759ee4c3ed5ff0c6e9641216d4b31ebb0fea9a7b5a9c4a86ce875ff3
F src/vdbe.c 2664b89eb243c24bd8dd66a7a13b04b5c83f41897dc80266ad13fed4bb09966c
F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97
F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9
F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1
F src/vdbeaux.c 3be977a032e54fe46cb1b1f3ba62158438b0cc93e091f6feca7742d20dad3203
F src/vdbeblob.c 635a79b60340a6a14a622ea8dcb081f0a66b1ac3836870c587f232eec08c0286
F src/vdbemem.c 2f9d672af5260f0145787e1dc2c6985414987cc0dc575133a0dc17dda767d868
F src/vdbemem.c 08f89979c4b359483acb21b044d8e47db55f071ca4326e8bfdca5ac4cb5770ac
F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
F src/vdbetrace.c 48e11ebe040c6b41d146abed2602e3d00d621d7ebe4eb29b0a0f1617fd3c2f6c
F src/vtab.c f1d5c23132fb0247af3e86146404112283ddedb6c518de0d4edc91cfb36970ef
@ -732,7 +732,7 @@ F test/e_createtable.test d4c6059d44dcd4b636de9aae322766062b471844
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5
F test/e_expr.test 146deba180273d19e3bf9f6b45f4e50094c64c7ec4756ea72f79dda25818eb17
F test/e_expr.test ca8896601ade1e27c6559614c7f32c63d44636fdfa720436a160f09b8bf66c89
F test/e_fkey.test dcdc6ad26b1d4f07636208de4c1c22aae7c0597a685a6c10fe6da91f3191dd96
F test/e_fts3.test 8cf40550bb088a6aa187c818c00fabe26ef82900a4cd5c66b427ccafe28bedaa
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
@ -1655,7 +1655,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 1b2de41453ac33de82f9cd6cbb92eee4fe184fb282c27e5efa5243c8cb239630
R e0e8cf7279386534b02109d8fa18ad99
P 5b2002f3df1902aaa571a0efd01ab8bae7f4d37ac4819cc51595277f4de93433
R 219c5c95f432e38325a9c8586b5b2761
U drh
Z 86920861ac015f347841db4c53c64a7b
Z e4dde272cb6c1ca1520bca8de194c744

View File

@ -1 +1 @@
5b2002f3df1902aaa571a0efd01ab8bae7f4d37ac4819cc51595277f4de93433
7f2bd4ff45fba29528c18cac6da983bd9b164303525d3965056f5b40f85dc83f

View File

@ -3076,7 +3076,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
const char *z = pExpr->u.zToken;
assert( z!=0 );
c = sqlite3DecOrHexToI64(z, &value);
if( c==1 || (c==2 && !negFlag) || (negFlag && value==SMALLEST_INT64)){
if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){
#ifdef SQLITE_OMIT_FLOATING_POINT
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
#else
@ -3090,7 +3090,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
}
#endif
}else{
if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
if( negFlag ){ value = c==3 ? SMALLEST_INT64 : -value; }
sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64);
}
}

View File

@ -3942,7 +3942,7 @@ sqlite3_int64 sqlite3_uri_int64(
){
const char *z = sqlite3_uri_parameter(zFilename, zParam);
sqlite3_int64 v;
if( z && sqlite3DecOrHexToI64(z, &v)==SQLITE_OK ){
if( z && sqlite3DecOrHexToI64(z, &v)==0 ){
bDflt = v;
}
return bDflt;

View File

@ -557,16 +557,12 @@ static int compare2pow63(const char *zNum, int incr){
** Convert zNum to a 64-bit signed integer. zNum must be decimal. This
** routine does *not* accept hexadecimal notation.
**
** If the zNum value is representable as a 64-bit twos-complement
** integer, then write that value into *pNum and return 0.
** Returns:
**
** If zNum is exactly 9223372036854775808, return 2. This special
** case is broken out because while 9223372036854775808 cannot be a
** signed 64-bit integer, its negative -9223372036854775808 can be.
**
** If zNum is too big for a 64-bit integer and is not
** 9223372036854775808 or if zNum contains any non-numeric text,
** then return 1.
** 0 Successful transformation. Fits in a 64-bit signed integer.
** 1 Excess text after the integer value
** 2 Integer too large for a 64-bit signed integer or is malformed
** 3 Special case of 9223372036854775808
**
** length is the number of bytes in the string (bytes, not characters).
** The string is not necessarily zero-terminated. The encoding is
@ -579,6 +575,7 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
int i;
int c = 0;
int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
int rc; /* Baseline return code */
const char *zStart;
const char *zEnd = zNum + length;
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
@ -618,31 +615,35 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
testcase( i==20 );
if( &zNum[i]<zEnd /* Extra bytes at the end */
|| (i==0 && zStart==zNum) /* No digits */
|| i>19*incr /* Too many digits */
|| nonNum /* UTF16 with high-order bytes non-zero */
){
rc = 1;
}else{
rc = 0;
}
if( i>19*incr ){ /* Too many digits */
/* zNum is empty or contains non-numeric text or is longer
** than 19 digits (thus guaranteeing that it is too large) */
return 1;
return 2;
}else if( i<19*incr ){
/* Less than 19 digits, so we know that it fits in 64 bits */
assert( u<=LARGEST_INT64 );
return 0;
return rc;
}else{
/* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */
c = compare2pow63(zNum, incr);
if( c<0 ){
/* zNum is less than 9223372036854775808 so it fits */
assert( u<=LARGEST_INT64 );
return 0;
return rc;
}else if( c>0 ){
/* zNum is greater than 9223372036854775808 so it overflows */
return 1;
return 2;
}else{
/* zNum is exactly 9223372036854775808. Fits if negative. The
** special case 2 overflow if positive */
assert( u-1==LARGEST_INT64 );
return neg ? 0 : 2;
return neg ? rc : 3;
}
}
}
@ -655,8 +656,9 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
** Returns:
**
** 0 Successful transformation. Fits in a 64-bit signed integer.
** 1 Integer too large for a 64-bit signed integer or is malformed
** 2 Special case of 9223372036854775808
** 1 Excess text after the integer value
** 2 Integer too large for a 64-bit signed integer or is malformed
** 3 Special case of 9223372036854775808
*/
int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
#ifndef SQLITE_OMIT_HEX_INTEGER
@ -670,7 +672,7 @@ int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
u = u*16 + sqlite3HexToInt(z[k]);
}
memcpy(pOut, &u, 8);
return (z[k]==0 && k-i<=16) ? 0 : 1;
return (z[k]==0 && k-i<=16) ? 0 : 2;
}else
#endif /* SQLITE_OMIT_HEX_INTEGER */
{

View File

@ -354,7 +354,7 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){
return 0;
}
if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){
if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==0 ){
return MEM_Int;
}
return MEM_Real;

View File

@ -597,14 +597,21 @@ int sqlite3VdbeMemRealify(Mem *pMem){
*/
int sqlite3VdbeMemNumerify(Mem *pMem){
if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){
int rc;
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) ){
rc = sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc);
if( rc==0 ){
MemSetTypeFlag(pMem, MEM_Int);
}else{
pMem->u.r = sqlite3VdbeRealValue(pMem);
MemSetTypeFlag(pMem, MEM_Real);
sqlite3VdbeIntegerAffinity(pMem);
i64 i = pMem->u.i;
sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
if( rc==1 && pMem->u.r==(double)i ){
pMem->u.i = i;
MemSetTypeFlag(pMem, MEM_Int);
}else{
MemSetTypeFlag(pMem, MEM_Real);
}
}
}
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );

View File

@ -1663,6 +1663,50 @@ do_expr_test e_expr-32.2.3 {
do_expr_test e_expr-32.2.4 {
CAST(9223372036854775807 AS NUMERIC)
} integer 9223372036854775807
do_expr_test e_expr-32.2.5 {
CAST('9223372036854775807 ' AS NUMERIC)
} integer 9223372036854775807
do_expr_test e_expr-32.2.6 {
CAST(' 9223372036854775807 ' AS NUMERIC)
} integer 9223372036854775807
do_expr_test e_expr-32.2.7 {
CAST(' ' AS NUMERIC)
} integer 0
do_execsql_test e_expr-32.2.8 {
WITH t1(x) AS (VALUES
('9000000000000000001'),
('9000000000000000001x'),
('9000000000000000001 '),
(' 9000000000000000001 '),
(' 9000000000000000001'),
(' 9000000000000000001.'),
('9223372036854775807'),
('9223372036854775807 '),
(' 9223372036854775807 '),
('9223372036854775808'),
(' 9223372036854775808 '),
('9223372036854775807.0'),
('9223372036854775807e+0'),
('-5.0'),
('-5e+0'))
SELECT typeof(CAST(x AS NUMERIC)), CAST(x AS NUMERIC)||'' FROM t1;
} [list \
integer 9000000000000000001 \
integer 9000000000000000001 \
integer 9000000000000000001 \
integer 9000000000000000001 \
integer 9000000000000000001 \
integer 9000000000000000001 \
integer 9223372036854775807 \
integer 9223372036854775807 \
integer 9223372036854775807 \
real 9.22337203685478e+18 \
real 9.22337203685478e+18 \
integer 9223372036854775807 \
integer 9223372036854775807 \
integer -5 \
integer -5 \
]
# EVIDENCE-OF: R-64550-29191 Note that the result from casting any
# non-BLOB value into a BLOB and the result from casting any BLOB value