/** * 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 SQL_RESV #include "ob_create_package_resolver.h" #include "ob_create_package_stmt.h" #include "share/ob_rpc_struct.h" #include "sql/resolver/ob_resolver_utils.h" #include "pl/ob_pl.h" #include "pl/ob_pl_package.h" #include "pl/ob_pl_compile.h" #include "lib/charset/ob_charset.h" namespace oceanbase { using namespace common; using namespace share::schema; using namespace pl; namespace sql { int ObCreatePackageResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; CK (T_PACKAGE_CREATE == parse_tree.type_); CK (CREATE_PACKAGE_NODE_CHILD_COUNT == parse_tree.num_child_); CK (OB_NOT_NULL(parse_tree.children_)); CK (OB_NOT_NULL(session_info_)); if (OB_SUCC(ret) && lib::is_mysql_mode() && OB_SYS_TENANT_ID != session_info_->get_effective_tenant_id()) { ret = OB_NOT_SUPPORTED; LOG_WARN("not supported package in mysql mode", K(ret), K(lbt())); LOG_USER_ERROR(OB_NOT_SUPPORTED, "not supported package in mysql mode"); } if (OB_SUCC(ret)) { bool resolve_success = true; HEAP_VAR(ObPLPackageAST, package_ast, *allocator_) { ObPLPackageGuard package_guard(params_.session_info_->get_effective_tenant_id()); ObPLResolver resolver(*params_.allocator_, *params_.session_info_, *(params_.schema_checker_->get_schema_mgr()), package_guard, *params_.sql_proxy_, *params_.expr_factory_, NULL, false); ObCreatePackageStmt *stmt = NULL; ParseNode *package_block_node = NULL ; ParseNode *sp_name_node = NULL; ParseNode *package_name_node = NULL; ParseNode *package_stmts_node = NULL; ParseNode *package_clause_node = NULL; ObString db_name; ObString package_name; bool is_invoker_right = false; bool has_accessible_by = false; CK (OB_NOT_NULL(package_block_node = parse_tree.children_[0])); CK (T_PACKAGE_BLOCK == package_block_node->type_); CK (OB_UNLIKELY(PACKAGE_BLOCK_NODE_CHILD_COUNT == package_block_node->num_child_)); CK (OB_NOT_NULL(package_block_node->children_)); CK (OB_NOT_NULL(sp_name_node = package_block_node->children_[0])); OX (package_clause_node = package_block_node->children_[1]); OX (package_stmts_node = package_block_node->children_[2]); OX (package_name_node = package_block_node->children_[3]); OZ (ObResolverUtils::resolve_sp_name(*session_info_, *sp_name_node, db_name, package_name)); CK (OB_NOT_NULL(schema_checker_)); if (OB_SUCC(ret) && ObSchemaChecker::is_ora_priv_check()) { OZ (schema_checker_->check_ora_ddl_priv( session_info_->get_effective_tenant_id(), session_info_->get_priv_user_id(), db_name, stmt::T_CREATE_ROUTINE, session_info_->get_enable_role_array())); } //Resolve package clause: invoker right and accessible by OZ (resolve_invoke_accessible(package_clause_node, is_invoker_right, has_accessible_by)); //NOTE: null package stmts is possible if (OB_SUCC(ret) && OB_NOT_NULL(package_stmts_node)) { CK (T_PACKAGE_STMTS == package_stmts_node->type_); OZ (package_ast.init(db_name, package_name, PL_PACKAGE_SPEC, OB_INVALID_ID, OB_INVALID_ID, OB_INVALID_VERSION, NULL)); OZ (resolver.init(package_ast)); if (OB_SUCC(ret) && OB_FAIL(resolver.resolve(package_stmts_node, package_ast))) { LOG_WARN("resolve package spec failed", K(ret)); LOG_USER_WARN(OB_ERR_PACKAGE_COMPILE_ERROR, "PACKAGE", db_name.length(), db_name.ptr(), package_name.length(), package_name.ptr()); resolve_success = ObPLResolver::is_object_not_exist_error(ret) ? true : false; ObPL::insert_error_msg(ret); ret = OB_SUCCESS; } } //NOTE: null package name is possible if (OB_SUCC(ret) && OB_NOT_NULL(package_name_node)) { ObString opt_package_name(package_name_node->str_len_, package_name_node->str_value_); CK (T_IDENT == package_name_node->type_); if (OB_SUCC(ret) && OB_UNLIKELY(0 != package_name.case_compare(opt_package_name))) { ret = OB_ERR_SP_LILABEL_MISMATCH; LOG_WARN("end package name not match", K(ret), K(package_name), K(opt_package_name)); LOG_USER_ERROR(OB_ERR_SP_LILABEL_MISMATCH, opt_package_name.length(), opt_package_name.ptr()); } } if (OB_SUCC(ret)) { if (OB_ISNULL(stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory for create package stmt failed", K(ret)); } else { common::ObCompatibilityMode compa_mode = lib::is_mysql_mode() ? common::MYSQL_MODE : common::ORACLE_MODE; obrpc::ObCreatePackageArg &create_package_arg = stmt->get_create_package_arg(); ObPackageInfo &package_info = create_package_arg.package_info_; ObString package_block(static_cast(package_block_node->str_len_), package_block_node->str_value_); create_package_arg.is_replace_ = static_cast(parse_tree.int32_values_[0]); create_package_arg.is_editionable_ = !static_cast(parse_tree.int32_values_[1]); create_package_arg.db_name_ = db_name; package_info.set_tenant_id(session_info_->get_effective_tenant_id()); package_info.set_owner_id(session_info_->get_user_id()); package_info.set_type(PACKAGE_TYPE); package_info.set_compatibility_mode(compa_mode); if (is_invoker_right) { package_info.set_invoker_right(); } if (has_accessible_by) { package_info.set_accessible_by_clause(); } if (!create_package_arg.is_editionable_) { create_package_arg.package_info_.set_noneditionable(); } if (OB_FAIL(ObSQLUtils::convert_sql_text_to_schema_for_storing( *allocator_, session_info_->get_dtc_params(), package_block))) { LOG_WARN("fail to convert package block", K(ret)); } else if (OB_FAIL(package_info.set_package_name(package_name))) { LOG_WARN("set package name failed", K(ret), K(package_name)); } else if (OB_FAIL(package_info.set_source(package_block))) { LOG_WARN("set package source failed", K(ret)); } else if (OB_SYS_TENANT_ID == session_info_->get_effective_tenant_id()) { // 系统租户在创建系统包, 环境变量使用Oracle租户默认的环境变量 // sql_mode = "PIPES_AS_CONCAT,STRICT_ALL_TABLES,PAD_CHAR_TO_FULL_LENGTH" if (common::ORACLE_MODE == compa_mode) { if (OB_FAIL(package_info.set_exec_env(ObString("2151677954,45,46,46,")))) { LOG_WARN("failed to set system package exec env", K(ret), K(session_info_->get_effective_tenant_id()), K(package_info)); } } else { OZ (package_info.set_exec_env(ObString("4194304,45,45,45,"))); } } else { char buf[OB_MAX_PROC_ENV_LENGTH]; int64_t pos = 0; if (OB_FAIL(ObExecEnv::gen_exec_env(*session_info_, buf, OB_MAX_PROC_ENV_LENGTH, pos))) { LOG_WARN("failed to generate exec env", K(ret)); } else if (OB_FAIL(package_info.set_exec_env(ObString(pos, buf)))) { LOG_WARN("set exec env failed", K(ret)); } else {} } if (OB_SUCC(ret) && resolve_success) { OZ (resolve_functions_spec(package_info, create_package_arg.public_routine_infos_, package_ast.get_routine_table())); } if (OB_SUCC(ret)) { ObString dep_attr; OZ (ObDependencyInfo::collect_dep_infos(package_ast.get_dependency_table(), create_package_arg.dependency_infos_, ObObjectType::PACKAGE, 0, dep_attr, dep_attr)); } if (OB_SUCC(ret)) { ObErrorInfo &error_info = create_package_arg.error_info_; ObPackageInfo &pkg_info = create_package_arg.package_info_; error_info.collect_error_info(&pkg_info); } } } } if (OB_NOT_NULL(session_info_) && OB_SYS_TENANT_ID == session_info_->get_effective_tenant_id() /*&& !session_info_->is_inner()*/) { // 低版本升级到2274, 老的升级脚本中包含了创建Package语句, 部分语句在2274 Server上会产生Warning // 比如: Create Package pack IS Procedure proc(x Boolean := 1); End;会报错Boolean表达式默认值非法的Warning // 2274的升级脚本还会用最新的Package脚本重建这个包, 为了避免产生的Warning使得升级失败, 这里把Warning清理掉 common::ob_reset_tsi_warning_buffer(); } } return ret; } int ObCreatePackageResolver::resolve_invoke_accessible(const ParseNode *package_clause_node, bool &is_invoker_right, bool &has_accessible_by) { int ret = OB_SUCCESS; bool has_sp_invoker_clause = false; bool has_accessible_by_clause = false; if (OB_NOT_NULL(package_clause_node)) { CK (T_SP_CLAUSE_LIST == package_clause_node->type_); for (int64_t i = 0; OB_SUCC(ret) && i < package_clause_node->num_child_; ++i) { const ParseNode *node = package_clause_node->children_[i]; if (OB_NOT_NULL(node)) { if (T_SP_INVOKE == node->type_) { if (has_sp_invoker_clause) { ret = OB_ERR_DECL_MORE_THAN_ONCE; LOG_WARN("PLS-00371: at most one declaration for 'string' is permitted", K(ret), K(node->type_), K(has_sp_invoker_clause)); } else { has_sp_invoker_clause = true; if (1 == node->value_) { is_invoker_right = true; } } } else if (T_SP_ACCESSIBLE_BY == node->type_) { if (has_accessible_by_clause) { ret = OB_ERR_DECL_MORE_THAN_ONCE; LOG_WARN("PLS-00371: at most one declaration for 'string' is permitted", K(ret), K(node->type_), K(has_accessible_by_clause)); } else { has_accessible_by_clause = true; has_accessible_by = true; } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("not supported other clause yet", K(ret), K(node)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "specified invoker clause"); } } } } return ret; } int ObCreatePackageResolver::check_overload_out_argument(const pl::ObPLRoutineTable &routine_table, int64_t idx) { int64_t ret = OB_SUCCESS; const ObPLRoutineInfo *right_info = NULL; OZ (routine_table.get_routine_info(idx, right_info)); CK (OB_NOT_NULL(right_info)); for (int64_t i = idx - 1; OB_SUCC(ret) && i >= ObPLRoutineTable::NORMAL_ROUTINE_START_IDX; --i) { const ObPLRoutineInfo *left_info = NULL; OZ (routine_table.get_routine_info(i, left_info)); OV (OB_NOT_NULL(left_info), OB_ERR_UNEXPECTED, i); if (OB_FAIL(ret)) { } else if (left_info->get_name() == right_info->get_name() && left_info->get_type() == right_info->get_type()) { int64_t left_param_cnt = left_info->get_param_count(); int64_t right_param_cnt = right_info->get_param_count(); int64_t param_cnt = left_param_cnt >= right_param_cnt ? left_param_cnt : right_param_cnt; for (int64_t j = 0; OB_SUCC(ret) && j < param_cnt; ++j) { ObPLRoutineParam *left_param = NULL; ObPLRoutineParam *right_param = NULL; if (j < left_param_cnt) { OZ (left_info->get_routine_param(j, left_param)); CK (OB_NOT_NULL(left_param)); } if (j < right_param_cnt) { OZ (right_info->get_routine_param(j, right_param)); CK (OB_NOT_NULL(right_param)); } if (OB_FAIL(ret)) { } else if (OB_NOT_NULL(left_param) && OB_NOT_NULL(right_param)) { bool left_out_mode = left_param->is_out_param() || left_param->is_inout_param(); bool right_out_mode = right_param->is_out_param() || right_param->is_inout_param(); if (left_out_mode != right_out_mode) { ret = OB_NOT_SUPPORTED; LOG_WARN("overloaded routine out parameter not in same position!", K(ret), K(j), K(left_info->get_name())); LOG_USER_ERROR(OB_NOT_SUPPORTED, "overloaded routine out parameter not in same position"); } } else if (OB_NOT_NULL(left_param) && (left_param->is_out_param() || left_param->is_inout_param())) { ret = OB_NOT_SUPPORTED; LOG_WARN("overloaded routine out parameter not in same position!", K(ret), K(j), K(left_info->get_name())); LOG_USER_ERROR(OB_NOT_SUPPORTED, "overloaded routine out parameter not in same position"); } else if (OB_NOT_NULL(right_param) && (right_param->is_out_param() || right_param->is_inout_param())) { ret = OB_NOT_SUPPORTED; LOG_WARN("overloaded routine out parameter not in same position!", K(ret), K(j), K(left_info->get_name())); LOG_USER_ERROR(OB_NOT_SUPPORTED, "overloaded routine out parameter not in same position"); } } break; } } return ret; } int ObCreatePackageResolver::resolve_functions_spec(const ObPackageInfo &package_info, ObIArray &routine_list, const ObPLRoutineTable &routine_table, ObRoutineType routine_type) { int ret = OB_SUCCESS; uint64_t routine_count = routine_table.get_count(); ObRoutineInfo routine_info; const ObPLRoutineInfo *pl_routine_info = NULL; for (int64_t i = ObPLRoutineTable::NORMAL_ROUTINE_START_IDX; OB_SUCC(ret) && iget_name()))) { LOG_WARN("set routine name failed", "routine name", pl_routine_info->get_name(), K(ret)); } /*else if (i > ObPLRoutineTable::NORMAL_ROUTINE_START_IDX) { // && OB_FAIL(check_overload_out_argument(routine_table, i))) { LOG_WARN("failed to check overload out argument", K(ret)); } */else { if (pl_routine_info->is_deterministic()) { routine_info.set_deterministic(); } if (pl_routine_info->is_parallel_enable()) { routine_info.set_parallel_enable(); } if (pl_routine_info->is_pipelined()) { routine_info.set_pipelined(); } // udt type 相关信息设置 if (pl_routine_info->is_udt_routine()) { routine_info.set_is_udt_udf(); if (pl_routine_info->is_udt_static_routine()) { routine_info.set_is_static(); } if (pl_routine_info->is_function()) { routine_info.set_is_udt_function(); } if (pl_routine_info->is_udt_cons()) { routine_info.set_is_udt_cons(); } if (pl_routine_info->is_udt_map()) { routine_info.set_is_udt_map(); } if (pl_routine_info->is_udt_order()) { routine_info.set_is_udt_order(); } } if (package_info.is_invoker_right()) { routine_info.set_invoker_right(); } if (package_info.has_accessible_by_clause() || pl_routine_info->has_accessible_by_clause()) { routine_info.set_accessible_by_clause(); } routine_info.set_overload(NO_OVERLOAD_IDX); //no overload for (int64_t k = routine_list.count(); OB_SUCC(ret) && k>0; k--) { ObRoutineInfo &tmp_routine_info = routine_list.at(k-1); if (ObCharset::case_insensitive_equal(routine_info.get_routine_name(), tmp_routine_info.get_routine_name())) { if (NO_OVERLOAD_IDX == tmp_routine_info.get_overload()) { tmp_routine_info.set_overload(OVERLOAD_START_IDX); } routine_info.set_overload(tmp_routine_info.get_overload()+1); break; } } } //process ret and param info if (OB_SUCC(ret)) { int64_t start_position = 1; int64_t start_sequence = 1; int64_t start_level = 0; if (OB_SUCC(ret) && OB_NOT_NULL(pl_routine_info->get_ret_info())) { const ObPLRoutineParam *ret_info = static_cast(pl_routine_info->get_ret_info()); CK (OB_NOT_NULL(ret_info)); OZ (ObPLDataType::transform_and_add_routine_param(ret_info, 0, // position start_level, start_sequence, routine_info)); /*if (OB_FAIL(ret_info->get_type().add_package_routine_schema_param( resolver.get_resolve_ctx(), resolver.get_current_namespace(), package_name, ret_info->get_name(), ret_info->get_mode(), 0, start_level, start_sequence, routine_info))) { LOG_WARN("add package routine return param failed", K(ret)); } */ } if (OB_SUCC(ret)) { uint64_t param_count = pl_routine_info->get_param_count(); for (int64_t j = 0; OB_SUCC(ret) && j < param_count; j++) { ObPLRoutineParam *param = pl_routine_info->get_params().at(j); CK (OB_NOT_NULL(param)); OZ (ObPLDataType::transform_and_add_routine_param(param, start_position++, start_level, start_sequence, routine_info)); /* if (OB_FAIL(param->get_type().add_package_routine_schema_param( resolver.get_resolve_ctx(), resolver.get_current_namespace(), package_name, param->get_name(), param->get_mode(), start_position++, start_level, start_sequence, routine_info))) { LOG_WARN("add package routine param failed", K(ret)); } else*/ if (OB_SUCC(ret)) { int64_t idx = routine_info.get_routine_params().count() - 1; ObRoutineParam* rountine_param = routine_info.get_routine_params().at(idx); if (OB_ISNULL(rountine_param)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("rountine param is null", K(ret), K(idx)); } else if (OB_FAIL(rountine_param->set_default_value(param->get_default_value()))) { LOG_WARN("failed to set default value", K(ret)); } } } } } //add routine info if (OB_SUCC(ret)) { routine_list.push_back(routine_info); } } return ret; } int ObCreatePackageBodyResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObCreatePackageStmt *stmt = NULL; ParseNode *package_body_block_node = NULL; ObString db_name; ObString package_name; CK (OB_NOT_NULL(parse_tree.children_)); CK (OB_NOT_NULL(session_info_)); CK (OB_NOT_NULL(schema_checker_)); CK (OB_NOT_NULL(schema_checker_->get_schema_guard())); CK (OB_NOT_NULL(allocator_)); CK (OB_NOT_NULL(params_.allocator_)); CK (OB_NOT_NULL(params_.session_info_)); CK (OB_NOT_NULL(params_.sql_proxy_)); CK (OB_LIKELY(T_PACKAGE_CREATE_BODY == parse_tree.type_)); CK (OB_LIKELY(CREATE_PACKAGE_BODY_NODE_CHILD_COUNT == parse_tree.num_child_)); if (OB_SUCC(ret) && lib::is_mysql_mode() && OB_SYS_TENANT_ID != session_info_->get_effective_tenant_id()) { ret = OB_NOT_SUPPORTED; LOG_WARN("not supported package in mysql mode", K(ret), K(lbt())); LOG_USER_ERROR(OB_NOT_SUPPORTED, "package in mysql mode"); } if (OB_SUCC(ret) && OB_ISNULL(stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory for create package stmt failed", K(ret)); } if (OB_SUCC(ret)) { ParseNode *sp_name_node = NULL; ParseNode *package_name_node = NULL; CK (OB_NOT_NULL(package_body_block_node = parse_tree.children_[0])); CK (OB_LIKELY(T_PACKAGE_BODY_BLOCK == package_body_block_node->type_)); CK (OB_LIKELY(PACKAGE_BODY_BLOCK_NODE_CHILD_COUNT == package_body_block_node->num_child_)); CK (OB_NOT_NULL(package_body_block_node->children_)); CK (OB_NOT_NULL(sp_name_node = package_body_block_node->children_[0])); OZ (ObResolverUtils::resolve_sp_name(*session_info_, *sp_name_node, db_name, package_name)); // check end label if (OB_SUCC(ret) && OB_NOT_NULL(package_name_node = package_body_block_node->children_[3])) { ObString end_package_name; CK (OB_LIKELY(T_IDENT == package_name_node->type_)); OX (end_package_name = ObString(package_name_node->str_len_, package_name_node->str_value_)); if (OB_SUCC(ret) && OB_UNLIKELY(0 != package_name.case_compare(end_package_name))) { ret = OB_ERR_SP_LILABEL_MISMATCH; LOG_WARN("end package body name not match", K(ret), K(package_name), K(end_package_name)); LOG_USER_ERROR(OB_ERR_SP_LILABEL_MISMATCH, end_package_name.length(), end_package_name.ptr()); } } //syntax and semantic analysis bool is_invoker_right = false; if (OB_SUCC(ret) && OB_NOT_NULL(package_body_block_node->str_value_) && OB_LIKELY(package_body_block_node->str_len_ > 0)) { ObString package_body_src(package_body_block_node->str_len_, package_body_block_node->str_value_); HEAP_VARS_2((ObPLPackageAST, package_spec_ast, *allocator_), (ObPLPackageAST, package_body_ast, *allocator_)) { ObPLPackageGuard package_guard(params_.session_info_->get_effective_tenant_id()); ObSchemaGetterGuard *schema_guard = schema_checker_->get_schema_mgr(); ObPLCompiler compiler(*params_.allocator_, *params_.session_info_, *schema_guard, package_guard, *params_.sql_proxy_); const ObPackageInfo *package_spec_info = NULL; int64_t compatible_mode = lib::is_oracle_mode() ? COMPATIBLE_ORACLE_MODE : COMPATIBLE_MYSQL_MODE; ObString source; OZ (schema_checker_->get_package_info(session_info_->get_effective_tenant_id(), db_name, package_name, PACKAGE_TYPE, compatible_mode, package_spec_info)); if (OB_ERR_PACKAGE_DOSE_NOT_EXIST == ret) { ret = OB_ERR_SPEC_NOT_EXIST; LOG_USER_ERROR(OB_ERR_SPEC_NOT_EXIST, package_name.length(), package_name.ptr()); } CK (OB_NOT_NULL(package_spec_info)); OX (is_invoker_right = package_spec_info->is_invoker_right()); OZ (package_spec_ast.init(db_name, package_spec_info->get_package_name(), PL_PACKAGE_SPEC, package_spec_info->get_database_id(), package_spec_info->get_package_id(), package_spec_info->get_schema_version(), NULL)); OX (source = package_spec_info->get_source()); OZ (ObSQLUtils::convert_sql_text_from_schema_for_resolve( *allocator_, session_info_->get_dtc_params(), source)); OZ (compiler.analyze_package(source, NULL, package_spec_ast, false)); OZ (package_body_ast.init(db_name, package_name, PL_PACKAGE_BODY, OB_INVALID_ID, OB_INVALID_ID, OB_INVALID_VERSION, &package_spec_ast)); OZ (compiler.analyze_package(package_body_src, &(package_spec_ast.get_body()->get_namespace()), package_body_ast, false)); if (OB_SUCC(ret)) { if (package_body_ast.get_serially_reusable() != package_spec_ast.get_serially_reusable()) { ret = OB_NOT_SUPPORTED; LOG_WARN("PLS-00709: pragma string must be declared in package specification and body", K(ret), K(package_body_ast.get_serially_reusable()), K(package_spec_ast.get_serially_reusable())); LOG_USER_ERROR(OB_NOT_SUPPORTED, "pragma string not declared in package specification and body"); } } // update route sql of routine info if (OB_SUCC(ret)) { obrpc::ObCreatePackageArg &create_package_arg = stmt->get_create_package_arg(); ObIArray &routine_list = create_package_arg.public_routine_infos_; const ObPLRoutineTable &spec_routine_table = package_spec_ast.get_routine_table(); const ObPLRoutineTable &body_routine_table = package_body_ast.get_routine_table(); ObRoutineInfo routine_info; const ObPLRoutineInfo *pl_routine_info = NULL; ObSEArray routine_infos; ObSEArray routine_spec_infos; uint64_t database_id = OB_INVALID_ID; OZ (schema_checker_->get_schema_guard()->get_database_id( session_info_->get_effective_tenant_id(), db_name, database_id)); OZ (schema_checker_->get_schema_guard()->get_routine_infos_in_package( session_info_->get_effective_tenant_id(), package_spec_info->get_package_id(), routine_infos)); if (OB_SUCC(ret) && routine_infos.empty() && package_spec_ast.get_routine_table().get_count() > 1) { OZ (ObCreatePackageResolver::resolve_functions_spec( *package_spec_info, routine_spec_infos, package_spec_ast.get_routine_table())); CK (routine_spec_infos.count() > 0); for (int64_t i = 0; OB_SUCC(ret) && i < routine_spec_infos.count(); ++i) { OZ (routine_infos.push_back(&routine_spec_infos.at(i))); } } OZ (update_routine_route_sql(*allocator_, *session_info_, routine_list, spec_routine_table, body_routine_table, routine_infos)); } if (OB_FAIL(ret) && ret != OB_ERR_UNEXPECTED && ret != OB_ERR_TOO_LONG_IDENT) { LOG_USER_WARN(OB_ERR_PACKAGE_COMPILE_ERROR, "PACKAGE BODY", db_name.length(), db_name.ptr(), package_name.length(), package_name.ptr()); ObPL::insert_error_msg(ret); ret = OB_SUCCESS; } if (OB_SUCC(ret)) { ObString dep_attr; OZ (ObDependencyInfo::collect_dep_infos(package_body_ast.get_dependency_table(), stmt->get_create_package_arg().dependency_infos_, ObObjectType::PACKAGE_BODY, 0, dep_attr, dep_attr)); } } } //set package body common info if (OB_SUCC(ret)) { common::ObCompatibilityMode compa_mode = lib::is_mysql_mode() ? common::MYSQL_MODE : common::ORACLE_MODE; obrpc::ObCreatePackageArg &create_package_arg = stmt->get_create_package_arg(); ObPackageInfo &package_info = create_package_arg.package_info_; ObString package_body_block(static_cast(package_body_block_node->str_len_), package_body_block_node->str_value_); create_package_arg.is_replace_ = static_cast(parse_tree.int32_values_[0]); create_package_arg.is_editionable_ = !static_cast(parse_tree.int32_values_[1]); create_package_arg.db_name_ = db_name; package_info.set_tenant_id(session_info_->get_effective_tenant_id()); package_info.set_owner_id(session_info_->get_user_id()); package_info.set_type(PACKAGE_BODY_TYPE); package_info.set_compatibility_mode(compa_mode); if (!create_package_arg.is_editionable_) { create_package_arg.package_info_.set_noneditionable(); } if (is_invoker_right) { create_package_arg.package_info_.set_invoker_right(); } OZ (package_info.set_package_name(package_name), package_name); OZ (ObSQLUtils::convert_sql_text_to_schema_for_storing( *allocator_, session_info_->get_dtc_params(), package_body_block)); OZ (package_info.set_source(package_body_block), package_body_block); if (OB_SUCC(ret)) { if (OB_UNLIKELY(OB_SYS_TENANT_ID == session_info_->get_effective_tenant_id())) { // 系统租户在创建系统包, 环境变量使用Oracle租户默认的环境变量 // sql_mode = "PIPES_AS_CONCAT,STRICT_ALL_TABLES,PAD_CHAR_TO_FULL_LENGTH" if (common::ORACLE_MODE == compa_mode) { OZ (package_info.set_exec_env(ObString("2151677954,45,46,46,"))); } else { OZ (package_info.set_exec_env(ObString("4194304,45,45,45,"))); } } else { char buf[OB_MAX_PROC_ENV_LENGTH]; int64_t pos = 0; OZ (ObExecEnv::gen_exec_env(*session_info_, buf, OB_MAX_PROC_ENV_LENGTH, pos)); OZ (package_info.set_exec_env(ObString(pos, buf))); } } if (OB_SUCC(ret)) { ObErrorInfo &error_info = create_package_arg.error_info_; ObPackageInfo &pkg_info = create_package_arg.package_info_; error_info.collect_error_info(&pkg_info); } } if (OB_NOT_NULL(session_info_) && OB_SYS_TENANT_ID == session_info_->get_effective_tenant_id() /*&& !session_info_->is_inner()*/) { /* NOTE: REMOVE IS_INNER * Some system package like dbms_utility may produce warings in create stage under system tenant. * It will failed upgrade OCEANBASE. * But package still work, It will recompile in normal tenant without warnings. * So here, we ignore warnings in system package create stage. */ // 低版本升级到2274, 老的升级脚本中包含了创建Package语句, 部分语句在2274 Server上会产生Warning // 比如: Create Package pack IS Procedure proc(x Boolean := 1); End;会报错Boolean表达式默认值非法的Warning // 2274的升级脚本还会用最新的Package脚本重建这个包, 为了避免产生的Warning使得升级失败, 这里把Warning清理掉 common::ob_reset_tsi_warning_buffer(); } } return ret; } int ObCreatePackageBodyResolver::update_routine_route_sql(ObIAllocator &allocator, const ObSQLSessionInfo &session_info, ObIArray &public_routine_list, const ObPLRoutineTable &spec_routine_table, const ObPLRoutineTable &body_routine_table, ObIArray &routine_infos) { int ret = OB_SUCCESS; const ObPLRoutineInfo *pl_routine_info = NULL; ObRoutineInfo routine_info; for (int64_t i = ObPLRoutineTable::NORMAL_ROUTINE_START_IDX; OB_SUCC(ret) && i < spec_routine_table.get_count(); i++) { const ObRoutineInfo* tmp_routine_info = NULL; bool found = false; OX (routine_info.reset()); OZ (body_routine_table.get_routine_info(i, pl_routine_info)); for (int64_t j = 0; OB_SUCC(ret) && j < routine_infos.count(); ++j) { tmp_routine_info = routine_infos.at(j); if (tmp_routine_info->get_subprogram_id() == i) { ObString route_sql = pl_routine_info->get_route_sql(); ObString routine_body = pl_routine_info->get_routine_body(); CK (false == found); OX (found = true); OX (routine_info = *tmp_routine_info); OZ (ObSQLUtils::convert_sql_text_to_schema_for_storing(allocator, session_info.get_dtc_params(), route_sql)); OX (routine_info.set_route_sql(route_sql)); OZ (ObSQLUtils::convert_sql_text_to_schema_for_storing(allocator, session_info.get_dtc_params(), routine_body)); OX (routine_info.set_routine_body(routine_body)); } } OZ (public_routine_list.push_back(routine_info)); } return ret; } } //namespace sql } //namespace oceanbase