Skip to content

Commit 465c6ff

Browse files
authored
fixing text to float convertion (ronen-fr #42) (#64)
Signed-off-by: gal salomon <gal.salomon@gmail.com>
1 parent 73100a3 commit 465c6ff

File tree

2 files changed

+44
-25
lines changed

2 files changed

+44
-25
lines changed

include/s3select_functions.h

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -599,42 +599,43 @@ struct _fn_to_int : public base_function
599599

600600
struct _fn_to_float : public base_function
601601
{
602-
603602
value var_result;
604-
value v_from;
605603

606604
bool operator()(bs_stmt_vec_t* args, variable* result) override
607605
{
608-
char* perr;
609-
double d=0;
610606
value v = (*args->begin())->eval();
611607

612-
if (v.type == value::value_En_t::STRING)
608+
switch (v.type) {
609+
610+
case value::value_En_t::STRING:
613611
{
614-
errno = 0;
615-
d = strtod(v.str(), &perr) ; //TODO check error before constructor
616-
if ((errno == ERANGE && (d == LONG_MAX || d == LONG_MIN)) || (errno != 0 && d == 0)) {
612+
char* pend;
613+
double d = strtod(v.str(), &pend);
614+
if (errno == ERANGE) {
617615
throw base_s3select_exception("converted value would fall out of the range of the result type!");
618-
return false;
619-
}
620-
621-
if (*perr != '\0') {
622-
throw base_s3select_exception("characters after float!");
623-
return false;
624-
}
625-
}
626-
else if (v.type == value::value_En_t::FLOAT)
627-
{
628-
d = v.dbl();
616+
}
617+
if (pend == v.str()) {
618+
// no number found
619+
throw base_s3select_exception("text cannot be converted to a number");
620+
}
621+
if (*pend) {
622+
throw base_s3select_exception("extra characters after the number");
623+
}
624+
625+
var_result = d;
629626
}
630-
else
631-
{
632-
d = v.i64();
627+
break;
628+
629+
case value::value_En_t::FLOAT:
630+
var_result = v.dbl();
631+
break;
632+
633+
default:
634+
var_result = v.i64();
635+
break;
633636
}
634637

635-
var_result = d;
636638
*result = var_result;
637-
638639
return true;
639640
}
640641

test/s3select_test.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ int count_string(std::string in,std::string substr)
689689
}
690690

691691

692-
void test_single_column_single_row(const char* input_query,const char* expected_result)
692+
void test_single_column_single_row(const char* input_query,const char* expected_result,const char * error_description = 0)
693693
{
694694
s3select s3select_syntax;
695695
auto status = s3select_syntax.parse_query(input_query);
@@ -704,6 +704,17 @@ void test_single_column_single_row(const char* input_query,const char* expected_
704704
false, // dont skip last line
705705
true // aggregate call
706706
);
707+
708+
if(strcmp(expected_result,"#failure#") == 0)
709+
{
710+
if (status==0 && s3select_result.compare("#failure#")==0)
711+
{
712+
ASSERT_TRUE(0);
713+
}
714+
ASSERT_EQ(s3_csv_object.get_error_description(),error_description);
715+
return;
716+
}
717+
707718
ASSERT_EQ(status, 0);
708719
ASSERT_EQ(s3select_result, std::string(expected_result));
709720
}
@@ -3426,6 +3437,13 @@ TEST(TestS3selectFunctions, boolcast)
34263437
test_single_column_single_row("select cast('a' as bool) from s3object;","false,\n");
34273438
}
34283439

3440+
TEST(TestS3selectFunctions, floatcast)
3441+
{
3442+
test_single_column_single_row("select cast('1234a' as float) from s3object;","#failure#","extra characters after the number");
3443+
test_single_column_single_row("select cast('a1234' as float) from s3object;","#failure#","text cannot be converted to a number");
3444+
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!");
3445+
}
3446+
34293447
TEST(TestS3selectFunctions, predicate_as_projection_column)
34303448
{
34313449
std::string input;

0 commit comments

Comments
 (0)