diff --git a/src/pl/ob_pl.h b/src/pl/ob_pl.h index e73092349..5433b3124 100644 --- a/src/pl/ob_pl.h +++ b/src/pl/ob_pl.h @@ -47,6 +47,7 @@ namespace sql { class ObPsCache; class ObSQLSessionInfo; +class ObAlterRoutineResolver; } namespace jit { @@ -1078,6 +1079,7 @@ struct PlTransformTreeCtx class ObPL { + friend class sql::ObAlterRoutineResolver; public: ObPL() : sql_proxy_(NULL), diff --git a/src/sql/resolver/ddl/ob_alter_routine_resolver.cpp b/src/sql/resolver/ddl/ob_alter_routine_resolver.cpp index b8c9d0801..96702f6d7 100644 --- a/src/sql/resolver/ddl/ob_alter_routine_resolver.cpp +++ b/src/sql/resolver/ddl/ob_alter_routine_resolver.cpp @@ -21,6 +21,11 @@ #include "pl/ob_pl_router.h" #include "pl/ob_pl_stmt.h" #include "pl/parser/parse_stmt_item_type.h" +#include "lib/utility/ob_defer.h" + +#ifdef OB_BUILD_ORACLE_PL +#include "pl/debug/ob_pl_debugger_manager.h" +#endif namespace oceanbase { using namespace common; @@ -215,6 +220,12 @@ int ObAlterRoutineResolver::resolve_compile_clause( OZ (parse_routine(routine_info.get_routine_body(), parse_tree)); CK (OB_NOT_NULL(parse_tree)); OZ (resolve_routine(crt_routine_arg, routine_info, need_recreate, parse_tree)); + if (OB_SUCC(ret) + && 1 == alter_clause_node.int32_values_[0] // ALTER COMPILE DEBUG + && !need_recreate + && OB_INVALID_ID != session_info_->get_pl_attached_id()) { + OZ (register_debug_info(routine_info)); + } OZ (old_env.store(*session_info_)); } return ret; @@ -360,7 +371,141 @@ int ObAlterRoutineResolver::resolve_routine( return ret; } -} //namespace sql +int ObAlterRoutineResolver::register_debug_info(const share::schema::ObRoutineInfo &routine_info) +{ + int ret = OB_SUCCESS; + +#ifndef OB_BUILD_ORACLE_PL + UNUSED(routine_info); +#else + CK (OB_NOT_NULL(session_info_)); + CK (OB_NOT_NULL(session_info_->get_pl_engine())); + + if (OB_FAIL(ret)) { + // do nothing + } else { + uint32_t id = session_info_->get_pl_attached_id(); + pl::ObPLDebuggerGuard guard(id); + pl::debugger::ObPLDebugger *pl_debugger = nullptr; + ObExecContext *exec_ctx = nullptr; + + if (OB_FAIL(guard.get(pl_debugger))) { + LOG_WARN("failed get pl debugger", K(ret)); + } else if (OB_ISNULL(pl_debugger) || !pl_debugger->is_debug_on()) { + // do nothing + } else if (OB_ISNULL(exec_ctx = session_info_->get_cur_exec_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to get cur exec context", K(session_info_)); + } else if (OB_ISNULL(exec_ctx->get_package_guard())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to get package guard", K(session_info_), K(exec_ctx)); + } else { + pl::ObPLFunction *routine = nullptr; + pl::ObPLFunction *local_routine = nullptr; + ObCacheObjGuard cacheobj_guard(PL_ROUTINE_HANDLE); + ObArray subprogram_path; // empty array + + ObSqlString const_name; + common::ObIArray *pl_dwarf_helpers = nullptr; + + pl::debugger::ObPLDebugger *old_debugger = session_info_->get_pl_debugger(); + session_info_->set_pl_debugger(pl_debugger); + + // always set pl debugger back to old debugger + DEFER(session_info_->set_pl_debugger(old_debugger)); + + if (OB_FAIL(session_info_ + ->get_pl_engine() + ->get_pl_function(*exec_ctx, + *exec_ctx->get_package_guard(), + routine_info.get_package_id(), + routine_info.get_routine_id(), + subprogram_path, + cacheobj_guard, + local_routine))) { + LOG_WARN("failed to compile pl function", K(ret), K(routine_info)); + } else if (nullptr != local_routine) { + routine = local_routine; + } else { + routine = static_cast(cacheobj_guard.get_cache_obj()); + } + + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_ISNULL(routine)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected NULL routine", K(local_routine), K(cacheobj_guard)); + } else if (OB_ISNULL(pl_dwarf_helpers = pl_debugger->get_dwarf_helpers())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected NULL pl dwarf helpers", K(pl_debugger->get_dwarf_helpers())); + } else if (OB_FAIL(const_name.append(routine->get_name_debuginfo().owner_name_))) { + LOG_WARN("failed to append owner name", K(ret), K(routine->get_name_debuginfo().owner_name_)); + } else if (OB_FAIL(const_name.append("."))) { + LOG_WARN("failed to append sep .", K(ret)); + } else if (OB_FAIL(const_name.append(routine->get_name_debuginfo().routine_name_))) { + LOG_WARN("failed to append routine name", K(ret), K(routine->get_name_debuginfo().routine_name_)); + } else { + int64_t line = 1; + int64_t address = -1; + for (int64_t i = 0; OB_SUCC(ret) && address == -1 && i < pl_dwarf_helpers->count(); ++i) { + jit::ObDWARFHelper* dwarf_helper = pl_dwarf_helpers->at(i); + if (OB_ISNULL(dwarf_helper)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected NULL dwarf helper", KPC(pl_dwarf_helpers)); + } else if (OB_FAIL(dwarf_helper->find_address_by_function_line( + const_name.string(), + line, + address))) { + LOG_WARN("failed to find address by function line", K(ret), K(const_name), K(line)); + } + } + + if (OB_SUCC(ret) && address == -1) { + char *copy = nullptr; + jit::ObDIRawData di_raw_data = routine->get_debug_info(); + jit::ObDWARFHelper* dwarf_helper = nullptr; + + if (di_raw_data.empty()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected empty di raw data", K(di_raw_data.get_size()), K(di_raw_data.get_data())); + } else if (OB_ISNULL(pl_debugger->get_allocator())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected NULL allocator in pl_debugger", K(pl_debugger)); + } else if (OB_ISNULL(copy = static_cast( + pl_debugger->get_allocator()->alloc(di_raw_data.get_size())))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to alloc memory for debug info", K(di_raw_data.get_size())); + } else if (OB_ISNULL(MEMCPY(copy, di_raw_data.get_data(), di_raw_data.get_size()))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to MEMCPY debug info", + "dst", copy, + K(di_raw_data.get_data()), + K(di_raw_data.get_size())); + } else if (OB_ISNULL(dwarf_helper = static_cast( + pl_debugger->get_allocator()->alloc(sizeof(jit::ObDWARFHelper))))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to alloc memory for dwarf helper",K(sizeof(jit::ObDWARFHelper))); + } else if (OB_ISNULL( + dwarf_helper = new (dwarf_helper) + jit::ObDWARFHelper(*pl_debugger->get_allocator(), + copy, + di_raw_data.get_size()))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to placement new ObDWARFHelper"); + } else if (OB_FAIL(dwarf_helper->init())) { + LOG_WARN("failed to init dwarf helper", K(ret)); + } else if (OB_FAIL(pl_debugger->get_debugger_ctrl().register_debug_info(dwarf_helper))) { + LOG_WARN("failed to register debug info", K(ret)); + } + } + } + } + } +#endif + + return ret; +} +} // namespace sql } //namespace oceanbase diff --git a/src/sql/resolver/ddl/ob_alter_routine_resolver.h b/src/sql/resolver/ddl/ob_alter_routine_resolver.h index 462cd5a51..db50eaaf2 100644 --- a/src/sql/resolver/ddl/ob_alter_routine_resolver.h +++ b/src/sql/resolver/ddl/ob_alter_routine_resolver.h @@ -53,6 +53,7 @@ protected: bool need_recreate, const ParseNode *source_tree); int resolve_clause_list(const ParseNode *node, obrpc::ObCreateRoutineArg &crt_routine_arg); + int register_debug_info(const share::schema::ObRoutineInfo &routine_info); private: ObCreateRoutineResolver *crt_resolver_; diff --git a/src/sql/session/ob_sql_session_info.h b/src/sql/session/ob_sql_session_info.h index dca9c1835..efb8a0c23 100644 --- a/src/sql/session/ob_sql_session_info.h +++ b/src/sql/session/ob_sql_session_info.h @@ -888,6 +888,7 @@ public: #ifdef OB_BUILD_ORACLE_PL inline pl::debugger::ObPLDebugger *get_pl_debugger() const { return pl_debugger_; } + void set_pl_debugger (pl::debugger::ObPLDebugger *pl_debugger) {pl_debugger_ = pl_debugger; }; #endif bool is_pl_debug_on();