diff --git a/deps/oblib/src/rpc/obrpc/ob_rpc_packet_list.h b/deps/oblib/src/rpc/obrpc/ob_rpc_packet_list.h index 3423408d4a..95fa5627ad 100644 --- a/deps/oblib/src/rpc/obrpc/ob_rpc_packet_list.h +++ b/deps/oblib/src/rpc/obrpc/ob_rpc_packet_list.h @@ -1138,12 +1138,12 @@ PCODE_DEF(OB_CLONE_KEY, 0x1617) PCODE_DEF(OB_TRIM_KEY_LIST, 0x1618) //store routine -//PCODE_DEF(OB_CREATE_ROUTINE_WITH_RES, 0x1619) -//PCODE_DEF(OB_CREATE_PACKAGE_WITH_RES, 0x161A) -//PCODE_DEF(OB_CREATE_UDT_WITH_RES, 0x161B) -//PCODE_DEF(OB_ALTER_ROUTINE_WITH_RES, 0x161C) -//PCODE_DEF(OB_ALTER_PACKAGE_WITH_RES, 0x161D) -//PCODE_DEF(OB_ALTER_TRIGGER_WITH_RES, 0x161E) +PCODE_DEF(OB_CREATE_ROUTINE_WITH_RES, 0x1619) +PCODE_DEF(OB_CREATE_PACKAGE_WITH_RES, 0x161A) +PCODE_DEF(OB_CREATE_UDT_WITH_RES, 0x161B) +PCODE_DEF(OB_ALTER_ROUTINE_WITH_RES, 0x161C) +PCODE_DEF(OB_ALTER_PACKAGE_WITH_RES, 0x161D) +PCODE_DEF(OB_ALTER_TRIGGER_WITH_RES, 0x161E) PCODE_DEF(OB_GAIS_BROADCAST_AUTO_INC_CACHE, 0x161F) //proxy user diff --git a/src/objit/include/objit/common/ob_item_type.h b/src/objit/include/objit/common/ob_item_type.h index 041555bba5..03f28a6ef0 100755 --- a/src/objit/include/objit/common/ob_item_type.h +++ b/src/objit/include/objit/common/ob_item_type.h @@ -2481,6 +2481,7 @@ typedef enum ObItemType T_ALTER_TABLE_FORCE, T_SHOW_PROCEDURE_CODE, T_SHOW_FUNCTION_CODE, + T_CHANGE_EXTERNAL_STORAGE_DEST, T_ALTER_USER_PROXY, T_PARALLEL_DAS_DML, diff --git a/src/observer/ob_srv_xlator_rootserver.cpp b/src/observer/ob_srv_xlator_rootserver.cpp index 42e6e49e21..7a532d6a26 100644 --- a/src/observer/ob_srv_xlator_rootserver.cpp +++ b/src/observer/ob_srv_xlator_rootserver.cpp @@ -123,16 +123,21 @@ void oceanbase::observer::init_srv_xlator_for_rootserver(ObSrvRpcXlator *xlator) RPC_PROCESSOR(rootserver::ObRpcAlterOutlineP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcDropOutlineP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcCreateRoutineP, *gctx_.root_service_); + RPC_PROCESSOR(rootserver::ObRpcCreateRoutineWithResP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcDropRoutineP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcAlterRoutineP, *gctx_.root_service_); + RPC_PROCESSOR(rootserver::ObRpcAlterRoutineWithResP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcCreateDbLinkP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcDropDbLinkP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcCreatePackageP, *gctx_.root_service_); + RPC_PROCESSOR(rootserver::ObRpcCreatePackageWithResP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcAlterPackageP, *gctx_.root_service_); + RPC_PROCESSOR(rootserver::ObRpcAlterPackageWithResP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcDropPackageP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcCreateTriggerP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcCreateTriggerWithResP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcAlterTriggerP, *gctx_.root_service_); + RPC_PROCESSOR(rootserver::ObRpcAlterTriggerWithResP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcDropTriggerP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcCreateSynonymP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcDropSynonymP, *gctx_.root_service_); @@ -140,6 +145,7 @@ void oceanbase::observer::init_srv_xlator_for_rootserver(ObSrvRpcXlator *xlator) RPC_PROCESSOR(rootserver::ObRpcDropUserDefinedFunctionP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcDoSequenceDDLP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcCreateUDTP, *gctx_.root_service_); + RPC_PROCESSOR(rootserver::ObRpcCreateUDTWithResP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcDropUDTP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcOptimizeTableP, *gctx_.root_service_); RPC_PROCESSOR(rootserver::ObRpcSchemaReviseP, *gctx_.root_service_); diff --git a/src/pl/dblink/ob_pl_dblink_guard.cpp b/src/pl/dblink/ob_pl_dblink_guard.cpp index 01c8696f6e..b9b44f24cb 100644 --- a/src/pl/dblink/ob_pl_dblink_guard.cpp +++ b/src/pl/dblink/ob_pl_dblink_guard.cpp @@ -513,6 +513,71 @@ int ObPLDbLinkGuard::get_dblink_type_by_name(const uint64_t dblink_id, return ret; } +int ObPLDbLinkGuard::get_dblink_table_by_name(sql::ObSQLSessionInfo &session_info, + share::schema::ObSchemaGetterGuard &schema_guard, + const common::ObString &dblink_name, + const common::ObString &db_name, + const common::ObString &table_name, + const ObTableSchema *&table_schema) +{ + int ret = OB_SUCCESS; +#ifndef OB_BUILD_ORACLE_PL + ret = OB_NOT_SUPPORTED; + LOG_USER_ERROR(OB_NOT_SUPPORTED, "PL dblink"); +#else + const uint64_t tenant_id = MTL_ID(); + uint64_t dblink_id = OB_INVALID_ID; + const share::schema::ObDbLinkSchema *dblink_schema = NULL; + const ObPLDbLinkInfo *dblink_info = NULL; + CK (!table_name.empty()); + CK (!dblink_name.empty()); + OZ (schema_guard.get_dblink_schema(tenant_id, dblink_name, dblink_schema)); + OV (OB_NOT_NULL(dblink_schema), OB_DBLINK_NOT_EXIST_TO_ACCESS, dblink_name); + OV (OB_INVALID_ID != (dblink_id = dblink_schema->get_dblink_id()), OB_DBLINK_NOT_EXIST_TO_ACCESS, dblink_id); + for (uint64_t i = 0; OB_SUCC(ret) && OB_ISNULL(table_schema) && i < table_schemas_.count(); i++) { + const ObTableSchema *t = table_schemas_.at(i); + OV (OB_NOT_NULL(t)); + if (OB_SUCC(ret) + && t->get_dblink_id() == dblink_id + && db_name.compare(t->get_link_database_name()) + && table_name.compare(t->get_table_name_str())) { + table_schema = t; + } + } + if (OB_SUCC(ret) && OB_ISNULL(table_schema)) { + ObTableSchema *tmp_schema = NULL; + uint64_t *scn = NULL; + OZ (schema_guard.get_link_table_schema(tenant_id, + dblink_id, + db_name, + table_name, + alloc_, + tmp_schema, + &session_info, + dblink_name, + false/*is_reverse_link*/, + scn)); + if (OB_SUCC(ret)) { + if (OB_ISNULL(tmp_schema)) { + ObSqlString object_name; + OZ (object_name.append_fmt("%.*s@%.*s", + table_name.length(), table_name.ptr(), + dblink_name.length(), dblink_name.ptr())); + ret = OB_ERR_SP_UNDECLARED_VAR; + LOG_WARN("dblink table not exist", K(ret)); + LOG_USER_ERROR(OB_ERR_SP_UNDECLARED_VAR, object_name.string().length(), object_name.string().ptr()); + } else { + tmp_schema->set_table_id(next_link_object_id_++); + tmp_schema->set_link_table_id(tmp_schema->get_table_id()); + table_schema = tmp_schema; + OZ (table_schemas_.push_back(tmp_schema)); + } + } + } +#endif + return ret; +} + #ifdef OB_BUILD_ORACLE_PL int ObPLDbLinkGuard::get_dblink_info(const uint64_t dblink_id, const ObPLDbLinkInfo *&dblink_info) diff --git a/src/pl/dblink/ob_pl_dblink_guard.h b/src/pl/dblink/ob_pl_dblink_guard.h index c0e67a0b77..cbd5fd843d 100644 --- a/src/pl/dblink/ob_pl_dblink_guard.h +++ b/src/pl/dblink/ob_pl_dblink_guard.h @@ -22,6 +22,7 @@ #include "share/schema/ob_schema_getter_guard.h" #ifdef OB_BUILD_ORACLE_PL #include "pl/dblink/ob_pl_dblink_info.h" +#include "share/schema/ob_table_schema.h" #endif namespace oceanbase @@ -47,6 +48,7 @@ typedef share::schema::ObRoutineType ObRoutineType; typedef share::schema::ObRoutineParam ObRoutineParam; typedef share::schema::ObSchemaUtils ObSchemaUtils; typedef oceanbase::common::ObSqlString ObSqlString; +typedef oceanbase::share::schema::ObTableSchema ObTableSchema; class ObPLDbLinkGuard { public: @@ -60,6 +62,9 @@ public: for (int64_t i = 0; i < dblink_infos_.count(); i++) { dblink_infos_.at(i)->~ObPLDbLinkInfo(); } + for (int64_t i = 0; i < table_schemas_.count(); i++) { + table_schemas_.at(i)->~ObTableSchema(); + } #endif reset(); } @@ -67,6 +72,7 @@ public: { #ifdef OB_BUILD_ORACLE_PL dblink_infos_.reset(); + table_schemas_.reset(); #endif next_link_object_id_ = 1; } @@ -99,6 +105,13 @@ public: const common::ObString &pkg_name, const common::ObString &udt_name, const pl::ObUserDefinedType *&udt); + + int get_dblink_table_by_name(sql::ObSQLSessionInfo &session_info, + share::schema::ObSchemaGetterGuard &schema_guard, + const common::ObString &dblink_name, + const common::ObString &db_name, + const common::ObString &table_name, + const ObTableSchema *&table_schema); #ifdef OB_BUILD_ORACLE_PL int get_dblink_info(const uint64_t dblink_id, const ObPLDbLinkInfo *&dblink_info); @@ -140,6 +153,7 @@ private: common::ObArenaAllocator &alloc_; #ifdef OB_BUILD_ORACLE_PL common::ObSEArray dblink_infos_; + common::ObSEArray table_schemas_; #endif }; diff --git a/src/pl/ob_pl.cpp b/src/pl/ob_pl.cpp index e93d045a3f..3c12d03607 100644 --- a/src/pl/ob_pl.cpp +++ b/src/pl/ob_pl.cpp @@ -1775,6 +1775,10 @@ int ObPL::parameter_anonymous_block(ObExecContext &ctx, } } } + // generate sql_id using paramiterized sql, and overwrite privious sql_id + OZ (ObSQLUtils::md5(pc_key, ctx.get_sql_ctx()->sql_id_, + (int32_t)sizeof(ctx.get_sql_ctx()->sql_id_))); + OX (ctx.get_my_session()->set_cur_sql_id(ctx.get_sql_ctx()->sql_id_)); OZ (get_pl_function(ctx, params, OB_INVALID_ID, pc_key, cacheobj_guard)); return ret; } diff --git a/src/pl/ob_pl.h b/src/pl/ob_pl.h index 9b1c226403..86a070090e 100644 --- a/src/pl/ob_pl.h +++ b/src/pl/ob_pl.h @@ -1128,6 +1128,7 @@ public: int check_exec_priv(sql::ObExecContext &ctx, const ObString &database_name, ObPLFunction *routine); + private: // for normal routine int get_pl_function(sql::ObExecContext &ctx, @@ -1154,11 +1155,6 @@ private: const uint64_t stmt_id, bool is_anonymous_text = false); - // for normal routine - int generate_pl_function(sql::ObExecContext &ctx, - uint64_t proc_id, - ObCacheObjGuard& cacheobj_guard); - // for inner common execute int execute(sql::ObExecContext &ctx, ObIAllocator &allocator, @@ -1175,10 +1171,13 @@ private: uint64_t loc = 0, bool is_called_from_sql = false); - // add pl to cache - int add_pl_lib_cache(ObPLFunction *pl_func, ObPLCacheCtx &pc_ctx); - public: + // for normal routine + static int generate_pl_function(sql::ObExecContext &ctx, + uint64_t proc_id, + ObCacheObjGuard& cacheobj_guard); + // add pl to cache + static int add_pl_lib_cache(ObPLFunction *pl_func, ObPLCacheCtx &pc_ctx); static int execute_proc(ObPLExecCtx &ctx, uint64_t package_id, uint64_t proc_id, diff --git a/src/pl/ob_pl_compile.cpp b/src/pl/ob_pl_compile.cpp index 1cfee47137..3e83e47973 100644 --- a/src/pl/ob_pl_compile.cpp +++ b/src/pl/ob_pl_compile.cpp @@ -524,6 +524,24 @@ int ObPLCompiler::compile( OX (func.get_stat_for_update().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; } @@ -739,16 +757,17 @@ int ObPLCompiler::generate_package(const ObString &exec_env, ObPLPackageAST &pac session_info_.get_database_id(), package.get_id()); ObRoutinePersistentInfo::ObPLOperation op = ObRoutinePersistentInfo::ObPLOperation::NONE; - bool need_read_dll = GCONF._enable_persistent_compiled_routine - && package_ast.get_can_cached() - && (!session_info_.is_pl_debug_on() || get_tenant_id_by_object_id(package.get_id()) == OB_SYS_TENANT_ID) - && session_info_.get_pl_profiler() == nullptr; + bool enable_persistent = + GCONF._enable_persistent_compiled_routine + && package_ast.get_can_cached() + && (!session_info_.is_pl_debug_on() || get_tenant_id_by_object_id(package.get_id()) == OB_SYS_TENANT_ID) + && session_info_.get_pl_profiler() == nullptr; 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 (need_read_dll) { + 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)); @@ -762,7 +781,7 @@ int ObPLCompiler::generate_package(const ObString &exec_env, ObPLPackageAST &pac OZ (ObPL::check_session_alive(session_info_)); if (OB_SUCC(ret)) { - if (need_read_dll) { + 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)); @@ -771,7 +790,7 @@ int ObPLCompiler::generate_package(const ObString &exec_env, ObPLPackageAST &pac //do nothing } else { OZ (generate_package_routines(exec_env, package_ast.get_routine_table(), package)); - if (need_read_dll) { + if (enable_persistent) { OZ (routine_storage.process_storage_dll(allocator_, schema_guard_, package, op)); } } @@ -874,17 +893,38 @@ int ObPLCompiler::compile_package(const ObPackageInfo &package_info, 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)) { - ObErrorInfo error_info; if (package_info.is_for_trigger()) { CK (OB_NOT_NULL(trigger_info)); - OZ (error_info.delete_error(trigger_info), ret); + OZ (error_info.delete_error(trigger_info)); } else { - if (OB_FAIL(error_info.delete_error(&package_info))) { - LOG_WARN("delete error info failed", K(ret)); + 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; } + int64_t compile_end = ObTimeUtility::current_time(); OX (package.get_stat_for_update().compile_time_ = compile_end - compile_start); OX (package.get_stat_for_update().type_ = ObPLCacheObjectType::PACKAGE_ROUTINE_TYPE); diff --git a/src/pl/ob_pl_interface_pragma.h b/src/pl/ob_pl_interface_pragma.h index 1520050634..afa580d9be 100644 --- a/src/pl/ob_pl_interface_pragma.h +++ b/src/pl/ob_pl_interface_pragma.h @@ -62,6 +62,7 @@ #include "pl/sys_package/ob_dbms_mview.h" #include "pl/sys_package/ob_dbms_mview_stats.h" #include "pl/sys_package/ob_json_array_type.h" +#include "pl/sys_package/ob_utl_recomp.h" #include "pl/sys_package/ob_xml_type.h" #include "pl/sys_package/ob_sdo_geom.h" #include "pl/sys_package/ob_dbms_profiler.h" @@ -786,6 +787,13 @@ // start of dbms_external_table INTERFACE_DEF(INTERFACE_DBMS_EXTERNAL_TABLE_AUTO_REFRESH_EXTERNAL_TABLE, "AUTO_REFRESH_EXTERNAL_TABLE", (ObDBMSExternalTable::auto_refresh_external_table)) //end of dbms_external_table +#ifdef OB_BUILD_ORACLE_PL + // start of utl_recomp + INTERFACE_DEF(INTERFACE_UTL_RECOMP_INVALIDATE_OBJS, "UTL_RECOMP_INVALIDATE_OBJS", (ObUtlRecomp::invalidate_objs)) + INTERFACE_DEF(INTERFACE_UTL_RECOMP_DELETE_ERRORS, "UTL_RECOMP_DELETE_ERRORS", (ObUtlRecomp::delete_errors)) + // end of utl_recomp +#endif + INTERFACE_DEF(INTERFACE_END, "INVALID", (nullptr)) #endif diff --git a/src/pl/ob_pl_package_manager.cpp b/src/pl/ob_pl_package_manager.cpp index 9aa05820c3..99da6c9ad4 100644 --- a/src/pl/ob_pl_package_manager.cpp +++ b/src/pl/ob_pl_package_manager.cpp @@ -276,6 +276,7 @@ static ObSysPackageFile oracle_sys_package_file_table[] = { {"dbms_mview_stats", "dbms_mview_stats.sql", "dbms_mview_stats_body.sql"}, {"json_array_t", "json_array_type.sql", "json_array_type_body.sql"}, {"xmlsequence", "xml_sequence_type.sql", "xml_sequence_type_body.sql"}, + {"utl_recomp", "utl_recomp.sql", "utl_recomp_body.sql"}, {"sdo_geometry", "sdo_geometry.sql", "sdo_geometry_body.sql"}, {"sdo_geom", "sdo_geom.sql", "sdo_geom_body.sql"}, {"dbms_external_table", "dbms_external_table.sql", "dbms_external_table_body.sql"}, diff --git a/src/pl/ob_pl_package_manager.h b/src/pl/ob_pl_package_manager.h index ea99446cc4..bfa94513a8 100644 --- a/src/pl/ob_pl_package_manager.h +++ b/src/pl/ob_pl_package_manager.h @@ -16,6 +16,7 @@ #include #include "lib/utility/ob_macro_utils.h" #include "share/ob_define.h" +#include "share/schema/ob_package_info.h" namespace oceanbase { @@ -163,6 +164,10 @@ public: static int destory_package_state(sql::ObSQLSessionInfo &session_info, uint64_t package_id); int check_version(const ObPLResolveCtx &resolve_ctx, uint64_t package_id, const ObPackageStateVersion &state_version, bool &match); + int get_cached_package(const ObPLResolveCtx &resolve_ctx, uint64_t package_id, + ObPLPackage *&package_spec, + ObPLPackage *&package_body, + bool for_static_member = false); static int notify_package_variable_deserialize(sql::ObBasicSessionInfo *session, const ObString &name, const sql::ObSessionVariable &value); @@ -171,10 +176,6 @@ private: int get_cached_package_spec(const ObPLResolveCtx &resolve_ctx, uint64_t package_id, ObPLPackage *&package_spec); - int get_cached_package(const ObPLResolveCtx &resolve_ctx, uint64_t package_id, - ObPLPackage *&package_spec, - ObPLPackage *&package_body, - bool for_static_member = false); int get_package_item_state(const ObPLResolveCtx &resolve_ctx, sql::ObExecContext &exec_ctx, diff --git a/src/pl/ob_pl_persistent.cpp b/src/pl/ob_pl_persistent.cpp index cb790fd77b..45e03b4c0a 100644 --- a/src/pl/ob_pl_persistent.cpp +++ b/src/pl/ob_pl_persistent.cpp @@ -368,6 +368,9 @@ int ObRoutinePersistentInfo::check_dep_schema(ObSchemaGetterGuard &schema_guard, } } } + if (OB_SUCC(ret) && !match) { + LOG_INFO("not match schema", K(merge_version), K(dep_schema_objs)); + } return ret; } diff --git a/src/pl/ob_pl_resolver.cpp b/src/pl/ob_pl_resolver.cpp index 089993ca89..7978777b2c 100644 --- a/src/pl/ob_pl_resolver.cpp +++ b/src/pl/ob_pl_resolver.cpp @@ -2508,7 +2508,6 @@ int ObPLResolver::fill_record_type( view_schema->get_table_name_str().length(), view_schema->get_table_name_str().ptr())); \ } \ OZ (parser.parse(select_sql.string(), parse_result)); \ - OZ (schema_checker.init(ctx.schema_guard_, ctx.session_info_.get_sessid())); \ \ OX (resolver_ctx.allocator_ = &(alloc)); \ OX (resolver_ctx.schema_checker_ = &schema_checker); \ @@ -2517,9 +2516,11 @@ int ObPLResolver::fill_record_type( OX (resolver_ctx.stmt_factory_ = &stmt_factory); \ OX (resolver_ctx.sql_proxy_ = &(ctx.sql_proxy_)); \ CK (OB_NOT_NULL(resolver_ctx.query_ctx_ = stmt_factory.get_query_ctx())); \ + OX (resolver_ctx.query_ctx_->sql_schema_guard_.set_schema_guard(&ctx.schema_guard_)); \ OX (resolver_ctx.query_ctx_->question_marks_count_ \ = static_cast(parse_result.question_mark_ctx_.count_)); \ - \ + OZ (resolver_ctx.schema_checker_->init(resolver_ctx.query_ctx_->sql_schema_guard_, \ + ctx.session_info_.get_sessid())); \ CK (OB_NOT_NULL(select_stmt_node = parse_result.result_tree_->children_[0]));\ CK (T_SELECT == select_stmt_node->type_); \ ObSelectResolver select_resolver(resolver_ctx); \ @@ -3041,209 +3042,370 @@ int ObPLResolver::resolve_sp_row_type(const ParseNode *sp_data_type_node, CK (OB_NOT_NULL(sp_data_type_node), OB_LIKELY(T_SP_TYPE == sp_data_type_node->type_ || T_SP_ROWTYPE == sp_data_type_node->type_), - OB_LIKELY(1 == sp_data_type_node->num_child_), + OB_LIKELY(2 == sp_data_type_node->num_child_), OB_NOT_NULL(sp_data_type_node->children_[0]), OB_LIKELY(T_SP_OBJ_ACCESS_REF == sp_data_type_node->children_[0]->type_)); - - OZ (resolve_obj_access_idents(*(sp_data_type_node->children_[0]), obj_access_idents, func)); - CK (obj_access_idents.count() > 0); - OX (obj_access_idents.at(obj_access_idents.count() - 1).has_brackets_ = false); - if (OB_SUCC(ret)) { - ObPLSwitchDatabaseGuard switch_db_guard(resolve_ctx_.session_info_, - resolve_ctx_.schema_guard_, - func, - ret, - with_rowid); - ObArray access_idxs; - for (int64_t i = 0; OB_SUCC(ret) && i < obj_access_idents.count(); ++i) { - OZ (resolve_access_ident(obj_access_idents.at(i), - current_block_->get_namespace(), - expr_factory_, - &resolve_ctx_.session_info_, - access_idxs, - func, - false, - true)); - if (OB_ERR_SP_UNDECLARED_VAR == ret && is_data_type_name(obj_access_idents.at(i).access_name_)) { - ret = OB_ERR_TYPE_DECL_ILLEGAL; - LOG_USER_ERROR(OB_ERR_TYPE_DECL_ILLEGAL, obj_access_idents.at(i).access_name_.length(), - obj_access_idents.at(i).access_name_.ptr()); + if (OB_FAIL(ret)) { + } else if (NULL == sp_data_type_node->children_[1]) { + OZ (resolve_obj_access_idents(*(sp_data_type_node->children_[0]), obj_access_idents, func)); + CK (obj_access_idents.count() > 0); + OX (obj_access_idents.at(obj_access_idents.count() - 1).has_brackets_ = false); + if (OB_SUCC(ret)) { + ObPLSwitchDatabaseGuard switch_db_guard(resolve_ctx_.session_info_, + resolve_ctx_.schema_guard_, + func, + ret, + with_rowid); + ObArray access_idxs; + for (int64_t i = 0; OB_SUCC(ret) && i < obj_access_idents.count(); ++i) { + OZ (resolve_access_ident(obj_access_idents.at(i), + current_block_->get_namespace(), + expr_factory_, + &resolve_ctx_.session_info_, + access_idxs, + func, + false, + true)); + if (OB_ERR_SP_UNDECLARED_VAR == ret && is_data_type_name(obj_access_idents.at(i).access_name_)) { + ret = OB_ERR_TYPE_DECL_ILLEGAL; + LOG_USER_ERROR(OB_ERR_TYPE_DECL_ILLEGAL, obj_access_idents.at(i).access_name_.length(), + obj_access_idents.at(i).access_name_.ptr()); + } } - } - // 创建package的时候可能依赖的外部类型还没有创建, 记录下外部类型的name信息, 执行的时候重新解析 - if (OB_NOT_NULL(extern_type_info) - && is_object_not_exist_error(ret) - && obj_access_idents.count() >= 1) { - LOG_USER_WARN(OB_ERR_SP_UNDECLARED_TYPE, - obj_access_idents.at(obj_access_idents.count() - 1).access_name_.length(), - obj_access_idents.at(obj_access_idents.count() - 1).access_name_.ptr()); - record_error_line(sp_data_type_node, resolve_ctx_.session_info_); - ObPL::insert_error_msg(ret); - ret = OB_SUCCESS; - CK (T_SP_ROWTYPE == sp_data_type_node->type_ || T_SP_TYPE == sp_data_type_node->type_); - OZ (resolve_extern_type_info(T_SP_ROWTYPE == sp_data_type_node->type_, - resolve_ctx_.schema_guard_, - resolve_ctx_.session_info_, - obj_access_idents, - extern_type_info)); - } else if (OB_FAIL(ret)) { - // do nothing ... - } else { - int64_t idx_cnt = access_idxs.count(); - CK (OB_LIKELY(idx_cnt != 0)); - if (T_SP_TYPE == sp_data_type_node->type_) { - if (ObObjAccessIdx::is_table_column(access_idxs) - || ObObjAccessIdx::is_local_variable(access_idxs) - || ObObjAccessIdx::is_package_variable(access_idxs) - || ObObjAccessIdx::is_subprogram_variable(access_idxs)) { - OZ (pl_type.deep_copy(resolve_ctx_.allocator_, - ObObjAccessIdx::get_final_type(access_idxs))); - OX (pl_type.set_type_from_orgin(pl_type.get_type_from())); - OX (pl_type.set_type_from(PL_TYPE_ATTR_TYPE)); - OZ (resolve_extern_type_info(resolve_ctx_.schema_guard_, access_idxs, extern_type_info)); - if (OB_SUCC(ret) && ObObjAccessIdx::is_table_column(access_idxs)) { - ObSEArray dep_schemas; - const ObTableSchema* table_schema = NULL; - const uint64_t tenant_id = resolve_ctx_.session_info_.get_effective_tenant_id(); - CK (idx_cnt > 1); - OZ (resolve_ctx_.schema_guard_.get_table_schema(tenant_id, access_idxs.at(idx_cnt - 2).var_index_, table_schema)); - CK (OB_NOT_NULL(table_schema)); - OZ (collect_dep_info_by_schema(resolve_ctx_, table_schema, dep_schemas)); - OZ (func.add_dependency_objects(dep_schemas)); + // 创建package的时候可能依赖的外部类型还没有创建, 记录下外部类型的name信息, 执行的时候重新解析 + if (OB_NOT_NULL(extern_type_info) + && is_object_not_exist_error(ret) + && obj_access_idents.count() >= 1) { + LOG_USER_WARN(OB_ERR_SP_UNDECLARED_TYPE, + obj_access_idents.at(obj_access_idents.count() - 1).access_name_.length(), + obj_access_idents.at(obj_access_idents.count() - 1).access_name_.ptr()); + record_error_line(sp_data_type_node, resolve_ctx_.session_info_); + ObPL::insert_error_msg(ret); + ret = OB_SUCCESS; + CK (T_SP_ROWTYPE == sp_data_type_node->type_ || T_SP_TYPE == sp_data_type_node->type_); + OZ (resolve_extern_type_info(T_SP_ROWTYPE == sp_data_type_node->type_, + resolve_ctx_.schema_guard_, + resolve_ctx_.session_info_, + obj_access_idents, + extern_type_info)); + } else if (OB_FAIL(ret)) { + // do nothing ... + } else if (ObObjAccessIdx::is_dblink_table(access_idxs) + || ObObjAccessIdx::is_dblink_table_column(access_idxs)) { + OZ (resolve_dblink_row_type_with_synonym(resolve_ctx_, access_idxs, + pl_type, T_SP_ROWTYPE == sp_data_type_node->type_)); + OX (func.set_can_cached(false)); + } else { + int64_t idx_cnt = access_idxs.count(); + CK (OB_LIKELY(idx_cnt != 0)); + if (T_SP_TYPE == sp_data_type_node->type_) { + if (ObObjAccessIdx::is_table_column(access_idxs) + || ObObjAccessIdx::is_local_variable(access_idxs) + || ObObjAccessIdx::is_package_variable(access_idxs) + || ObObjAccessIdx::is_subprogram_variable(access_idxs)) { + OZ (pl_type.deep_copy(resolve_ctx_.allocator_, + ObObjAccessIdx::get_final_type(access_idxs))); + OX (pl_type.set_type_from_orgin(pl_type.get_type_from())); + OX (pl_type.set_type_from(PL_TYPE_ATTR_TYPE)); + OZ (resolve_extern_type_info(resolve_ctx_.schema_guard_, access_idxs, extern_type_info)); + if (OB_SUCC(ret) && ObObjAccessIdx::is_table_column(access_idxs)) { + ObSEArray dep_schemas; + const ObTableSchema* table_schema = NULL; + const uint64_t tenant_id = resolve_ctx_.session_info_.get_effective_tenant_id(); + CK (idx_cnt > 1); + OZ (resolve_ctx_.schema_guard_.get_table_schema(tenant_id, access_idxs.at(idx_cnt - 2).var_index_, table_schema)); + CK (OB_NOT_NULL(table_schema)); + OZ (collect_dep_info_by_schema(resolve_ctx_, table_schema, dep_schemas)); + OZ (func.add_dependency_objects(dep_schemas)); + } + } else { + ret = OB_ERR_TYPE_DECL_ILLEGAL; + LOG_WARN("PLS-00206: %TYPE must be applied to a variable, column, field or attribute", + K(ret), K(access_idxs)); } } else { - ret = OB_ERR_TYPE_DECL_ILLEGAL; - LOG_WARN("PLS-00206: %TYPE must be applied to a variable, column, field or attribute", - K(ret), K(access_idxs)); - } - } else { - if (ObObjAccessIdx::is_table(access_idxs)) { - ObSQLSessionInfo &session_info = resolve_ctx_.session_info_; - ObSchemaGetterGuard &schema_guard = resolve_ctx_.schema_guard_; - uint64_t db_id = OB_INVALID_ID; - const ObTableSchema* table_schema = NULL; - ObRecordType *record_type = NULL; - ObSEArray dep_schemas; - ObSEArray types; - const uint64_t tenant_id = session_info.get_effective_tenant_id(); - OZ (session_info.get_database_id(db_id)); - OZ (schema_guard.get_table_schema(tenant_id, access_idxs.at(idx_cnt - 1).var_index_, table_schema)); - CK (OB_NOT_NULL(table_schema)); - if (OB_FAIL(ret)) { - } else if (with_rowid) { - // with_rowid的情况只可能是oracle模式下的trigger - // 将trigger package中routine的参数类型设置为 PL_TYPE_PACKAGE, 并加入到包头的type_table_中 - ObSqlString record_name; - ObString record_name_str; - char* name_buf = NULL; - bool is_dup = false; - const void *dup_type = NULL; - const ObPLBlockNS *pre_ns = NULL; - CK (OB_NOT_NULL(current_block_)); - CK (OB_NOT_NULL(pre_ns = current_block_->get_namespace().get_pre_ns())); - CK (access_idxs.count() > 0); - OZ (record_name.append_fmt( - "__trigger_param_type_%.*s", - access_idxs.at(0).var_name_.length(), access_idxs.at(0).var_name_.ptr())); - if (access_idxs.count() >= 2) { - OZ (record_name.append_fmt("_%.*s", - access_idxs.at(1).var_name_.length(), access_idxs.at(1).var_name_.ptr())); - } + if (ObObjAccessIdx::is_table(access_idxs)) { + ObSQLSessionInfo &session_info = resolve_ctx_.session_info_; + ObSchemaGetterGuard &schema_guard = resolve_ctx_.schema_guard_; + uint64_t db_id = OB_INVALID_ID; + const ObTableSchema* table_schema = NULL; + ObRecordType *record_type = NULL; + ObSEArray dep_schemas; + ObSEArray types; + const uint64_t tenant_id = session_info.get_effective_tenant_id(); + OZ (session_info.get_database_id(db_id)); + OZ (schema_guard.get_table_schema(tenant_id, access_idxs.at(idx_cnt - 1).var_index_, table_schema)); + CK (OB_NOT_NULL(table_schema)); if (OB_FAIL(ret)) { - } else if (OB_ISNULL(name_buf = static_cast(resolve_ctx_.allocator_.alloc(record_name.length() + 1)))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("failed to allocate record name", K(ret)); - } else { - record_name.to_string(name_buf, record_name.length() + 1); - record_name_str.assign_ptr(name_buf, record_name.length()); - if (OB_FAIL(pre_ns->check_dup_type(record_name_str, is_dup, dup_type))) { - LOG_WARN("check dup type failed", K(record_name_str), K(is_dup), K(ret)); - } else if (is_dup) { - if (OB_ISNULL(dup_type)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("dup type is NULL", K(ret)); - } else if (OB_SUCC(ret) && is_dup) { - record_type = static_cast(const_cast(dup_type)); - OV (OB_NOT_NULL(record_type)); + } else if (with_rowid) { + // with_rowid的情况只可能是oracle模式下的trigger + // 将trigger package中routine的参数类型设置为 PL_TYPE_PACKAGE, 并加入到包头的type_table_中 + ObSqlString record_name; + ObString record_name_str; + char* name_buf = NULL; + bool is_dup = false; + const void *dup_type = NULL; + const ObPLBlockNS *pre_ns = NULL; + CK (OB_NOT_NULL(current_block_)); + CK (OB_NOT_NULL(pre_ns = current_block_->get_namespace().get_pre_ns())); + CK (access_idxs.count() > 0); + OZ (record_name.append_fmt( + "__trigger_param_type_%.*s", + access_idxs.at(0).var_name_.length(), access_idxs.at(0).var_name_.ptr())); + if (access_idxs.count() >= 2) { + OZ (record_name.append_fmt("_%.*s", + access_idxs.at(1).var_name_.length(), access_idxs.at(1).var_name_.ptr())); + } + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(name_buf = static_cast(resolve_ctx_.allocator_.alloc(record_name.length() + 1)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate record name", K(ret)); + } else { + record_name.to_string(name_buf, record_name.length() + 1); + record_name_str.assign_ptr(name_buf, record_name.length()); + if (OB_FAIL(pre_ns->check_dup_type(record_name_str, is_dup, dup_type))) { + LOG_WARN("check dup type failed", K(record_name_str), K(is_dup), K(ret)); + } else if (is_dup) { + if (OB_ISNULL(dup_type)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("dup type is NULL", K(ret)); + } else if (OB_SUCC(ret) && is_dup) { + record_type = static_cast(const_cast(dup_type)); + OV (OB_NOT_NULL(record_type)); + OX (pl_type.set_user_type_id(record_type->get_type(), record_type->get_user_type_id())); + OZ (collect_dep_info_by_schema(resolve_ctx_, table_schema, dep_schemas)); + OZ (func.add_dependency_objects(dep_schemas)); + } + } else { + OZ (build_record_type_by_schema(resolve_ctx_, table_schema, record_type, with_rowid, &dep_schemas)); + CK (OB_NOT_NULL(record_type)); + OX (record_type->set_name(record_name_str)); + OZ (pre_ns->expand_data_type(record_type, types)); + OZ (const_cast(pre_ns)->add_type(record_type)); + OX (record_type->set_type_from(PL_TYPE_PACKAGE)); OX (pl_type.set_user_type_id(record_type->get_type(), record_type->get_user_type_id())); - OZ (collect_dep_info_by_schema(resolve_ctx_, table_schema, dep_schemas)); + OZ (pl_type.get_all_depended_user_type(resolve_ctx_, *pre_ns)); OZ (func.add_dependency_objects(dep_schemas)); } - } else { - OZ (build_record_type_by_schema(resolve_ctx_, table_schema, record_type, with_rowid, &dep_schemas)); - CK (OB_NOT_NULL(record_type)); - OX (record_type->set_name(record_name_str)); - OZ (pre_ns->expand_data_type(record_type, types)); - OZ (const_cast(pre_ns)->add_type(record_type)); - OX (record_type->set_type_from(PL_TYPE_PACKAGE)); - OX (pl_type.set_user_type_id(record_type->get_type(), record_type->get_user_type_id())); - OZ (pl_type.get_all_depended_user_type(resolve_ctx_, *pre_ns)); - OZ (func.add_dependency_objects(dep_schemas)); + } + OX (pl_type.set_type_from(PL_TYPE_PACKAGE)); + OX (pl_type.set_type_from_orgin(PL_TYPE_PACKAGE)); + } else { + OZ (build_record_type_by_schema(resolve_ctx_, table_schema, record_type, with_rowid, &dep_schemas)); + CK (OB_NOT_NULL(record_type)); + CK (OB_NOT_NULL(current_block_)); + CK (OB_NOT_NULL(current_block_->get_namespace().get_type_table())); + OZ (current_block_->get_namespace().expand_data_type(record_type, types)); + OZ (current_block_->get_namespace().get_type_table()->add_external_type(record_type)); + OX (pl_type.set_user_type_id(record_type->get_type(), record_type->get_user_type_id())); + OX (pl_type.set_type_from_orgin(pl_type.get_type_from())); + OX (pl_type.set_type_from(PL_TYPE_ATTR_ROWTYPE)); + OZ (pl_type.get_all_depended_user_type(resolve_ctx_, current_block_->get_namespace())); + OZ (resolve_extern_type_info(resolve_ctx_.schema_guard_, access_idxs, extern_type_info)); + OZ (func.add_dependency_objects(dep_schemas)); + } + } else if (ObObjAccessIdx::is_local_cursor_variable(access_idxs) + || ObObjAccessIdx::is_local_refcursor_variable(access_idxs) + || ObObjAccessIdx::is_subprogram_cursor_variable(access_idxs) + || ObObjAccessIdx::is_package_cursor_variable(access_idxs)) { + const ObUserDefinedType* user_type = NULL; + const ObRecordType *record_type = NULL; + OX (pl_type.set_user_type_id( + PL_RECORD_TYPE, ObObjAccessIdx::get_final_type(access_idxs).get_user_type_id())); + CK (OB_NOT_NULL(current_block_)); + OZ (current_block_-> + get_namespace().get_pl_data_type_by_id(pl_type.get_user_type_id(), user_type)); + CK (OB_NOT_NULL(user_type)); + if (OB_SUCC(ret)) { + if (user_type->is_cursor_type() || user_type->is_sys_refcursor_type()) { + const ObRefCursorType *type = static_cast(user_type); + CK (OB_NOT_NULL(type)); + OX (user_type = NULL); + OZ (current_block_->get_namespace().get_pl_data_type_by_id(type->get_return_type_id(), user_type)); + CK (OB_NOT_NULL(user_type)); + OX (pl_type.set_user_type_id(PL_RECORD_TYPE, type->get_return_type_id())); } } - OX (pl_type.set_type_from(PL_TYPE_PACKAGE)); - OX (pl_type.set_type_from_orgin(PL_TYPE_PACKAGE)); - } else { - OZ (build_record_type_by_schema(resolve_ctx_, table_schema, record_type, with_rowid, &dep_schemas)); - CK (OB_NOT_NULL(record_type)); - CK (OB_NOT_NULL(current_block_)); + CK (user_type->is_record_type()); + CK (OB_NOT_NULL(record_type = static_cast(user_type))); CK (OB_NOT_NULL(current_block_->get_namespace().get_type_table())); - OZ (current_block_->get_namespace().expand_data_type(record_type, types)); + OX ((const_cast(record_type))->set_type_from(PL_TYPE_ATTR_ROWTYPE)); OZ (current_block_->get_namespace().get_type_table()->add_external_type(record_type)); - OX (pl_type.set_user_type_id(record_type->get_type(), record_type->get_user_type_id())); OX (pl_type.set_type_from_orgin(pl_type.get_type_from())); OX (pl_type.set_type_from(PL_TYPE_ATTR_ROWTYPE)); OZ (pl_type.get_all_depended_user_type(resolve_ctx_, current_block_->get_namespace())); - OZ (resolve_extern_type_info(resolve_ctx_.schema_guard_, access_idxs, extern_type_info)); - OZ (func.add_dependency_objects(dep_schemas)); - } - } else if (ObObjAccessIdx::is_local_cursor_variable(access_idxs) - || ObObjAccessIdx::is_local_refcursor_variable(access_idxs) - || ObObjAccessIdx::is_subprogram_cursor_variable(access_idxs) - || ObObjAccessIdx::is_package_cursor_variable(access_idxs)) { - const ObUserDefinedType* user_type = NULL; - const ObRecordType *record_type = NULL; - OX (pl_type.set_user_type_id( - PL_RECORD_TYPE, ObObjAccessIdx::get_final_type(access_idxs).get_user_type_id())); - CK (OB_NOT_NULL(current_block_)); - OZ (current_block_-> - get_namespace().get_pl_data_type_by_id(pl_type.get_user_type_id(), user_type)); - CK (OB_NOT_NULL(user_type)); - if (OB_SUCC(ret)) { - if (user_type->is_cursor_type() || user_type->is_sys_refcursor_type()) { - const ObRefCursorType *type = static_cast(user_type); - CK (OB_NOT_NULL(type)); - OX (user_type = NULL); - OZ (current_block_->get_namespace().get_pl_data_type_by_id(type->get_return_type_id(), user_type)); - CK (OB_NOT_NULL(user_type)); - OX (pl_type.set_user_type_id(PL_RECORD_TYPE, type->get_return_type_id())); + if (!ObObjAccessIdx::is_subprogram_cursor_variable(access_idxs)) { + OZ (resolve_extern_type_info(resolve_ctx_.schema_guard_, access_idxs, extern_type_info)); } + } else { + ret = OB_ERR_WRONG_ROWTYPE; + LOG_USER_ERROR(OB_ERR_WRONG_ROWTYPE, + static_cast(sp_data_type_node->str_len_), sp_data_type_node->str_value_); + LOG_WARN("PLS-00310: with %ROWTYPE attribute, ident must name a table, cursor or cursor-variable", + K(ret), K(access_idxs)); } - CK (user_type->is_record_type()); - CK (OB_NOT_NULL(record_type = static_cast(user_type))); - CK (OB_NOT_NULL(current_block_->get_namespace().get_type_table())); - OX ((const_cast(record_type))->set_type_from(PL_TYPE_ATTR_ROWTYPE)); - OZ (current_block_->get_namespace().get_type_table()->add_external_type(record_type)); - OX (pl_type.set_type_from_orgin(pl_type.get_type_from())); - OX (pl_type.set_type_from(PL_TYPE_ATTR_ROWTYPE)); - OZ (pl_type.get_all_depended_user_type(resolve_ctx_, current_block_->get_namespace())); - if (!ObObjAccessIdx::is_subprogram_cursor_variable(access_idxs)) { - OZ (resolve_extern_type_info(resolve_ctx_.schema_guard_, access_idxs, extern_type_info)); - } - } else { - ret = OB_ERR_WRONG_ROWTYPE; - LOG_USER_ERROR(OB_ERR_WRONG_ROWTYPE, - static_cast(sp_data_type_node->str_len_), sp_data_type_node->str_value_); - LOG_WARN("PLS-00310: with %ROWTYPE attribute, ident must name a table, cursor or cursor-variable", - K(ret), K(access_idxs)); } } } + } else { + CK (T_DBLINK_NAME == sp_data_type_node->children_[1]->type_); + CK (1 == sp_data_type_node->children_[1]->num_child_); + CK (OB_NOT_NULL(sp_data_type_node->children_[1]->children_[0])); + OZ (resolve_dblink_row_type_node(*sp_data_type_node->children_[0], + *sp_data_type_node->children_[1]->children_[0], + pl_type, + T_SP_ROWTYPE == sp_data_type_node->type_)); + OX (func.set_can_cached(false)); } CANCLE_LOG_CHECK_MODE(); return ret; } +int ObPLResolver::resolve_dblink_row_type_node(const ParseNode &access_node, + const ParseNode &dblink_node, + ObPLDataType &pl_type, + bool is_row_type) +{ + int ret = OB_SUCCESS; + const ParseNode *name_node = NULL; + ObString name_0; + ObString name_1; + ObString name_2; + ObString dblink_name; + CK (OB_LIKELY(T_SP_OBJ_ACCESS_REF == access_node.type_)); + CK (OB_LIKELY(T_USER_VARIABLE_IDENTIFIER == dblink_node.type_)); + CK (2 == access_node.num_child_); + if (OB_SUCC(ret) && NULL != access_node.children_[1]) { + ret = OB_ERR_PARSER_SYNTAX; + LOG_WARN("parse node error", K(ret)); + } + CK (NULL != (name_node = access_node.children_[0])); + CK (T_SP_ACCESS_NAME == name_node->type_); + if (OB_SUCC(ret) && NULL != name_node->children_[0]) { + CK (T_IDENT == name_node->children_[0]->type_); + OX (name_0.assign_ptr(name_node->children_[0]->str_value_, (int32_t)(name_node->children_[0]->str_len_))); + } + if (OB_SUCC(ret) && NULL != name_node->children_[1]) { + CK (T_IDENT == name_node->children_[1]->type_); + OX (name_1.assign_ptr(name_node->children_[1]->str_value_, (int32_t)(name_node->children_[1]->str_len_))); + } + if (OB_SUCC(ret) && NULL != name_node->children_[2]) { + CK (T_IDENT == name_node->children_[2]->type_); + OX (name_2.assign_ptr(name_node->children_[2]->str_value_, (int32_t)(name_node->children_[2]->str_len_))); + } + OX (dblink_name.assign_ptr(dblink_node.str_value_, (int32_t)(dblink_node.str_len_))); + if (OB_SUCC(ret)) { + if (is_row_type) { + CK (name_0.empty()); + OZ (resolve_dblink_row_type(name_1, name_2, name_0, dblink_name, pl_type, true)); + } else { + OZ (resolve_dblink_row_type(name_0, name_1, name_2, dblink_name, pl_type, false)); + } + } + return ret; +} + +int ObPLResolver::resolve_dblink_row_type_with_synonym(ObPLResolveCtx &resolve_ctx, + const common::ObIArray &access_idxs, + ObPLDataType &pl_type, + bool is_row_type) +{ + int ret = OB_SUCCESS; +#ifdef OB_BUILD_ORACLE_PL + ObString db_name; + ObString table_name; + ObString dblink_name; + ObSchemaChecker checker; + uint64_t syn_id = OB_INVALID_ID; + ObString empty_str; + int64_t cnt = access_idxs.count(); + int64_t syn_idx = cnt - (is_row_type ? 1 : 2); + OZ (checker.init(resolve_ctx.schema_guard_, resolve_ctx.session_info_.get_sessid())); + OV (is_row_type ? cnt >= 1 : cnt >= 2, OB_ERR_UNEXPECTED, K(is_row_type), K(cnt)); + OX (syn_id = static_cast(access_idxs.at(syn_idx).var_index_)); + OZ (ObPLDblinkUtil::separate_name_from_synonym(checker, resolve_ctx.allocator_, + resolve_ctx.session_info_.get_effective_tenant_id(), + resolve_ctx.session_info_.get_database_name(), + syn_id, dblink_name, db_name, table_name)); + OZ (resolve_dblink_row_type(db_name, table_name, + is_row_type ? empty_str : access_idxs.at(cnt-1).var_name_, /*col name*/ + dblink_name, pl_type, is_row_type)); +#endif + return ret; +} + +int ObPLResolver::resolve_dblink_row_type(const ObString &db_name, + const ObString &table_name, + const ObString &col_name, + const ObString &dblink_name, + ObPLDataType &pl_type, + bool is_row_type) +{ + int ret = OB_SUCCESS; + const ObTableSchema *table_schema = NULL; + if (!is_row_type) { + CK (!col_name.empty()); + } + CK (!table_name.empty()); + if (OB_SUCC(ret)) { + if (db_name.empty()) { + ObString default_dblink_user; + OZ (resolve_ctx_.schema_guard_.get_dblink_user(resolve_ctx_.session_info_.get_effective_tenant_id(), + dblink_name, + default_dblink_user, + resolve_ctx_.allocator_)); + OZ (resolve_ctx_.package_guard_.dblink_guard_.get_dblink_table_by_name( + resolve_ctx_.session_info_, resolve_ctx_.schema_guard_, + dblink_name, default_dblink_user, table_name, table_schema)); + } else { + OZ (resolve_ctx_.package_guard_.dblink_guard_.get_dblink_table_by_name( + resolve_ctx_.session_info_, resolve_ctx_.schema_guard_, + dblink_name, db_name, table_name, table_schema)); + } + CK (OB_NOT_NULL(table_schema)); + if (OB_SUCC(ret)) { + ObSqlString record_name; + ObString record_name_str; + char* name_buf = NULL; + ObRecordType *record_type = NULL; + ObSEArray dep_schemas; + OZ (record_name.append_fmt("__dblink_param_type_%.*s_%.*s", + table_schema->get_link_database_name().length(), table_schema->get_link_database_name().ptr(), + table_schema->get_table_name_str().length(), table_schema->get_table_name_str().ptr())); + OV (OB_NOT_NULL(name_buf = static_cast(resolve_ctx_.allocator_.alloc(record_name.length() + 1))), + OB_ALLOCATE_MEMORY_FAILED); + OX (record_name.to_string(name_buf, record_name.length() + 1)); + OX (record_name_str.assign_ptr(name_buf, record_name.length())); + OZ (build_record_type_by_schema(resolve_ctx_, table_schema, record_type, false, &dep_schemas)); + CK (OB_NOT_NULL(record_type)); + OX (record_type->set_name(record_name_str)); + OX (record_type->set_user_type_id( + common::combine_pl_type_id(table_schema->get_dblink_id() | common::OB_MOCK_DBLINK_UDT_ID_MASK, + table_schema->get_table_id()))); + if (OB_FAIL(ret)) { + } else if (is_row_type) { + CK (OB_NOT_NULL(current_block_)); + CK (OB_NOT_NULL(current_block_->get_namespace().get_type_table())); + OZ (current_block_->get_namespace().get_type_table()->add_external_type(record_type)); + OX (pl_type.set_user_type_id(record_type->get_type(), record_type->get_user_type_id())); + OX (pl_type.set_type_from_orgin(pl_type.get_type_from())); + OX (pl_type.set_type_from(PL_TYPE_ATTR_ROWTYPE)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < record_type->get_member_count(); i++) { + const ObString *mem_name = record_type->get_record_member_name(i); + CK (OB_NOT_NULL(mem_name)); + if (OB_SUCC(ret) && 0 == mem_name->case_compare(col_name)) { + CK (OB_NOT_NULL(record_type->get_record_member_type(i))); + OX (pl_type = *(record_type->get_record_member_type(i))); + break; + } + } // end for + } // end if + } + } + return ret; +} + // 注意: 该函数参考ObResolverUtils::resolve_data_type进行实现, 调整类型精度信息到默认值 int ObPLResolver::adjust_routine_param_type(ObPLDataType &type) { @@ -5554,6 +5716,8 @@ int ObPLResolver::check_and_record_stmt_type(ObPLFunctionAST &func, case stmt::T_SHOW_PRIVILEGES: case stmt::T_SHOW_CREATE_PROCEDURE: case stmt::T_SHOW_CREATE_FUNCTION: + case stmt::T_SHOW_PROCEDURE_CODE: + case stmt::T_SHOW_FUNCTION_CODE: case stmt::T_SHOW_PROCEDURE_STATUS: case stmt::T_SHOW_FUNCTION_STATUS: case stmt::T_SHOW_CREATE_TABLEGROUP: @@ -14539,10 +14703,16 @@ int ObPLResolver::resolve_access_ident(ObObjAccessIdent &access_ident, // 当前 ? reinterpret_cast(access_idxs.at(cnt - 1).label_ns_) : access_idxs.at(cnt - 1).label_ns_->get_package_id()); } else if (0 != cnt - && ObObjAccessIdx::IS_DBLINK_PKG_NS == access_idxs.at(cnt-1).access_type_ && !is_routine) { - OZ (resolve_dblink_type_with_synonym(parent_id, access_ident.access_name_, func, pl_data_type)); - OX (type = ObPLExternalNS::PKG_TYPE); - OX (var_index = pl_data_type.get_user_type_id()); + && ObObjAccessIdx::IS_DBLINK_PKG_NS == access_idxs.at(cnt-1).access_type_ + && (!is_routine || is_resolve_rowtype)) { + if (!is_routine && !is_resolve_rowtype) { + OZ (resolve_dblink_type_with_synonym(parent_id, access_ident.access_name_, func, pl_data_type)); + OX (type = ObPLExternalNS::PKG_TYPE); + OX (var_index = pl_data_type.get_user_type_id()); + } else { + type = ObPLExternalNS::TABLE_COL; + var_index = 1; // set var_index value, and resolve type in `resolve_dblink_row_type_with_synonym` + } } else { if (access_ident.is_pl_var() && access_ident.access_name_.empty()) { // questionmark variable const ObPLSymbolTable *sym_tbl = ns.get_symbol_table(); diff --git a/src/pl/ob_pl_resolver.h b/src/pl/ob_pl_resolver.h index e029c42a19..6e39fe2d25 100644 --- a/src/pl/ob_pl_resolver.h +++ b/src/pl/ob_pl_resolver.h @@ -645,6 +645,20 @@ private: ObPLDataType &pl_type, ObPLExternTypeInfo *extern_type_info = NULL, bool with_rowid = false); + int resolve_dblink_row_type_node(const ParseNode &access_node, + const ParseNode &dblink_node, + ObPLDataType &pl_type, + bool is_row_type); + int resolve_dblink_row_type(const ObString &db_name, + const ObString &table_name, + const ObString &col_name, + const ObString &dblink_name, + ObPLDataType &pl_type, + bool is_row_type); + int resolve_dblink_row_type_with_synonym(ObPLResolveCtx &resolve_ctx, + const common::ObIArray &access_idxs, + ObPLDataType &pl_type, + bool is_row_type); int resolve_dblink_type(const ParseNode *node, ObPLCompileUnitAST &func, ObPLDataType &pl_type); diff --git a/src/pl/ob_pl_type.cpp b/src/pl/ob_pl_type.cpp index 11d9e5eb5a..33aa898a6c 100644 --- a/src/pl/ob_pl_type.cpp +++ b/src/pl/ob_pl_type.cpp @@ -1593,6 +1593,28 @@ bool ObObjAccessIdx::is_table_column(const common::ObIArray &acc && ObObjAccessIdx::IS_TABLE_COL == access_idxs.at(2).access_type_)); } +bool ObObjAccessIdx::is_dblink_table(const common::ObIArray &access_idxs) +{ + return !access_idxs.empty() + && ((1 == access_idxs.count() + && ObObjAccessIdx::IS_DBLINK_PKG_NS == access_idxs.at(0).access_type_) + || (2 == access_idxs.count() + && ObObjAccessIdx::IS_DB_NS == access_idxs.at(0).access_type_ + && ObObjAccessIdx::IS_DBLINK_PKG_NS == access_idxs.at(1).access_type_)); +} + +bool ObObjAccessIdx::is_dblink_table_column(const common::ObIArray &access_idxs) +{ + return !access_idxs.empty() + && ((2 == access_idxs.count() + && ObObjAccessIdx::IS_DBLINK_PKG_NS == access_idxs.at(0).access_type_ + && ObObjAccessIdx::IS_TABLE_COL == access_idxs.at(1).access_type_) + || (3 == access_idxs.count() + && ObObjAccessIdx::IS_DB_NS == access_idxs.at(0).access_type_ + && ObObjAccessIdx::IS_DBLINK_PKG_NS == access_idxs.at(1).access_type_ + && ObObjAccessIdx::IS_TABLE_COL == access_idxs.at(2).access_type_)); +} + bool ObObjAccessIdx::is_local_variable(const common::ObIArray &access_idxs) { bool is_local = false; diff --git a/src/pl/ob_pl_type.h b/src/pl/ob_pl_type.h index 94b566735a..38c464e25b 100644 --- a/src/pl/ob_pl_type.h +++ b/src/pl/ob_pl_type.h @@ -741,6 +741,8 @@ public: static bool is_table(const common::ObIArray &access_idxs); static bool is_table_column(const common::ObIArray &access_idxs); + static bool is_dblink_table(const common::ObIArray &access_idxs); + static bool is_dblink_table_column(const common::ObIArray &access_idxs); static bool is_local_variable(const common::ObIArray &access_idxs); static bool is_function_return_variable(const common::ObIArray &access_idxs); static bool is_subprogram_variable(const common::ObIArray &access_idxs); diff --git a/src/pl/parser/pl_parser_mysql_mode.y b/src/pl/parser/pl_parser_mysql_mode.y index 98494fd633..3a2b7f9f38 100644 --- a/src/pl/parser/pl_parser_mysql_mode.y +++ b/src/pl/parser/pl_parser_mysql_mode.y @@ -254,7 +254,7 @@ void obpl_mysql_wrap_get_user_var_into_subquery(ObParseCtx *parse_ctx, ParseNode %type sp_param sp_fparam sp_alter_chistics %type opt_sp_definer sp_create_chistics sp_create_chistic sp_chistic opt_parentheses user opt_host_name %type param_type sp_cparams opt_sp_cparam_list cexpr sp_cparam opt_sp_cparam_with_assign -%type opt_sp_inout opt_if_exists +%type opt_sp_inout opt_if_exists opt_if_not_exists %type call_sp_stmt do_sp_stmt %type sp_cond sp_hcond_list sp_hcond %type sp_unlabeled_control sp_labeled_control @@ -579,7 +579,15 @@ call_sp_stmt: { malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_CALL_STMT, 2, $2, $3); } - | CALL PROCEDURE sp_name '(' opt_sp_param_list ')' sp_create_chistics procedure_body + | CALL PROCEDURE opt_if_not_exists sp_name '(' opt_sp_param_list ')' sp_create_chistics procedure_body + { + if (!parse_ctx->is_inner_parse_) { + obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error\n"); + YYERROR; //生成一个语法错误 + } + $$ = $9; + } + | CALL PROCEDURE opt_if_not_exists sp_name '(' opt_sp_param_list ')' procedure_body { if (!parse_ctx->is_inner_parse_) { obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error\n"); @@ -587,15 +595,15 @@ call_sp_stmt: } $$ = $8; } - | CALL PROCEDURE sp_name '(' opt_sp_param_list ')' procedure_body + | CALL FUNCTION opt_if_not_exists sp_name '(' opt_sp_fparam_list ')' RETURNS sp_data_type sp_create_chistics function_body { if (!parse_ctx->is_inner_parse_) { obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error\n"); YYERROR; //生成一个语法错误 } - $$ = $7; + $$ = $11; } - | CALL FUNCTION sp_name '(' opt_sp_fparam_list ')' RETURNS sp_data_type sp_create_chistics function_body + | CALL FUNCTION opt_if_not_exists sp_name '(' opt_sp_fparam_list ')' RETURNS sp_data_type function_body { if (!parse_ctx->is_inner_parse_) { obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error\n"); @@ -603,14 +611,6 @@ call_sp_stmt: } $$ = $10; } - | CALL FUNCTION sp_name '(' opt_sp_fparam_list ')' RETURNS sp_data_type function_body - { - if (!parse_ctx->is_inner_parse_) { - obpl_mysql_yyerror(&@2, parse_ctx, "Syntax Error\n"); - YYERROR; //生成一个语法错误 - } - $$ = $9; - } ; opt_sp_cparam_list: @@ -1068,16 +1068,17 @@ create_trigger_stmt: ; plsql_trigger_source: - TRIGGER sp_name trigger_definition + TRIGGER opt_if_not_exists sp_name trigger_definition { - check_ptr($3); + check_ptr($4); const char *stmt_str = parse_ctx->stmt_str_ + @1.first_column; - int32_t str_len = @3.last_column - @1.first_column + 1; - $3->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_); - check_ptr($3->str_value_); - $3->str_len_ = str_len; - $3->pl_str_off_ = @1.first_column; - malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_TG_SOURCE, 2, $2, $3); + int32_t str_len = @4.last_column - @1.first_column + 1; + $4->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_); + check_ptr($4->str_value_); + $4->str_len_ = str_len; + $4->pl_str_off_ = @1.first_column; + malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_TG_SOURCE, 2, $3, $4); + $$->value_ = $2; } ; @@ -1152,73 +1153,11 @@ drop_trigger_stmt: * *****************************************************************************/ create_procedure_stmt: - CREATE opt_sp_definer PROCEDURE sp_name '(' opt_sp_param_list ')' sp_create_chistics procedure_body - { - check_ptr($9); - ParseNode *sp_clause_node = NULL; - merge_nodes(sp_clause_node, parse_ctx->mem_pool_, T_SP_CLAUSE_LIST, $8); - const char *stmt_str = parse_ctx->stmt_str_ + @3.first_column; - int32_t str_len = @9.last_column - @3.first_column + 1; - $9->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_); - check_ptr($9->str_value_); - $9->str_len_ = str_len; - $9->raw_text_ = $9->str_value_ + @9.first_column - @3.first_column; - $9->text_len_ = str_len - (@9.first_column - @3.first_column); - if (NULL != $6) { - const char *param_str = parse_ctx->stmt_str_ + @5.first_column + 1; - int32_t param_len = @7.last_column - @5.last_column - 1; - $6->str_value_ = parse_strndup(param_str, param_len, parse_ctx->mem_pool_); - check_ptr($6->str_value_); - $6->str_len_ = param_len; - } - malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_CREATE, 5, $2, $4, $6, sp_clause_node, $9); - } - | CREATE opt_sp_definer PROCEDURE sp_name '(' opt_sp_param_list ')' procedure_body - { - check_ptr($8); - const char *stmt_str = parse_ctx->stmt_str_ + @3.first_column; - int32_t str_len = @8.last_column - @3.first_column + 1; - $8->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_); - check_ptr($8->str_value_); - $8->str_len_ = str_len; - $8->raw_text_ = $8->str_value_ + @8.first_column - @3.first_column; - $8->text_len_ = str_len - (@8.first_column - @3.first_column); - if (NULL != $6) { - const char *param_str = parse_ctx->stmt_str_ + @5.first_column + 1; - int32_t param_len = @7.last_column - @5.last_column - 1; - $6->str_value_ = parse_strndup(param_str, param_len, parse_ctx->mem_pool_); - check_ptr($6->str_value_); - $6->str_len_ = param_len; - } - malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_CREATE, 5, $2, $4, $6, NULL, $8); - } -; - -create_function_stmt: - CREATE opt_sp_definer FUNCTION sp_name '(' opt_sp_fparam_list ')' RETURNS sp_data_type sp_create_chistics function_body - { - check_ptr($11); - ParseNode *sp_clause_node = NULL; - merge_nodes(sp_clause_node, parse_ctx->mem_pool_, T_SP_CLAUSE_LIST, $10); - const char *stmt_str = parse_ctx->stmt_str_ + @3.first_column; - int32_t str_len = @11.last_column - @3.first_column + 1; - $11->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_); - check_ptr($11->str_value_); - $11->str_len_ = str_len; - $11->raw_text_ = $11->str_value_ + @11.first_column - @3.first_column; - $11->text_len_ = str_len - (@11.first_column - @3.first_column); - if (NULL != $6) { - const char *param_str = parse_ctx->stmt_str_ + @5.first_column + 1; - int32_t param_len = @7.last_column - @5.last_column - 1; - $6->str_value_ = parse_strndup(param_str, param_len, parse_ctx->mem_pool_); - check_ptr($6->str_value_); - $6->str_len_ = param_len; - } - malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SF_CREATE, 6, $2, $4, $6, $9, sp_clause_node, $11); - } - | CREATE opt_sp_definer FUNCTION sp_name '(' opt_sp_fparam_list ')' RETURNS sp_data_type function_body + CREATE opt_sp_definer PROCEDURE opt_if_not_exists sp_name '(' opt_sp_param_list ')' sp_create_chistics procedure_body { check_ptr($10); + ParseNode *sp_clause_node = NULL; + merge_nodes(sp_clause_node, parse_ctx->mem_pool_, T_SP_CLAUSE_LIST, $9); const char *stmt_str = parse_ctx->stmt_str_ + @3.first_column; int32_t str_len = @10.last_column - @3.first_column + 1; $10->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_); @@ -1226,14 +1165,80 @@ create_function_stmt: $10->str_len_ = str_len; $10->raw_text_ = $10->str_value_ + @10.first_column - @3.first_column; $10->text_len_ = str_len - (@10.first_column - @3.first_column); - if (NULL != $6) { - const char *param_str = parse_ctx->stmt_str_ + @5.first_column + 1; - int32_t param_len = @7.last_column - @5.last_column - 1; - $6->str_value_ = parse_strndup(param_str, param_len, parse_ctx->mem_pool_); - check_ptr($6->str_value_); - $6->str_len_ = param_len; + if (NULL != $7) { + const char *param_str = parse_ctx->stmt_str_ + @6.first_column + 1; + int32_t param_len = @8.last_column - @6.last_column - 1; + $7->str_value_ = parse_strndup(param_str, param_len, parse_ctx->mem_pool_); + check_ptr($7->str_value_); + $7->str_len_ = param_len; } - malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SF_CREATE, 6, $2, $4, $6, $9, NULL, $10); + malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_CREATE, 5, $2, $5, $7, sp_clause_node, $10); + $$->value_ = $4; + } + | CREATE opt_sp_definer PROCEDURE opt_if_not_exists sp_name '(' opt_sp_param_list ')' procedure_body + { + check_ptr($9); + const char *stmt_str = parse_ctx->stmt_str_ + @3.first_column; + int32_t str_len = @9.last_column - @3.first_column + 1; + $9->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_); + check_ptr($9->str_value_); + $9->str_len_ = str_len; + $9->raw_text_ = $9->str_value_ + @9.first_column - @3.first_column; + $9->text_len_ = str_len - (@9.first_column - @3.first_column); + if (NULL != $7) { + const char *param_str = parse_ctx->stmt_str_ + @6.first_column + 1; + int32_t param_len = @8.last_column - @6.last_column - 1; + $7->str_value_ = parse_strndup(param_str, param_len, parse_ctx->mem_pool_); + check_ptr($7->str_value_); + $7->str_len_ = param_len; + } + malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_CREATE, 5, $2, $5, $7, NULL, $9); + $$->value_ = $4; + } +; + +create_function_stmt: + CREATE opt_sp_definer FUNCTION opt_if_not_exists sp_name '(' opt_sp_fparam_list ')' RETURNS sp_data_type sp_create_chistics function_body + { + check_ptr($12); + ParseNode *sp_clause_node = NULL; + merge_nodes(sp_clause_node, parse_ctx->mem_pool_, T_SP_CLAUSE_LIST, $11); + const char *stmt_str = parse_ctx->stmt_str_ + @3.first_column; + int32_t str_len = @12.last_column - @3.first_column + 1; + $12->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_); + check_ptr($12->str_value_); + $12->str_len_ = str_len; + $12->raw_text_ = $12->str_value_ + @12.first_column - @3.first_column; + $12->text_len_ = str_len - (@12.first_column - @3.first_column); + if (NULL != $7) { + const char *param_str = parse_ctx->stmt_str_ + @6.first_column + 1; + int32_t param_len = @8.last_column - @6.last_column - 1; + $7->str_value_ = parse_strndup(param_str, param_len, parse_ctx->mem_pool_); + check_ptr($7->str_value_); + $7->str_len_ = param_len; + } + malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SF_CREATE, 6, $2, $5, $7, $10, sp_clause_node, $12); + $$->value_ = $4; + } + | CREATE opt_sp_definer FUNCTION opt_if_not_exists sp_name '(' opt_sp_fparam_list ')' RETURNS sp_data_type function_body + { + check_ptr($11); + const char *stmt_str = parse_ctx->stmt_str_ + @3.first_column; + int32_t str_len = @11.last_column - @3.first_column + 1; + $11->str_value_ = parse_strndup(stmt_str, str_len, parse_ctx->mem_pool_); + check_ptr($11->str_value_); + $11->str_len_ = str_len; + $11->raw_text_ = $11->str_value_ + @11.first_column - @3.first_column; + $11->text_len_ = str_len - (@11.first_column - @3.first_column); + if (NULL != $7) { + const char *param_str = parse_ctx->stmt_str_ + @6.first_column + 1; + int32_t param_len = @8.last_column - @6.last_column - 1; + $7->str_value_ = parse_strndup(param_str, param_len, parse_ctx->mem_pool_); + check_ptr($7->str_value_); + $7->str_len_ = param_len; + } + malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SF_CREATE, 6, $2, $5, $7, $10, NULL, $11); + $$->value_ = $4; } ; @@ -1956,6 +1961,11 @@ opt_if_exists: | IF EXISTS { $$ = 1; } ; +opt_if_not_exists: + /*Empty*/ { $$ = 0; } + | IF NOT EXISTS { $$ = 1; } +; + scalar_data_type: int_type_i opt_int_length_i %prec LOWER_PARENS { @@ -2290,7 +2300,7 @@ scalar_data_type: | pl_obj_access_ref '%' ROWTYPE { if (parse_ctx->is_for_trigger_ && parse_ctx->is_inner_parse_) { - malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_ROWTYPE, 1, $1); + malloc_non_terminal_node($$, parse_ctx->mem_pool_, T_SP_ROWTYPE, 2, $1, NULL); } else { obpl_mysql_yyerror(&@3, parse_ctx, "Syntax Error\n"); YYERROR; diff --git a/src/rootserver/ob_ddl_operator.cpp b/src/rootserver/ob_ddl_operator.cpp index 5bf4691ac6..0aefbd3292 100644 --- a/src/rootserver/ob_ddl_operator.cpp +++ b/src/rootserver/ob_ddl_operator.cpp @@ -9048,6 +9048,11 @@ int ObDDLOperator::replace_routine(ObRoutineInfo &routine_info, routine_info.set_routine_id(old_routine_info->get_routine_id()); routine_info.set_schema_version(new_schema_version); } + if (OB_SUCC(ret) && ERROR_STATUS_NO_ERROR == error_info.get_error_status()) { + OZ (pl::ObRoutinePersistentInfo::delete_dll_from_disk(trans, old_routine_info->get_tenant_id(), + old_routine_info->get_routine_id(), + old_routine_info->get_database_id())); + } OZ (ObDependencyInfo::delete_schema_object_dependency(trans, old_routine_info->get_tenant_id(), old_routine_info->get_routine_id(), new_schema_version, @@ -9326,6 +9331,31 @@ int ObDDLOperator::create_package(const ObPackageInfo *old_package_info, } } if (is_replace) { + if (OB_SUCC(ret) && ERROR_STATUS_NO_ERROR == error_info.get_error_status()) { + // when recreate package header, need clear package body cache if exist package body + if (PACKAGE_TYPE == old_package_info->get_type()) { + const ObPackageInfo *del_package_info = NULL; + if (OB_FAIL(schema_guard.get_package_info(tenant_id, + old_package_info->get_database_id(), + old_package_info->get_package_name(), + PACKAGE_BODY_TYPE, + old_package_info->get_compatibility_mode(), + del_package_info))) { + LOG_WARN("get package body info failed", K(ret)); + } else if (OB_NOT_NULL(del_package_info)) { + OZ (pl::ObRoutinePersistentInfo::delete_dll_from_disk(trans, + tenant_id, + del_package_info->get_package_id(), + del_package_info->get_database_id())); + } + } else { + // do nothing + } + OZ (pl::ObRoutinePersistentInfo::delete_dll_from_disk(trans, + tenant_id, + old_package_info->get_package_id(), + old_package_info->get_database_id())); + } OZ (ObDependencyInfo::delete_schema_object_dependency(trans, tenant_id, old_package_info->get_package_id(), new_schema_version, @@ -9343,7 +9373,7 @@ int ObDDLOperator::create_package(const ObPackageInfo *old_package_info, return ret; } -int ObDDLOperator::alter_package(const ObPackageInfo &package_info, +int ObDDLOperator::alter_package(ObPackageInfo &package_info, ObSchemaGetterGuard &schema_guard, ObMySQLTransaction &trans, ObIArray &public_routine_infos, @@ -9356,7 +9386,6 @@ int ObDDLOperator::alter_package(const ObPackageInfo &package_info, const uint64_t tenant_id = package_info.get_tenant_id(); int64_t new_schema_version = OB_INVALID_VERSION; uint64_t package_id = package_info.get_package_id(); - ObPackageInfo new_package_info; OV (OB_NOT_NULL(schema_service_impl), OB_ERR_SYS); OV (OB_INVALID_ID != tenant_id && OB_INVALID_ID != package_id, OB_INVALID_ARGUMENT); if (OB_SUCC(ret)) { @@ -9386,12 +9415,13 @@ int ObDDLOperator::alter_package(const ObPackageInfo &package_info, } } // if alter package, we need push up schema version, because we need update package state - OZ (new_package_info.assign(package_info)); OZ (schema_service_.gen_new_schema_version(tenant_id, new_schema_version)); - OX (new_package_info.set_schema_version(new_schema_version)); - OZ (schema_service_impl->get_routine_sql_service().alter_package(new_package_info, &trans, ddl_stmt_str)); + OX (package_info.set_schema_version(new_schema_version)); + OZ (schema_service_impl->get_routine_sql_service().alter_package(package_info, &trans, ddl_stmt_str)); } + OZ (error_info.handle_error_info(trans, &package_info)); + return ret; } @@ -9606,6 +9636,15 @@ int ObDDLOperator::create_trigger(ObTriggerInfo &trigger_info, trigger_info.get_object_type())); OZ (insert_dependency_infos(trans, dep_infos, trigger_info.get_tenant_id(), trigger_info.get_trigger_id(), trigger_info.get_schema_version(), trigger_info.get_owner_id())); + + if (OB_SUCC(ret) && is_replace && ERROR_STATUS_NO_ERROR == error_info.get_error_status()) { + OZ (pl::ObRoutinePersistentInfo::delete_dll_from_disk( + trans, tenant_id, share::schema::ObTriggerInfo::get_trigger_spec_package_id(trigger_info.get_trigger_id()), + trigger_info.get_database_id())); + OZ (pl::ObRoutinePersistentInfo::delete_dll_from_disk( + trans, tenant_id, share::schema::ObTriggerInfo::get_trigger_body_package_id(trigger_info.get_trigger_id()), + trigger_info.get_database_id())); + } } if (OB_SUCC(ret)) { if (OB_FAIL(error_info.handle_error_info(trans, &trigger_info))) { @@ -9679,6 +9718,12 @@ int ObDDLOperator::alter_trigger(ObTriggerInfo &trigger_info, trans, tenant_id, base_table_id, false/*in offline ddl white list*/), base_table_id, trigger_info.get_trigger_name()); } + OZ (pl::ObRoutinePersistentInfo::delete_dll_from_disk( + trans, tenant_id, share::schema::ObTriggerInfo::get_trigger_spec_package_id(trigger_info.get_trigger_id()), + trigger_info.get_database_id())); + OZ (pl::ObRoutinePersistentInfo::delete_dll_from_disk( + trans, tenant_id, share::schema::ObTriggerInfo::get_trigger_body_package_id(trigger_info.get_trigger_id()), + trigger_info.get_database_id())); ObErrorInfo error_info; OZ (error_info.handle_error_info(trans, &trigger_info), error_info); return ret; @@ -10047,7 +10092,19 @@ int ObDDLOperator::replace_udt(ObUDTTypeInfo &udt_info, // do nothing } } - + if (OB_SUCC(ret) && public_routine_infos.count() > 0 && ERROR_STATUS_NO_ERROR == error_info.get_error_status()) { + if (OB_INVALID_ID != ObUDTObjectType::mask_object_id(old_udt_info->get_object_spec_id(tenant_id))) { + OZ (pl::ObRoutinePersistentInfo::delete_dll_from_disk( + trans, tenant_id, ObUDTObjectType::mask_object_id(old_udt_info->get_object_spec_id(tenant_id)), + old_udt_info->get_database_id())); + if (old_udt_info->has_type_body() + && OB_INVALID_ID != ObUDTObjectType::mask_object_id(old_udt_info->get_object_body_id(tenant_id))) { + OZ (pl::ObRoutinePersistentInfo::delete_dll_from_disk( + trans, tenant_id, ObUDTObjectType::mask_object_id(old_udt_info->get_object_body_id(tenant_id)), + old_udt_info->get_database_id())); + } + } + } OZ (ObDependencyInfo::delete_schema_object_dependency(trans, tenant_id, old_udt_info->get_type_id(), new_schema_version, diff --git a/src/rootserver/ob_ddl_operator.h b/src/rootserver/ob_ddl_operator.h index 1d357a4df8..28fb755f55 100644 --- a/src/rootserver/ob_ddl_operator.h +++ b/src/rootserver/ob_ddl_operator.h @@ -815,7 +815,7 @@ public: share::schema::ObErrorInfo &error_info, common::ObIArray &dep_infos, const common::ObString *ddl_stmt_str/*=NULL*/); - int alter_package(const share::schema::ObPackageInfo &package_info, + int alter_package(share::schema::ObPackageInfo &package_info, ObSchemaGetterGuard &schema_guard, common::ObMySQLTransaction &trans, ObIArray &public_routine_infos, diff --git a/src/rootserver/ob_ddl_service.cpp b/src/rootserver/ob_ddl_service.cpp index 38b4c4ac49..650e9e3423 100755 --- a/src/rootserver/ob_ddl_service.cpp +++ b/src/rootserver/ob_ddl_service.cpp @@ -34151,7 +34151,7 @@ int ObDDLService::create_package(ObSchemaGetterGuard &schema_guard, } int ObDDLService::alter_package(ObSchemaGetterGuard &schema_guard, - const ObPackageInfo &package_info, + ObPackageInfo &package_info, ObIArray &public_routine_infos, share::schema::ObErrorInfo &error_info, const ObString *ddl_stmt_str) @@ -34290,7 +34290,7 @@ int ObDDLService::create_trigger(const ObCreateTriggerArg &arg, schema_guard, table_schema_version))) { LOG_WARN("create trigger in trans failed", K(ret)); - } else if (with_res && !arg.in_second_stage_) { + } else if (with_res) { res->table_schema_version_ = table_schema_version; res->trigger_schema_version_ = new_trigger_info.get_schema_version(); } @@ -34416,7 +34416,8 @@ int ObDDLService::drop_trigger_in_trans(const ObTriggerInfo &trigger_info, return ret; } -int ObDDLService::alter_trigger(const ObAlterTriggerArg &arg) +int ObDDLService::alter_trigger(const ObAlterTriggerArg &arg, + obrpc::ObRoutineDDLRes *res) { int ret = OB_SUCCESS; ObSchemaGetterGuard schema_guard; @@ -34457,6 +34458,10 @@ int ObDDLService::alter_trigger(const ObAlterTriggerArg &arg) } OZ (ddl_operator.alter_trigger(new_tg_info, trans, &arg.ddl_stmt_str_)); } + // alter trigger scenes + if (OB_SUCC(ret) && 1 == arg.trigger_infos_.count() && OB_NOT_NULL(res)) { + res->store_routine_schema_version_ = new_tg_info.get_schema_version(); + } } if (trans.is_started()) { int temp_ret = OB_SUCCESS; diff --git a/src/rootserver/ob_ddl_service.h b/src/rootserver/ob_ddl_service.h index 35b0d2ac99..5767536504 100644 --- a/src/rootserver/ob_ddl_service.h +++ b/src/rootserver/ob_ddl_service.h @@ -1008,7 +1008,7 @@ int check_table_udt_id_is_exist(share::schema::ObSchemaGetterGuard &schema_guard common::ObIArray &dep_infos, const common::ObString *ddl_stmt_str); virtual int alter_package(share::schema::ObSchemaGetterGuard &schema_guard, - const ObPackageInfo &package_info, + ObPackageInfo &package_info, ObIArray &public_routine_infos, share::schema::ObErrorInfo &error_info, const common::ObString *ddl_stmt_str); @@ -1022,7 +1022,8 @@ int check_table_udt_id_is_exist(share::schema::ObSchemaGetterGuard &schema_guard ObSchemaGetterGuard &schema_guard, obrpc::ObCreateTriggerRes *res); virtual int drop_trigger(const obrpc::ObDropTriggerArg &arg); - virtual int alter_trigger(const obrpc::ObAlterTriggerArg &arg); + virtual int alter_trigger(const obrpc::ObAlterTriggerArg &arg, + obrpc::ObRoutineDDLRes *res = nullptr); //----End of functions for managing trigger---- //----Functions for managing sequence---- diff --git a/src/rootserver/ob_root_service.cpp b/src/rootserver/ob_root_service.cpp index fd42bd9570..09fea4786d 100755 --- a/src/rootserver/ob_root_service.cpp +++ b/src/rootserver/ob_root_service.cpp @@ -6681,7 +6681,8 @@ int ObRootService::drop_outline(const obrpc::ObDropOutlineArg &arg) } //-----End of functions for managing outlines----- -int ObRootService::create_routine(const ObCreateRoutineArg &arg) +int ObRootService::create_routine_common(const ObCreateRoutineArg &arg, + obrpc::ObRoutineDDLRes *res) { int ret = OB_SUCCESS; if (!inited_) { @@ -6808,11 +6809,30 @@ int ObRootService::create_routine(const ObCreateRoutineArg &arg) } } } + if (OB_SUCC(ret) && OB_NOT_NULL(res)) { + res->store_routine_schema_version_ = routine_info.get_schema_version(); + } } return ret; } -int ObRootService::alter_routine(const ObCreateRoutineArg &arg) +int ObRootService::create_routine(const ObCreateRoutineArg &arg) +{ + int ret = OB_SUCCESS; + OZ (create_routine_common(arg)); + return ret; +} + +int ObRootService::create_routine_with_res(const ObCreateRoutineArg &arg, + obrpc::ObRoutineDDLRes &res) +{ + int ret = OB_SUCCESS; + OZ (create_routine_common(arg, &res)); + return ret; +} + +int ObRootService::alter_routine_common(const ObCreateRoutineArg &arg, + obrpc::ObRoutineDDLRes* res) { int ret = OB_SUCCESS; if (!inited_) { @@ -6843,19 +6863,36 @@ int ObRootService::alter_routine(const ObCreateRoutineArg &arg) if (OB_FAIL(ret)) { } else if ((is_oracle_mode && arg.is_or_replace_) || (!is_oracle_mode && arg.is_need_alter_)) { - if (OB_FAIL(create_routine(arg))) { + if (OB_FAIL(create_routine_common(arg, res))) { LOG_WARN("failed to alter routine with create", K(ret)); } } else { if (OB_FAIL(ddl_service_.alter_routine(*routine_info, error_info, &arg.ddl_stmt_str_, schema_guard))) { LOG_WARN("alter routine failed", K(ret), K(arg.routine_info_), K(error_info)); + } else if (OB_NOT_NULL(res)) { + res->store_routine_schema_version_ = routine_info->get_schema_version(); } } } return ret; } +int ObRootService::alter_routine(const ObCreateRoutineArg &arg) +{ + int ret = OB_SUCCESS; + OZ (alter_routine_common(arg)); + return ret; +} + +int ObRootService::alter_routine_with_res(const ObCreateRoutineArg &arg, + obrpc::ObRoutineDDLRes &res) +{ + int ret = OB_SUCCESS; + OZ (alter_routine_common(arg, &res)); + return ret; +} + int ObRootService::drop_routine(const ObDropRoutineArg &arg) { int ret = OB_SUCCESS; @@ -6961,7 +6998,8 @@ int ObRootService::drop_routine(const ObDropRoutineArg &arg) return ret; } -int ObRootService::create_udt(const ObCreateUDTArg &arg) +int ObRootService::create_udt_common(const ObCreateUDTArg &arg, + obrpc::ObRoutineDDLRes *res) { int ret = OB_SUCCESS; if (!inited_) { @@ -7112,10 +7150,28 @@ int ObRootService::create_udt(const ObCreateUDTArg &arg) } } } + if (OB_SUCC(ret) && OB_NOT_NULL(res)) { + res->store_routine_schema_version_ = udt_info.get_schema_version(); + } } return ret; } +int ObRootService::create_udt(const ObCreateUDTArg &arg) +{ + int ret = OB_SUCCESS; + OZ (create_udt_common(arg)); + return ret; +} + +int ObRootService::create_udt_with_res(const ObCreateUDTArg &arg, + obrpc::ObRoutineDDLRes &res) +{ + int ret = OB_SUCCESS; + OZ (create_udt_common(arg, &res)); + return ret; +} + int ObRootService::drop_udt(const ObDropUDTArg &arg) { int ret = OB_SUCCESS; @@ -7435,7 +7491,8 @@ int ObRootService::admin_sync_rewrite_rules(const obrpc::ObSyncRewriteRuleArg &a return ret; } -int ObRootService::create_package(const obrpc::ObCreatePackageArg &arg) +int ObRootService::create_package_common(const obrpc::ObCreatePackageArg &arg, + obrpc::ObRoutineDDLRes *res) { int ret = OB_SUCCESS; if (!inited_) { @@ -7555,11 +7612,31 @@ int ObRootService::create_package(const obrpc::ObCreatePackageArg &arg) new_package_info.get_package_name().length(), new_package_info.get_package_name().ptr()); } } + if (OB_SUCC(ret) && OB_NOT_NULL(res)) { + res->store_routine_schema_version_ = new_package_info.get_schema_version(); + } } return ret; } -int ObRootService::alter_package(const obrpc::ObAlterPackageArg &arg) +int ObRootService::create_package(const obrpc::ObCreatePackageArg &arg) +{ + int ret = OB_SUCCESS; + OZ (create_package_common(arg)); + return ret; +} + +int ObRootService::create_package_with_res(const obrpc::ObCreatePackageArg &arg, + obrpc::ObRoutineDDLRes &res) +{ + int ret = OB_SUCCESS; + OZ (create_package_common(arg, &res)); + return ret; +} + + +int ObRootService::alter_package_common(const obrpc::ObAlterPackageArg &arg, + obrpc::ObRoutineDDLRes *res) { int ret = OB_SUCCESS; if (!inited_) { @@ -7603,15 +7680,20 @@ int ObRootService::alter_package(const obrpc::ObAlterPackageArg &arg) LOG_WARN("package info is null", K(db_schema->get_database_id()), K(package_name), K(package_type), K(ret)); } if (OB_SUCC(ret)) { - if (!((GET_MIN_CLUSTER_VERSION() >= MOCK_CLUSTER_VERSION_4_2_4_0 && GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_3_0_0) || - GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_4_3_1_0)) { + if (!((GET_MIN_CLUSTER_VERSION() >= MOCK_CLUSTER_VERSION_4_2_4_0 + && GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_3_0_0) + || GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_4_3_1_0) + || PACKAGE_TYPE == package_type) { if (OB_FAIL(ddl_service_.alter_package(schema_guard, - *package_info, + const_cast(*package_info), public_routine_infos, const_cast(arg.error_info_), &arg.ddl_stmt_str_))) { LOG_WARN("drop package failed", K(ret), K(package_name)); } + if (OB_SUCC(ret) && OB_NOT_NULL(res)) { + res->store_routine_schema_version_ = package_info->get_schema_version(); + } } else { ObSArray &dep_infos = const_cast &>(arg.dependency_infos_); @@ -7629,6 +7711,9 @@ int ObRootService::alter_package(const obrpc::ObAlterPackageArg &arg) &arg.ddl_stmt_str_))) { LOG_WARN("create package failed", K(ret), K(new_package_info)); } + if (OB_SUCC(ret) && OB_NOT_NULL(res)) { + res->store_routine_schema_version_ = new_package_info.get_schema_version(); + } } } } else { @@ -7644,6 +7729,21 @@ int ObRootService::alter_package(const obrpc::ObAlterPackageArg &arg) return ret; } +int ObRootService::alter_package(const obrpc::ObAlterPackageArg &arg) +{ + int ret = OB_SUCCESS; + OZ (alter_package_common(arg)); + return ret; +} + +int ObRootService::alter_package_with_res(const obrpc::ObAlterPackageArg &arg, + obrpc::ObRoutineDDLRes &res) +{ + int ret = OB_SUCCESS; + OZ (alter_package_common(arg, &res)); + return ret; +} + int ObRootService::drop_package(const obrpc::ObDropPackageArg &arg) { int ret = OB_SUCCESS; @@ -7737,7 +7837,8 @@ int ObRootService::create_trigger_with_res(const obrpc::ObCreateTriggerArg &arg, return ret; } -int ObRootService::alter_trigger(const obrpc::ObAlterTriggerArg &arg) +int ObRootService::alter_trigger_common(const obrpc::ObAlterTriggerArg &arg, + obrpc::ObRoutineDDLRes *res) { int ret = OB_SUCCESS; if (!inited_) { @@ -7746,12 +7847,27 @@ int ObRootService::alter_trigger(const obrpc::ObAlterTriggerArg &arg) } else if (!arg.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arg", K(arg), K(ret)); - } else if (OB_FAIL(ddl_service_.alter_trigger(arg))) { + } else if (OB_FAIL(ddl_service_.alter_trigger(arg, res))) { LOG_WARN("failed to alter trigger", K(ret)); } return ret; } +int ObRootService::alter_trigger(const obrpc::ObAlterTriggerArg &arg) +{ + int ret = OB_SUCCESS; + OZ (alter_trigger_common(arg)); + return ret; +} + +int ObRootService::alter_trigger_with_res(const obrpc::ObAlterTriggerArg &arg, + obrpc::ObRoutineDDLRes &res) +{ + int ret = OB_SUCCESS; + OZ (alter_trigger_common(arg, &res)); + return ret; +} + int ObRootService::drop_trigger(const obrpc::ObDropTriggerArg &arg) { int ret = OB_SUCCESS; diff --git a/src/rootserver/ob_root_service.h b/src/rootserver/ob_root_service.h index 008ab81f61..cbaa9e3060 100644 --- a/src/rootserver/ob_root_service.h +++ b/src/rootserver/ob_root_service.h @@ -571,12 +571,24 @@ public: //----Functions for managing routines---- int create_routine(const obrpc::ObCreateRoutineArg &arg); + int create_routine_common(const obrpc::ObCreateRoutineArg &arg, + obrpc::ObRoutineDDLRes *res = nullptr); + int create_routine_with_res(const obrpc::ObCreateRoutineArg &arg, + obrpc::ObRoutineDDLRes &res); int drop_routine(const obrpc::ObDropRoutineArg &arg); + int alter_routine_common(const obrpc::ObCreateRoutineArg &arg, + obrpc::ObRoutineDDLRes* res = nullptr); int alter_routine(const obrpc::ObCreateRoutineArg &arg); + int alter_routine_with_res(const obrpc::ObCreateRoutineArg &arg, + obrpc::ObRoutineDDLRes &res); //----End of functions for managing routines---- //----Functions for managing routines---- int create_udt(const obrpc::ObCreateUDTArg &arg); + int create_udt_common(const obrpc::ObCreateUDTArg &arg, + obrpc::ObRoutineDDLRes *res = nullptr); + int create_udt_with_res(const obrpc::ObCreateUDTArg &arg, + obrpc::ObRoutineDDLRes &res); int drop_udt(const obrpc::ObDropUDTArg &arg); //----End of functions for managing routines---- @@ -606,7 +618,15 @@ public: //----Functions for managing package---- int create_package(const obrpc::ObCreatePackageArg &arg); + int create_package_common(const obrpc::ObCreatePackageArg &arg, + obrpc::ObRoutineDDLRes *res = nullptr); + int create_package_with_res(const obrpc::ObCreatePackageArg &arg, + obrpc::ObRoutineDDLRes &res); int alter_package(const obrpc::ObAlterPackageArg &arg); + int alter_package_common(const obrpc::ObAlterPackageArg &arg, + obrpc::ObRoutineDDLRes *res = nullptr); + int alter_package_with_res(const obrpc::ObAlterPackageArg &arg, + obrpc::ObRoutineDDLRes &res); int drop_package(const obrpc::ObDropPackageArg &arg); //----End of functions for managing package---- @@ -615,6 +635,10 @@ public: int create_trigger_with_res(const obrpc::ObCreateTriggerArg &arg, obrpc::ObCreateTriggerRes &res); int alter_trigger(const obrpc::ObAlterTriggerArg &arg); + int alter_trigger_common(const obrpc::ObAlterTriggerArg &arg, + obrpc::ObRoutineDDLRes *res = nullptr); + int alter_trigger_with_res(const obrpc::ObAlterTriggerArg &arg, + obrpc::ObRoutineDDLRes &res); int drop_trigger(const obrpc::ObDropTriggerArg &arg); //----End of functions for managing trigger---- diff --git a/src/rootserver/ob_rs_rpc_processor.h b/src/rootserver/ob_rs_rpc_processor.h index c58292875e..b712ee95be 100644 --- a/src/rootserver/ob_rs_rpc_processor.h +++ b/src/rootserver/ob_rs_rpc_processor.h @@ -423,11 +423,14 @@ DEFINE_RS_RPC_PROCESSOR(obrpc::OB_DROP_RESTORE_POINT, ObRpcDropRestorePointP, dr //routine ddl DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_CREATE_ROUTINE, ObRpcCreateRoutineP, create_routine(arg_)); +DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_CREATE_ROUTINE_WITH_RES, ObRpcCreateRoutineWithResP, create_routine_with_res(arg_, result_)); DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_DROP_ROUTINE, ObRpcDropRoutineP, drop_routine(arg_)); DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_ALTER_ROUTINE, ObRpcAlterRoutineP, alter_routine(arg_)); +DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_ALTER_ROUTINE_WITH_RES, ObRpcAlterRoutineWithResP, alter_routine_with_res(arg_, result_)); //udt ddl DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_CREATE_UDT, ObRpcCreateUDTP, create_udt(arg_)); +DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_CREATE_UDT_WITH_RES, ObRpcCreateUDTWithResP, create_udt_with_res(arg_, result_)); DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_DROP_UDT, ObRpcDropUDTP, drop_udt(arg_)); DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_CREATE_SYNONYM, ObRpcCreateSynonymP, create_synonym(arg_)); @@ -441,12 +444,15 @@ DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_DROP_USER_DEFINED_FUNCTION, ObRpcDropUserD //package ddl DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_CREATE_PACKAGE, ObRpcCreatePackageP, create_package(arg_)); +DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_CREATE_PACKAGE_WITH_RES, ObRpcCreatePackageWithResP, create_package_with_res(arg_, result_)); DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_ALTER_PACKAGE, ObRpcAlterPackageP, alter_package(arg_)); +DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_ALTER_PACKAGE_WITH_RES, ObRpcAlterPackageWithResP, alter_package_with_res(arg_, result_)); DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_DROP_PACKAGE, ObRpcDropPackageP, drop_package(arg_)); DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_CREATE_TRIGGER, ObRpcCreateTriggerP, create_trigger(arg_)); DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_CREATE_TRIGGER_WITH_RES, ObRpcCreateTriggerWithResP, create_trigger_with_res(arg_, result_)); DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_ALTER_TRIGGER, ObRpcAlterTriggerP, alter_trigger(arg_)); +DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_ALTER_TRIGGER_WITH_RES, ObRpcAlterTriggerWithResP, alter_trigger_with_res(arg_, result_)); DEFINE_DDL_RS_RPC_PROCESSOR(obrpc::OB_DROP_TRIGGER, ObRpcDropTriggerP, drop_trigger(arg_)); //profile ddl diff --git a/src/share/inner_table/sys_package/utl_recomp.sql b/src/share/inner_table/sys_package/utl_recomp.sql new file mode 100644 index 0000000000..a055671ea4 --- /dev/null +++ b/src/share/inner_table/sys_package/utl_recomp.sql @@ -0,0 +1,17 @@ +-- package_name: utl_recomp +-- author: webber.wb + +CREATE OR REPLACE PACKAGE UTL_RECOMP AS + USE_EXIST_TABLE CONSTANT PLS_INTEGER := 512; + DROP_EXIST_TABLE CONSTANT PLS_INTEGER := 1024; + + PROCEDURE recomp_parallel(threads PLS_INTEGER := NULL, + schema VARCHAR2 := NULL, + flags PLS_INTEGER := 0); + PROCEDURE recomp_serial(schema VARCHAR2 := NULL, + flags PLS_INTEGER := 0); + PROCEDURE parallel_slave(flags PLS_INTEGER); + PROCEDURE truncate_utl_recomp_skip_list(flags PLS_INTEGER := 0); + PROCEDURE populate_utl_recomp_skip_list(flags PLS_INTEGER := 0); +END; +// diff --git a/src/share/inner_table/sys_package/utl_recomp_body.sql b/src/share/inner_table/sys_package/utl_recomp_body.sql new file mode 100644 index 0000000000..a582a82484 --- /dev/null +++ b/src/share/inner_table/sys_package/utl_recomp_body.sql @@ -0,0 +1,370 @@ +-- package_name: utl_recomp +-- author: webber.wb + +create or replace package body utl_recomp AS + num_threads number; + num_batch number; + current_batch number := 0; + + sorted_table varchar2(50) := 'SYS.UTL_RECOMP_SORTED'; + compiled_table varchar2(50) := 'SYS.UTL_RECOMP_COMPILED'; + errors_table varchar2(50) := 'SYS.UTL_RECOMP_ERRORS'; + skip_list_table varchar2(50) := 'SYS.UTL_RECOMP_SKIP_LIST'; + + sorted_table_ddl varchar2(500) := 'create table sys.utl_recomp_sorted ( + obj# number not null enable, + owner varchar2(128), + objname varchar2(128), + edition_name varchar2(128), + namespace number, + depth number, + batch# number)'; + idx_sorted_table_ddl varchar2(500) := 'create index sys.idx_utl_recomp_sorted_1 on sys.utl_recomp_sorted(obj#,depth)'; + compiled_table_ddl varchar2(500) := 'create table sys.utl_recomp_compiled ( + obj# number not null enable, + batch# number, + compiled_at timestamp (6), + completed_at timestamp (6), + compiled_by varchar2(64))'; + idx_compiled_table_ddl varchar2(500) := 'create index sys.idx_utl_recomp_compiled_1 on sys.utl_recomp_compiled(obj#)'; + errors_table_ddl varchar2(500) := 'create table sys.utl_recomp_errors( + obj# number, + error_at timestamp (6), + compile_err varchar2(4000))'; + idx_errors_table_ddl varchar2(500) := 'create index sys.idx_errors_table_ddl_1 on sys.utl_recomp_errors(obj#)'; + skip_list_table_ddl varchar2(500) := 'create table sys.utl_recomp_skip_list + (OBJ# NUMBER NOT NULL ENABLE)'; + + + table_not_exist exception; + pragma exception_init(table_not_exist, -5019); + + valid_routine_name exception; + pragma exception_init(valid_routine_name, -5980); + + TYPE str_array is table of varchar2(200); + + TYPE OBJECT_INFO IS RECORD (object_id number, + owner varchar2(128), + object_name varchar2(128), + object_type varchar2(23)); + TYPE OBJECT_INFO_ARRAY IS TABLE OF OBJECT_INFO; + + procedure check_privilege as + begin + if user != 'SYS' then + raise valid_routine_name; + end if; + end; + + procedure dynamic_execute(sql_str varchar2) as + begin + execute immediate sql_str; + end; + + procedure check_table_exist(table_name varchar2, is_exist out bool) as + select_str varchar2(200); + begin + is_exist := false; + select_str := 'select count(1) from ' || table_name || ' where 0 = 1'; + execute immediate select_str; + is_exist := true; + exception + when table_not_exist then + is_exist := false; + when others then + raise; + end; + + procedure prepare_table(table_name varchar2, ddl varchar2, flags PLS_INTEGER) as + is_exist boolean := false; + begin + check_table_exist(table_name, is_exist); + if (is_exist) then + if (flags = USE_EXIST_TABLE) then + null; + elsif (flags = DROP_EXIST_TABLE) then + dynamic_execute('drop table ' || table_name); + dynamic_execute(ddl); + if table_name = sorted_table then + dynamic_execute(idx_sorted_table_ddl); + elsif table_name = compiled_table then + dynamic_execute(idx_compiled_table_ddl); + elsif table_name = errors_table then + dynamic_execute(idx_errors_table_ddl); + end if; + else + RAISE_APPLICATION_ERROR(-20001, + 'table ' || table_name ||' exists, parameter FLAGS must be set to 512 to continue using the table, or set to 1024 to automatically drop and recreate the table'); + end if; + else + dynamic_execute(ddl); + if table_name = sorted_table then + dynamic_execute(idx_sorted_table_ddl); + elsif table_name = compiled_table then + dynamic_execute(idx_compiled_table_ddl); + elsif table_name = errors_table then + dynamic_execute(idx_errors_table_ddl); + end if; + end if; + end; + + + PROCEDURE truncate_utl_recomp_skip_list(flags PLS_INTEGER := 0) as + is_exist boolean := false; + begin + check_privilege(); + check_table_exist(skip_list_table, is_exist); + if is_exist then + if (flags = USE_EXIST_TABLE) then + dynamic_execute('truncate table sys.utl_recomp_skip_list'); + elsif (flags = DROP_EXIST_TABLE) then + dynamic_execute('drop table sys.utl_recomp_skip_list'); + dynamic_execute(skip_list_table_ddl); + else + RAISE_APPLICATION_ERROR(-20001, + 'table UTL_RECOMP_SKIP_LIST exists, parameter FLAGS must be set to 512 to continue using the table, or set to 1024 to automatically drop and recreate the table'); + end if; + else + dynamic_execute(skip_list_table_ddl); + end if; + end; + + PROCEDURE populate_utl_recomp_skip_list(flags PLS_INTEGER := 0) as + dml_str varchar2(500); + begin + check_privilege(); + prepare_table(skip_list_table, skip_list_table_ddl, flags); + prepare_table(compiled_table, compiled_table_ddl, flags); + dml_str := 'insert into sys.utl_recomp_skip_list select object_id from sys.all_objects o + where o.status != ''VALID'' + and o.object_id not in + (select OBJ# from sys.utl_recomp_compiled + union all select OBJ# from sys.utl_recomp_skip_list) + and o.object_type in (''PACKAGE'', ''PROCEDURE'', ''FUNCTION'', ''TYPE'', ''TRIGGER'')'; + + dynamic_execute(dml_str); + end; + + + procedure parallel_slave(flags pls_integer) as + TYPE compile_info IS RECORD (object_id number, + owner varchar2(128), + object_name varchar2(128), + object_type varchar2(23), + compile_time timestamp, + complete_time timestamp, + compile_by varchar2(64)); + type compile_info_array is table of compile_info; + compile_arr compile_info_array; + batch_no int := flags; + error_msg varchar2(4000); + begin + check_privilege(); + execute immediate 'select o.object_id, o.owner, o.object_name, o.object_type, null, null, null + from sys.all_objects o + join sys.utl_recomp_sorted s on o.object_id = s.obj# and s.batch# = :1 + where o.object_type in (''PACKAGE'', ''PROCEDURE'', ''FUNCTION'', ''TYPE'', ''TRIGGER'')' + bulk collect into compile_arr using batch_no; + for i in 1 .. compile_arr.count() loop + begin + compile_arr(i).compile_time := systimestamp; + sys.dbms_utility.VALIDATE(compile_arr(i).object_id); + exception when others then + error_msg := sys.dbms_utility.format_error_stack(); + execute immediate 'insert into sys.utl_recomp_errors values (:1, :2, :3)' + using compile_arr(i).object_id, systimestamp, error_msg; + end; + compile_arr(i).complete_time := systimestamp; + execute immediate 'insert into sys.utl_recomp_compiled values (:1, :2, :3, :4, :5)' + using compile_arr(i).object_id, batch_no, compile_arr(i).compile_time, + compile_arr(i).complete_time, batch_no; + commit; + end loop; + exception when others then + error_msg := sys.dbms_utility.format_error_stack(); + execute immediate 'insert into sys.utl_recomp_errors values (:1, :2, :3)' + using 0, systimestamp, error_msg; + commit; + end; + + + procedure drop_jobs is + job_names str_array; + begin + select job_name bulk collect into job_names from SYS.DBA_SCHEDULER_JOBS where job_action like 'SYS.UTL_RECOMP.PARALLEL_SLAVE(%'; + for i in 1 .. job_names.count() loop + begin + dbms_scheduler.drop_job(job_names(i), true); + exception when others then + null; + end; + end loop; + end; + + -- 清理utl_recomp_compiled表和utl_recomp_errors表,清理系统中已有的job + procedure init(schema varchar2) is + begin + if (schema is null) then + dynamic_execute('truncate table sys.utl_recomp_compiled'); + dynamic_execute('truncate table sys.utl_recomp_errors'); + else + execute immediate 'delete from sys.utl_recomp_compiled where obj# in (select object_id from sys.all_objects where owner + = :1 and object_type in (''PACKAGE'', ''PROCEDURE'', ''FUNCTION'', ''TYPE'', ''TRIGGER''))' + using schema; + execute immediate 'delete from sys.utl_recomp_errors where obj# in (select object_id from sys.all_objects where owner + = :1 and object_type in (''PACKAGE'', ''PROCEDURE'', ''FUNCTION'', ''TYPE'', ''TRIGGER''))' + using schema; + end if; + dynamic_execute('truncate table sys.utl_recomp_sorted'); + drop_jobs(); + end; + + procedure invalidate_objs(obj_info_arr OBJECT_INFO_ARRAY); + PRAGMA INTERFACE(C, UTL_RECOMP_INVALIDATE_OBJS); + + procedure delete_errors; + PRAGMA INTERFACE(C, UTL_RECOMP_DELETE_ERRORS); + + PROCEDURE COMPUTE_NUM_THREADS(threads PLS_INTEGER) AS + begin + num_threads := threads; + if (num_threads is null or num_threads <= 0) then + select (select nvl(min(TO_NUMBER(value)), 1) from SYS.GV$OB_PARAMETERS where name = 'cpu_count') + * (select nvl(min(TO_NUMBER(value)), 1) from SYS.GV$OB_PARAMETERS where name = 'cpu_quota_concurrency') num + into num_threads from dual; + if (num_threads is null or num_threads <= 0) then + num_threads := 1; + end if; + end if; + end; + + procedure collect_and_sort_object(schema varchar2) as + type object_group is record (obj_cnt int, depth int); + type object_groups is table of object_group; + obj_gs object_groups; + insert_str varchar(2000) := + 'insert into sys.utl_recomp_sorted (obj#, owner, objname, edition_name, namespace) + select o.object_id, o.owner, o.object_name, o.edition_name, o.namespace + from sys.all_objects o + where o.status != ''VALID'' + and o.object_id not in + (select c.OBJ# from sys.utl_recomp_compiled c + union all + select l.OBJ# from sys.utl_recomp_skip_list l) + and o.object_type in (''PACKAGE'', ''PROCEDURE'', ''FUNCTION'', ''TYPE'', ''TRIGGER'') + and o.object_id > 500000 '; + + update_depth_str varchar2(2000) := + 'update sys.utl_recomp_sorted o set depth = :1 + where depth is null and + not exists (select s.obj# from (select * from sys.ALL_VIRTUAL_TENANT_DEPENDENCY_REAL_AGENT where dep_obj_id != ref_obj_id) d, sys.utl_recomp_sorted s + where d.dep_obj_id = o.obj# + and d.ref_obj_id = s.obj# + and s.depth is null)'; + current_depth int := 0; + min_batch_size int := 10; + max_batch_size int := 50; + batch_size int := 0; + begin + if (schema is null) then + execute immediate insert_str; + else + execute immediate insert_str || 'and owner = :1' using schema; + end if; + commit; + + loop + execute immediate update_depth_str using current_depth; + current_depth := current_depth + 1; + exit when SQL%ROWCOUNT = 0; + commit; + end loop; + execute immediate 'update sys.utl_recomp_sorted set depth = :1 where depth is null' using current_depth; + commit; + + execute immediate 'select count(obj#), depth from sys.utl_recomp_sorted group by depth order by depth' + bulk collect into obj_gs; + num_batch := 0; + for i in 1 .. obj_gs.count() loop + batch_size := least(max_batch_size, obj_gs(i).obj_cnt/num_threads); + batch_size := greatest(min_batch_size, batch_size); + execute immediate 'update sys.utl_recomp_sorted set batch# = floor((rownum-1)/(:1)) + :2 + where depth = :3 and batch# is null' + using batch_size, num_batch, obj_gs(i).depth; + num_batch := num_batch + ceil(SQL%ROWCOUNT/batch_size); + commit; + end loop; + end; + + + procedure create_jobs as + begin + for i in 0 .. num_threads-1 loop + dbms_scheduler.create_job(JOB_NAME => 'UTL_RECOMP_SLAVE_' || current_batch, + JOB_TYPE => 'PLSQL_BLOCK', + JOB_ACTION => 'SYS.UTL_RECOMP.PARALLEL_SLAVE(' || current_batch || ')', + START_DATE => systimestamp, + END_DATE => systimestamp + 1, + ENABLED => true, + AUTO_DROP => false, + MAX_RUN_DURATION => 7200); + current_batch := current_batch + 1; + exit when current_batch > num_batch; + end loop; + end; + + + procedure wait_jobs as + remain_job_cnt int; + begin + loop + select count(*) into remain_job_cnt + from sys.ALL_VIRTUAL_TENANT_SCHEDULER_JOB_REAL_AGENT + where LAST_DATE is NULL and job > 0 and JOB_NAME LIKE 'UTL_RECOMP_SLAVE_%'; + exit when remain_job_cnt = 0; + DBMS_LOCK.SLEEP(3); + end loop; + end; + + + procedure recomp_parallel(threads PLS_INTEGER := NULL, schema varchar2 := NULL, flags PLS_INTEGER := 0) as + obj_info_arr OBJECT_INFO_ARRAY; + begin + current_batch := 0; + check_privilege(); + prepare_table(skip_list_table, skip_list_table_ddl, flags); + prepare_table(sorted_table, sorted_table_ddl, flags); + prepare_table(compiled_table, compiled_table_ddl, flags); + prepare_table(errors_table, errors_table_ddl, flags); + + init(schema); + + execute immediate 'select o.object_id, o.owner, o.object_name, o.object_type from sys.all_objects o + where o.status = ''VALID'' + and (:1 is null or :2 = owner) + and o.object_type in (''PACKAGE'', ''PROCEDURE'', ''FUNCTION'', ''TYPE'', ''TRIGGER'') + and o.object_id not in (select obj# from sys.utl_recomp_skip_list) + and o.object_id > 500000' + bulk collect into obj_info_arr using schema, schema; + delete_errors(); + invalidate_objs(obj_info_arr); + + COMPUTE_NUM_THREADS(threads); + collect_and_sort_object(schema); + + for i in 1 .. ceil(num_batch/num_threads) loop + create_jobs(); + wait_jobs(); + drop_jobs(); + end loop; + delete_errors(); + end; + + + procedure recomp_serial(schema varchar2 := null, flags pls_integer := 0) is + begin + recomp_parallel(1, schema, flags); + end; +end; +// diff --git a/src/share/ob_common_rpc_proxy.h b/src/share/ob_common_rpc_proxy.h index 5e577cd804..86af4aa254 100644 --- a/src/share/ob_common_rpc_proxy.h +++ b/src/share/ob_common_rpc_proxy.h @@ -122,10 +122,13 @@ public: //----End of definitions for managing outlines---- RPC_S(PRD create_routine, obrpc::OB_CREATE_ROUTINE, (ObCreateRoutineArg)); + RPC_S(PRD create_routine_with_res, obrpc::OB_CREATE_ROUTINE_WITH_RES, (ObCreateRoutineArg), ObRoutineDDLRes); RPC_S(PRD drop_routine, obrpc::OB_DROP_ROUTINE, (ObDropRoutineArg)); RPC_S(PRD alter_routine, obrpc::OB_ALTER_ROUTINE, (ObCreateRoutineArg)); + RPC_S(PRD alter_routine_with_res, obrpc::OB_ALTER_ROUTINE_WITH_RES, (ObCreateRoutineArg), ObRoutineDDLRes); RPC_S(PRD create_udt, obrpc::OB_CREATE_UDT, (ObCreateUDTArg)); + RPC_S(PRD create_udt_with_res, obrpc::OB_CREATE_UDT_WITH_RES, (ObCreateUDTArg), ObRoutineDDLRes); RPC_S(PRD drop_udt, obrpc::OB_DROP_UDT, (ObDropUDTArg)); //----Definitions for managing dblinks---- @@ -175,12 +178,15 @@ public: //----End of definitions for managing profile---- RPC_S(PRD create_package, obrpc::OB_CREATE_PACKAGE, (ObCreatePackageArg)); + RPC_S(PRD create_package_with_res, obrpc::OB_CREATE_PACKAGE_WITH_RES, (ObCreatePackageArg), ObRoutineDDLRes); RPC_S(PRD alter_package, obrpc::OB_ALTER_PACKAGE, (ObAlterPackageArg)); + RPC_S(PRD alter_package_with_res, obrpc::OB_ALTER_PACKAGE_WITH_RES, (ObAlterPackageArg), ObRoutineDDLRes); RPC_S(PRD drop_package, obrpc::OB_DROP_PACKAGE, (ObDropPackageArg)); RPC_S(PRD create_trigger, obrpc::OB_CREATE_TRIGGER, (ObCreateTriggerArg)); RPC_S(PRD create_trigger_with_res, obrpc::OB_CREATE_TRIGGER_WITH_RES, (ObCreateTriggerArg), ObCreateTriggerRes); RPC_S(PRD alter_trigger, obrpc::OB_ALTER_TRIGGER, (ObAlterTriggerArg)); + RPC_S(PRD alter_trigger_with_res, obrpc::OB_ALTER_TRIGGER_WITH_RES, (ObAlterTriggerArg), ObRoutineDDLRes); RPC_S(PRD drop_trigger, obrpc::OB_DROP_TRIGGER, (ObDropTriggerArg)); RPC_S(PR5 execute_bootstrap, OB_EXECUTE_BOOTSTRAP, (ObBootstrapArg)); diff --git a/src/share/ob_rpc_struct.cpp b/src/share/ob_rpc_struct.cpp index 13e2a282a4..245b0bbe09 100755 --- a/src/share/ob_rpc_struct.cpp +++ b/src/share/ob_rpc_struct.cpp @@ -5983,6 +5983,9 @@ OB_SERIALIZE_MEMBER(ObAdminSetTPArg, zone_, cond_); +OB_SERIALIZE_MEMBER(ObRoutineDDLRes, + store_routine_schema_version_); + bool ObCreateRoutineArg::is_valid() const { return OB_INVALID_ID != routine_info_.get_tenant_id() diff --git a/src/share/ob_rpc_struct.h b/src/share/ob_rpc_struct.h index 8bcee16769..324fc6c1af 100755 --- a/src/share/ob_rpc_struct.h +++ b/src/share/ob_rpc_struct.h @@ -6927,7 +6927,7 @@ public: bool is_or_replace_; bool is_need_alter_; // used in mysql mode share::schema::ObErrorInfo error_info_; - common::ObSArray dependency_infos_; + common::ObSArray dependency_infos_; bool with_if_not_exist_; }; @@ -7085,6 +7085,22 @@ public: common::ObSArray dependency_infos_; }; +struct ObRoutineDDLRes +{ + OB_UNIS_VERSION(1); + +public: + ObRoutineDDLRes() : + store_routine_schema_version_(OB_INVALID_VERSION) + {} + int assign(const ObRoutineDDLRes &other) { + store_routine_schema_version_ = other.store_routine_schema_version_; + return common::OB_SUCCESS; + } + TO_STRING_KV(K_(store_routine_schema_version)); + int64_t store_routine_schema_version_; +}; + struct ObCreateTriggerRes { OB_UNIS_VERSION(1); diff --git a/src/share/parameter/ob_parameter_seed.ipp b/src/share/parameter/ob_parameter_seed.ipp index 2c53ea7951..752c23281b 100644 --- a/src/share/parameter/ob_parameter_seed.ipp +++ b/src/share/parameter/ob_parameter_seed.ipp @@ -1307,7 +1307,7 @@ DEF_BOOL(plsql_debug, OB_TENANT_PARAMETER, "False", "specifies whether or not PL/SQL library units will be compiled for debugging", ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); DEF_BOOL(plsql_v2_compatibility, OB_TENANT_PARAMETER, "False", - "allows some abnormal behavior that Version 8 disallows, not available", + "allows to control store routine compile action at DDL stage", ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); // for bloom filter DEF_BOOL(_bloom_filter_enabled, OB_TENANT_PARAMETER, "True", diff --git a/src/share/schema/ob_error_info.cpp b/src/share/schema/ob_error_info.cpp index 4769d45e05..e5bd327f01 100644 --- a/src/share/schema/ob_error_info.cpp +++ b/src/share/schema/ob_error_info.cpp @@ -107,7 +107,8 @@ bool ObErrorInfo::is_valid() const int ObErrorInfo::collect_error_info(const IObErrorInfo *info, const ObWarningBuffer *buf, - bool fill_info) + bool fill_info, + const ObObjectType obj_type) { int ret = OB_SUCCESS; if (OB_ISNULL(info)) { @@ -119,7 +120,7 @@ int ObErrorInfo::collect_error_info(const IObErrorInfo *info, (set_database_id(info->get_database_id())); (set_tenant_id(info->get_tenant_id())); (set_schema_version(info->get_schema_version())); - (set_obj_type(static_cast(info->get_object_type()))); + (set_obj_type(static_cast(obj_type == ObObjectType::INVALID ? info->get_object_type() : obj_type))); if (NULL != buf) { (set_error_number(buf->get_err_code())); set_line((const_cast(buf))->get_error_line()); @@ -147,7 +148,8 @@ int ObErrorInfo::collect_error_info(const IObErrorInfo *info, return ret; } -int ObErrorInfo::collect_error_info(const IObErrorInfo *info) +int ObErrorInfo::collect_error_info(const IObErrorInfo *info, + const ObObjectType obj_type) { int ret = OB_SUCCESS; if (NULL == info) { @@ -157,7 +159,7 @@ int ObErrorInfo::collect_error_info(const IObErrorInfo *info) const ObWarningBuffer *warnings_buf = common::ob_get_tsi_warning_buffer(); if (OB_NOT_NULL(warnings_buf)) { uint16_t wcnt = static_cast(warnings_buf->get_readable_warning_count()); - if (OB_FAIL(collect_error_info(info, warnings_buf, wcnt > 0))) { + if (OB_FAIL(collect_error_info(info, warnings_buf, wcnt > 0, obj_type))) { LOG_WARN("failed to fill error info", K(ret), K(*this)); } else { // do nothing @@ -226,7 +228,7 @@ int ObErrorInfo::gen_error_dml(const uint64_t exec_tenant_id, return ret; } -int ObErrorInfo::update_error_info(const IObErrorInfo *info) { +int ObErrorInfo::update_error_info(const IObErrorInfo *info, const ObObjectType obj_type) { int ret = OB_SUCCESS; if (NULL == info) { @@ -234,7 +236,7 @@ int ObErrorInfo::update_error_info(const IObErrorInfo *info) { LOG_WARN("update update error info failed due to null info", K(ret)); } else { (set_obj_id(info->get_object_id())); - (set_obj_type(static_cast(info->get_object_type()))); + (set_obj_type(static_cast(obj_type == ObObjectType::INVALID ? info->get_object_type() : obj_type))); (set_database_id(info->get_database_id())); (set_tenant_id(info->get_tenant_id())); (set_schema_version(info->get_schema_version())); @@ -399,11 +401,12 @@ int ObErrorInfo::get_error_obj_seq(common::ObISQLClient &sql_client, return ret; } -int ObErrorInfo::handle_error_info(ObMySQLTransaction &trans, const IObErrorInfo *info) +int ObErrorInfo::handle_error_info(ObMySQLTransaction &trans, const IObErrorInfo *info, + const ObObjectType obj_type) { int ret = OB_SUCCESS; ObErrorInfo &error_info = *this; - if (OB_NOT_NULL(info) && OB_FAIL(update_error_info(info))) { + if (OB_NOT_NULL(info) && OB_FAIL(update_error_info(info, obj_type))) { LOG_WARN("update error info failed.", K(ret)); } else if (error_info.is_valid()) { bool exist = false; @@ -437,15 +440,16 @@ int ObErrorInfo::handle_error_info(ObMySQLTransaction &trans, const IObErrorInfo return ret; } -int ObErrorInfo::handle_error_info(const IObErrorInfo *info) +int ObErrorInfo::handle_error_info(const IObErrorInfo *info, + const ObObjectType obj_type) { int ret = OB_SUCCESS; ObMySQLTransaction trans; - if (OB_FAIL(collect_error_info(info))) { + if (OB_FAIL(collect_error_info(info, obj_type))) { LOG_WARN("collect error info failed", K(ret)); } else if (OB_FAIL(trans.start(GCTX.sql_proxy_, get_tenant_id(), true))) { LOG_WARN("fail start trans", K(ret)); - } else if (OB_FAIL(handle_error_info(trans, info))) { + } else if (OB_FAIL(handle_error_info(trans, info, obj_type))) { LOG_WARN("handle error info failed.", K(ret)); } if (trans.is_started()) { diff --git a/src/share/schema/ob_error_info.h b/src/share/schema/ob_error_info.h index 4738d5b145..7be054efb4 100644 --- a/src/share/schema/ob_error_info.h +++ b/src/share/schema/ob_error_info.h @@ -104,12 +104,16 @@ public: bool is_user_field_valid() const; void reset(); int64_t get_convert_size() const; - int collect_error_info(const IObErrorInfo *info); - int collect_error_info(const IObErrorInfo *info, const common::ObWarningBuffer *buf, bool fill_info); - int update_error_info(const IObErrorInfo *info); + int collect_error_info(const IObErrorInfo *info, + const ObObjectType obj_type = ObObjectType::INVALID); + int collect_error_info(const IObErrorInfo *info, const common::ObWarningBuffer *buf, bool fill_info, + const ObObjectType obj_type = ObObjectType::INVALID); + int update_error_info(const IObErrorInfo *info, const ObObjectType obj_type = ObObjectType::INVALID); int get_error_info_from_table(common::ObISQLClient &sql_client, ObErrorInfo *old_err_info); - int handle_error_info(common::ObMySQLTransaction &trans, const IObErrorInfo *info); - int handle_error_info(const IObErrorInfo *info); + int handle_error_info(common::ObMySQLTransaction &trans, const IObErrorInfo *info, + const ObObjectType obj_type = ObObjectType::INVALID); + int handle_error_info(const IObErrorInfo *info, + const ObObjectType obj_type = ObObjectType::INVALID); int del_error(common::ObISQLClient &sql_client); int del_error(common::ObMySQLProxy *sql_proxy); int add_error(common::ObISQLClient & sql_client, bool is_replace, bool only_history); diff --git a/src/sql/engine/cmd/ob_package_executor.cpp b/src/sql/engine/cmd/ob_package_executor.cpp index b4758fcf1a..cdeffda3ab 100644 --- a/src/sql/engine/cmd/ob_package_executor.cpp +++ b/src/sql/engine/cmd/ob_package_executor.cpp @@ -19,6 +19,7 @@ #include "pl/ob_pl.h" #include "share/ob_common_rpc_proxy.h" #include "share/ob_rpc_struct.h" +#include "pl/ob_pl_resolver.h" namespace oceanbase { @@ -27,6 +28,52 @@ namespace sql using namespace common; using namespace share::schema; +int ObCompilePackageInf::compile_package(sql::ObExecContext &ctx, + uint64_t tenant_id, + const ObString &db_name, + schema::ObPackageType type, + const ObString &package_name, + int64_t schema_version) +{ + int ret = OB_SUCCESS; + ObSchemaChecker schema_checker; + const ObPackageInfo *package_info = nullptr; + int64_t compatible_mode = lib::is_oracle_mode() ? COMPATIBLE_ORACLE_MODE + : COMPATIBLE_MYSQL_MODE; + CK (OB_NOT_NULL(ctx.get_sql_ctx()->schema_guard_)); + OZ (schema_checker.init(*ctx.get_sql_ctx()->schema_guard_, ctx.get_my_session()->get_sessid())); + OZ (schema_checker.get_package_info(tenant_id, db_name, package_name, type, compatible_mode, package_info)); + CK (OB_NOT_NULL(package_info)); + CK (OB_NOT_NULL(ctx.get_sql_proxy())); + CK (OB_NOT_NULL(ctx.get_pl_engine())); + if (OB_SUCC(ret) && schema_version == package_info->get_schema_version()) { + const ObPackageInfo *package_spec_info = NULL; + const ObPackageInfo *package_body_info = NULL; + pl::ObPLPackage *package_spec = nullptr; + pl::ObPLPackage *package_body = nullptr; + pl::ObPLPackageGuard package_guard(ctx.get_my_session()->get_effective_tenant_id()); + pl::ObPLResolveCtx resolve_ctx(ctx.get_allocator(), + *ctx.get_my_session(), + *ctx.get_sql_ctx()->schema_guard_, + package_guard, + *ctx.get_sql_proxy(), + false); + + OZ (package_guard.init()); + OZ (ctx.get_pl_engine()->get_package_manager().get_package_schema_info(resolve_ctx.schema_guard_, + package_info->get_package_id(), + package_spec_info, + package_body_info)); + // trigger compile package & add to disk & add to pl cache only has package body + if (OB_SUCC(ret) && OB_NOT_NULL(package_body_info)) { + OZ (ctx.get_pl_engine()->get_package_manager().get_cached_package(resolve_ctx, package_info->get_package_id(), package_spec, package_body)); + CK (OB_NOT_NULL(package_spec)); + } + } + + return ret; +} + int ObCreatePackageExecutor::execute(ObExecContext &ctx, ObCreatePackageStmt &stmt) { int ret = OB_SUCCESS; @@ -34,7 +81,17 @@ int ObCreatePackageExecutor::execute(ObExecContext &ctx, ObCreatePackageStmt &st obrpc::ObCommonRpcProxy *common_rpc_proxy = NULL; obrpc::UInt64 table_id; obrpc::ObCreatePackageArg &arg = stmt.get_create_package_arg(); + uint64_t tenant_id = arg.package_info_.get_tenant_id(); + bool has_error = ERROR_STATUS_HAS_ERROR == arg.error_info_.get_error_status(); + ObString &db_name = arg.db_name_; + const ObString &package_name = arg.package_info_.get_package_name(); + share::schema::ObPackageType type = arg.package_info_.get_type(); ObString first_stmt; + obrpc::ObRoutineDDLRes res; + bool with_res = ((GET_MIN_CLUSTER_VERSION() >= MOCK_CLUSTER_VERSION_4_2_3_0 + && GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_3_0_0) + || GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_4_3_2_0); + omt::ObTenantConfigGuard tenant_config(TENANT_CONF(ctx.get_my_session()->get_effective_tenant_id())); if (OB_FAIL(stmt.get_first_stmt(first_stmt))) { LOG_WARN("fail to get first stmt" , K(ret)); } else { @@ -49,9 +106,28 @@ int ObCreatePackageExecutor::execute(ObExecContext &ctx, ObCreatePackageStmt &st } else if (OB_ISNULL(common_rpc_proxy)){ ret = OB_ERR_UNEXPECTED; LOG_WARN("common rpc proxy should not be null", K(ret)); - } else if (OB_FAIL(common_rpc_proxy->create_package(arg))) { + } else if (!with_res && OB_FAIL(common_rpc_proxy->create_package(arg))) { LOG_WARN("rpc proxy create package failed", K(ret), "dst", common_rpc_proxy->get_server()); + } else if (with_res && OB_FAIL(common_rpc_proxy->create_package_with_res(arg, res))) { + LOG_WARN("rpc proxy create package failed", K(ret), + "dst", common_rpc_proxy->get_server()); + } + if (OB_SUCC(ret) && !has_error && with_res && + tenant_config.is_valid() && + tenant_config->plsql_v2_compatibility) { + OZ (ObSPIService::force_refresh_schema(tenant_id, res.store_routine_schema_version_)); + OZ (ctx.get_task_exec_ctx().schema_service_-> + get_tenant_schema_guard(ctx.get_my_session()->get_effective_tenant_id(), *ctx.get_sql_ctx()->schema_guard_)); + OZ (compile_package(ctx, tenant_id, db_name, type, package_name, res.store_routine_schema_version_)); + if (OB_FAIL(ret)) { + LOG_WARN("fail to persitent package", K(ret)); + common::ob_reset_tsi_warning_buffer(); + ret = OB_SUCCESS; + if (NULL != ctx.get_my_session()) { + ctx.get_my_session()->reset_warnings_buf(); + } + } } return ret; } @@ -63,12 +139,23 @@ int ObAlterPackageExecutor::execute(ObExecContext &ctx, ObAlterPackageStmt &stmt obrpc::ObCommonRpcProxy *common_rpc_proxy = NULL; obrpc::UInt64 table_id; obrpc::ObAlterPackageArg &arg = stmt.get_alter_package_arg(); + uint64_t tenant_id = arg.tenant_id_; + bool has_error = ERROR_STATUS_HAS_ERROR == arg.error_info_.get_error_status(); + ObString &db_name = arg.db_name_; + const ObString &package_name = arg.package_name_; + share::schema::ObPackageType type = arg.package_type_; ObString first_stmt; + obrpc::ObRoutineDDLRes res; + bool with_res = ((GET_MIN_CLUSTER_VERSION() >= MOCK_CLUSTER_VERSION_4_2_3_0 + && GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_3_0_0) + || GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_4_3_2_0); + omt::ObTenantConfigGuard tenant_config(TENANT_CONF(ctx.get_my_session()->get_effective_tenant_id())); if (OB_FAIL(stmt.get_first_stmt(first_stmt))) { LOG_WARN("fail to get first stmt" , K(ret)); } else { arg.ddl_stmt_str_ = first_stmt; } + // we need send rpc for alter package, because it must refresh package state after alter package if (OB_FAIL(ret)) { } else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) { ret = OB_NOT_INIT; @@ -78,9 +165,24 @@ int ObAlterPackageExecutor::execute(ObExecContext &ctx, ObAlterPackageStmt &stmt } else if (OB_ISNULL(common_rpc_proxy)){ ret = OB_ERR_UNEXPECTED; LOG_WARN("common rpc proxy should not be null", K(ret)); - } else if (OB_FAIL(common_rpc_proxy->alter_package(arg))) { + } else if (!with_res && OB_FAIL(common_rpc_proxy->alter_package(arg))) { + LOG_WARN("rpc proxy drop procedure failed", K(ret), "dst", common_rpc_proxy->get_server()); + } else if (with_res && OB_FAIL(common_rpc_proxy->alter_package_with_res(arg, res))) { LOG_WARN("rpc proxy drop procedure failed", K(ret), "dst", common_rpc_proxy->get_server()); } + if (OB_SUCC(ret) && !has_error && with_res && + tenant_config.is_valid() && + tenant_config->plsql_v2_compatibility) { + OZ (ObSPIService::force_refresh_schema(tenant_id, res.store_routine_schema_version_)); + OZ (ctx.get_task_exec_ctx().schema_service_-> + get_tenant_schema_guard(ctx.get_my_session()->get_effective_tenant_id(), *ctx.get_sql_ctx()->schema_guard_)); + OZ (compile_package(ctx, tenant_id, db_name, type, package_name, res.store_routine_schema_version_)); + if (OB_FAIL(ret)) { + LOG_WARN("fail to persitent package", K(ret)); + ret = OB_SUCCESS; + } + } + return ret; } diff --git a/src/sql/engine/cmd/ob_package_executor.h b/src/sql/engine/cmd/ob_package_executor.h index 53efb53f11..f0afd7c59e 100644 --- a/src/sql/engine/cmd/ob_package_executor.h +++ b/src/sql/engine/cmd/ob_package_executor.h @@ -16,6 +16,7 @@ #include "lib/container/ob_vector.h" #include "sql/parser/parse_node.h" #include "sql/resolver/ob_stmt_type.h" +#include "share/schema/ob_package_info.h" #define DEF_SIMPLE_EXECUTOR(name) \ class name##Executor \ @@ -37,8 +38,41 @@ class ObCreatePackageStmt; class ObAlterPackageStmt; class ObDropPackageStmt; -DEF_SIMPLE_EXECUTOR(ObCreatePackage); -DEF_SIMPLE_EXECUTOR(ObAlterPackage); +class ObCompilePackageInf +{ +public: + ObCompilePackageInf() {} + virtual ~ObCompilePackageInf() {} + static int compile_package(sql::ObExecContext &ctx, + uint64_t tenant_id, + const ObString &db_name, + oceanbase::share::schema::ObPackageType type, + const ObString &package_name, + int64_t schema_version); +private: + DISALLOW_COPY_AND_ASSIGN(ObCompilePackageInf); +}; + +class ObCreatePackageExecutor : ObCompilePackageInf +{ +public: + ObCreatePackageExecutor() {} + virtual ~ObCreatePackageExecutor() {} + int execute(ObExecContext &ctx, ObCreatePackageStmt &stmt); +private: + DISALLOW_COPY_AND_ASSIGN(ObCreatePackageExecutor); +}; + +class ObAlterPackageExecutor : ObCompilePackageInf +{ +public: + ObAlterPackageExecutor() {} + virtual ~ObAlterPackageExecutor() {} + int execute(ObExecContext &ctx, ObAlterPackageStmt &stmt); +private: + DISALLOW_COPY_AND_ASSIGN(ObAlterPackageExecutor); +}; + DEF_SIMPLE_EXECUTOR(ObDropPackage); }//namespace sql }//namespace oceanbase diff --git a/src/sql/engine/cmd/ob_routine_executor.cpp b/src/sql/engine/cmd/ob_routine_executor.cpp index b13e925be4..46b4a62d18 100644 --- a/src/sql/engine/cmd/ob_routine_executor.cpp +++ b/src/sql/engine/cmd/ob_routine_executor.cpp @@ -29,12 +29,74 @@ #include "share/ob_common_rpc_proxy.h" #include "share/ob_rpc_struct.h" #include "sql/engine/expr/ob_expr_column_conv.h" +#include "share/config/ob_config_helper.h" namespace oceanbase { namespace sql { +int ObCompileRoutineInf::compile_routine(ObExecContext &ctx, + uint64_t tenant_id, + uint64_t database_id, + ObString &routine_name, + ObRoutineType routine_type, + int64_t schema_version) +{ + int ret = OB_SUCCESS; + ObCacheObjGuard cacheobj_guard(PL_ROUTINE_HANDLE); + const ObRoutineInfo *routine_info = nullptr; + pl::ObPLFunction* routine = nullptr; + uint64_t db_id = OB_INVALID_ID; + CK (OB_NOT_NULL(ctx.get_sql_ctx()->schema_guard_)); + OZ (ctx.get_task_exec_ctx().schema_service_-> + get_tenant_schema_guard(ctx.get_my_session()->get_effective_tenant_id(), *ctx.get_sql_ctx()->schema_guard_)); + if (ROUTINE_PROCEDURE_TYPE == routine_type) { + OZ (ctx.get_sql_ctx()->schema_guard_->get_standalone_procedure_info(tenant_id, + database_id, + routine_name, + routine_info)); + } else { + OZ (ctx.get_sql_ctx()->schema_guard_->get_standalone_function_info(tenant_id, + database_id, + routine_name, + routine_info)); + } + OZ (ctx.get_my_session()->get_database_id(db_id)); + if (OB_SUCC(ret) && OB_NOT_NULL(routine_info) && schema_version == routine_info->get_schema_version()) { + pl::ObPLCacheCtx pc_ctx; + pc_ctx.session_info_ = ctx.get_my_session(); + pc_ctx.schema_guard_ = ctx.get_sql_ctx()->schema_guard_; + + pc_ctx.key_.namespace_ = ObLibCacheNameSpace::NS_PRCR; + pc_ctx.key_.db_id_ = db_id; + pc_ctx.key_.key_id_ = routine_info->get_routine_id(); + pc_ctx.key_.sessid_ = ctx.get_my_session()->is_pl_debug_on() ? ctx.get_my_session()->get_sessid() : 0; + CK (OB_NOT_NULL(ctx.get_pl_engine())); + if (OB_FAIL(ret)) { + } else if (OB_FAIL(pl::ObPLCacheMgr::get_pl_cache(ctx.get_my_session()->get_plan_cache(), cacheobj_guard, pc_ctx))) { + LOG_TRACE("get pl function from ol cache failed", K(ret), K(pc_ctx.key_)); + ret = OB_ERR_UNEXPECTED != ret ? OB_SUCCESS : ret; + } else { + routine = static_cast(cacheobj_guard.get_cache_obj()); + } + if (OB_SUCC(ret) && OB_ISNULL(routine)) { + OZ (ctx.get_pl_engine()->generate_pl_function(ctx, routine_info->get_routine_id(), cacheobj_guard)); + OX (routine = static_cast(cacheobj_guard.get_cache_obj())); + CK (OB_NOT_NULL(routine)); + OZ (ctx.get_my_session()->get_database_id(db_id)); + if (OB_SUCC(ret) + && routine->get_can_cached()) { + routine->get_stat_for_update().name_ = routine->get_function_name(); + routine->get_stat_for_update().type_ = pl::ObPLCacheObjectType::STANDALONE_ROUTINE_TYPE; + OZ (ctx.get_pl_engine()->add_pl_lib_cache(routine, pc_ctx)); + } + } + } + + return ret; +} + int ObCreateRoutineExecutor::execute(ObExecContext &ctx, ObCreateRoutineStmt &stmt) { int ret = OB_SUCCESS; @@ -43,12 +105,22 @@ int ObCreateRoutineExecutor::execute(ObExecContext &ctx, ObCreateRoutineStmt &st obrpc::UInt64 table_id; obrpc::ObCreateRoutineArg &crt_routine_arg = stmt.get_routine_arg(); ObString first_stmt; + uint64_t tenant_id = crt_routine_arg.routine_info_.get_tenant_id(); + uint64_t database_id = crt_routine_arg.routine_info_.get_database_id(); + ObString db_name = crt_routine_arg.db_name_; + ObString routine_name = crt_routine_arg.routine_info_.get_routine_name(); + ObRoutineType type = crt_routine_arg.routine_info_.get_routine_type(); + obrpc::ObRoutineDDLRes res; + bool with_res = (GET_MIN_CLUSTER_VERSION() >= MOCK_CLUSTER_VERSION_4_2_3_0 + && GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_3_0_0) + || GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_4_3_2_0; + bool has_error = ERROR_STATUS_HAS_ERROR == crt_routine_arg.error_info_.get_error_status(); + omt::ObTenantConfigGuard tenant_config(TENANT_CONF(ctx.get_my_session()->get_effective_tenant_id())); if (OB_FAIL(stmt.get_first_stmt(first_stmt))) { LOG_WARN("fail to get first stmt" , K(ret)); } else { crt_routine_arg.ddl_stmt_str_ = first_stmt; } - if (OB_FAIL(ret)) { } else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) { ret = OB_NOT_INIT; @@ -58,8 +130,29 @@ int ObCreateRoutineExecutor::execute(ObExecContext &ctx, ObCreateRoutineStmt &st } else if (OB_ISNULL(common_rpc_proxy)){ ret = OB_ERR_UNEXPECTED; LOG_WARN("common rpc proxy should not be null", K(ret)); - } else if (OB_FAIL(common_rpc_proxy->create_routine(crt_routine_arg))) { + } else if (!with_res && OB_FAIL(common_rpc_proxy->create_routine(crt_routine_arg))) { LOG_WARN("rpc proxy create procedure failed", K(ret), "dst", common_rpc_proxy->get_server()); + } else if (with_res && OB_FAIL(common_rpc_proxy->create_routine_with_res(crt_routine_arg, res))) { + LOG_WARN("rpc proxy create procedure failed", K(ret), "dst", common_rpc_proxy->get_server()); + } + if (OB_SUCC(ret) && !has_error && with_res && + tenant_config.is_valid() && + tenant_config->plsql_v2_compatibility) { + CK (OB_NOT_NULL(ctx.get_sql_ctx()->schema_guard_)); + OZ (ObSPIService::force_refresh_schema(tenant_id, res.store_routine_schema_version_)); + OZ (compile_routine(ctx, tenant_id, database_id, routine_name, type, + res.store_routine_schema_version_)); + if (OB_FAIL(ret)) { + LOG_WARN("fail to persistent routine", K(ret)); + ret = OB_SUCCESS; + if (NULL != ctx.get_my_session()) { + ctx.get_my_session()->reset_warnings_buf(); + } + } + } + if(crt_routine_arg.with_if_not_exist_ && ret == OB_ERR_SP_ALREADY_EXISTS) { + LOG_USER_WARN(OB_ERR_SP_ALREADY_EXISTS, "ROUTINE", crt_routine_arg.routine_info_.get_routine_name().length(), crt_routine_arg.routine_info_.get_routine_name().ptr()); + ret = OB_SUCCESS; } return ret; } @@ -328,23 +421,86 @@ int ObAlterRoutineExecutor::execute(ObExecContext &ctx, ObAlterRoutineStmt &stmt ObTaskExecutorCtx *task_exec_ctx = NULL; obrpc::ObCommonRpcProxy *common_rpc_proxy = NULL; obrpc::ObCreateRoutineArg &alter_routine_arg = stmt.get_routine_arg(); + uint64_t tenant_id = alter_routine_arg.routine_info_.get_tenant_id(); + uint64_t database_id = alter_routine_arg.routine_info_.get_database_id(); + ObString db_name = alter_routine_arg.db_name_; + ObString routine_name = alter_routine_arg.routine_info_.get_routine_name(); + ObRoutineType type = alter_routine_arg.routine_info_.get_routine_type(); + bool has_error = ERROR_STATUS_HAS_ERROR == alter_routine_arg.error_info_.get_error_status(); + bool need_create_routine = (lib::is_oracle_mode() && alter_routine_arg.is_or_replace_) || + (lib::is_mysql_mode() && alter_routine_arg.is_need_alter_); ObString first_stmt; - if (OB_FAIL(stmt.get_first_stmt(first_stmt))) { - LOG_WARN("fail to get first stmt" , K(ret)); + omt::ObTenantConfigGuard tenant_config(TENANT_CONF(ctx.get_my_session()->get_effective_tenant_id())); + if (need_create_routine) { + obrpc::ObRoutineDDLRes res; + bool with_res = (GET_MIN_CLUSTER_VERSION() >= MOCK_CLUSTER_VERSION_4_2_3_0 + && GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_3_0_0) + || GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_4_3_2_0; + if (OB_ISNULL(ctx.get_pl_engine())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("pl engine is null", K(ret)); + } else if (OB_FAIL(stmt.get_first_stmt(first_stmt))) { + LOG_WARN("fail to get first stmt" , K(ret)); + } else { + alter_routine_arg.ddl_stmt_str_ = first_stmt; + } + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) { + ret = OB_NOT_INIT; + LOG_WARN("get task executor context failed", K(ret)); + } else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) { + LOG_WARN("get common rpc proxy failed", K(ret)); + } else if (OB_ISNULL(common_rpc_proxy)){ + ret = OB_ERR_UNEXPECTED; + LOG_WARN("common rpc proxy should not be null", K(ret)); + } else if (!with_res && OB_FAIL(common_rpc_proxy->alter_routine(alter_routine_arg))) { + LOG_WARN("rpc proxy alter procedure failed", K(ret), "dst", common_rpc_proxy->get_server()); + } else if (with_res && OB_FAIL(common_rpc_proxy->alter_routine_with_res(alter_routine_arg, res))) { + LOG_WARN("rpc proxy alter procedure failed", K(ret), "dst", common_rpc_proxy->get_server()); + } + if (OB_SUCC(ret) && !has_error && with_res && + tenant_config.is_valid() && + tenant_config->plsql_v2_compatibility) { + CK (OB_NOT_NULL(ctx.get_sql_ctx()->schema_guard_)); + OZ (ObSPIService::force_refresh_schema(tenant_id, res.store_routine_schema_version_)); + OZ (compile_routine(ctx, tenant_id, database_id, routine_name, type, + res.store_routine_schema_version_)); + if (OB_FAIL(ret)) { + LOG_WARN("fail to persistent routine", K(ret)); + common::ob_reset_tsi_warning_buffer(); + ret = OB_SUCCESS; + } + } } else { - alter_routine_arg.ddl_stmt_str_ = first_stmt; - } - if (OB_FAIL(ret)) { - } else if (OB_ISNULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx))) { - ret = OB_NOT_INIT; - LOG_WARN("get task executor context failed", K(ret)); - } else if (OB_FAIL(task_exec_ctx->get_common_rpc(common_rpc_proxy))) { - LOG_WARN("get common rpc proxy failed", K(ret)); - } else if (OB_ISNULL(common_rpc_proxy)){ - ret = OB_ERR_UNEXPECTED; - LOG_WARN("common rpc proxy should not be null", K(ret)); - } else if (OB_FAIL(common_rpc_proxy->alter_routine(alter_routine_arg))) { - LOG_WARN("rpc proxy alter procedure failed", K(ret), "dst", common_rpc_proxy->get_server()); + ObMySQLTransaction trans; + const ObRoutineInfo *routine_info = nullptr; + ObSchemaGetterGuard schema_guard; + OZ (ctx.get_task_exec_ctx().schema_service_-> + get_tenant_schema_guard(ctx.get_my_session()->get_effective_tenant_id(), schema_guard)); + OZ(schema_guard.get_routine_info(tenant_id, alter_routine_arg.routine_info_.get_routine_id(), routine_info)); + CK (OB_NOT_NULL(routine_info)); + OZ (trans.start(GCTX.sql_proxy_, tenant_id, true)); + OZ (alter_routine_arg.error_info_.handle_error_info(trans, routine_info)); + if (trans.is_started()) { + int tmp_ret = OB_SUCCESS; + if (OB_SUCCESS != (tmp_ret = trans.end(OB_SUCCESS == ret))) { + LOG_WARN("trans end failed", K(ret), K(tmp_ret)); + ret = OB_SUCCESS == ret ? tmp_ret : ret; + } + } + if (OB_SUCC(ret) && !has_error + && ((GET_MIN_CLUSTER_VERSION() >= MOCK_CLUSTER_VERSION_4_2_3_0 + && GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_3_0_0) + || GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_4_3_2_0) + && tenant_config.is_valid() && tenant_config->plsql_v2_compatibility) { + OZ (compile_routine(ctx, tenant_id, database_id, routine_name, type, + routine_info->get_schema_version())); + if (OB_FAIL(ret)) { + LOG_WARN("fail to persistent routine", K(ret)); + common::ob_reset_tsi_warning_buffer(); + ret = OB_SUCCESS; + } + } } return ret; } diff --git a/src/sql/engine/cmd/ob_routine_executor.h b/src/sql/engine/cmd/ob_routine_executor.h index d15f3ef6fe..fae8c2cdc6 100644 --- a/src/sql/engine/cmd/ob_routine_executor.h +++ b/src/sql/engine/cmd/ob_routine_executor.h @@ -54,10 +54,43 @@ class ObCallProcedureStmt; class ObAnonymousBlockStmt; class ObRawExpr; +class ObCompileRoutineInf +{ +public: + ObCompileRoutineInf() {} + virtual ~ObCompileRoutineInf() {} + static int compile_routine(ObExecContext &ctx, + uint64_t tenant_id, + uint64_t database_id, + ObString &routine_name, + ObRoutineType routine_type, + int64_t schema_version); +private: + DISALLOW_COPY_AND_ASSIGN(ObCompileRoutineInf); +}; + +class ObCreateRoutineExecutor : ObCompileRoutineInf +{ +public: + ObCreateRoutineExecutor() {} + virtual ~ObCreateRoutineExecutor() {} + int execute(ObExecContext &ctx, ObCreateRoutineStmt &stmt); +private: + DISALLOW_COPY_AND_ASSIGN(ObCreateRoutineExecutor); +}; + +class ObAlterRoutineExecutor : ObCompileRoutineInf +{ +public: + ObAlterRoutineExecutor() {} + virtual ~ObAlterRoutineExecutor() {} + int execute(ObExecContext &ctx, ObAlterRoutineStmt &stmt); +private: + DISALLOW_COPY_AND_ASSIGN(ObAlterRoutineExecutor); +}; + //参考alter system定义 -DEF_SIMPLE_EXECUTOR(ObCreateRoutine); DEF_SIMPLE_EXECUTOR(ObDropRoutine); -DEF_SIMPLE_EXECUTOR(ObAlterRoutine); class ObCallProcedureExecutor { diff --git a/src/sql/engine/cmd/ob_trigger_executor.cpp b/src/sql/engine/cmd/ob_trigger_executor.cpp index e1b3853581..61c6bfba35 100644 --- a/src/sql/engine/cmd/ob_trigger_executor.cpp +++ b/src/sql/engine/cmd/ob_trigger_executor.cpp @@ -30,6 +30,43 @@ using namespace share::schema; namespace sql { + +int ObCompileTriggerInf::compile_trigger(sql::ObExecContext &ctx, + uint64_t tenant_id, + uint64_t db_id, + const ObString &trigger_name, + int64_t schema_version) +{ + int ret = OB_SUCCESS; + const ObTriggerInfo *trigger_info = nullptr; + CK (OB_NOT_NULL(ctx.get_sql_proxy())); + CK (OB_NOT_NULL(ctx.get_sql_ctx()->schema_guard_)); + OZ (ctx.get_sql_ctx()->schema_guard_->get_trigger_info(tenant_id, db_id, trigger_name, trigger_info)); + CK (OB_NOT_NULL(trigger_info)); + CK (OB_NOT_NULL(ctx.get_pl_engine())); + if (OB_SUCC(ret) && schema_version == trigger_info->get_schema_version()) { + ObPLPackage *package_spec = nullptr; + ObPLPackage *package_body = nullptr; + pl::ObPLPackageGuard package_guard(ctx.get_my_session()->get_effective_tenant_id()); + pl::ObPLResolveCtx resolve_ctx(ctx.get_allocator(), + *ctx.get_my_session(), + *ctx.get_sql_ctx()->schema_guard_, + package_guard, + *ctx.get_sql_proxy(), + false); + + OZ (package_guard.init()); + OZ (ctx.get_pl_engine()->get_package_manager().get_cached_package(resolve_ctx, + trigger_info->get_package_spec_info().get_package_id(), + package_spec, + package_body)); + CK (OB_NOT_NULL(package_spec)); + CK (OB_NOT_NULL(package_body)); + } + + return ret; +} + int ObCreateTriggerExecutor::execute(ObExecContext &ctx, ObCreateTriggerStmt &stmt) { int ret = OB_SUCCESS; @@ -37,9 +74,13 @@ int ObCreateTriggerExecutor::execute(ObExecContext &ctx, ObCreateTriggerStmt &st ObCommonRpcProxy *common_rpc_proxy = NULL; ObCreateTriggerArg &arg = stmt.get_trigger_arg(); uint64_t tenant_id = arg.trigger_info_.get_tenant_id(); + bool has_error = false; ObString first_stmt; obrpc::ObCreateTriggerRes res; bool with_res = (GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_4_2_1_2); + pl::ObPL *pl_engine = nullptr; + omt::ObTenantConfigGuard tenant_config(TENANT_CONF(ctx.get_my_session()->get_effective_tenant_id())); + CK (OB_NOT_NULL(pl_engine = ctx.get_my_session()->get_pl_engine())); OZ (stmt.get_first_stmt(first_stmt)); arg.ddl_stmt_str_ = first_stmt; OV (OB_NOT_NULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx)), OB_NOT_INIT); @@ -65,6 +106,7 @@ int ObCreateTriggerExecutor::execute(ObExecContext &ctx, ObCreateTriggerStmt &st ctx.get_sql_proxy(), ctx.get_allocator(), arg)); + OX (has_error = ERROR_STATUS_HAS_ERROR == arg.error_info_.get_error_status()); OZ (ctx.get_sql_ctx()->schema_guard_->reset()); if (OB_SUCC(ret)) { arg.ddl_stmt_str_.reset(); @@ -85,6 +127,33 @@ int ObCreateTriggerExecutor::execute(ObExecContext &ctx, ObCreateTriggerStmt &st OZ (common_rpc_proxy->create_trigger(arg), common_rpc_proxy->get_server()); } } + if (OB_SUCC(ret) && !has_error + && ((GET_MIN_CLUSTER_VERSION() >= MOCK_CLUSTER_VERSION_4_2_3_0 + && GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_3_0_0) + || GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_4_3_2_0) + && tenant_config.is_valid() && tenant_config->plsql_v2_compatibility) { + OZ (ObSPIService::force_refresh_schema(arg.trigger_info_.get_tenant_id(), res.trigger_schema_version_)); + OZ (ctx.get_task_exec_ctx().schema_service_-> + get_tenant_schema_guard(ctx.get_my_session()->get_effective_tenant_id(), *ctx.get_sql_ctx()->schema_guard_)); + OZ (compile_trigger(ctx, + arg.trigger_info_.get_tenant_id(), + arg.trigger_info_.get_database_id(), + arg.trigger_info_.get_trigger_name(), + res.trigger_schema_version_)); + if (OB_FAIL(ret)) { + LOG_WARN("fail to persistent trigger", K(ret)); + ret = OB_SUCCESS; + if (NULL != ctx.get_my_session()) { + ctx.get_my_session()->reset_warnings_buf(); + } + } + } + if(arg.with_if_not_exist_ && ret == OB_ERR_TRIGGER_ALREADY_EXIST) { + const ObString &trigger_name = arg.trigger_info_.get_trigger_name(); + LOG_WARN("trigger with if not exist grammar, ignore the error", K(ret), K(arg.with_if_not_exist_), K(trigger_name)); + LOG_USER_WARN(OB_ERR_TRIGGER_ALREADY_EXIST, trigger_name.length(), trigger_name.ptr()); + ret = OB_SUCCESS; + } return ret; } @@ -111,13 +180,52 @@ int ObAlterTriggerExecutor::execute(ObExecContext &ctx, ObAlterTriggerStmt &stmt ObCommonRpcProxy *common_rpc_proxy = NULL; ObAlterTriggerArg &arg = stmt.get_trigger_arg(); ObString first_stmt; + pl::ObPL *pl_engine = nullptr; + CK (arg.trigger_infos_.count() > 0); + CK (OB_NOT_NULL(pl_engine = ctx.get_my_session()->get_pl_engine())); OZ (stmt.get_first_stmt(first_stmt)); - arg.ddl_stmt_str_ = first_stmt; - OV (OB_NOT_NULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx)), OB_NOT_INIT); - OZ (task_exec_ctx->get_common_rpc(common_rpc_proxy)); - OV (OB_NOT_NULL(common_rpc_proxy)); - if (OB_SUCC(ret) && !arg.is_alter_compile_) { - OZ (common_rpc_proxy->alter_trigger(arg), common_rpc_proxy->get_server()); + if (OB_SUCC(ret)) { + const ObTriggerInfo& trigger_info = arg.trigger_infos_.at(0); + int64_t latest_schema_version = OB_INVALID_VERSION; + arg.ddl_stmt_str_ = first_stmt; + omt::ObTenantConfigGuard tenant_config(TENANT_CONF(ctx.get_my_session()->get_effective_tenant_id())); + OV (OB_NOT_NULL(task_exec_ctx = GET_TASK_EXECUTOR_CTX(ctx)), OB_NOT_INIT); + OZ (task_exec_ctx->get_common_rpc(common_rpc_proxy)); + OV (OB_NOT_NULL(common_rpc_proxy)); + if (OB_FAIL(ret)) { + } else if (!arg.is_alter_compile_) { + obrpc::ObRoutineDDLRes res; + bool with_res = (GET_MIN_CLUSTER_VERSION() >= MOCK_CLUSTER_VERSION_4_2_3_0 + && GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_3_0_0) + || GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_4_3_2_0; + if (with_res) { + OZ (common_rpc_proxy->alter_trigger_with_res(arg, res), common_rpc_proxy->get_server()); + } else { + OZ (common_rpc_proxy->alter_trigger(arg), common_rpc_proxy->get_server()); + } + if (OB_SUCC(ret) && with_res) { + OZ (ObSPIService::force_refresh_schema(trigger_info.get_tenant_id(), res.store_routine_schema_version_)); + OX (latest_schema_version = res.store_routine_schema_version_); + } + } else { + latest_schema_version = trigger_info.get_schema_version(); + } + if (OB_SUCC(ret) && + tenant_config.is_valid() && + tenant_config->plsql_v2_compatibility) { + OZ (ctx.get_task_exec_ctx().schema_service_-> + get_tenant_schema_guard(ctx.get_my_session()->get_effective_tenant_id(), *ctx.get_sql_ctx()->schema_guard_)); + OZ (compile_trigger(ctx, + trigger_info.get_tenant_id(), + trigger_info.get_database_id(), + trigger_info.get_trigger_name(), + latest_schema_version)); + if (OB_FAIL(ret)) { + LOG_WARN("fail to persistent trigger", K(ret)); + common::ob_reset_tsi_warning_buffer(); + ret = OB_SUCCESS; + } + } } return ret; } diff --git a/src/sql/engine/cmd/ob_trigger_executor.h b/src/sql/engine/cmd/ob_trigger_executor.h index 1e17667e6a..a5d0c855fb 100644 --- a/src/sql/engine/cmd/ob_trigger_executor.h +++ b/src/sql/engine/cmd/ob_trigger_executor.h @@ -29,7 +29,21 @@ class ObCreateTriggerStmt; class ObAlterTriggerStmt; class ObDropTriggerStmt; -class ObCreateTriggerExecutor +class ObCompileTriggerInf +{ +public: + ObCompileTriggerInf() {} + virtual ~ObCompileTriggerInf() {} + static int compile_trigger(sql::ObExecContext &ctx, + uint64_t tenant_id, + uint64_t db_id, + const ObString &trigger_name, + int64_t schema_version); +private: + DISALLOW_COPY_AND_ASSIGN(ObCompileTriggerInf); +}; + +class ObCreateTriggerExecutor : ObCompileTriggerInf { public: ObCreateTriggerExecutor() {} @@ -56,7 +70,7 @@ private: void operator=(const ObDropTriggerExecutor&); }; -class ObAlterTriggerExecutor +class ObAlterTriggerExecutor : ObCompileTriggerInf { public: ObAlterTriggerExecutor() {} diff --git a/src/sql/engine/cmd/ob_udt_executor.h b/src/sql/engine/cmd/ob_udt_executor.h index 10042e5a39..1b721c48e9 100644 --- a/src/sql/engine/cmd/ob_udt_executor.h +++ b/src/sql/engine/cmd/ob_udt_executor.h @@ -36,8 +36,22 @@ class ObExecContext; class ObCreateUDTStmt; class ObDropUDTStmt; +class ObCreateUDTExecutor +{ +public: + ObCreateUDTExecutor() {} + virtual ~ObCreateUDTExecutor() {} + int execute(ObExecContext &ctx, ObCreateUDTStmt &stmt); + static int compile_udt(sql::ObExecContext &ctx, + const ObString &db_name, + const ObString &udt_name, + int64_t type_code, + int64_t schema_version); +private: + DISALLOW_COPY_AND_ASSIGN(ObCreateUDTExecutor); +}; + //参考alter system定义 -DEF_SIMPLE_EXECUTOR(ObCreateUDT); DEF_SIMPLE_EXECUTOR(ObDropUDT); }//namespace sql diff --git a/src/sql/engine/cmd/ob_variable_set_executor.cpp b/src/sql/engine/cmd/ob_variable_set_executor.cpp index 5b45ef43ff..ba1c20e228 100644 --- a/src/sql/engine/cmd/ob_variable_set_executor.cpp +++ b/src/sql/engine/cmd/ob_variable_set_executor.cpp @@ -327,25 +327,32 @@ int ObVariableSetExecutor::execute(ObExecContext &ctx, ObVariableSetStmt &stmt) } } - if (OB_SUCC(ret) && set_var.set_scope_ == ObSetVar::SET_SCOPE_GLOBAL) { - if(set_var.var_name_ == OB_SV_TIME_ZONE) { - if(OB_FAIL(global_variable_timezone_formalize(ctx, value_obj))) { - LOG_WARN("failed to formalize global variables", K(ret)); + if(OB_SUCC(ret) && OB_FAIL(is_support(set_var))) { + if(ret == OB_NOT_SUPPORTED) { + ret = OB_SUCCESS; + LOG_USER_WARN(OB_NOT_SUPPORTED, "This system variable now is mock"); + } + } else { + if (OB_SUCC(ret) && set_var.set_scope_ == ObSetVar::SET_SCOPE_GLOBAL) { + if(set_var.var_name_ == OB_SV_TIME_ZONE) { + if(OB_FAIL(global_variable_timezone_formalize(ctx, value_obj))) { + LOG_WARN("failed to formalize global variables", K(ret)); + } + } + if (OB_SUCC(ret) && OB_FAIL(update_global_variables(ctx, stmt, set_var, value_obj))) { + LOG_WARN("failed to update global variables", K(ret)); + } else { } + } + if (OB_SUCC(ret) && set_var.set_scope_ == ObSetVar::SET_SCOPE_SESSION) { + if (OB_FAIL(sys_var->session_update(ctx, set_var, value_obj))) { + LOG_WARN("fail to update", K(ret), K(*sys_var), K(set_var), K(value_obj)); } } - if (OB_SUCC(ret) && OB_FAIL(update_global_variables(ctx, stmt, set_var, value_obj))) { - LOG_WARN("failed to update global variables", K(ret)); - } else { } - } - if (OB_SUCC(ret) && set_var.set_scope_ == ObSetVar::SET_SCOPE_SESSION) { - if (OB_FAIL(sys_var->session_update(ctx, set_var, value_obj))) { - LOG_WARN("fail to update", K(ret), K(*sys_var), K(set_var), K(value_obj)); - } - } - //某些变量需要立即更新状态 - if (OB_SUCC(ret)) { - if (OB_FAIL(sys_var->update(ctx, set_var, value_obj))) { - LOG_WARN("update sys var state failed", K(ret), K(set_var)); + //某些变量需要立即更新状态 + if (OB_SUCC(ret)) { + if (OB_FAIL(sys_var->update(ctx, set_var, value_obj))) { + LOG_WARN("update sys var state failed", K(ret), K(set_var)); + } } } } @@ -1364,6 +1371,19 @@ int ObVariableSetExecutor::cascade_set_validate_password(ObExecContext &ctx, return ret; } +int ObVariableSetExecutor::is_support(const share::ObSetVar &set_var) +{ + int ret = OB_SUCCESS; + ObSysVarClassType var_id = SYS_VAR_INVALID; + if(SYS_VAR_INVALID == (var_id = ObSysVarFactory::find_sys_var_id_by_name(set_var.var_name_))) { + ret = OB_ERR_SYS_VARIABLE_UNKNOWN; + LOG_WARN("unknown variable", K(set_var.var_name_), K(ret)); + } else if (SYS_VAR_DEBUG <= var_id && SYS_VAR_STORED_PROGRAM_CACHE >= var_id) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("This variable not support, just mock", K(set_var.var_name_), K(var_id), K(ret)); + } + return ret; +} #undef DEFINE_CAST_CTX }/* ns sql*/ diff --git a/src/sql/engine/cmd/ob_variable_set_executor.h b/src/sql/engine/cmd/ob_variable_set_executor.h index 9972c1a6e5..7c119ba7de 100644 --- a/src/sql/engine/cmd/ob_variable_set_executor.h +++ b/src/sql/engine/cmd/ob_variable_set_executor.h @@ -121,6 +121,7 @@ private: common::ObIAllocator &calc_buf, common::ObMySQLProxy &sql_proxy, const ObValidatePasswordCtx &password_ctx); + int is_support(const share::ObSetVar &set_var); int do_set_names(ObExecContext &ctx, ObSetNamesStmt &stmt); private: DISALLOW_COPY_AND_ASSIGN(ObVariableSetExecutor); diff --git a/src/sql/ob_spi.cpp b/src/sql/ob_spi.cpp index b5628c3b86..6b4ac5ae2e 100644 --- a/src/sql/ob_spi.cpp +++ b/src/sql/ob_spi.cpp @@ -8851,7 +8851,7 @@ bool ObSPIService::is_get_package_or_subprogram_var_expression(const ObSqlExpres return T_OP_GET_PACKAGE_VAR == get_expression_type(expr) || T_OP_GET_SUBPROGRAM_VAR == get_expression_type(expr); } -int ObSPIService::force_refresh_schema(uint64_t tenant_id) +int ObSPIService::force_refresh_schema(uint64_t tenant_id, int64_t refresh_version) { int ret = OB_SUCCESS; int64_t local_version = OB_INVALID_VERSION; @@ -8865,11 +8865,15 @@ int ObSPIService::force_refresh_schema(uint64_t tenant_id) } else if (OB_FAIL(GCTX.schema_service_->get_tenant_received_broadcast_version( tenant_id, global_version))) { LOG_WARN("fail to get global version", K(ret), K(tenant_id)); - } else if (local_version >= global_version) { - // do nothing - } else if (OB_FAIL(GCTX.schema_service_->async_refresh_schema(tenant_id, global_version))) { - LOG_WARN("failed to refresh schema", - K(ret), K(tenant_id), K(local_version), K(global_version)); + } + if (OB_SUCC(ret)) { + int64_t need_refresh_version = OB_INVALID_VERSION == refresh_version ? global_version : refresh_version; + if (local_version >= need_refresh_version) { + // do nothing + } else if (OB_FAIL(GCTX.schema_service_->async_refresh_schema(tenant_id, need_refresh_version))) { + LOG_WARN("failed to refresh schema", + K(ret), K(tenant_id), K(local_version), K(global_version), K(refresh_version)); + } } return ret; } diff --git a/src/sql/ob_spi.h b/src/sql/ob_spi.h index c1eb2ce033..a600c9528f 100644 --- a/src/sql/ob_spi.h +++ b/src/sql/ob_spi.h @@ -770,7 +770,7 @@ public: int64_t &into_cnt, bool &skip_locked, common::ColumnsFieldArray *field_list = NULL); - static int force_refresh_schema(uint64_t tenant_id); + static int force_refresh_schema(uint64_t tenant_id, int64_t refresh_version = OB_INVALID_VERSION); static int spi_update_package_change_info( pl::ObPLExecCtx *ctx, uint64_t package_id, uint64_t var_idx); diff --git a/src/sql/ob_sql.cpp b/src/sql/ob_sql.cpp index 03956192e9..34350d1eb2 100644 --- a/src/sql/ob_sql.cpp +++ b/src/sql/ob_sql.cpp @@ -5496,8 +5496,9 @@ void ObSql::generate_sql_id(ObPlanCacheCtx &pc_ctx, { // It has been checked during parser_and_check, there is no need to check again here if (OB_SUCCESS == err_code - && parse_result.result_tree_->children_[0]->type_ == T_SP_CALL_STMT) { - signature_sql = pc_ctx.sql_ctx_.spm_ctx_.bl_key_.constructed_sql_; + && PC_TEXT_MODE == pc_ctx.mode_ + && T_SP_CALL_STMT == parse_result.result_tree_->children_[0]->type_) { + signature_sql = pc_ctx.fp_result_.pc_key_.name_; } else if (add_plan_to_pc == false || PC_PS_MODE == pc_ctx.mode_ || PC_PL_MODE == pc_ctx.mode_ diff --git a/src/sql/parser/sql_parser_mysql_mode.y b/src/sql/parser/sql_parser_mysql_mode.y index 26395e0249..96286c4f5b 100644 --- a/src/sql/parser/sql_parser_mysql_mode.y +++ b/src/sql/parser/sql_parser_mysql_mode.y @@ -12660,7 +12660,7 @@ index_hint_definition } ; -/* diff normal_relation_facotr and dot_relation_factor for relation_factor_in_hint*/ +/* diff normal_relation_factor and dot_relation_factor for relation_factor_in_hint*/ relation_factor: normal_relation_factor { @@ -13913,6 +13913,10 @@ SHOW opt_extended_or_full TABLES opt_from_or_in_database_clause opt_show_conditi { malloc_non_terminal_node($$, result->malloc_pool_, T_SHOW_PROCEDURE_STATUS, 2, $4, $5); } | SHOW FUNCTION STATUS opt_from_or_in_database_clause opt_show_condition { malloc_non_terminal_node($$, result->malloc_pool_, T_SHOW_FUNCTION_STATUS, 2, $4, $5); } +| SHOW PROCEDURE CODE relation_factor +{ malloc_non_terminal_node($$, result->malloc_pool_, T_SHOW_PROCEDURE_CODE, 1, $4); } +| SHOW FUNCTION CODE relation_factor +{ malloc_non_terminal_node($$, result->malloc_pool_, T_SHOW_FUNCTION_CODE, 1, $4); } | SHOW TRIGGERS opt_from_or_in_database_clause opt_show_condition { malloc_non_terminal_node($$, result->malloc_pool_, T_SHOW_TRIGGERS, 2, $3, $4); } | SHOW SERVER STATUS opt_show_condition diff --git a/src/sql/resolver/cmd/ob_show_resolver.cpp b/src/sql/resolver/cmd/ob_show_resolver.cpp index 0953946331..f1e114c2b1 100644 --- a/src/sql/resolver/cmd/ob_show_resolver.cpp +++ b/src/sql/resolver/cmd/ob_show_resolver.cpp @@ -105,8 +105,9 @@ int ObShowResolver::resolve(const ParseNode &parse_tree) K(params_.allocator_), K(schema_checker_)); } else if (OB_UNLIKELY(parse_tree.type_ < T_SHOW_TABLES || parse_tree.type_ > T_SHOW_GRANTS) - && (parse_tree.type_ != T_SHOW_TRIGGERS) && (parse_tree.type_ != T_SHOW_PROFILE) - && (parse_tree.type_ != T_SHOW_ENGINE) && (parse_tree.type_ != T_SHOW_OPEN_TABLES)) { + && (parse_tree.type_ != T_SHOW_TRIGGERS) && (parse_tree.type_ != T_SHOW_PROFILE) + && (parse_tree.type_ != T_SHOW_PROCEDURE_CODE) && (parse_tree.type_ != T_SHOW_FUNCTION_CODE) + && (parse_tree.type_ != T_SHOW_ENGINE) && (parse_tree.type_ != T_SHOW_OPEN_TABLES)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected parse tree type", K(ret), K(parse_tree.type_)); } else { @@ -564,12 +565,12 @@ int ObShowResolver::resolve(const ParseNode &parse_tree) if (OB_FAIL(resolve_show_from_routine(parse_tree.children_[0], NULL, database_name.empty(), parse_tree.type_, real_tenant_id, show_db_name, show_db_id, show_routine_name, show_routine_id, proc_type))) { - LOG_WARN("fail to resolve show from table", K(ret)); + LOG_WARN("fail to resolve show from routine", K(ret)); } if (OB_FAIL(ret)) { } else if (OB_FAIL(schema_checker_->check_routine_show( session_priv, show_db_name, show_routine_name, allow_show))) { - LOG_WARN("Check table show error", K(ret)); + LOG_WARN("Check routine show error", K(ret)); } else if (!allow_show) { ret = OB_ERR_NO_TABLE_PRIVILEGE; LOG_USER_ERROR(OB_ERR_NO_TABLE_PRIVILEGE, static_cast(strlen("SHOW")), "SHOW", @@ -591,6 +592,54 @@ int ObShowResolver::resolve(const ParseNode &parse_tree) }(); break; } + case T_SHOW_PROCEDURE_CODE: + case T_SHOW_FUNCTION_CODE: { + [&] { + if (is_oracle_mode) { + ret = OB_NOT_SUPPORTED; + LOG_USER_ERROR(OB_NOT_SUPPORTED, "show procedure/function code in oracle mode is"); + } else if (OB_UNLIKELY(parse_tree.num_child_ != 1 || NULL == parse_tree.children_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("parse tree is wrong", K(ret), K(parse_tree.num_child_), K(parse_tree.children_)); + } else { + ObString show_db_name; + uint64_t show_db_id = OB_INVALID_ID; + ObString show_routine_name; + uint64_t show_routine_id = OB_INVALID_ID; + int64_t proc_type = -1; + bool allow_show = false; + if (OB_FAIL(resolve_show_from_routine(parse_tree.children_[0], NULL, database_name.empty(), + parse_tree.type_, real_tenant_id, show_db_name, + show_db_id, show_routine_name, show_routine_id, proc_type))) { + LOG_WARN("fail to resolve show from routine", K(ret)); + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(schema_checker_->check_routine_show( + session_priv, show_db_name, show_routine_name, allow_show))) { + LOG_WARN("Check routine show error", K(ret)); + } else if (!allow_show) { + ret = OB_ERR_NO_TABLE_PRIVILEGE; + LOG_USER_ERROR(OB_ERR_NO_TABLE_PRIVILEGE, static_cast(strlen("SHOW")), "SHOW", + session_priv.user_name_.length(), session_priv.user_name_.ptr(), + session_priv.host_name_.length(), session_priv.host_name_.ptr(), + show_routine_name.length(), show_routine_name.ptr()); + } else { }//do nothing + if (OB_SUCC(ret)) { + show_resv_ctx.stmt_type_ = (parse_tree.type_ == T_SHOW_PROCEDURE_CODE) ? stmt::T_SHOW_PROCEDURE_CODE : stmt::T_SHOW_FUNCTION_CODE; + if (parse_tree.type_ == T_SHOW_PROCEDURE_CODE) { + GEN_SQL_STEP_1(ObShowSqlSet::SHOW_PROCEDURE_CODE); + GEN_SQL_STEP_2(ObShowSqlSet::SHOW_PROCEDURE_CODE); + LOG_USER_WARN(OB_NOT_SUPPORTED, "show procedure code statement is currently implemented as mock,"); + } else { + GEN_SQL_STEP_1(ObShowSqlSet::SHOW_FUNCTION_CODE); + GEN_SQL_STEP_2(ObShowSqlSet::SHOW_FUNCTION_CODE); + LOG_USER_WARN(OB_NOT_SUPPORTED, "show function code statement is currently implemented as mock,"); + } + } + } + }(); + break; + } case T_SHOW_CREATE_TRIGGER: { [&] { if (OB_UNLIKELY(parse_tree.num_child_ != 1 || NULL == parse_tree.children_)) { @@ -2090,7 +2139,7 @@ int ObShowResolver::resolve_show_from_routine(const ParseNode *from_routine_node if (OB_FAIL(ret)) { // do nothing } else { - if (T_SHOW_CREATE_PROCEDURE == node_type) { + if (T_SHOW_CREATE_PROCEDURE == node_type || T_SHOW_PROCEDURE_CODE == node_type) { if (OB_FAIL(schema_checker_->get_standalone_procedure_info(real_tenant_id, show_database_name, show_routine_name, routine_info))) { LOG_WARN("get procedure info failed", K(ret), @@ -3179,6 +3228,16 @@ DEFINE_SHOW_CLAUSE_SET(SHOW_CREATE_FUNCTION, "SELECT routine_name AS `Function`, sql_mode, create_routine AS `Create Function`, character_set_client, collation_connection, collation_database AS `Database Collation` FROM %s.%s WHERE routine_id = %ld and proc_type = %ld", R"(SELECT "ROUTINE_NAME" AS "FUNCTION", "SQL_MODE", "CREATE_ROUTINE" AS "CREATE FUNCTION", "CHARACTER_SET_CLIENT", "COLLATION_CONNECTION", "COLLATION_DATABASE" AS "DATABASE COLLATION" FROM %s.%s WHERE ROUTINE_ID = %ld AND PROC_TYPE = %ld)", NULL); +DEFINE_SHOW_CLAUSE_SET(SHOW_PROCEDURE_CODE, + NULL, + "SELECT 1 `Pos`, 1 `Instruction` FROM (SELECT 1 FROM DUAL) tmp_table WHERE 1 != 1", + NULL, + NULL); +DEFINE_SHOW_CLAUSE_SET(SHOW_FUNCTION_CODE, + NULL, + "SELECT 1 `Pos`, 1 `Instruction` FROM (SELECT 1 FROM DUAL) tmp_table WHERE 1 != 1", + NULL, + NULL); DEFINE_SHOW_CLAUSE_SET(SHOW_CREATE_TRIGGER, NULL, "SELECT trigger_name AS `Trigger`, sql_mode, create_trigger AS `SQL Original Statement`, character_set_client, collation_connection, collation_database AS `Database Collation` FROM %s.%s WHERE trigger_id = %ld", diff --git a/src/sql/resolver/cmd/ob_show_resolver.h b/src/sql/resolver/cmd/ob_show_resolver.h index d7f1e3d56b..bdc1b6a5b5 100644 --- a/src/sql/resolver/cmd/ob_show_resolver.h +++ b/src/sql/resolver/cmd/ob_show_resolver.h @@ -148,6 +148,8 @@ struct ObShowResolver::ObShowSqlSet DECLARE_SHOW_CLAUSE_SET(SHOW_CREATE_VIEW); DECLARE_SHOW_CLAUSE_SET(SHOW_CREATE_PROCEDURE); DECLARE_SHOW_CLAUSE_SET(SHOW_CREATE_FUNCTION); + DECLARE_SHOW_CLAUSE_SET(SHOW_PROCEDURE_CODE); + DECLARE_SHOW_CLAUSE_SET(SHOW_FUNCTION_CODE); DECLARE_SHOW_CLAUSE_SET(SHOW_RECYCLEBIN); DECLARE_SHOW_CLAUSE_SET(SHOW_PROFILE); DECLARE_SHOW_CLAUSE_SET(SHOW_SYS_RECYCLEBIN); diff --git a/src/sql/resolver/ddl/ob_alter_package_resolver.cpp b/src/sql/resolver/ddl/ob_alter_package_resolver.cpp index d839ba51e4..8f963686af 100644 --- a/src/sql/resolver/ddl/ob_alter_package_resolver.cpp +++ b/src/sql/resolver/ddl/ob_alter_package_resolver.cpp @@ -235,8 +235,12 @@ int ObAlterPackageResolver::compile_package(const ObString& db_name, if (OB_FAIL(ret)) { } else if (!collect_package_body_info) { COLLECT_PACKAGE_INFO(pkg_arg, package_spec_info); + if (OB_SUCC(ret) && !has_error) { + share::schema::ObErrorInfo error_info; + OZ (error_info.delete_error(package_spec_info)); + } } else { - bool has_error = false; + bool body_has_error = false; OZ (package_body_ast.init(db_name, package_name, PL_PACKAGE_BODY, @@ -245,7 +249,7 @@ int ObAlterPackageResolver::compile_package(const ObString& db_name, OB_INVALID_VERSION, &package_spec_ast)); OZ (analyze_package(compiler, &(package_spec_ast.get_body()->get_namespace()), - package_body_ast, db_name, package_body_info, error_info, has_error)); + package_body_ast, db_name, package_body_info, error_info, body_has_error)); if (OB_SUCC(ret)) { ObArray routine_infos; OZ (schema_checker_->get_schema_guard()->get_routine_infos_in_package( @@ -253,7 +257,7 @@ int ObAlterPackageResolver::compile_package(const ObString& db_name, package_spec_info->get_package_id(), routine_infos)); if (OB_FAIL(ret)) { - } else if (!has_error) { + } else if (!body_has_error) { // if has_error, don't need to update routine route sql ObSEArray routine_spec_infos; ObPLRoutineTable &spec_routine_table = package_spec_ast.get_routine_table(); @@ -274,6 +278,12 @@ int ObAlterPackageResolver::compile_package(const ObString& db_name, routine_infos)); if (OB_FAIL(ret)) { pkg_arg.public_routine_infos_.reset(); + } else { + share::schema::ObErrorInfo error_info; + if (!has_error) { + OZ (error_info.delete_error(package_spec_info)); + } + OZ (error_info.delete_error(package_body_info)); } } else if (0 != package_body_info->get_exec_env().case_compare(pkg_arg.exec_env_)) { for (int64_t i = 0; OB_SUCC(ret) && i < routine_infos.count(); ++i) { diff --git a/src/sql/resolver/ddl/ob_create_routine_resolver.cpp b/src/sql/resolver/ddl/ob_create_routine_resolver.cpp index 07cdf478d1..b5bd2ab353 100644 --- a/src/sql/resolver/ddl/ob_create_routine_resolver.cpp +++ b/src/sql/resolver/ddl/ob_create_routine_resolver.cpp @@ -451,8 +451,9 @@ int ObCreateRoutineResolver::resolve_param_type(const ParseNode *type_node, || T_SP_TYPE == type_node->type_) { // %Type %RowType ObArray access_idxs; ObArray obj_access_idents; - CK (OB_LIKELY(1 == type_node->num_child_), + CK (OB_LIKELY(2 == type_node->num_child_), OB_NOT_NULL(type_node->children_[0]), + OB_ISNULL(type_node->children_[1]), OB_LIKELY(T_SP_OBJ_ACCESS_REF == type_node->children_[0]->type_), OB_NOT_NULL(schema_checker_), OB_NOT_NULL(schema_checker_->get_schema_guard()), @@ -993,14 +994,16 @@ int ObCreateRoutineResolver::resolve_impl(ObRoutineType routine_type, LOG_WARN("fail to get database schema", K(ret)); LOG_USER_ERROR(OB_ERR_BAD_DATABASE, crt_routine_arg->db_name_.length(), crt_routine_arg->db_name_.ptr()); } - if (OB_SUCC(ret) - && database_schema->get_database_name_str() != session_info_->get_database_name()) { + if (OB_FAIL(ret)) { + }else if (database_schema->get_database_name_str() != session_info_->get_database_name()) { OZ (old_database_name.append(session_info_->get_database_name())); OX (old_database_id = session_info_->get_database_id()); OZ (session_info_->set_default_database(database_schema->get_database_name_str())); OX (session_info_->set_database_id(database_id)); OX (crt_routine_arg->routine_info_.set_database_id(database_id)); OX (need_reset_default_database = true); + } else { + OX (crt_routine_arg->routine_info_.set_database_id(database_id)); } } OZ (resolve_sp_body(body_node, crt_routine_arg->routine_info_)); @@ -1073,7 +1076,11 @@ int ObCreateRoutineResolver::resolve(const ParseNode &parse_tree, clause_list, crt_routine_arg))) { LOG_WARN("failed to resolve routine info", K(ret)); - } else { /*do nothing*/ } + } else { + if (parse_tree.value_ != 0 && is_mysql_mode()) { + OX (crt_routine_arg->with_if_not_exist_ = parse_tree.value_); + } + } } return ret; } diff --git a/src/sql/resolver/ddl/ob_trigger_resolver.cpp b/src/sql/resolver/ddl/ob_trigger_resolver.cpp index 3a0d0ed990..0e31dfccd4 100644 --- a/src/sql/resolver/ddl/ob_trigger_resolver.cpp +++ b/src/sql/resolver/ddl/ob_trigger_resolver.cpp @@ -278,6 +278,9 @@ int ObTriggerResolver::resolve_trigger_source(const ParseNode &parse_node, ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "default collation in create trigger"); } + if (OB_SUCC(ret) && parse_node.value_ != 0 && is_mysql_mode()) { + OX (trigger_arg.with_if_not_exist_ = parse_node.value_); + } return ret; } diff --git a/src/sql/resolver/ob_resolver.cpp b/src/sql/resolver/ob_resolver.cpp index a8dc7fc1ff..ad9e96d2fc 100644 --- a/src/sql/resolver/ob_resolver.cpp +++ b/src/sql/resolver/ob_resolver.cpp @@ -713,6 +713,8 @@ int ObResolver::resolve(IsPrepared if_prepared, const ParseNode &parse_tree, ObS case T_SHOW_PROFILE: case T_SHOW_PROCEDURE_STATUS: case T_SHOW_FUNCTION_STATUS: + case T_SHOW_PROCEDURE_CODE: + case T_SHOW_FUNCTION_CODE: case T_SHOW_TRIGGERS: case T_SHOW_CREATE_TABLEGROUP: case T_SHOW_RESTORE_PREVIEW: diff --git a/src/sql/resolver/ob_resolver_utils.cpp b/src/sql/resolver/ob_resolver_utils.cpp index e454c6680b..2047dd6fd4 100644 --- a/src/sql/resolver/ob_resolver_utils.cpp +++ b/src/sql/resolver/ob_resolver_utils.cpp @@ -2308,6 +2308,8 @@ stmt::StmtType ObResolverUtils::get_stmt_type_by_item_type(const ObItemType item SET_STMT_TYPE(T_SHOW_PROCEDURE_STATUS); SET_STMT_TYPE(T_SHOW_FUNCTION_STATUS); SET_STMT_TYPE(T_SHOW_CREATE_TABLEGROUP); + SET_STMT_TYPE(T_SHOW_PROCEDURE_CODE); + SET_STMT_TYPE(T_SHOW_FUNCTION_CODE); SET_STMT_TYPE(T_CREATE_SAVEPOINT); SET_STMT_TYPE(T_RELEASE_SAVEPOINT); SET_STMT_TYPE(T_ROLLBACK_SAVEPOINT);