From 422632016891cdd329de22c3d4a2d27c39671128 Mon Sep 17 00:00:00 2001 From: obdev Date: Wed, 28 Dec 2022 03:11:50 +0000 Subject: [PATCH] [to #46045492] fix serval signal/resignal issues --- src/pl/ob_pl_code_generator.cpp | 65 +++++++++++++++++++++-------- src/pl/ob_pl_exception_handling.cpp | 24 ++++++++--- src/pl/ob_pl_resolver.cpp | 8 ++++ src/pl/ob_pl_resolver.h | 1 + src/pl/ob_pl_stmt.cpp | 24 +++++------ src/pl/ob_pl_stmt.h | 2 +- src/sql/ob_spi.cpp | 33 +++++++++------ src/sql/ob_spi.h | 10 +++-- 8 files changed, 115 insertions(+), 52 deletions(-) diff --git a/src/pl/ob_pl_code_generator.cpp b/src/pl/ob_pl_code_generator.cpp index ab39ec182..a14378355 100644 --- a/src/pl/ob_pl_code_generator.cpp +++ b/src/pl/ob_pl_code_generator.cpp @@ -2290,30 +2290,30 @@ int ObPLCodeGenerateVisitor::visit(const ObPLSignalStmt &s) OZ (generator_.generate_goto_label(s)); ObLLVMBasicBlock normal; + ObLLVMType unwind_exception_type, unwind_exception_pointer_type; + ObLLVMType condition_type; + ObLLVMType condition_pointer_type; + ObLLVMValue unwindException = generator_.get_saved_exception(); + ObLLVMValue ob_error_code = generator_.get_saved_ob_error(); + ObLLVMValue unwind_exception_header; + ObLLVMValue condition; + ObLLVMValue sql_state; + ObLLVMValue error_code; + OZ (generator_.get_adt_service().get_unwind_exception(unwind_exception_type)); + OZ (unwind_exception_type.get_pointer_to(unwind_exception_pointer_type)); + OZ (generator_.get_adt_service().get_pl_condition_value(condition_type)); + OZ (condition_type.get_pointer_to(condition_pointer_type)); if (OB_FAIL(ret)) { } else if (s.is_signal_null()) { - ObLLVMValue null_sql_state, status; - ObLLVMValue unwindException = generator_.get_saved_exception(); - ObLLVMValue ob_error_code = generator_.get_saved_ob_error(); - ObLLVMType unwind_exception_type, unwind_exception_pointer_type; - ObLLVMValue unwind_exception_header; - ObLLVMType condition_type; - ObLLVMType condition_pointer_type; - ObLLVMValue condition; - ObLLVMValue sql_state; - ObLLVMValue error_code; + ObLLVMValue status; CK (OB_NOT_NULL(generator_.get_saved_exception().get_v())); CK (OB_NOT_NULL(generator_.get_saved_ob_error().get_v())); OZ (generator_.extract_status_from_context(generator_.get_vars().at(generator_.CTX_IDX), status)); OZ (generator_.get_helper().create_store(ob_error_code, status)); - OZ (generator_.get_adt_service().get_unwind_exception(unwind_exception_type)); - OZ (unwind_exception_type.get_pointer_to(unwind_exception_pointer_type)); OZ (generator_.get_helper().create_const_gep1_64(ObString("extract_unwind_exception_header"), unwindException, generator_.get_eh_service().pl_exception_base_offset_, unwind_exception_header)); - OZ (generator_.get_adt_service().get_pl_condition_value(condition_type)); - OZ (condition_type.get_pointer_to(condition_pointer_type)); OZ (generator_.get_helper().create_pointer_cast(ObString("cast_header"), unwind_exception_header, condition_pointer_type, @@ -2328,16 +2328,19 @@ int ObPLCodeGenerateVisitor::visit(const ObPLSignalStmt &s) s.get_block()->in_notfound(), s.get_block()->in_warning(), true)); OZ (generator_.set_current(normal)); } else { - ObLLVMValue type, ob_err_code, err_code, sql_state, str_len, is_signal, stmt_id, loc; + ObLLVMValue type, ob_err_code, err_code, sql_state, str_len, is_signal, stmt_id, loc, err_code_ptr; if (lib::is_mysql_mode() && (s.is_resignal_stmt() || s.get_cond_type() != ERROR_CODE)) { ObLLVMValue int_value; - ObLLVMType int_type; + ObLLVMType int_type, int32_type, int32_type_ptr; ObSEArray args; int64_t *err_idx = const_cast(s.get_expr_idx( static_cast(SignalCondInfoItem::DIAG_MYSQL_ERRNO))); int64_t *msg_idx = const_cast(s.get_expr_idx( static_cast(SignalCondInfoItem::DIAG_MESSAGE_TEXT))); + OZ (generator_.get_helper().get_llvm_type(ObIntType, int_type)); + OZ (generator_.get_helper().get_llvm_type(ObInt32Type, int32_type)); + OZ (int32_type.get_pointer_to(int32_type_ptr)); OZ (args.push_back(generator_.get_vars().at(generator_.CTX_IDX))); OZ (generator_.generate_pointer(NULL != err_idx ? generator_.get_expr(*err_idx) : NULL, int_value)); OZ (args.push_back(int_value)); @@ -2345,14 +2348,38 @@ int ObPLCodeGenerateVisitor::visit(const ObPLSignalStmt &s) OZ (args.push_back(int_value)); OZ (generator_.generate_string(ObString(s.get_str_len(), s.get_sql_state()), sql_state, str_len)); OZ (args.push_back(sql_state)); + OZ (generator_.get_helper().create_alloca(ObString("error_code"), int_type, err_code_ptr)); + if (s.is_resignal_stmt()) { + // ObLLVMValue code_ptr; + CK (OB_NOT_NULL(generator_.get_saved_exception().get_v())); + CK (OB_NOT_NULL(generator_.get_saved_ob_error().get_v())); + OZ (generator_.get_helper().create_const_gep1_64(ObString("extract_unwind_exception_header"), + unwindException, + generator_.get_eh_service().pl_exception_base_offset_, + unwind_exception_header)); + OZ (generator_.get_helper().create_pointer_cast(ObString("cast_header"), + unwind_exception_header, + condition_pointer_type, + condition)); + OZ (generator_.extract_name_from_condition_value(condition, sql_state)); + OZ (generator_.extract_code_from_condition_value(condition, error_code)); + OZ (generator_.get_helper().create_store(error_code, err_code_ptr)); + } else { + OZ (generator_.get_helper().get_int64(OB_SUCCESS, err_code)); + OZ (generator_.get_helper().create_store(err_code, err_code_ptr)); + } + OZ (args.push_back(err_code_ptr)); + OZ (args.push_back(sql_state)); OZ (generator_.get_helper().get_int8(!s.is_resignal_stmt(), is_signal)); OZ (args.push_back(is_signal)); OZ (generator_.get_helper().create_call(ObString("spi_process_resignal"), generator_.get_spi_service().spi_process_resignal_error_, args, ob_err_code)); - OZ (generator_.get_helper().get_llvm_type(ObIntType, int_type)); - OZ (generator_.get_helper().create_sext(ObString("sext to int64"), ob_err_code, int_type, err_code)); + OZ (generator_.check_success(ob_err_code, s.get_stmt_id(), s.get_block()->in_notfound(), s.get_block()->in_warning())); + OZ (generator_.get_helper().create_load(ObString("load_error_code"), err_code_ptr, err_code)); + OZ (generator_.get_helper().create_bit_cast(ObString("cast_int64_to_int32"), err_code_ptr, int32_type_ptr, err_code_ptr)); + OZ (generator_.get_helper().create_load(ObString("load_error_code"), err_code_ptr, ob_err_code)); } else { OZ (generator_.get_helper().get_int32(s.get_ob_error_code(), ob_err_code)); OZ (generator_.get_helper().get_int64(s.get_error_code(), err_code)); @@ -3803,6 +3830,8 @@ int ObPLCodeGenerator::init_spi_service() OZ (arg_types.push_back(int64_type)); OZ (arg_types.push_back(int64_type)); OZ (arg_types.push_back(char_type)); + OZ (arg_types.push_back(int_pointer_type)); + OZ (arg_types.push_back(char_type)); OZ (arg_types.push_back(bool_type)); OZ (ObLLVMFunctionType::get(int32_type, arg_types, ft)); OZ (helper_.create_function(ObString("spi_process_resignal"), ft, spi_service_.spi_process_resignal_error_)); diff --git a/src/pl/ob_pl_exception_handling.cpp b/src/pl/ob_pl_exception_handling.cpp index d556db545..6be8e0fd0 100644 --- a/src/pl/ob_pl_exception_handling.cpp +++ b/src/pl/ob_pl_exception_handling.cpp @@ -81,16 +81,30 @@ int ObPLEH::eh_convert_exception(bool oracle_mode, int oberr, ObPLConditionType *error_code = oberr; *type = ERROR_CODE; } else { - if (oberr < 0) { - *error_code = ob_mysql_errno(oberr); - if (-1 == *error_code) { + if (OB_SP_RAISE_APPLICATION_ERROR == oberr) { + ObWarningBuffer *wb = NULL; + CK (OB_NOT_NULL(wb = common::ob_get_tsi_warning_buffer())); + OX (*error_code = wb->get_err_code()); + OX (*sql_state = wb->get_sql_state()); + OX (*str_len = STRLEN(*sql_state)); + if (OB_FAIL(ret)) { + } else if (-1 == *error_code) { *type = SQL_STATE; } else { *type = ERROR_CODE; } } else { - *error_code = oberr; - *type = SQL_STATE; + if (oberr < 0) { + *error_code = ob_mysql_errno(oberr); + if (-1 == *error_code) { + *type = SQL_STATE; + } else { + *type = ERROR_CODE; + } + } else { + *error_code = oberr; + *type = SQL_STATE; + } } } } diff --git a/src/pl/ob_pl_resolver.cpp b/src/pl/ob_pl_resolver.cpp index ac688f6d3..64c90f725 100644 --- a/src/pl/ob_pl_resolver.cpp +++ b/src/pl/ob_pl_resolver.cpp @@ -5182,13 +5182,21 @@ int ObPLResolver::resolve_declare_handler(const ObStmtNodeTree *parse_tree, ObPL LOG_WARN("Invalid else node", K(parse_tree->children_[1]->type_), K(ret)); } else { ObPLStmtBlock *body_block = NULL; + int64_t top_continue = handler_analyzer_.get_continue(); + ++current_level_; + handler_analyzer_.set_continue(OB_INVALID_INDEX); if (OB_FAIL(resolve_stmt_list(parse_tree->children_[1], body_block, func, true,/*stop scarch label*/ true /*in exception handler scope*/))) { LOG_WARN("failed to resolve stmt list", K(parse_tree->children_[1]->type_), K(ret)); + } else if (OB_FAIL(handler_analyzer_.reset_handlers(current_level_))) { + LOG_WARN("failed to reset handlers", K(ret), K(current_level_)); } else { + --current_level_; + handler_analyzer_.reset_notfound_and_warning(current_level_); + handler_analyzer_.set_continue(top_continue); desc->set_body(body_block); } } diff --git a/src/pl/ob_pl_resolver.h b/src/pl/ob_pl_resolver.h index 265fa6e2d..659214c4f 100644 --- a/src/pl/ob_pl_resolver.h +++ b/src/pl/ob_pl_resolver.h @@ -153,6 +153,7 @@ public: inline void set_warning(int64_t level) { top_warning_level_ = level; } inline int64_t get_continue() { return top_continue_; } inline void set_continue() { top_continue_ = handler_stack_.count() - 1; } + inline void set_continue(int64_t top_continue) { top_continue_ = top_continue; } inline int64_t get_stack_depth() { return handler_stack_.count(); } inline bool in_continue() { return OB_INVALID_INDEX != top_continue_; } inline bool in_notfound() { return OB_INVALID_INDEX != top_notfound_level_; } diff --git a/src/pl/ob_pl_stmt.cpp b/src/pl/ob_pl_stmt.cpp index f607520ae..16b7a40e8 100644 --- a/src/pl/ob_pl_stmt.cpp +++ b/src/pl/ob_pl_stmt.cpp @@ -993,7 +993,7 @@ int ObPLBlockNS::add_label(const ObString &name, LOG_USER_ERROR(OB_ERR_IDENTIFIER_TOO_LONG, name.length(), name.ptr()); } else { bool is_dup = false; - if (OB_FAIL(check_dup_label(name, is_dup, true))) { + if (OB_FAIL(check_dup_label(name, is_dup))) { LOG_INFO("check dup label fail. ", K(ret), K(name)); } else if (is_dup) { ret = OB_ERR_REDEFINE_LABEL; @@ -1218,29 +1218,29 @@ int ObPLBlockNS::check_dup_symbol(const ObString &name, const ObPLDataType &type return ret; } -int ObPLBlockNS::check_dup_label(const ObString &name, bool &is_dup, bool check_parent) const +int ObPLBlockNS::check_dup_label(const ObString &name, bool &is_dup) const { int ret = OB_SUCCESS; is_dup = false; if (lib::is_oracle_mode()) { // do nothing - } else if (OB_ISNULL(label_table_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("label table is NULL", K(ret)); } else { - const ObPLBlockNS *ns = check_parent ? pre_ns_ : this; - while (NULL != ns && !is_dup && !ns->stop_search_label()) { + const ObPLBlockNS *ns = this; + while (NULL != ns && !is_dup) { for (int64_t i = 0; OB_SUCC(ret) && !is_dup && i < ns->get_labels().count(); ++i) { - if (OB_ISNULL(ns->get_label_table()->get_label(ns->get_labels().at(i)))) { + if (OB_ISNULL(ns->get_label_table()) + || OB_ISNULL(ns->get_label_table()->get_label(ns->get_labels().at(i)))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("label is NULL", K(i), K(ns->get_labels().at(i)), K(ret)); - } else if (*ns->get_label_table()->get_label(ns->get_labels().at(i)) == name && - ns->get_label_table()->is_ended(ns->get_labels().at(i)) == false) { + } else if (*ns->get_label_table()->get_label(ns->get_labels().at(i)) == name + && ns->get_label_table()->is_ended(ns->get_labels().at(i)) == false) { is_dup = true; - } else { /*do nothing*/ } + } } - if (!is_dup && check_parent) { + if (!is_dup && !ns->stop_search_label()) { ns = ns->get_pre_ns(); + } else { + break; } } } diff --git a/src/pl/ob_pl_stmt.h b/src/pl/ob_pl_stmt.h index 8351493af..780f7ba79 100644 --- a/src/pl/ob_pl_stmt.h +++ b/src/pl/ob_pl_stmt.h @@ -1281,7 +1281,7 @@ public: inline const ObPLExternalNS *get_external_ns() const { return external_ns_; } inline void set_external_ns(ObPLExternalNS *external_ns) { external_ns_ = external_ns; } int check_dup_symbol(const ObString &name, const ObPLDataType &type, bool &is_dup) const; - int check_dup_label(const ObString &name, bool &is_dup, bool check_parent) const; + int check_dup_label(const ObString &name, bool &is_dup) const; int check_dup_goto_label(const ObString &name, bool &is_dup) const; int check_dup_condition(const ObString &name, bool &is_dup, const void *&dup_item) const; int check_dup_cursor(const ObString &name, bool &is_dup) const; diff --git a/src/sql/ob_spi.cpp b/src/sql/ob_spi.cpp index 072778c23..e3bfe3367 100644 --- a/src/sql/ob_spi.cpp +++ b/src/sql/ob_spi.cpp @@ -4168,10 +4168,12 @@ int ObSPIService::spi_raise_application_error(pl::ObPLExecCtx *ctx, } int ObSPIService::spi_process_resignal(pl::ObPLExecCtx *ctx, - const ObSqlExpression *errcode_expr, - const ObSqlExpression *errmsg_expr, - const char *sql_state, - bool is_signal) + const ObSqlExpression *errcode_expr, + const ObSqlExpression *errmsg_expr, + const char *sql_state, + int *error_code, + const char *resignal_sql_state, + bool is_signal) { int ret = OB_SUCCESS; ObObjParam result; @@ -4187,6 +4189,7 @@ int ObSPIService::spi_process_resignal(pl::ObPLExecCtx *ctx, CK (OB_NOT_NULL(session_info = ctx->exec_ctx_->get_my_session())); CK (OB_NOT_NULL(sqlcode_info = ctx->exec_ctx_->get_my_session()->get_pl_sqlcode_info())); CK (OB_NOT_NULL(wb = common::ob_get_tsi_warning_buffer())); + CK (OB_NOT_NULL(error_code)); #define CALC(expr, type, result) \ do { \ @@ -4197,17 +4200,22 @@ int ObSPIService::spi_process_resignal(pl::ObPLExecCtx *ctx, OX (expected_type.set_collation_type(tmp.get_collation_type())); \ OZ (spi_convert(ctx->exec_ctx_->get_my_session(), ctx->allocator_, tmp, expected_type, result)); \ } while(0) + if (OB_SUCC(ret)) { type = ObPLEH::eh_classify_exception(sql_state); cur_err_code = wb->get_err_code(); } - if (OB_ISNULL(errcode_expr)) { - if (type == ObPLConditionType::NOT_FOUND) { - sqlcode_info->set_sqlcode(ER_SIGNAL_NOT_FOUND); + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(errcode_expr)) { + if (!is_signal && *error_code != -1 && NULL == sql_state) { + sqlcode_info->set_sqlcode(*error_code); } else { - sqlcode_info->set_sqlcode(ER_SIGNAL_EXCEPTION); + if (type == ObPLConditionType::NOT_FOUND) { + sqlcode_info->set_sqlcode(ER_SIGNAL_NOT_FOUND); + } else { + sqlcode_info->set_sqlcode(ER_SIGNAL_EXCEPTION); + } } - LOG_INFO("error code is not set", K(ret)); } else { CALC(errcode_expr, int32, result); if (OB_SUCC(ret)) { @@ -4269,7 +4277,6 @@ int ObSPIService::spi_process_resignal(pl::ObPLExecCtx *ctx, sqlcode_info->set_sqlcode(OB_SUCCESS); wb->reset_err(); } - ret = OB_SUCCESS; } else { if (is_signal) { LOG_MYSQL_USER_ERROR(OB_SP_RAISE_APPLICATION_ERROR, @@ -4279,9 +4286,11 @@ int ObSPIService::spi_process_resignal(pl::ObPLExecCtx *ctx, wb->set_sql_state(sql_state); } else { wb->set_error(err_msg, sqlcode_info->get_sqlcode()); - wb->set_sql_state(sql_state != NULL ? sql_state : ob_sqlstate(cur_err_code)); + wb->set_sql_state(sql_state != NULL + ? sql_state + : (resignal_sql_state != NULL) ? resignal_sql_state : ob_sqlstate(cur_err_code)); } - ret = sqlcode_info->get_sqlcode(); + *error_code = sqlcode_info->get_sqlcode(); } } return ret; diff --git a/src/sql/ob_spi.h b/src/sql/ob_spi.h index 74863d53a..6edd7ed1b 100644 --- a/src/sql/ob_spi.h +++ b/src/sql/ob_spi.h @@ -388,10 +388,12 @@ public: const ObSqlExpression *errmsg_expr); static int spi_process_resignal(pl::ObPLExecCtx *ctx, - const ObSqlExpression *errcode_expr, - const ObSqlExpression *errmsg_expr, - const char *sql_state = NULL, - bool is_signal = false); + const ObSqlExpression *errcode_expr, + const ObSqlExpression *errmsg_expr, + const char *sql_state, + int *error_code, + const char *resignal_sql_state, + bool is_signal); static int spi_delete_collection(pl::ObPLExecCtx *ctx, const ObSqlExpression *collection_expr,