From 8fc2d566db41c18514d19d2b47c6de732ffa6836 Mon Sep 17 00:00:00 2001 From: Kenichi Ishigaki Date: Sun, 25 Mar 2012 02:37:09 +0000 Subject: [PATCH] applied two more patches from Yuriy Kaminskiy to fix 64bit integer handling --- dbdimp.c | 23 ++++++++++++++++++++--- t/09_create_function.t | 9 ++++++++- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 6550b2b..7eabdfb 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -142,8 +142,12 @@ sqlite_set_result(pTHX_ sqlite3_context *context, SV *result, int is_error) if ( !SvOK(result) ) { sqlite3_result_null( context ); } else if( SvIOK_UV(result) ) { - s = SvPV(result, len); - sqlite3_result_text( context, s, len, SQLITE_TRANSIENT ); + if ((UV)(sqlite3_int64)UV_MAX == UV_MAX) + sqlite3_result_int64( context, (sqlite3_int64)SvUV(result)); + else { + s = SvPV(result, len); + sqlite3_result_text( context, s, len, SQLITE_TRANSIENT ); + } } else if ( SvIOK(result) ) { #if defined(USE_64_BIT_INT) @@ -1241,11 +1245,24 @@ sqlite_db_func_dispatcher(int is_unicode, sqlite3_context *context, int argc, sq SV *arg; STRLEN len; int type = sqlite3_value_type(value[i]); + sqlite_int64 iv; /* warn("func dispatch type: %d, value: %s\n", type, sqlite3_value_text(value[i])); */ switch(type) { case SQLITE_INTEGER: - arg = sv_2mortal(newSViv(sqlite3_value_int(value[i]))); + iv = sqlite3_value_int64(value[i]); + if ( iv >= IV_MIN && iv <= IV_MAX ) { + /* ^^^ compile-time constant (= true) when IV == int64 */ + arg = sv_2mortal(newSViv((IV)iv)); + } + else if ( iv >= 0 && iv <= UV_MAX ) { + /* warn("integer overflow, cast to UV"); */ + arg = sv_2mortal(newSVuv((UV)iv)); + } + else { + /* warn("integer overflow, cast to NV"); */ + arg = sv_2mortal(newSVnv((NV)iv)); + } break; case SQLITE_FLOAT: arg = sv_2mortal(newSVnv(sqlite3_value_double(value[i]))); diff --git a/t/09_create_function.t b/t/09_create_function.t index d00e6e6..a868b5b 100644 --- a/t/09_create_function.t +++ b/t/09_create_function.t @@ -11,7 +11,7 @@ use t::lib::Test qw/connect_ok @CALL_FUNCS/; use Test::More; use Test::NoWarnings; -plan tests => 27 * @CALL_FUNCS + 1; +plan tests => 29 * @CALL_FUNCS + 1; sub now { return time(); @@ -119,5 +119,12 @@ foreach my $call_func (@CALL_FUNCS) { $result = $dbh->selectrow_arrayref( "SELECT noop(1.0625)" ); is_deeply( $result, [ 1.0625 ], "SELECT noop(1.0625)" ); + # 2147483648 == 1<<31 + $result = $dbh->selectrow_arrayref( "SELECT noop(2147483648)" ); + is_deeply( $result, [ 2147483648 ], "SELECT noop(2147483648)" ); + + $result = $dbh->selectrow_arrayref( "SELECT typeof(noop(2147483648))" ); + is_deeply( $result, [ 'integer' ], "SELECT typeof(noop(2147483648))" ); + $dbh->disconnect; }