diff --git a/CMakeLists.txt b/CMakeLists.txt index 049a0358..47fcc94c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) project(s3select) -set(CMAKE_CXX_FLAGS "-std=gnu++17 -ggdb -Wnon-virtual-dtor -Wreorder -Wunused-variable") +set(CMAKE_CXX_FLAGS "-std=gnu++17 -ggdb -Wnon-virtual-dtor -Wreorder -Wunused-variable -Wmaybe-uninitialized") set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/include/s3select_functions.h b/include/s3select_functions.h index 6849de96..24c412be 100644 --- a/include/s3select_functions.h +++ b/include/s3select_functions.h @@ -556,42 +556,44 @@ struct _fn_max : public base_function struct _fn_to_int : public base_function { - value var_result; - value func_arg; bool operator()(bs_stmt_vec_t* args, variable* result) override { - char* perr; - int64_t i=0; - func_arg = (*args->begin())->eval(); + value v = (*args->begin())->eval(); - if (func_arg.type == value::value_En_t::STRING) + switch (v.type) { + + case value::value_En_t::STRING: { + char* pend; errno = 0; - i = strtol(func_arg.str(), &perr, 10) ; //TODO check error before constructor - if ((errno == ERANGE && (i == LONG_MAX || i == LONG_MIN)) || (errno != 0 && i == 0)) { + int64_t i= strtol(v.str(), &pend, 10); + if (errno == ERANGE) { throw base_s3select_exception("converted value would fall out of the range of the result type!"); - return false; - } - - if (*perr != '\0') { - throw base_s3select_exception("characters after int!"); - return false; - } - } - else if (func_arg.type == value::value_En_t::FLOAT) - { - i = func_arg.dbl(); - } - else - { - i = func_arg.i64(); + } + if (pend == v.str()) { + // no number found + throw base_s3select_exception("text cannot be converted to a number"); + } + if (*pend) { + throw base_s3select_exception("extra characters after the number"); + } + + var_result = i; } + break; - var_result = i ; - *result = var_result; + case value::value_En_t::FLOAT: + var_result = static_cast(v.dbl()); + break; + default: + var_result = v.i64(); + break; + } + + *result = var_result; return true; } diff --git a/test/s3select_test.cpp b/test/s3select_test.cpp index 66f33eb9..a09731a9 100644 --- a/test/s3select_test.cpp +++ b/test/s3select_test.cpp @@ -3444,6 +3444,14 @@ TEST(TestS3selectFunctions, floatcast) test_single_column_single_row("select cast('999e+999' as float) from s3object;","#failure#","converted value would fall out of the range of the result type!"); } +TEST(TestS3selectFunctions, intcast) +{ + test_single_column_single_row("select cast('1234a' as int) from s3object;","#failure#","extra characters after the number"); + test_single_column_single_row("select cast('a1234' as int) from s3object;","#failure#","text cannot be converted to a number"); + test_single_column_single_row("select cast('9223372036854775808' as int) from s3object;","#failure#","converted value would fall out of the range of the result type!"); + test_single_column_single_row("select cast('-9223372036854775809' as int) from s3object;","#failure#","converted value would fall out of the range of the result type!"); +} + TEST(TestS3selectFunctions, predicate_as_projection_column) { std::string input;