/** * Copyright (c) 2021 OceanBase * OceanBase CE is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. * You may obtain a copy of Mulan PubL v2 at: * http://license.coscl.org.cn/MulanPubL-2.0 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. */ #define USING_LOG_PREFIX PL #include "pl/ob_pl_compile.h" #include "src/sql/resolver/ob_resolver_utils.h" #include "pl/ob_pl_code_generator.h" #include "pl/ob_pl_package.h" #ifdef OB_BUILD_ORACLE_PL #include "pl/ob_pl_package_type.h" #endif #include "pl/ob_pl_dependency_util.h" namespace oceanbase { using namespace common; using namespace share; using namespace schema; using namespace sql; namespace pl { ObMutex ObPLCompiler::package_dep_info_lock_; int ObPLCompiler::check_dep_schema(ObSchemaGetterGuard &schema_guard, const DependenyTableStore &dep_schema_objs) { int ret = OB_SUCCESS; uint64_t tenant_id = OB_INVALID_ID; for (int64_t i = 0; OB_SUCC(ret) && i < dep_schema_objs.count(); ++i) { tenant_id = MTL_ID(); if (TABLE_SCHEMA != dep_schema_objs.at(i).get_schema_type()) { int64_t new_version = 0; if (PACKAGE_SCHEMA == dep_schema_objs.at(i).get_schema_type() || UDT_SCHEMA == dep_schema_objs.at(i).get_schema_type() || ROUTINE_SCHEMA == dep_schema_objs.at(i).get_schema_type()) { tenant_id = pl::get_tenant_id_by_object_id(dep_schema_objs.at(i).object_id_); } if (OB_FAIL(schema_guard.get_schema_version(dep_schema_objs.at(i).get_schema_type(), tenant_id, dep_schema_objs.at(i).object_id_, new_version))) { LOG_WARN("failed to get schema version", K(ret), K(tenant_id), K(dep_schema_objs.at(i))); } else if (OB_INVALID_VERSION == new_version || new_version != dep_schema_objs.at(i).version_) { LOG_WARN("schema version is invalid", K(ret), K(dep_schema_objs.at(i)), K(new_version)); } } else { const ObSimpleTableSchemaV2 *table_schema = nullptr; if (OB_FAIL(schema_guard.get_simple_table_schema(MTL_ID(), dep_schema_objs.at(i).object_id_, table_schema))) { LOG_WARN("failed to get table schema", K(ret), K(dep_schema_objs.at(i))); } else if (nullptr == table_schema) { LOG_WARN("get an unexpected null table schema", K(dep_schema_objs.at(i).object_id_)); } else if (table_schema->is_index_table()) { // do nothing } else if (table_schema->get_schema_version() != dep_schema_objs.at(i).version_) { LOG_WARN("schema version is invalid", K(ret), K(dep_schema_objs.at(i)), K(table_schema->get_schema_version())); } } } return ret; } int ObPLCompiler::init_anonymous_ast( ObPLFunctionAST &func_ast, ObIAllocator &allocator, ObSQLSessionInfo &session_info, ObMySQLProxy &sql_proxy, ObSchemaGetterGuard &schema_guard, ObPLPackageGuard &package_guard, const ParamStore *params, bool is_prepare_protocol) { int ret = OB_SUCCESS; ObPLDataType pl_type; common::ObDataType data_type; ObPLResolveCtx resolve_ctx(allocator, session_info, schema_guard, package_guard, sql_proxy, false); func_ast.set_name(ObPLResolver::ANONYMOUS_BLOCK); data_type.set_obj_type(common::ObNullType); pl_type.set_data_type(data_type); func_ast.set_ret_type(pl_type); for (int64_t i = 0; OB_SUCC(ret) && OB_NOT_NULL(params) && i < params->count(); ++i) { ObObjParam& param = const_cast(params->at(i)); if (param.is_pl_extend()) { #ifdef OB_BUILD_ORACLE_PL if (PL_REF_CURSOR_TYPE == param.get_meta().get_extend_type()) { pl_type.reset(); pl_type.set_type(pl::PL_REF_CURSOR_TYPE); pl_type.set_type_from(pl::PL_TYPE_SYS_REFCURSOR); } else #endif if (!is_mocked_anonymous_array_id(param.get_udt_id())) { const ObUserDefinedType *user_type = nullptr; // try schema type first if (OB_FAIL(resolve_ctx.get_user_type(param.get_udt_id(), user_type, &allocator))) { LOG_WARN("failed to ObResolverUtils::get_user_type", K(ret), K(param.get_udt_id()), KPC(user_type)); } else if (OB_NOT_NULL(user_type)) { // schema type, add it to dependencies recursively if (OB_FAIL(func_ast.get_user_type_table().add_external_type(user_type))) { LOG_WARN("failed to add_external_type", K(ret), KPC(user_type)); } } else { // not schema type, try AST if (OB_NOT_NULL(user_type = func_ast.get_user_type_table().get_type(param.get_udt_id()))) { // do nothing // try parent type if it is inner mock PL } else if (OB_NOT_NULL(session_info.get_pl_context()) && session_info.get_pl_context()->get_is_inner_mock() && OB_NOT_NULL(session_info.get_pl_context()->get_current_ctx())) { const ObPLFunction *parent = session_info.get_pl_context()->get_current_ctx()->func_; CK (OB_NOT_NULL(parent)); // iterate parent type table to find the param udt for (int64_t i = 0; OB_SUCC(ret) && i < parent->get_type_table().count(); ++i) { const ObUserDefinedType *type = parent->get_type_table().at(i); if (OB_NOT_NULL(type) && type->get_user_type_id() == param.get_udt_id()) { user_type = type; break; } } // if the param udt is found, add all parent types to current anonymous block AST if (OB_SUCC(ret) && OB_NOT_NULL(user_type)) { for (int64_t i = 0; OB_SUCC(ret) && i < parent->get_type_table().count(); ++i) { const ObUserDefinedType *type = parent->get_type_table().at(i); OZ (func_ast.get_user_type_table().add_type(type)); OZ (func_ast.get_user_type_table().add_external_type(type)); } } } // if a param type is a local type, current anonymous block can't be cached // because different types may have the same local type id if (OB_SUCC(ret) && OB_NOT_NULL(user_type) && user_type->is_local_type()) { func_ast.set_can_cached(false); } } CK (OB_NOT_NULL(user_type)); OX (pl_type.reset()); OX (pl_type = *user_type); #ifdef OB_BUILD_ORACLE_PL } else if (PL_NESTED_TABLE_TYPE == param.get_meta().get_extend_type()) { ObPLCollection *coll = reinterpret_cast(param.get_ext()); ObNestedTableType *nested_type = NULL; ObPLDataType element_type; if (OB_ISNULL(nested_type = reinterpret_cast(allocator.alloc(sizeof(ObNestedTableType))))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to alloc memory for ObNestedTableType", K(ret)); } CK (OB_NOT_NULL(coll)); OX (new(nested_type)ObNestedTableType()); OX (element_type.reset()); OX (element_type.set_data_type(coll->get_element_type())); if (OB_FAIL(ret)) { } else if (coll->get_element_desc().is_obj_type()) { OZ (ObPLResolver::adjust_routine_param_type(element_type)); } else { const ObUserDefinedType *user_type = nullptr; OZ (resolve_ctx.get_user_type(coll->get_element_type().get_udt_id(), user_type, &allocator)); CK (OB_NOT_NULL(user_type)); OZ (func_ast.get_user_type_table().add_external_type(user_type)); OX (element_type = *user_type); } OX (nested_type->set_element_type(element_type)); OX (nested_type->set_user_type_id( func_ast.get_user_type_table().generate_user_type_id(OB_PL_MOCK_ANONYMOUS_ID))); OZ (func_ast.get_user_type_table().add_type(nested_type)); OZ (func_ast.get_user_type_table().add_external_type(nested_type)); OX (param.set_udt_id(nested_type->get_user_type_id())); OX (pl_type = *nested_type); #endif } else { ret = OB_NOT_SUPPORTED; LOG_WARN( "anonymous block`s parameter has invalid udt id and not collection not supported", K(ret), K(param)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "anonymous block`s parameter has invalid udt id and not a coll"); } } else { data_type.reset(); data_type.set_accuracy(params->at(i).get_accuracy()); if (params->at(i).is_null() && !params->at(i).get_param_meta().is_ext()) { data_type.set_meta_type(params->at(i).get_param_meta()); } else { data_type.set_meta_type(params->at(i).get_meta()); } pl_type.reset(); int64_t int_value = 0; // 参数化整型常量按照会按照numbger来生成param if (!is_prepare_protocol && (ObNumberType == params->at(i).get_type() || ObUNumberType == params->at(i).get_type()) && params->at(i).get_number().is_valid_int64(int_value) && int_value <= INT32_MAX && int_value >= INT32_MIN) { pl_type.set_pl_integer_type(PL_SIMPLE_INTEGER, data_type); } else { pl_type.set_data_type(data_type); } OZ (ObPLResolver::adjust_routine_param_type(pl_type)); } OZ (func_ast.add_argument(ObPLResolver::ANONYMOUS_ARG, pl_type, NULL, NULL, true)); } return ret; } //for anonymous int ObPLCompiler::compile( const ObStmtNodeTree *block, const uint64_t stmt_id, ObPLFunction &func, ParamStore *params/*=NULL*/, bool is_prepare_protocol/*=false*/) { int ret = OB_SUCCESS; FLTSpanGuard(pl_compile); int64_t compile_start = ObTimeUtility::current_time(); uint64_t block_hash = OB_INVALID_ID; ObPLASHGuard plash_guard(ObPLASHGuard::ObPLASHStatus::IS_PLSQL_COMPILATION); //Step 1:构造匿名块的ObPLFunctionAST HEAP_VAR(ObPLFunctionAST, func_ast, allocator_) { func_ast.set_db_name(session_info_.get_database_name()); func_ast.set_proc_type(STANDALONE_ANONYMOUS); OZ (init_anonymous_ast(func_ast, allocator_, session_info_, sql_proxy_, schema_guard_, package_guard_, params, is_prepare_protocol)); //Step 2:Resolver if (OB_SUCC(ret)) { ObPLResolver resolver(allocator_, session_info_, schema_guard_, package_guard_, sql_proxy_, func_ast.get_expr_factory(), NULL/*parent ns*/, is_prepare_protocol, false/*is_check_mode_ = false*/, false/*bool is_sql_scope_ = false*/, params); if (OB_ISNULL(block)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("pl body is NULL", K(block), K(ret)); } else if (OB_FAIL(resolver.init(func_ast))) { LOG_WARN("failed to init resolver", K(block), K(ret)); } else if (OB_FAIL(resolver.resolve_root(block, func_ast))) { LOG_WARN("failed to analyze pl body", K(block), K(ret)); } else if (session_info_.is_pl_debug_on()) { if (OB_FAIL(func_ast.generate_symbol_debuginfo())) { LOG_WARN("failed to generate symbol debuginfo", K(ret)); } } } if (OB_SUCC(ret)) { block_hash = murmurhash(block->str_value_, block->str_len_, 0); func.set_profiler_unit_info(block_hash, STANDALONE_ANONYMOUS); } // Process Prepare SQL Ref if (OB_SUCC(ret)) { func.set_proc_type(STANDALONE_ANONYMOUS); func.set_ns(ObLibCacheNameSpace::NS_ANON); OZ (func.get_exec_env().load(session_info_, &(func.get_allocator()))); } //Step 3:Code Generator if (OB_SUCC(ret)) { #ifdef USE_MCJIT HEAP_VAR(ObPLCodeGenerator, cg ,allocator_, session_info_) { #else HEAP_VAR(ObPLCodeGenerator, cg, func.get_allocator(), session_info_, schema_guard_, func_ast, func.get_expressions(), func.get_helper(), func.get_di_helper(), lib::is_oracle_mode()) { #endif int64_t cg_jit_mem = 0; ObPLCGMallocCallback pmcb(cg_jit_mem); lib::ObMallocCallbackGuard memory_guard(pmcb); lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(MTL_ID(), GET_PL_MOD_STRING(OB_PL_CODE_GEN))); uint64_t lock_idx = stmt_id != OB_INVALID_ID ? stmt_id : block_hash; // latch_id = (bucket_id % bucket_cnt_) / 8, so it is needed to multiply 8 to avoid consecutive ids being mapped to the same latch ObBucketHashWLockGuard compile_id_guard(GCTX.pl_engine_->get_jit_lock().first, lock_idx * 8); ObBucketHashWLockGuard compile_num_guard(GCTX.pl_engine_->get_jit_lock().second, (lock_idx % GCONF._ob_pl_compile_max_concurrency) * 8); // check session status after get lock if (OB_FAIL(ObPL::check_session_alive(session_info_))) { LOG_WARN("query or session is killed after get PL jit lock", K(ret)); } else if (OB_FAIL(cg.init())) { LOG_WARN("failed to init code generator", K(ret)); } else if (OB_FAIL(cg.generate(func))) { LOG_WARN("failed to code generate for stmt", K(ret)); } OX (func.set_arg_count(func_ast.get_arg_count())); for (int64_t i = 0; OB_SUCC(ret) && i < func_ast.get_arg_count(); ++i) { const ObPLSymbolTable &symbol_table = func_ast.get_symbol_table(); const ObPLVar *symbol = symbol_table.get_symbol(i); CK (OB_NOT_NULL(symbol)); if (OB_FAIL(ret)) { } else if (!symbol->is_readonly()) { OZ (func.add_out_arg(i)); if (OB_SUCC(ret) && (0 == symbol->get_name().case_compare(ObPLResolver::ANONYMOUS_INOUT_ARG) || 0 == symbol->get_name().case_compare(ObPLResolver::ANONYMOUS_SQL_ARG))) { OZ (func.add_in_arg(i)); } } else { OZ (func.add_in_arg(i)); } if (OB_SUCC(ret) && OB_NOT_NULL(params) && 0 == symbol->get_name().case_compare(ObPLResolver::ANONYMOUS_SQL_ARG)) { params->at(i).set_need_to_check_type(false); } } if (OB_SUCC(ret)) { //anonymous + ps情况func也需要进plan cache,因此需要设置version int64_t tenant_id = session_info_.get_effective_tenant_id(); int64_t tenant_schema_version = OB_INVALID_VERSION; int64_t sys_schema_version = OB_INVALID_VERSION; if (OB_FAIL(schema_guard_.get_schema_version(tenant_id, tenant_schema_version)) || OB_FAIL(schema_guard_.get_schema_version(OB_SYS_TENANT_ID, sys_schema_version))) { LOG_WARN("fail to get schema version", K(ret), K(tenant_id)); } else { func.get_stat_for_update().pl_cg_mem_hold_ = cg_jit_mem; func.set_tenant_schema_version(tenant_schema_version); func.set_sys_schema_version(sys_schema_version); } } if (OB_SUCC(ret) && OB_FAIL(check_dep_schema(schema_guard_, func.get_dependency_table()))) { LOG_WARN("fail to check schema version", K(ret)); } } // end of HEAP_VAR } } int64_t compile_end = ObTimeUtility::current_time(); OX (func.get_stat_for_update().compile_time_ = compile_end - compile_start); OX (session_info_.add_plsql_compile_time(compile_end - compile_start)); LOG_INFO(">>>>>>>>Final Compile Anonymous Block Time: ", K(ret), K(stmt_id), K(compile_end - compile_start)); return ret; } int ObPLCompiler::read_dll_from_disk(bool enable_persistent, ObRoutinePersistentInfo &routine_storage, ObPLFunctionAST &func_ast, ObPLCodeGenerator &cg, const ObRoutineInfo &routine, ObPLFunction &func, ObRoutinePersistentInfo::ObPLOperation &op) { int ret = OB_SUCCESS; if (enable_persistent) { OZ (routine_storage.read_dll_from_disk( &session_info_, schema_guard_, func.get_exec_env(), func_ast, func, op)); } if (OB_SUCC(ret) && func.get_action() != 0) { OZ (cg.prepare_expression(func)); OZ (cg.final_expression(func)); OZ (func.set_variables(func_ast.get_symbol_table())); OZ (func.set_types(func_ast.get_user_type_table())); OZ (func.get_dependency_table().assign(func_ast.get_dependency_table())); OZ (func.add_members(func_ast.get_flag())); OX (func.set_pipelined(func_ast.get_pipelined())); OX (func.set_can_cached(func_ast.get_can_cached())); OX (func.set_is_all_sql_stmt(func_ast.get_is_all_sql_stmt())); OX (func.set_has_parallel_affect_factor(func_ast.has_parallel_affect_factor())); } return ret; } //for function/ procedure int ObPLCompiler::compile(const uint64_t id, ObPLFunction &func) { int ret = OB_SUCCESS; ObPLASHGuard plash_guard(ObPLASHGuard::ObPLASHStatus::IS_PLSQL_COMPILATION); HEAP_VAR(ObPLFunctionAST, func_ast, allocator_) { const share::schema::ObRoutineInfo *routine = NULL; OZ (schema_guard_.get_routine_info(get_tenant_id_by_object_id(id), id, routine)); if (OB_SUCC(ret) && OB_ISNULL(routine)) { ret = OB_ERR_SP_DOES_NOT_EXIST; LOG_WARN("routine info is not exist!", K(ret), K(id)); } OZ (init_function(routine, func)); OZ (compile(*routine, func_ast, func)); } return ret; } int ObPLCompiler::compile( const share::schema::ObRoutineInfo &routine, ObPLFunctionAST &func_ast, ObPLFunction &func) { int ret = OB_SUCCESS; FLTSpanGuard(pl_compile); ObPLCompilerEnvGuard env_guard(routine, session_info_, schema_guard_, ret); const share::schema::ObDatabaseSchema *db_schema = NULL; int64_t init_start = ObTimeUtility::current_time(); //Step 1: Initialize AST if (OB_SUCC(ret)) { func_ast.set_name(routine.get_routine_name()); func_ast.set_id(routine.get_routine_id()); func_ast.set_subprogram_id(routine.get_routine_id()); if (routine.is_udt_routine()) { func_ast.set_is_udt_routine(); } if (routine.is_invoker_right()) { func_ast.get_compile_flag().add_invoker_right(); } if (routine.is_pipelined()) { func_ast.set_pipelined(); } if (routine.is_procedure() && (ROUTINE_PROCEDURE_TYPE == routine.get_routine_type() || ROUTINE_UDT_TYPE == routine.get_routine_type())) { func_ast.set_proc_type(STANDALONE_PROCEDURE); } else if (routine.is_function() && (ROUTINE_FUNCTION_TYPE == routine.get_routine_type() || ROUTINE_UDT_TYPE == routine.get_routine_type())) { func_ast.set_proc_type(STANDALONE_FUNCTION); } OZ (schema_guard_.get_database_schema(routine.get_tenant_id(), routine.get_database_id(), db_schema)); CK (OB_NOT_NULL(db_schema)); OX (func_ast.set_db_name(db_schema->get_database_name_str())); for (int64_t i = 0; OB_SUCC(ret) && i < routine.get_routine_params().count(); ++i) { ObRoutineParam *param = routine.get_routine_params().at(i); ObPLDataType param_type; ObSEArray deps; CK (OB_NOT_NULL(param)); OX (param_type.set_enum_set_ctx(&func_ast.get_enum_set_ctx())); OZ (pl::ObPLDataType::transform_from_iparam(param, schema_guard_, session_info_, allocator_, sql_proxy_, param_type, &deps)); if (OB_FAIL(ret)) { } else if (param->is_ret_param()) { func_ast.set_ret_type(param_type); if (ob_is_enum_or_set_type(param->get_param_type().get_obj_type())) { OZ (func_ast.set_ret_type_info(param->get_extended_type_info(), &func_ast.get_enum_set_ctx())); } } else { OZ (func_ast.add_argument(param->get_param_name(), param_type, NULL, &(param->get_extended_type_info()), param->is_in_sp_param(), param->is_self_param())); } OZ (ObPLDependencyUtil::add_dependency_objects(&func_ast.get_dependency_table(), deps)); } ObSchemaObjVersion obj_version(routine.get_routine_id(), routine.get_schema_version(), routine.is_procedure() ? DEPENDENCY_PROCEDURE : DEPENDENCY_FUNCTION); OZ (ObPLDependencyUtil::add_dependency_object_impl(func_ast.get_dependency_table(), obj_version)); } int64_t init_end = ObTimeUtility::current_time(); LOG_INFO(">>>>>>>>Init AST Time: ", K(routine.get_routine_id()), K(routine.get_routine_name()), K(init_end - init_start)); //Step 2: Parser ObStmtNodeTree *parse_tree = NULL; if (OB_SUCC(ret)) { ObString body = routine.get_routine_body(); ObDataTypeCastParams dtc_params = session_info_.get_dtc_params(); ObPLParser parser(allocator_, session_info_.get_charsets4parser(), session_info_.get_sql_mode()); OZ (ObSQLUtils::convert_sql_text_from_schema_for_resolve(allocator_, dtc_params, body), K(body)); OZ (parser.parse_routine_body(body, parse_tree, session_info_.is_for_trigger_package()), K(body)); } int64_t parse_end = ObTimeUtility::current_time(); LOG_INFO(">>>>>>>>Parse Time: ", K(routine.get_routine_id()), K(routine.get_routine_name()), K(parse_end - init_end)); //Step 3: Resolver if (OB_SUCC(ret)) { bool is_prepare_protocol = false; ObPLResolver resolver(allocator_, session_info_, schema_guard_, package_guard_, sql_proxy_, func_ast.get_expr_factory(), NULL/*parent ns*/, false/*is_prepare_protocol*/); CK (OB_NOT_NULL(parse_tree)); OZ (resolver.init(func_ast)); OZ (resolver.init_default_exprs(func_ast, routine.get_routine_params())); OZ (resolver.resolve_root(parse_tree, func_ast)); if (session_info_.is_pl_debug_on()) { OZ (func_ast.generate_symbol_debuginfo()); } ObErrorInfo error_info; error_info.set_tenant_id(routine.get_tenant_id()); if (OB_SUCC(ret)) { OZ (error_info.delete_error(&routine)); } else { int tmp_ret = OB_SUCCESS; LOG_USER_WARN(OB_ERR_PACKAGE_COMPILE_ERROR, "ROUTINE", func_ast.get_db_name().length(), func_ast.get_db_name().ptr(), func_ast.get_name().length(), func_ast.get_name().ptr()); if (OB_SUCCESS != (tmp_ret = error_info.handle_error_info(&routine))) { LOG_WARN("handler compile routine error failed", K(ret), KR(tmp_ret), K(routine)); } } } OX (func.set_profiler_unit_info(routine.get_routine_id(), func.get_proc_type())); int64_t resolve_end = ObTimeUtility::current_time(); LOG_INFO(">>>>>>>>Resolve Time: ", K(routine.get_routine_id()), K(routine.get_routine_name()), K(resolve_end - parse_end)); //Step 4: Code Generator if (OB_SUCC(ret)) { #ifdef USE_MCJIT HEAP_VAR(ObPLCodeGenerator, cg, allocator_, session_info_) { #else HEAP_VAR(ObPLCodeGenerator, cg, func.get_allocator(), session_info_, schema_guard_, func_ast, func.get_expressions(), func.get_helper(), func.get_di_helper(), lib::is_oracle_mode()) { #endif int64_t cg_jit_mem = 0; ObPLCGMallocCallback pmcb(cg_jit_mem); lib::ObMallocCallbackGuard memory_guard(pmcb); lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(MTL_ID(), GET_PL_MOD_STRING(OB_PL_CODE_GEN))); ObRoutinePersistentInfo::ObPLOperation op = ObRoutinePersistentInfo::ObPLOperation::NONE; ObRoutinePersistentInfo routine_storage( MTL_ID(), routine.get_database_id(), session_info_.get_database_id(), func_ast.get_id(), routine.get_tenant_id()); bool exist_same_name_obj_with_public_synonym = false; OZ (ObRoutinePersistentInfo::has_same_name_dependency_with_public_synonym(schema_guard_, func_ast.get_dependency_table(), exist_same_name_obj_with_public_synonym, session_info_)); bool enable_persistent = GCONF._enable_persistent_compiled_routine && func_ast.get_can_cached() && !func_ast.has_incomplete_rt_dep_error() && !cg.get_debug_mode() && !cg.get_profile_mode() && !exist_same_name_obj_with_public_synonym && (!func_ast.get_is_all_sql_stmt() || !func_ast.get_obj_access_exprs().empty()); OZ (cg.init()); OZ (read_dll_from_disk(enable_persistent, routine_storage, func_ast, cg, routine, func, op)); if (OB_SUCC(ret) && 0 == func.get_action()) { // not in disk // latch_id = (bucket_id % bucket_cnt_) / 8, so it is needed to multiply 8 to avoid consecutive ids being mapped to the same latch ObBucketHashWLockGuard compile_id_guard(GCTX.pl_engine_->get_jit_lock().first, routine.get_routine_id() * 8); ObBucketHashWLockGuard compile_num_guard(GCTX.pl_engine_->get_jit_lock().second, (routine.get_routine_id() % GCONF._ob_pl_compile_max_concurrency) * 8); OZ (ObPL::check_session_alive(session_info_)); OZ (read_dll_from_disk(enable_persistent, routine_storage, func_ast, cg, routine, func, op)); // has lock, try read dll again if (OB_SUCC(ret) && 0 == func.get_action()) { // nobody code gen yet! do real code generate OZ (cg.generate(func)); if (enable_persistent) { OZ (routine_storage.process_storage_dll(allocator_, schema_guard_, func, op)); } } } if (OB_SUCC(ret)) { OZ (func.set_tenant_sys_schema_version(schema_guard_, session_info_.get_effective_tenant_id())); OX (func.set_ret_type(func_ast.get_ret_type())); OX (func.get_stat_for_update().schema_version_ = routine.get_schema_version()); OX (func.get_stat_for_update().pl_cg_mem_hold_ = cg_jit_mem); } OZ (check_dep_schema(schema_guard_, func.get_dependency_table())); } // end heap var } int64_t cg_end = ObTimeUtility::current_time(); LOG_INFO(">>>>>>>>CG Time: ", K(routine.get_routine_id()), K(routine.get_routine_name()), K(cg_end - resolve_end)); int64_t final_end = ObTimeUtility::current_time(); LOG_INFO(">>>>>>>>Final Compile Routine Time: ", K(routine.get_routine_id()), K(routine.get_routine_name()), K(final_end - init_start)); OX (func.get_stat_for_update().compile_time_ = final_end - init_start); OX (session_info_.add_plsql_compile_time(final_end - init_start)); ObErrorInfo error_info; error_info.set_tenant_id(routine.get_tenant_id()); if (OB_SUCC(ret)) { OZ (error_info.delete_error(&routine)); } else { int tmp_ret = OB_SUCCESS; if (NULL != db_schema) { LOG_USER_WARN(OB_ERR_PACKAGE_COMPILE_ERROR, "ROUTINE", db_schema->get_database_name_str().length(), db_schema->get_database_name_str().ptr(), routine.get_routine_name().length(), routine.get_routine_name().ptr()); } if (OB_SUCCESS != (tmp_ret = error_info.handle_error_info(&routine))) { LOG_WARN("handler compile udt error failed", K(ret), KR(tmp_ret), K(routine)); } } return ret; } int ObPLCompiler::update_schema_object_dep_info(ObIArray &dp_tbl, uint64_t tenant_id, uint64_t owner_id, uint64_t dep_obj_id, uint64_t schema_version, ObObjectType dep_obj_type) { int ret = OB_SUCCESS; ObMySQLProxy *sql_proxy = nullptr; ObMySQLTransaction trans; bool skip = false; if (!MTL_TENANT_ROLE_CACHE_IS_PRIMARY()) { skip = true; } else if (ObTriggerInfo::is_trigger_package_id(dep_obj_id)) { if (lib::is_oracle_mode()) { dep_obj_id = ObTriggerInfo::get_package_trigger_id(dep_obj_id); dep_obj_type = ObObjectType::TRIGGER; } else { skip = true; } } if (!skip) { if (OB_ISNULL(sql_proxy = GCTX.sql_proxy_)) { ret = OB_ERR_UNEXPECTED; } else if (OB_FAIL(trans.start(sql_proxy, tenant_id))) { LOG_WARN("failed to start trans", K(ret), K(tenant_id)); } else { OZ (ObDependencyInfo::delete_schema_object_dependency(trans, tenant_id, dep_obj_id, schema_version, dep_obj_type)); ObSArray dep_infos; ObString dummy; OZ (ObDependencyInfo::collect_dep_infos(dp_tbl, dep_infos, dep_obj_type, 0, dummy, dummy)); if (OB_FAIL(ret)) { LOG_WARN("delete failed", K(ret)); } else if (OB_INVALID_ID == owner_id || OB_INVALID_ID == dep_obj_id || OB_INVALID_ID == tenant_id || OB_INVALID_SCHEMA_VERSION == schema_version) { ret = OB_ERR_UNEXPECTED; LOG_WARN("illegal schema version or owner id", K(ret), K(schema_version), K(owner_id), K(dep_obj_id)); } else { for (int64_t i = 0 ; OB_SUCC(ret) && i < dep_infos.count(); ++i) { ObDependencyInfo & dep = dep_infos.at(i); dep.set_tenant_id(tenant_id); dep.set_dep_obj_id(dep_obj_id); dep.set_dep_obj_owner_id(owner_id); dep.set_schema_version(schema_version); OZ (dep.insert_schema_object_dependency(trans)); // 理论上pl是单线程编译的,但是如果把这个相同的pl在多个observer上同时编译,这个依赖关系可能会多次重建。 // 发生这种情况下,简单的忽略错误码 if (OB_ERR_PRIMARY_KEY_DUPLICATE == ret) { ret = OB_SUCCESS; } } } } if (trans.is_started()) { int temp_ret = OB_SUCCESS; if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCC(ret)))) { LOG_WARN("trans end failed", "is_commit", OB_SUCCESS == ret, K(ret), K(temp_ret)); ret = OB_SUCC(ret) ? temp_ret : ret; } } } return ret; } int ObPLCompiler::check_package_body_legal(const ObPLBlockNS *parent_ns, const ObPLPackageAST &package_ast) { int ret = OB_SUCCESS; const ObPLRoutineTable* spec_routine_table = parent_ns->get_routine_table(); const ObPLRoutineTable& body_routine_table = package_ast.get_routine_table(); CK (OB_NOT_NULL(spec_routine_table)); for (int i = ObPLRoutineTable::NORMAL_ROUTINE_START_IDX; OB_SUCC(ret) && i < spec_routine_table->get_count(); ++i) { const ObPLRoutineInfo* spec_routine_info = NULL; const ObPLRoutineInfo* body_routine_info = NULL; bool exist = false; OZ (spec_routine_table->get_routine_info(i, spec_routine_info)); CK (OB_NOT_NULL(spec_routine_info)); OZ (body_routine_table.get_routine_info(i, body_routine_info)); if (OB_SUCC(ret) && OB_NOT_NULL(body_routine_info)) { OZ (spec_routine_info->is_equal(body_routine_info, exist)); } if (OB_SUCC(ret) && !exist) { ret = OB_ERR_ITEM_NOT_IN_BODY; LOG_USER_ERROR(OB_ERR_ITEM_NOT_IN_BODY, spec_routine_info->get_name().length(), spec_routine_info->get_name().ptr()); LOG_WARN("PLS-00323: subprogram or cursor is declared in a package specification and must be defined in the package body", K(ret), K(i), K(spec_routine_info->get_decl_str())); ObPL::insert_error_msg(ret); ObPLResolver::record_error_line(session_info_, spec_routine_info->get_line_number(), spec_routine_info->get_col_number()); } } CK (OB_NOT_NULL(parent_ns->get_cursor_table())); for (int i = 0; OB_SUCC(ret) && i < parent_ns->get_cursor_table()->get_count(); ++i) { const ObPLCursor *cursor = parent_ns->get_cursor_table()->get_cursor(i); CK (OB_NOT_NULL(cursor)); if (OB_SUCC(ret) && cursor->get_state() != ObPLCursor::DEFINED) { const ObPLVar *var = NULL; OZ (parent_ns->get_cursor_var( cursor->get_package_id(), cursor->get_routine_id(), cursor->get_index(), var)); CK (OB_NOT_NULL(var)); if (OB_SUCC(ret)) { ret = OB_ERR_ITEM_NOT_IN_BODY; LOG_WARN("PLS-00323: subprogram or cursor is declared in a package specification and must be defined in the package body", K(ret), K(i)); LOG_USER_ERROR(OB_ERR_ITEM_NOT_IN_BODY, var->get_name().length(), var->get_name().ptr()); } } } return ret; } int ObPLCompiler::analyze_package(const ObString &source, const ObPLBlockNS *parent_ns, ObPLPackageAST &package_ast, bool is_for_trigger) { int ret = OB_SUCCESS; bool origin_is_for_trigger = session_info_.is_for_trigger_package(); session_info_.set_for_trigger_package(is_for_trigger); CK (!source.empty()); CK (package_ast.is_inited()); if (OB_SUCC(ret)) { ObPLParser parser(allocator_, session_info_.get_charsets4parser(), session_info_.get_sql_mode()); ObStmtNodeTree *parse_tree = NULL; CHECK_COMPATIBILITY_MODE(&session_info_); ObPLResolver resolver(allocator_, session_info_, schema_guard_, package_guard_, sql_proxy_, package_ast.get_expr_factory(), parent_ns, false); const ObTriggerInfo *trg_info = NULL; if (PL_PACKAGE_BODY == package_ast.get_package_type() && is_for_trigger) { uint64_t trg_id = ObTriggerInfo::get_package_trigger_id(package_ast.get_id()); OZ (schema_guard_.get_trigger_info(session_info_.get_effective_tenant_id(), trg_id, trg_info)); CK (OB_NOT_NULL(trg_info)); } if (OB_SUCC(ret) && is_for_trigger && PL_PACKAGE_SPEC == package_ast.get_package_type()) { const uint64_t trg_id = ObTriggerInfo::get_package_trigger_id(package_ast.get_id()); const ObTriggerInfo *trg_info = NULL; const uint64_t tenant_id = session_info_.get_effective_tenant_id(); OZ (schema_guard_.get_trigger_info(tenant_id, trg_id, trg_info)); OV (OB_NOT_NULL(trg_info), OB_ERR_UNEXPECTED, trg_id); if (OB_SUCC(ret) && !trg_info->get_ref_trg_db_name().empty() && lib::is_oracle_mode()) { uint64_t ref_db_id = OB_INVALID_ID; const ObTriggerInfo *ref_trg_info = NULL; OV (!trg_info->get_ref_trg_db_name().empty()); OZ (schema_guard_.get_database_id(tenant_id, trg_info->get_ref_trg_db_name(), ref_db_id)); OZ (schema_guard_.get_trigger_info(tenant_id, ref_db_id, trg_info->get_ref_trg_name(), ref_trg_info)); if (OB_SUCC(ret) && NULL == ref_trg_info) { ret = OB_ERR_TRIGGER_NOT_EXIST; LOG_WARN("ref_trg_info is NULL", K(trg_info->get_ref_trg_db_name()), K(trg_info->get_ref_trg_name()), K(ret)); if (lib::is_oracle_mode()) { LOG_ORACLE_USER_ERROR(OB_ERR_TRIGGER_NOT_EXIST, trg_info->get_ref_trg_name().length(), trg_info->get_ref_trg_name().ptr()); } } if (OB_SUCC(ret)) { ObSchemaObjVersion obj_version; obj_version.object_id_ = ref_trg_info->get_trigger_id(); obj_version.object_type_ = DEPENDENCY_TRIGGER; obj_version.version_ = ref_trg_info->get_schema_version(); OZ (ObPLDependencyUtil::add_dependency_object_impl(package_ast.get_dependency_table(), obj_version)); } } } OZ (parser.parse_package(source, parse_tree, session_info_.get_dtc_params(), &schema_guard_, is_for_trigger, trg_info)); OZ (resolver.init(package_ast)); OZ (resolver.resolve(parse_tree, package_ast)); if (OB_SUCC(ret) && PL_PACKAGE_SPEC == package_ast.get_package_type()) { package_ast.process_default_compile_flag(); package_ast.process_generic_type(); } //external_ns's lifetime is same with ObPLResolver, but we need package ast's namespace info outside(except external ns) //explicit set to null in case of wild pointer if (OB_NOT_NULL(package_ast.get_body())) { (const_cast(package_ast.get_body()->get_namespace())).set_external_ns(NULL); } } if (OB_SUCC(ret) && OB_NOT_NULL(parent_ns)) { // after resolve package body, check package legal OZ (check_package_body_legal(parent_ns, package_ast)); } session_info_.set_for_trigger_package(origin_is_for_trigger); return ret; } int ObPLCompiler::generate_package(const ObString &exec_env, ObPLPackageAST &package_ast, ObPLPackage &package, bool &is_from_disk) { int ret = OB_SUCCESS; CK (OB_NOT_NULL(session_info_.get_pl_engine())); OX (is_from_disk = false); if (OB_SUCC(ret)) { WITH_CONTEXT(package.get_mem_context()) { ObRoutinePersistentInfo routine_storage(MTL_ID(), session_info_.get_database_id(), session_info_.get_database_id(), package.get_id(), get_tenant_id_by_object_id(package.get_id())); ObRoutinePersistentInfo::ObPLOperation op = ObRoutinePersistentInfo::ObPLOperation::NONE; bool exist_same_name_obj_with_public_synonym = false; OZ (ObRoutinePersistentInfo::has_same_name_dependency_with_public_synonym(schema_guard_, package_ast.get_dependency_table(), exist_same_name_obj_with_public_synonym, session_info_)); bool enable_persistent = GCONF._enable_persistent_compiled_routine && package_ast.get_can_cached() && session_info_.get_pl_profiler() == nullptr && !exist_same_name_obj_with_public_synonym && (!session_info_.is_pl_debug_on() || get_tenant_id_by_object_id(package.get_id()) == OB_SYS_TENANT_ID); CK (package.is_inited()); OZ (package.get_dependency_table().assign(package_ast.get_dependency_table())); OZ (generate_package_conditions(package_ast.get_condition_table(), package)); OZ (generate_package_vars(package_ast, package_ast.get_symbol_table(), package)); OZ (generate_package_types(package_ast.get_user_type_table(), package)); if (enable_persistent) { sql::ObExecEnv env; OZ (env.init(exec_env)); OZ (routine_storage.read_dll_from_disk(&session_info_, schema_guard_, env, package_ast, package, op)); } if (op == ObRoutinePersistentInfo::ObPLOperation::SUCC) { OX (is_from_disk = true); } else { // latch_id = (bucket_id % bucket_cnt_) / 8, so it is needed to multiply 8 to avoid consecutive ids being mapped to the same latch ObBucketHashWLockGuard compile_id_guard(GCTX.pl_engine_->get_jit_lock().first, package.get_id() * 8); ObBucketHashWLockGuard compile_num_guard(GCTX.pl_engine_->get_jit_lock().second, (package.get_id() % GCONF._ob_pl_compile_max_concurrency) * 8); OZ (ObPL::check_session_alive(session_info_)); if (OB_SUCC(ret)) { if (enable_persistent) { sql::ObExecEnv env; OZ (env.init(exec_env)); OZ (routine_storage.read_dll_from_disk(&session_info_, schema_guard_, env, package_ast, package, op)); } if (op == ObRoutinePersistentInfo::ObPLOperation::SUCC) { OX (is_from_disk = true); } else { OZ (generate_package_routines(exec_env, package_ast.get_routine_table(), package)); if (enable_persistent) { OZ (routine_storage.process_storage_dll(allocator_, schema_guard_, package, op)); } } } } OZ (generate_package_cursors(package_ast, package_ast.get_cursor_table(), package)); } } return ret; } int ObPLCompiler::compile_package(const ObPackageInfo &package_info, const ObPLBlockNS *parent_ns, ObPLPackageAST &package_ast, ObPLPackage &package) { int ret = OB_SUCCESS; bool saved_trigger_flag = session_info_.is_for_trigger_package(); ObString source; int64_t compile_start = ObTimeUtility::current_time(); ObPLCompilerEnvGuard guard(package_info, session_info_, schema_guard_, ret, parent_ns); ObPLASHGuard plash_guard(ObPLASHGuard::ObPLASHStatus::IS_PLSQL_COMPILATION); session_info_.set_for_trigger_package(package_info.is_for_trigger()); if (OB_NOT_NULL(parent_ns)) { if (parent_ns->get_compile_flag().compile_with_invoker_right()) { OZ (package_ast.get_compile_flag().add_invoker_right()); } } else if (package_info.is_invoker_right()) { OZ (package_ast.get_compile_flag().add_invoker_right()); } if (OB_SUCC(ret)) { ObString copy_exec_env; OZ (ob_write_string(package.get_allocator(), package_info.get_exec_env(), copy_exec_env)); OZ (package.get_exec_env().init(copy_exec_env)); } const ObTriggerInfo *trigger_info = nullptr; if (OB_SUCC(ret) && package_info.is_for_trigger()) { uint64_t trigger_id = ObTriggerInfo::get_package_trigger_id(package_info.get_package_id()); const uint64_t tenant_id = get_tenant_id_by_object_id(trigger_id); OZ (schema_guard_.get_trigger_info(tenant_id, trigger_id, trigger_info)); OX (package_ast.set_priv_user(trigger_info->get_trigger_priv_user())); } if (OB_SUCC(ret)) { if (package_info.is_for_trigger()) { OZ (ObTriggerInfo::gen_package_source(package_info.get_tenant_id(), package_info.get_package_id(), source, schema::PACKAGE_TYPE == package_info.get_type(), schema_guard_, package.get_allocator())); LOG_DEBUG("trigger package source", K(source), K(package_info.get_type()), K(ret)); } else { source = package_info.get_source(); } } OZ (ObSQLUtils::convert_sql_text_from_schema_for_resolve( allocator_, session_info_.get_dtc_params(), source)); OZ (analyze_package(source, parent_ns, package_ast, package_info.is_for_trigger())); #ifdef OB_BUILD_ORACLE_PL if (package_info.is_package()) { int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = ObPLPackageType::update_package_type_info(package_info, package_ast, OB_FAIL(ret)))) { LOG_WARN("update package type info failed", K(tmp_ret), K(ret)); ret = OB_SUCC(ret) ? tmp_ret : ret; } } #endif bool is_from_disk = false; { if (OB_SUCC(ret)) { #ifdef USE_MCJIT HEAP_VAR(ObPLCodeGenerator, cg ,allocator_, session_info_) { #else HEAP_VAR(ObPLCodeGenerator, cg, package.get_allocator(), session_info_, schema_guard_, package_ast, package.get_expressions(), package.get_helper(), package.get_di_helper(), lib::is_oracle_mode()) { #endif int64_t cg_jit_mem = 0; ObPLCGMallocCallback pmcb(cg_jit_mem); lib::ObMallocCallbackGuard memory_guard(pmcb); lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(MTL_ID(), GET_PL_MOD_STRING(pl::OB_PL_CODE_GEN))); // latch_id = (bucket_id % bucket_cnt_) / 8, so it is needed to multiply 8 to avoid consecutive ids being mapped to the same latch ObBucketHashWLockGuard compile_id_guard(GCTX.pl_engine_->get_jit_lock().first, package.get_id() * 8); ObBucketHashWLockGuard compile_num_guard(GCTX.pl_engine_->get_jit_lock().second, (package.get_id() % GCONF._ob_pl_compile_max_concurrency) * 8); // check session status after get lock OZ (ObPL::check_session_alive(session_info_)); OZ (cg.init()); OZ (cg.generate(package)); OX (package.get_stat_for_update().pl_cg_mem_hold_ = cg_jit_mem); } } OZ (generate_package(package_info.get_exec_env(), package_ast, package, is_from_disk)); } OX (package.set_can_cached(package_ast.get_can_cached())); OX (package_ast.get_serially_reusable() ? package.set_serially_reusable() : void(NULL)); session_info_.set_for_trigger_package(saved_trigger_flag); OZ (check_dep_schema(schema_guard_, package.get_dependency_table())); if (OB_SUCC(ret) && !is_from_disk) { ObMutexGuard guard(package_dep_info_lock_); OZ (update_schema_object_dep_info(package_ast.get_dependency_table(), package_info.get_tenant_id(), package_info.get_owner_id(), package_info.get_package_id(), package_info.get_schema_version(), package_info.get_object_type())); } ObErrorInfo error_info; error_info.set_tenant_id(package_info.get_tenant_id()); if (OB_SUCC(ret)) { if (package_info.is_for_trigger()) { CK (OB_NOT_NULL(trigger_info)); OZ (error_info.delete_error(trigger_info)); } else { OZ (error_info.delete_error(&package_info)); } } else { int tmp_ret = ret; ret = OB_SUCCESS; const ObDatabaseSchema *db_schema = NULL; OZ (schema_guard_.get_database_schema(package_info.get_tenant_id(), package_info.get_database_id(), db_schema)); CK (OB_NOT_NULL(db_schema)); if (OB_SUCC(ret)) { if (package_info.is_for_trigger()) { LOG_USER_WARN(OB_ERR_TRIGGER_COMPILE_ERROR, "TRIGGER", db_schema->get_database_name_str().length(), db_schema->get_database_name_str().ptr(), package_info.get_package_name().length(), package_info.get_package_name().ptr()); CK (OB_NOT_NULL(trigger_info)); OZ (error_info.handle_error_info(trigger_info)); } else { LOG_USER_WARN(OB_ERR_PACKAGE_COMPILE_ERROR, "PACKAGE", db_schema->get_database_name_str().length(), db_schema->get_database_name_str().ptr(), package_info.get_package_name().length(), package_info.get_package_name().ptr()); OZ (error_info.handle_error_info(&package_info)); } } ret = tmp_ret; } if (OB_SUCC(ret)) { int64_t public_syn_cnt = 0; int64_t tenant_id = session_info_.get_effective_tenant_id(); int64_t tenant_schema_version = OB_INVALID_VERSION; int64_t sys_schema_version = OB_INVALID_VERSION; OZ (schema_guard_.get_schema_version(tenant_id, tenant_schema_version)); OZ (schema_guard_.get_schema_version(OB_SYS_TENANT_ID, sys_schema_version)); OX (package.set_tenant_schema_version(tenant_schema_version)); OX (package.set_sys_schema_version(sys_schema_version)); for (int64_t i = 0; OB_SUCC(ret) && i < package.get_dependency_table().count(); ++i) { uint64_t object_id = package.get_dependency_table().at(i).object_id_; if (SYNONYM_SCHEMA == package.get_dependency_table().at(i).get_schema_type()) { const ObSimpleSynonymSchema *synonym_info = nullptr; if (OB_FAIL(schema_guard_.get_simple_synonym_info(tenant_id, object_id, synonym_info))) { LOG_WARN("failed to get synonym_info", K(ret), K(object_id)); } else if (OB_NOT_NULL(synonym_info) && OB_PUBLIC_SCHEMA_ID == synonym_info->get_database_id()) { public_syn_cnt++; } } } OX (package.set_public_syn_count(public_syn_cnt)); } int64_t compile_end = ObTimeUtility::current_time(); OX (package.get_stat_for_update().compile_time_ = compile_end - compile_start); OX (session_info_.add_plsql_compile_time(compile_end - compile_start)); OZ (package.set_tenant_sys_schema_version(schema_guard_, session_info_.get_effective_tenant_id())); if (package_info.is_for_trigger()) { CK (OB_NOT_NULL(trigger_info)); OX (package.get_stat_for_update().schema_version_ = trigger_info->get_schema_version()); } else { OX (package.get_stat_for_update().schema_version_ = package_info.get_schema_version()); } OX (package.get_stat_for_update().name_ = package.get_name()); if (PL_PACKAGE_BODY == package_ast.get_package_type()) { OX (package.get_stat_for_update().type_ = ObPLCacheObjectType::PACKAGE_BODY_TYPE); } else { OX (package.get_stat_for_update().type_ = ObPLCacheObjectType::PACKAGE_TYPE); } LOG_INFO(">>>>>>>>Final Compile Package Time: ", K(package.get_id()), K(package.get_name()), K(compile_end - compile_start)); return ret; } int ObPLCompiler::init_function(const share::schema::ObRoutineInfo *routine, ObPLFunction &func) { int ret = OB_SUCCESS; ObString copy_exec_env; if (OB_ISNULL(routine)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("routine info is NULL", K(routine), K(ret)); } else if (OB_FAIL(ob_write_string(func.get_allocator(), routine->get_exec_env(), copy_exec_env))) { LOG_WARN("failed to copy exec env", K(ret), K(routine->get_exec_env())); } else if (OB_FAIL(func.get_exec_env().init(copy_exec_env))) { LOG_WARN("Failed to load exec env", K(ret)); } else { const ObUDTTypeInfo *udt_info = NULL; if (routine->is_udt_routine()) { OZ(schema_guard_.get_udt_info(routine->get_tenant_id(), routine->get_package_id(), udt_info)); CK (OB_NOT_NULL(udt_info)); // if type body is droped, the routine is exist in __all_routine, but we can't use it; if (OB_SUCC(ret) && !udt_info->has_type_body()) { ret = OB_ERR_TYPE_BODY_NOT_EXIST; LOG_WARN("type body does not exist", K(routine->get_package_id()), K(ret)); LOG_USER_ERROR(OB_ERR_TYPE_BODY_NOT_EXIST, udt_info->get_type_name().length(), udt_info->get_type_name().ptr()); } } if (OB_SUCC(ret)) { if (routine->is_procedure() && (ROUTINE_PROCEDURE_TYPE == routine->get_routine_type() || ROUTINE_UDT_TYPE == routine->get_routine_type())) { func.set_proc_type(STANDALONE_PROCEDURE); func.set_ns(ObLibCacheNameSpace::NS_PRCR); } else if (routine->is_function() && (ROUTINE_FUNCTION_TYPE == routine->get_routine_type() || ROUTINE_UDT_TYPE == routine->get_routine_type())) { func.set_proc_type(STANDALONE_FUNCTION); func.set_ns(ObLibCacheNameSpace::NS_SFC); } else { // do nothing... } func.set_tenant_id(routine->get_tenant_id()); func.set_database_id(routine->get_database_id()); func.set_package_id(routine->get_package_id()); func.set_routine_id(routine->get_routine_id()); func.set_arg_count(routine->get_param_count()); func.set_owner(routine->get_owner_id()); func.set_priv_user(routine->get_priv_user()); if (routine->is_invoker_right()) { func.set_invoker_right(); } // 对于function而言,输出参数也在params里面,这里不能简单的按照param_count进行遍历 for (int64_t i = 0; OB_SUCC(ret) && i < routine->get_routine_params().count(); ++i) { ObRoutineParam *param = routine->get_routine_params().at(i); int64_t param_pos = param->get_param_position(); if (OB_ISNULL(param)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("routine param is NULL", K(i), K(ret)); } else if (param->is_ret_param()) { // 对于返回值, 既不是in也不是out, 不做处理 } else { if (param->is_inout_sp_param() || param->is_out_sp_param()) { if (OB_FAIL(func.add_out_arg(param_pos - 1))) { LOG_WARN("Failed to add out arg", K(param_pos), K(ret)); } } if (OB_SUCC(ret)) { if (param->is_inout_sp_param() || param->is_in_sp_param()) { if (OB_FAIL(func.add_in_arg(param_pos - 1))) { LOG_WARN("Failed to add out arg", K(i), K(param_pos), K(ret)); } } } } } ObString database_name, package_name; OZ (format_object_name(schema_guard_, routine->get_tenant_id(), routine->get_database_id(), routine->get_package_id(), database_name, package_name)); OZ (func.set_database_name(database_name)); OZ (func.set_package_name(package_name)); OZ (func.set_function_name(routine->get_routine_name())); } } return ret; } int ObPLCompiler::init_function(share::schema::ObSchemaGetterGuard &schema_guard, const sql::ObExecEnv &exec_env, const ObPLRoutineInfo &routine_info, ObPLFunction &routine) { int ret = OB_SUCCESS; routine.set_exec_env(exec_env); const ObIArray ¶m_infos = routine_info.get_params(); int64_t param_cnt = param_infos.count(); routine.set_arg_count(param_cnt); routine.set_proc_type(routine_info.get_type()); routine.set_tenant_id(routine_info.get_tenant_id()); routine.set_database_id(routine_info.get_db_id()); routine.set_package_id(routine_info.get_pkg_id()); routine.set_routine_id(routine_info.get_id()); routine.set_priv_user(routine_info.get_priv_user()); if (routine_info.is_invoker_right()) { routine.set_invoker_right(); } for (int64_t i = 0; OB_SUCC(ret) && i < routine_info.get_params().count(); ++i) { const ObPLRoutineParam *param = routine_info.get_params().at(i); if (param->is_inout_param() || param->is_out_param()) { if (OB_FAIL(routine.add_out_arg(i))) { LOG_WARN("Failed to add out arg", K(i), K(ret)); } } if (OB_SUCC(ret)) { if (param->is_inout_param() || param->is_in_param()) { if (OB_FAIL(routine.add_in_arg(i))) { LOG_WARN("Failed to add in arg", K(i), K(ret)); } } } } ObString database_name, package_name; OZ (format_object_name(schema_guard, routine_info.get_tenant_id(), routine_info.get_db_id(), routine_info.get_pkg_id(), database_name, package_name)); OZ (routine.set_database_name(database_name)); OZ (routine.set_package_name(package_name)); OZ (routine.set_function_name(routine_info.get_name())); return ret; } int ObPLCompiler::generate_package_conditions(const ObPLConditionTable &ast_condition_table, ObPLPackage &package) { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < ast_condition_table.get_count(); ++i) { const ObPLCondition *ast_condition = ast_condition_table.get_condition(i); if (OB_ISNULL(ast_condition)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("pl condition is null", K(ret), K(i), K(package.get_id())); } else { ObIAllocator &alloc = package.get_allocator(); ObPLCondition *package_condition = static_cast(alloc.alloc(sizeof(ObPLCondition))); if (OB_ISNULL(package_condition)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory failed", K(ret), K(package_condition)); } else { ObIArray &package_condition_table = const_cast &>(package.get_condition_table()); new (package_condition) ObPLCondition(); OZ (package_condition->deep_copy(*ast_condition, alloc)); OZ (package_condition_table.push_back(package_condition)); } } } return ret; } int ObPLCompiler::generate_package_cursors( const ObPLPackageAST &package_ast, const ObPLCursorTable &ast_cursor_table, ObPLPackage &package) { int ret = OB_SUCCESS; ObPLCursorTable &cursor_table = const_cast(package.get_cursor_table()); for (int64_t i = 0; OB_SUCC(ret) && i < ast_cursor_table.get_count(); ++i) { const ObPLCursor *ast_cursor = ast_cursor_table.get_cursor(i); if (OB_ISNULL(ast_cursor)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("package ast cursor is null", K(ret), K(i), K(ast_cursor)); } else { ObString sql; ObString ps_sql; ObRecordType *row_desc = NULL; ObPLDataType cursor_type; OZ (ob_write_string(package.get_allocator(), ast_cursor->get_sql(), sql)); OZ (ob_write_string(package.get_allocator(), ast_cursor->get_ps_sql(), ps_sql)); if (OB_SUCC(ret) && OB_NOT_NULL(ast_cursor->get_row_desc())) { row_desc = static_cast(package.get_allocator().alloc(sizeof(ObRecordType))); if (OB_ISNULL(row_desc)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to alloc record memory for record type", K(ret), K(row_desc)); } OX (row_desc = new(row_desc)ObRecordType()); OZ (row_desc->deep_copy(package.get_allocator(), *(ast_cursor->get_row_desc()), false)); } OZ (cursor_type.deep_copy(package.get_allocator(), ast_cursor->get_cursor_type())); //Sql参数表达式,需要Copy下 ObSEArray sql_params; for (int64_t i = 0; OB_SUCC(ret) && i < ast_cursor->get_sql_params().count(); ++i) { ObRawExpr *expr = NULL; CK (OB_NOT_NULL(package_ast.get_expr(ast_cursor->get_sql_params().at(i)))); OZ (ObPLExprCopier::copy_expr(package.get_expr_factory(), package_ast.get_expr(ast_cursor->get_sql_params().at(i)), expr)); CK (OB_NOT_NULL(expr)); //不再构造Exprs,直接将表达式存在int64的数组上 OZ (sql_params.push_back(reinterpret_cast(expr))); } OZ (cursor_table.add_cursor(ast_cursor->get_package_id(), ast_cursor->get_routine_id(), ast_cursor->get_index(),//代表在Package符号表中的位置 sql,//Cursor Sql sql_params,//Cursor参数表达式 ps_sql, ast_cursor->get_stmt_type(), ast_cursor->is_for_update(), ast_cursor->has_hidden_rowid(), ast_cursor->get_rowid_table_id(), ast_cursor->get_ref_objects(), row_desc, cursor_type, ast_cursor->get_formal_params(), ast_cursor->get_state(), ast_cursor->is_dup_column())); } } return ret; } int ObPLCompiler::generate_package_vars( const ObPLPackageAST &package_ast, const ObPLSymbolTable &ast_var_table, ObPLPackage &package) { int ret = OB_SUCCESS; const ObIArray *symbols = NULL; for (int64_t i = 0; OB_SUCC(ret) && i < ast_var_table.get_count(); ++i) { const ObPLVar *ast_var = ast_var_table.get_symbol(i); if (OB_ISNULL(ast_var)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("pl var is null", "package_id", package.get_id(), K(i), K(ret)); } else { ObIAllocator &alloc = package.get_allocator(); ObPLVar *package_var = static_cast(alloc.alloc(sizeof(ObPLVar))); if (OB_ISNULL(package_var)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory failed", K(ret)); } else { new (package_var) ObPLVar(); OZ (package_var->deep_copy(*ast_var, alloc), K(package.get_id()), K(i)); if (OB_SUCC(ret)) { ObIArray &package_var_table = const_cast &>(package.get_var_table()); if (OB_FAIL(package_var_table.push_back(package_var))) { LOG_WARN("package var table add var failed", "package_id", package.get_id(), K(i), K(ret)); } } } } } return ret; } int ObPLCompiler::compile_types(const ObIArray &types, ObPLCompileUnit &unit) { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < types.count(); ++i) { ObUserDefinedType *ast_type = const_cast(types.at(i)); if (OB_ISNULL(ast_type)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("pl user defined type is null", K(i), K(ret)); } else { ObIAllocator &alloc = unit.get_allocator(); ObUserDefinedType *user_type = NULL; switch(ast_type->get_type()) { case PL_RECORD_TYPE: { ObRecordType *record_type = static_cast(alloc.alloc(sizeof(ObRecordType))); if (OB_ISNULL(record_type)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory failed", K(ret), KPC(ast_type), K(i)); } else { new (record_type) ObRecordType(); if (OB_FAIL(record_type->deep_copy(alloc, *(static_cast(ast_type)), false))) { LOG_WARN("pl user type deep copy failed", K(ret), KPC(ast_type), K(i)); } else { user_type = record_type; } } } break; case PL_CURSOR_TYPE: { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected package cursor type, should ref cursor type", K(ret)); } break; case PL_REF_CURSOR_TYPE: { ObRefCursorType *cursor_type = static_cast(alloc.alloc(sizeof(ObRefCursorType))); if (OB_ISNULL(cursor_type)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory for cursor type failed", K(ret), K(cursor_type), KPC(ast_type), K(i)); } else { new (cursor_type) ObRefCursorType(); if (OB_FAIL(cursor_type->deep_copy(alloc, *(static_cast(ast_type))))) { LOG_WARN("deep copy ref cursor type failed", K(ret), KPC(ast_type), K(i)); } else { user_type = cursor_type; } } } break; #ifdef OB_BUILD_ORACLE_PL case PL_NESTED_TABLE_TYPE: { ObNestedTableType *table_type = static_cast(alloc.alloc(sizeof(ObNestedTableType))); if (OB_ISNULL(table_type)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory failed", K(ret), KPC(ast_type), K(i)); } else { new (table_type) ObNestedTableType(); if (OB_FAIL(table_type->deep_copy(alloc, *(static_cast(ast_type))))) { LOG_WARN("pl user type deep copy failed", K(ret), KPC(ast_type), K(i)); } else { user_type = table_type; } } } break; case PL_ASSOCIATIVE_ARRAY_TYPE: { ObAssocArrayType *assoc_array_type = static_cast(alloc.alloc(sizeof(ObAssocArrayType))); if (OB_ISNULL(assoc_array_type)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory failed", K(ret), KPC(ast_type), K(i)); } else { new (assoc_array_type) ObAssocArrayType(); if (OB_FAIL(assoc_array_type->deep_copy(alloc, *(static_cast(ast_type))))) { LOG_WARN("pl user type deep copy failed", K(ret), KPC(ast_type), K(i)); } else { user_type = assoc_array_type; } } } break; case PL_VARRAY_TYPE: { ObVArrayType *varray_type = static_cast(alloc.alloc(sizeof(ObVArrayType))); if (OB_ISNULL(varray_type)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory for varray type failed", K(ret), K(varray_type), KPC(ast_type), K(i)); } else { new (varray_type) ObVArrayType(); if (OB_FAIL(varray_type->deep_copy(alloc, *(static_cast(ast_type))))) { LOG_WARN("deep copy varray type failed", K(ret), KPC(ast_type), K(i)); } else { user_type = varray_type; } } } break; case PL_SUBTYPE: { ObUserDefinedSubType *subtype = static_cast(alloc.alloc(sizeof(ObUserDefinedSubType))); if (OB_ISNULL(subtype)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory for user define sub type", K(ret), K(subtype), KPC(ast_type), K(i)); } else { new(subtype)ObUserDefinedSubType(); OZ (subtype->deep_copy(alloc, *(static_cast(ast_type))), ast_type, i); OX (user_type = subtype); } } break; case PL_OPAQUE_TYPE: { ObOpaqueType *opaqua_type = static_cast(alloc.alloc(sizeof(ObOpaqueType))); if (OB_ISNULL(opaqua_type)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory for cursor type failed", K(ret), K(opaqua_type), KPC(ast_type), K(i)); } else { new (opaqua_type) ObOpaqueType(); if (OB_FAIL(opaqua_type->deep_copy(alloc, *(static_cast(ast_type))))) { LOG_WARN("deep copy ref cursor type failed", K(ret), KPC(ast_type), K(i)); } else { user_type = opaqua_type; } } } break; #endif default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid pl type", K(ret), KPC(ast_type), K(i)); } break; } if (OB_SUCC(ret)) { ObIArray &unit_type_table = const_cast &>(unit.get_type_table()); if (OB_FAIL(unit_type_table.push_back(user_type))) { LOG_WARN("package user type table add type failed", K(ret)); } } } } return ret; } int ObPLCompiler::compile_type_table(const ObPLUserTypeTable &ast_type_table, ObPLCompileUnit &unit) { int ret = OB_SUCCESS; OZ (ObPLCompiler::compile_types(ast_type_table.get_types(), unit)); OZ (ObPLCompiler::compile_types(ast_type_table.get_external_types(), unit)); return ret; } int ObPLCompiler::generate_package_types(const ObPLUserTypeTable &ast_type_table, ObPLCompileUnit &compile_unit) { return ObPLCompiler::compile_types(ast_type_table.get_types(), compile_unit); } int ObPLCompiler::compile_subprogram_table(common::ObIAllocator &allocator, sql::ObSQLSessionInfo &session_info, const sql::ObExecEnv &exec_env, ObPLRoutineTable &routine_table, ObPLCompileUnit &compile_unit, ObSchemaGetterGuard &schema_guard) { int ret = OB_SUCCESS; compile_unit.init_routine_table(routine_table.get_count()); for(int64_t routine_idx = 0; OB_SUCC(ret) && routine_idx < routine_table.get_count(); routine_idx++) { ObPLFunctionAST *routine_ast = NULL; const ObPLRoutineInfo *routine_info = NULL; if (OB_FAIL(ObPL::check_session_alive(session_info))) { LOG_WARN("session is killed or interrupted", K(ret)); } else if (OB_FAIL(routine_table.get_routine_info(routine_idx, routine_info))) { LOG_WARN("get routine info failed", K(ret)); } else if (OB_ISNULL(routine_info)) { //empty routine info is possible when package body is empty, push null to make idx correct if (OB_FAIL(compile_unit.add_routine(NULL))) { LOG_WARN("package add routine failed", K(ret)); } } else if (OB_FAIL(routine_table.get_routine_ast(routine_idx, routine_ast))) { LOG_WARN("get routine ast failed", K(routine_idx), K(ret)); } else if (OB_ISNULL(routine_ast)) { //empty routine ast is possible when package spec generating or package body is empty // push null to make idx correct, will report error when called if (OB_FAIL(compile_unit.add_routine(NULL))) { LOG_WARN("add routine failed", K(ret)); } } else { ObPLFunction *routine = NULL; if (OB_ISNULL(routine = static_cast(compile_unit.get_allocator().alloc(sizeof(ObPLFunction))))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory failed", K(ret)); } else { new (routine) ObPLFunction(compile_unit.get_mem_context()); OZ (init_function(schema_guard, exec_env, *routine_info, *routine)); if (OB_SUCC(ret)) { #ifdef USE_MCJIT HEAP_VAR(ObPLCodeGenerator, cg ,allocator_, session_info) { #else HEAP_VAR(ObPLCodeGenerator, cg, allocator, session_info, schema_guard, *routine_ast, routine->get_expressions(), routine->get_helper(), routine->get_di_helper(), lib::is_oracle_mode()) { #endif lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(MTL_ID(), GET_PL_MOD_STRING(pl::OB_PL_CODE_GEN))); if (OB_FAIL(cg.init())) { LOG_WARN("init code generator failed", K(ret)); } else if (OB_FAIL(cg.generate(*routine))) { LOG_WARN("code generate failed", "routine name", routine_ast->get_name(), K(ret)); } else { routine->set_ret_type(routine_ast->get_ret_type()); if (OB_FAIL(compile_unit.add_routine(routine))) { LOG_WARN("package add routine failed", K(ret)); } } } // end of HEAP_VAR } } if (OB_FAIL(ret) && OB_NOT_NULL(routine)) { routine->~ObPLFunction(); compile_unit.get_allocator().free(routine); routine = NULL; } } } return ret; } int ObPLCompiler::generate_package_routines( const ObString &exec_env, ObPLRoutineTable &routine_table, ObPLPackage &package) { int ret = OB_SUCCESS; sql::ObExecEnv env; if (OB_FAIL(env.init(exec_env))) { LOG_WARN("failed to init exec env", K(exec_env), K(ret)); } else if (OB_FAIL(ObPLCompiler::compile_subprogram_table(allocator_, session_info_, env, routine_table, package, schema_guard_))) { LOG_WARN("failed to compile subprogram table", K(package.get_id()), K(package.get_db_name()), K(package.get_name()), K(ret)); } else { uint64_t package_id = package.get_id(); if (ObTriggerInfo::is_trigger_package_id(package_id)) { package_id = ObTriggerInfo::get_package_trigger_id(package_id); } for (int64_t i = 0; OB_SUCC(ret) && i < package.get_routine_table().count(); ++i) { if (OB_NOT_NULL(package.get_routine_table().at(i))) { package.get_routine_table().at(i)->set_profiler_unit_info( package_id, package.get_routine_table().at(i)->get_proc_type()); OZ (SMART_CALL( ObPLCodeGenerator::set_profiler_unit_info_recursive(*package.get_routine_table().at(i)))); } } } return ret; } int ObPLCompiler::format_object_name(ObSchemaGetterGuard &schema_guard, const uint64_t tenant_id, const uint64_t db_id, const uint64_t package_id, ObString &database_name, ObString &package_name) { int ret = OB_SUCCESS; const ObPackageInfo *pkg_info = NULL; const ObUDTTypeInfo *udt_info = NULL; const ObDatabaseSchema *database_schema = NULL; if (OB_INVALID_ID != db_id) { OZ (schema_guard.get_database_schema(tenant_id, db_id, database_schema)); } if (OB_INVALID_ID != package_id) { OZ (schema_guard.get_package_info(tenant_id, package_id, pkg_info)); if (OB_SUCCESS == ret && NULL == pkg_info) { OZ (schema_guard.get_udt_info(tenant_id, package_id, udt_info)); } } if (OB_SUCC(ret)) { if (OB_NOT_NULL(database_schema)) { OX (database_name = database_schema->get_database_name_str()); } if (OB_NOT_NULL(pkg_info)) { OX (package_name = pkg_info->get_package_name()); } else if (OB_NOT_NULL(udt_info)) { OX (package_name = udt_info->get_type_name()); } } return ret; } ObPLCompilerEnvGuard::ObPLCompilerEnvGuard(const ObPackageInfo &info, ObSQLSessionInfo &session_info, share::schema::ObSchemaGetterGuard &schema_guard, int &ret, const ObPLBlockNS *parent_ns) : ret_(ret), session_info_(session_info) { init(info, session_info, schema_guard, ret, parent_ns); } ObPLCompilerEnvGuard::ObPLCompilerEnvGuard(const ObRoutineInfo &info, ObSQLSessionInfo &session_info, share::schema::ObSchemaGetterGuard &schema_guard, int &ret) : ret_(ret), session_info_(session_info), allocator_() { init(info, session_info, schema_guard, ret); } template void ObPLCompilerEnvGuard::init(const Info &info, ObSQLSessionInfo &session_info, share::schema::ObSchemaGetterGuard &schema_guard, int &ret, const ObPLBlockNS *parent_ns) { ObExecEnv env; bool need_set_db = true; bool is_invoker_right = OB_NOT_NULL(parent_ns) ? parent_ns->get_compile_flag().compile_with_invoker_right() : info.is_invoker_right(); OX (need_reset_exec_env_ = false); OX (need_reset_default_database_ = false); OX (old_db_id_ = OB_INVALID_ID); OZ (old_exec_env_.load(session_info_, &allocator_)); OZ (env.init(info.get_exec_env())); if (OB_SUCC(ret) && old_exec_env_ != env) { OZ (env.store(session_info_)); OX (need_reset_exec_env_ = true); } // in mysql mode, only system packages with invoker's right do not need set db // in oracle mode, set db by if the routine is invoker's right if (OB_SUCC(ret) && (lib::is_oracle_mode() || get_tenant_id_by_object_id(info.get_package_id()) == OB_SYS_TENANT_ID)) { need_set_db = !is_invoker_right; } if (OB_SUCC(ret) && need_set_db && info.get_database_id() != session_info_.get_database_id()) { const share::schema::ObDatabaseSchema *db_schema = NULL; old_db_id_ = session_info_.get_database_id(); OZ (old_db_name_.append(session_info_.get_database_name())); OZ (schema_guard.get_database_schema(info.get_tenant_id(), info.get_database_id(), db_schema)); CK (OB_NOT_NULL(db_schema)); OZ (session_info_.set_default_database(db_schema->get_database_name_str())); OX (session_info_.set_database_id(db_schema->get_database_id())); OX (need_reset_default_database_ = true); } } ObPLCompilerEnvGuard::~ObPLCompilerEnvGuard() { int ret = OB_SUCCESS; if (need_reset_exec_env_) { if ((ret = old_exec_env_.store(session_info_)) != OB_SUCCESS) { ret_ = OB_SUCCESS == ret_ ? ret : ret_; LOG_WARN("failed to restore exec env in pl env guard", K(ret), K(ret_), K(old_exec_env_)); } } if (need_reset_default_database_) { if ((ret = session_info_.set_default_database(old_db_name_.string())) != OB_SUCCESS) { ret_ = OB_SUCCESS == ret_ ? ret : ret_; LOG_WARN("failed to reset default database in pl env guard", K(ret), K(ret_), K(old_db_name_)); } else { session_info_.set_database_id(old_db_id_); } } } } //end namespace pl } //end namespace oceanbase