Keep the full precision of integers if possible when casting to "numeric".

Ticket . (CVS 4012)

FossilOrigin-Name: 2ac985a38034da87b0fa3837976e1f2164b22672
This commit is contained in:
drh 2007-05-16 11:55:56 +00:00
parent 056c8f782e
commit cd7b46db84
5 changed files with 99 additions and 20 deletions

@ -1,5 +1,5 @@
C Additional\stests\sfor\smalformed\sUTF-8.\s(CVS\s4011)
D 2007-05-15T18:35:21
C Keep\sthe\sfull\sprecision\sof\sintegers\sif\spossible\swhen\scasting\sto\s"numeric".\nTicket\s#2364.\s(CVS\s4012)
D 2007-05-16T11:55:57
F Makefile.in 87b200ad9970907f76df734d29dff3d294c10935
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@ -132,14 +132,14 @@ F src/update.c 3359041db390a8f856d67272f299600e2104f350
F src/utf.c b881fe54498f6a35de424a62f8e071b621111728
F src/util.c a44710b94da6d0d606521a5e1fd40c8067282c74
F src/vacuum.c 8bd895d29e7074e78d4e80f948e35ddc9cf2beef
F src/vdbe.c 5deb4cdccd57065ccf8a2e5c704e8473c90d204b
F src/vdbe.c 55b1d46273584bb4739e923562a71069237f9f97
F src/vdbe.h 001c5b257567c1d3de7feb2203aac71d0d7b16a3
F src/vdbeInt.h bddb7931fc1216fda6f6720e18d2a9b1e0f8fc96
F src/vdbeapi.c f89d6bc5264e66f44589e454fbeeee96854d0dd3
F src/vdbeaux.c 62011e2ccf5fa9b3dcc7fa6ff5f0e0638d324a70
F src/vdbeblob.c 96f3572fdc45eda5be06e6372b612bc30742d9f0
F src/vdbefifo.c 3ca8049c561d5d67cbcb94dc909ae9bb68c0bf8f
F src/vdbemem.c 01237a4844106b9da838fc313bf1f86ddc6b0679
F src/vdbemem.c f04d1a25a71c41f86cad9d4dcc81abcd2a9ff403
F src/vtab.c c5ebebf615b2f29499fbe97a584c4bb342632aa0
F src/where.c f3920748cc650fc25ac916215500bdb90dee568e
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
@ -185,7 +185,7 @@ F test/capi2.test 7ecc9b342cc9ec27b53bbf95724cf2e5874fd496
F test/capi3.test 1675323145d128e5942a9faffcfd5cf4e219a33f
F test/capi3b.test 5f0bc94b104e11086b1103b20277e1910f59c7f4
F test/capi3c.test 96e35164739c6fe3357fa36f0fe74bc23abc8ef7
F test/cast.test f88e7b6946e9a467cf4bb142d92bb65a83747fc2
F test/cast.test 6f5073af07723d15d51568508739e99855fd0fa3
F test/check.test e5ea0c1a06c10e81e3434ca029e2c4a562f2b673
F test/collate1.test e3eaa48c21e150814be1a7b852d2a8af24458d04
F test/collate2.test 701d9651c5707024fd86a20649af9ea55e2c0eb8
@ -492,7 +492,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
P f84d9dab110c4415d9b772f8043397640162b6b2
R 53fa1bf671cabc8be454726443bd9326
P 448d3ef670dce6d27c7d7b1be58088d45f8b6274
R c8d1b4af067fdea86c8ef5e23b538719
U drh
Z 08fe10d1e019c102afe7db67bcfd77dd
Z 5f8f6c00eb0bad475fb07ee3737fa3b6

@ -1 +1 @@
448d3ef670dce6d27c7d7b1be58088d45f8b6274
2ac985a38034da87b0fa3837976e1f2164b22672

@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.618 2007/05/12 12:08:51 drh Exp $
** $Id: vdbe.c,v 1.619 2007/05/16 11:55:57 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -1509,7 +1509,7 @@ case OP_ToBlob: { /* same as TK_TO_BLOB, no-push */
*/
case OP_ToNumeric: { /* same as TK_TO_NUMERIC, no-push */
assert( pTos>=p->aStack );
if( (pTos->flags & MEM_Null)==0 ){
if( (pTos->flags & (MEM_Null|MEM_Int|MEM_Real))==0 ){
sqlite3VdbeMemNumerify(pTos);
}
break;
@ -1763,8 +1763,10 @@ case OP_Or: { /* same as TK_OR, no-push */
case OP_Negative: /* same as TK_UMINUS, no-push */
case OP_AbsValue: {
assert( pTos>=p->aStack );
if( (pTos->flags & (MEM_Real|MEM_Int|MEM_Null))==0 ){
sqlite3VdbeMemNumerify(pTos);
}
if( pTos->flags & MEM_Real ){
neg_abs_real_case:
Release(pTos);
if( pOp->opcode==OP_Negative || pTos->r<0.0 ){
pTos->r = -pTos->r;
@ -1776,11 +1778,6 @@ case OP_AbsValue: {
pTos->u.i = -pTos->u.i;
}
pTos->flags = MEM_Int;
}else if( pTos->flags & MEM_Null ){
/* Do nothing */
}else{
sqlite3VdbeMemNumerify(pTos);
goto neg_abs_real_case;
}
break;
}

@ -362,8 +362,20 @@ int sqlite3VdbeMemRealify(Mem *pMem){
** Invalidate any prior representations.
*/
int sqlite3VdbeMemNumerify(Mem *pMem){
sqlite3VdbeMemRealify(pMem);
sqlite3VdbeIntegerAffinity(pMem);
double r1, r2;
i64 i;
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 );
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
r1 = sqlite3VdbeRealValue(pMem);
i = (i64)r1;
r2 = (double)i;
if( r1==r2 ){
sqlite3VdbeMemIntegerify(pMem);
}else{
pMem->r = r1;
pMem->flags = MEM_Real;
sqlite3VdbeMemRelease(pMem);
}
return SQLITE_OK;
}

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the CAST operator.
#
# $Id: cast.test,v 1.5 2006/03/03 19:12:30 drh Exp $
# $Id: cast.test,v 1.6 2007/05/16 11:55:57 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -192,5 +192,75 @@ do_test cast-2.2 {
execsql {SELECT CAST(' -123.456' AS real)}
} -123.456
# ticket #2364. Use full percision integers if possible when casting
# to numeric. Do not fallback to real (and the corresponding 48-bit
# mantissa) unless absolutely necessary.
#
do_test cast-3.1 {
execsql {SELECT CAST(9223372036854774800 AS integer)}
} 9223372036854774800
do_test cast-3.2 {
execsql {SELECT CAST(9223372036854774800 AS numeric)}
} 9223372036854774800
do_test cast-3.3 {
execsql {SELECT CAST(9223372036854774800 AS real)}
} 9.22337203685477e+18
do_test cast-3.4 {
execsql {SELECT CAST(CAST(9223372036854774800 AS real) AS integer)}
} 9223372036854774784
do_test cast-3.5 {
execsql {SELECT CAST(-9223372036854774800 AS integer)}
} -9223372036854774800
do_test cast-3.6 {
execsql {SELECT CAST(-9223372036854774800 AS numeric)}
} -9223372036854774800
do_test cast-3.7 {
execsql {SELECT CAST(-9223372036854774800 AS real)}
} -9.22337203685477e+18
do_test cast-3.8 {
execsql {SELECT CAST(CAST(-9223372036854774800 AS real) AS integer)}
} -9223372036854774784
do_test cast-3.11 {
execsql {SELECT CAST('9223372036854774800' AS integer)}
} 9223372036854774800
do_test cast-3.12 {
execsql {SELECT CAST('9223372036854774800' AS numeric)}
} 9223372036854774800
do_test cast-3.13 {
execsql {SELECT CAST('9223372036854774800' AS real)}
} 9.22337203685477e+18
do_test cast-3.14 {
execsql {SELECT CAST(CAST('9223372036854774800' AS real) AS integer)}
} 9223372036854774784
do_test cast-3.15 {
execsql {SELECT CAST('-9223372036854774800' AS integer)}
} -9223372036854774800
do_test cast-3.16 {
execsql {SELECT CAST('-9223372036854774800' AS numeric)}
} -9223372036854774800
do_test cast-3.17 {
execsql {SELECT CAST('-9223372036854774800' AS real)}
} -9.22337203685477e+18
do_test cast-3.18 {
execsql {SELECT CAST(CAST('-9223372036854774800' AS real) AS integer)}
} -9223372036854774784
if {[db eval {PRAGMA encoding}]=="UTF-8"} {
do_test cast-3.21 {
execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS integer)}
} 9223372036854774800
do_test cast-3.22 {
execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS numeric)}
} 9223372036854774800
do_test cast-3.23 {
execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS real)}
} 9.22337203685477e+18
do_test cast-3.24 {
execsql {SELECT CAST(CAST(x'39323233333732303336383534373734383030' AS real) AS integer)}
} 9223372036854774784
}
do_test case-3.31 {
execsql {SELECT CAST(NULL AS numeric)}
} {{}}
finish_test