From 861cd00eba9c6a79c0a5f2834c6d0fbe0b9ef5ff Mon Sep 17 00:00:00 2001 From: galsalomon66 Date: Wed, 1 Nov 2023 22:41:46 +0200 Subject: [PATCH] add exception handling to avoid crash, and produce informative message instead Signed-off-by: galsalomon66 --- include/s3select.h | 41 ++++++++++++++++++++++++++++++++---- include/s3select_functions.h | 41 ++++++++++++++++++++++++++++++++---- test/s3select_test.cpp | 5 ++++- 3 files changed, 78 insertions(+), 9 deletions(-) diff --git a/include/s3select.h b/include/s3select.h index 3db17905..963b6705 100644 --- a/include/s3select.h +++ b/include/s3select.h @@ -2196,6 +2196,16 @@ class base_s3object Status m_sql_processing_status; + void set_processing_time_error() + { + m_sql_processing_status = Status::SQL_ERROR; + } + + bool is_processing_time_error() + { + return m_sql_processing_status == Status::SQL_ERROR; + } + Status get_sql_processing_status() { return m_sql_processing_status; @@ -2277,19 +2287,32 @@ class base_s3object for(auto& res : projections_resuls.values) { + + std::string column_result; + + try{ + column_result = res->to_string(); + } + catch(std::exception& e) + { + column_result = "{failed to compute projection: " + std::string(e.what()) + "}"; + set_processing_time_error();//TODO obsolete ?? + } + + if(fp_ext_debug_mesg) - fp_ext_debug_mesg( res->to_string() ); + fp_ext_debug_mesg(column_result.data()); if (m_csv_defintion.quote_fields_always) { std::ostringstream quoted_result; - quoted_result << std::quoted(res->to_string(),m_csv_defintion.output_quot_char, m_csv_defintion.escape_char); + quoted_result << std::quoted(column_result,m_csv_defintion.output_quot_char, m_csv_defintion.escape_char); result.append(quoted_result.str()); m_returned_bytes_size += quoted_result.str().size(); }//TODO to add asneeded else { - result.append(res->to_string()); - m_returned_bytes_size += strlen(res->to_string()); + result.append(column_result); + m_returned_bytes_size += column_result.size(); } if(!m_csv_defintion.redundant_column) { @@ -2318,6 +2341,11 @@ class base_s3object return m_sql_processing_status = Status::LIMIT_REACHED; } + if(is_processing_time_error()) + { + return m_sql_processing_status = Status::SQL_ERROR; + } + if (m_aggr_flow == true) { do @@ -2624,6 +2652,11 @@ class csv_object : public base_s3object m_error_description = "with_file_line failure while csv parsing"; return -1; } + catch(std::exception& e) + { + m_error_description = "error while processing CSV object : " + std::string(e.what()); + return -1; + } return status; } diff --git a/include/s3select_functions.h b/include/s3select_functions.h index 8c507fca..448cbe23 100644 --- a/include/s3select_functions.h +++ b/include/s3select_functions.h @@ -350,6 +350,7 @@ class __function : public base_statement s3select_functions* m_s3select_functions; variable m_result; bool m_is_aggregate_function; + value eval_result; void _resolve_name() { @@ -437,14 +438,28 @@ class __function : public base_statement {//all rows prior to last row if(m_skip_non_aggregate_op == false || is_aggregate() == true) { - (*m_func_impl)(&arguments, &m_result); + try { + (*m_func_impl)(&arguments, &m_result); + } + catch(std::exception& e) + { + std::string error_msg = "[" + m_func_impl->m_function_name + " failed : " + std::string(e.what()) + "]"; + throw base_s3select_exception(error_msg.data(), base_s3select_exception::s3select_exp_en_t::FATAL); + } } else if(m_skip_non_aggregate_op == true) { for(auto& p : arguments) {//evaluating the arguments (not the function itself, which is a non-aggregate function) //i.e. in the following use case substring( , sum(),count() ) ; only sum() and count() are evaluated. - p->eval(); + try { + p->eval(); + } + catch(std::exception& e) + { + std::string error_msg = m_func_impl->m_function_name + " failed : " + std::string(e.what()); + throw base_s3select_exception(error_msg.data(), base_s3select_exception::s3select_exp_en_t::FATAL); + } } } } @@ -452,9 +467,27 @@ class __function : public base_statement {//on the last row, the aggregate function is finalized, //and non-aggregate function is evaluated with the result of aggregate function. if(is_aggregate()) - (*m_func_impl).get_aggregate_result(&m_result); + { + try{ + (*m_func_impl).get_aggregate_result(&m_result); + } + catch(std::exception& e) + { + std::string error_msg = m_func_impl->m_function_name + " failed : " + std::string(e.what()); + throw base_s3select_exception(error_msg.data(), base_s3select_exception::s3select_exp_en_t::FATAL); + } + } else - (*m_func_impl)(&arguments, &m_result); + { + try{ + (*m_func_impl)(&arguments, &m_result); + } + catch(std::exception& e) + { + std::string error_msg = m_func_impl->m_function_name + " failed : " + std::string(e.what()); + throw base_s3select_exception(error_msg.data(), base_s3select_exception::s3select_exp_en_t::FATAL); + } + } } return m_result.get_value(); diff --git a/test/s3select_test.cpp b/test/s3select_test.cpp index 3dbad19d..bc110cf9 100644 --- a/test/s3select_test.cpp +++ b/test/s3select_test.cpp @@ -880,7 +880,10 @@ void test_single_column_single_row(const char* input_query,const char* expected_ { ASSERT_TRUE(false); } - ASSERT_EQ(s3_csv_object.get_error_description(),error_description); + if(s3_csv_object.get_error_description().find(error_description) == std::string::npos ) + { + FAIL() << "getting error: " << s3_csv_object.get_error_description() << " instead of: " << error_description << std::endl; + } return; }