/** * Copyright (c) 2021 OceanBase * OceanBase CE is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. * You may obtain a copy of Mulan PubL v2 at: * http://license.coscl.org.cn/MulanPubL-2.0 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. */ #define USING_LOG_PREFIX SQL_RESV #include "sql/resolver/cmd/ob_alter_system_resolver.h" #include "common/ob_region.h" #include "lib/string/ob_sql_string.h" #include "share/schema/ob_schema_getter_guard.h" #include "share/ob_locality_parser.h" #include "share/ob_time_utility2.h" #include "share/ob_encryption_util.h" #ifdef OB_BUILD_TDE_SECURITY #include "share/ob_encrypt_kms.h" #endif #include "observer/ob_server_struct.h" #include "observer/omt/ob_tenant_config_mgr.h" #include "share/ob_zone_table_operation.h" #include "share/backup/ob_backup_struct.h" #include "share/restore/ob_import_table_struct.h" #include "share/restore/ob_recover_table_util.h" #include "sql/session/ob_sql_session_info.h" #include "sql/resolver/cmd/ob_alter_system_stmt.h" #include "sql/resolver/cmd/ob_system_cmd_stmt.h" #include "sql/resolver/cmd/ob_clear_balance_task_stmt.h" #include "sql/resolver/cmd/ob_switch_tenant_resolver.h" #include "sql/resolver/ddl/ob_create_table_resolver.h" #include "sql/resolver/ddl/ob_drop_table_stmt.h" #include "sql/resolver/ddl/ob_alter_table_stmt.h" #include "common/sql_mode/ob_sql_mode_utils.h" #include "sql/resolver/cmd/ob_variable_set_stmt.h" #include "observer/ob_server.h" #include "share/backup/ob_backup_io_adapter.h" #include "share/backup/ob_backup_config.h" #include "observer/mysql/ob_query_response_time.h" #include "rootserver/ob_rs_job_table_operator.h" //ObRsJobType #include "sql/resolver/cmd/ob_kill_stmt.h" #include "share/table/ob_table_config_util.h" namespace oceanbase { using namespace common; using namespace obrpc; using namespace share; using namespace share::schema; using namespace observer; namespace sql { typedef ObAlterSystemResolverUtil Util; int ObAlterSystemResolverUtil::sanity_check(const ParseNode *parse_tree, ObItemType item_type) { int ret = OB_SUCCESS; if (OB_UNLIKELY(NULL == parse_tree)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("parse tree should not be null"); } else if (OB_UNLIKELY(item_type != parse_tree->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid type", "expect", get_type_name(item_type), "actual", get_type_name(parse_tree->type_)); } else if (OB_UNLIKELY(parse_tree->num_child_ <= 0)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid num_child", "num_child", parse_tree->num_child_); } else if (OB_UNLIKELY(NULL == parse_tree->children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } return ret; } template int ObAlterSystemResolverUtil::resolve_server_or_zone(const ParseNode *parse_tree, RPC_ARG &arg) { int ret = OB_SUCCESS; arg.server_.reset(); arg.zone_.reset(); if (NULL != parse_tree) { switch (parse_tree->type_) { case T_IP_PORT: { if (OB_FAIL(resolve_server(parse_tree, arg.server_))) { LOG_WARN("resolve server address failed", K(ret)); } break; } case T_ZONE: { if (OB_FAIL(resolve_zone(parse_tree, arg.zone_))) { LOG_WARN("resolve zone failed", K(ret)); } break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("only server or zone type allowed here", "type", get_type_name(parse_tree->type_)); break; } } } return ret; } int ObAlterSystemResolverUtil::resolve_server_value(const ParseNode *parse_tree, ObAddr &server) { int ret = OB_SUCCESS; if (OB_UNLIKELY(NULL == parse_tree)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("parse tree should not be null"); } else if (OB_UNLIKELY(T_VARCHAR != parse_tree->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_VARCHAR", "type", get_type_name(parse_tree->type_)); } else { char ip_port[128] = {0}; snprintf(ip_port, 128, "%.*s", static_cast(parse_tree->str_len_), parse_tree->str_value_); if (OB_FAIL(server.parse_from_cstring(ip_port))) { LOG_WARN("string not in server address format", K(ip_port), K(ret)); } } return ret; } int ObAlterSystemResolverUtil::resolve_replica_type(const ParseNode *parse_tree, ObReplicaType &replica_type) { int ret = OB_SUCCESS; if (OB_UNLIKELY(NULL == parse_tree)) { replica_type = REPLICA_TYPE_FULL; // 为了兼容早期命令,不指定replica_type时默认为FULL类型 LOG_INFO("resolve_replica_type without any value. default to FULL."); } else if (OB_UNLIKELY(T_VARCHAR != parse_tree->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_VARCHAR", "type", get_type_name(parse_tree->type_)); } else { int64_t len = parse_tree->str_len_; const char *str = parse_tree->str_value_; if (OB_FAIL(ObLocalityParser::parse_type(str, len, replica_type))) { // do nothing, error log will print inside parse_type } } return ret; } int ObAlterSystemResolverUtil::resolve_memstore_percent(const ParseNode *parse_tree, ObReplicaProperty &replica_property) { int ret = OB_SUCCESS; if (OB_UNLIKELY(NULL == parse_tree)) { replica_property.reset(); LOG_INFO("resolve_memstore_percent without any value. default to 100"); } else if (OB_UNLIKELY(T_INT != parse_tree->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_INT", "type", get_type_name(parse_tree->type_)); } else { const ParseNode *node = parse_tree; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else { int64_t temp_value = node->value_; if(temp_value > 100 || temp_value < 0) { LOG_WARN("err memstore percent"); } else if (OB_FAIL(replica_property.set_memstore_percent(temp_value))) { LOG_WARN("set memstore percent failed"); } } } return ret; } int ObAlterSystemResolverUtil::resolve_server(const ParseNode *parse_tree, ObAddr &server) { int ret = OB_SUCCESS; if (NULL == parse_tree) { server.reset(); } else if (OB_FAIL(sanity_check(parse_tree, T_IP_PORT))) { LOG_WARN("sanity check failed"); } else { const ParseNode *node = parse_tree->children_[0]; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else if (OB_FAIL(resolve_server_value(node, server))) { LOG_WARN("resolve server value failed", K(ret)); } } return ret; } int ObAlterSystemResolverUtil::resolve_zone(const ParseNode *parse_tree, ObZone &zone) { int ret = OB_SUCCESS; if (NULL == parse_tree) { zone.reset(); } else if (OB_FAIL(sanity_check(parse_tree, T_ZONE))) { LOG_WARN("sanity check failed"); } else { const ParseNode *node = parse_tree->children_[0]; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else if (node->value_ <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("empty zone string"); } else { ObString zone_name(static_cast(node->str_len_), node->str_value_); if (OB_FAIL(zone.assign(zone_name))) { LOG_WARN("assign zone string failed", K(zone_name), K(ret)); } } } return ret; } int ObAlterSystemResolverUtil::resolve_tenant(const ParseNode *parse_tree, ObFixedLengthString < OB_MAX_TENANT_NAME_LENGTH + 1 > &tenant_name) { int ret = OB_SUCCESS; if (NULL == parse_tree) { tenant_name.reset(); } else if (OB_FAIL(sanity_check(parse_tree, T_TENANT_NAME))) { LOG_WARN("sanity check failed"); } else { const ParseNode *node = parse_tree->children_[0]; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else if (node->value_ <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("empty tenant string"); } else { ObString tenant(static_cast(node->str_len_), node->str_value_); if (OB_FAIL(tenant_name.assign(tenant))) { LOG_WARN("assign tenant string failed", K(tenant), K(ret)); } } } return ret; } int ObAlterSystemResolverUtil::resolve_tenant_id(const ParseNode *parse_tree, uint64_t &tenant_id) { int ret = OB_SUCCESS; tenant_id = OB_INVALID_TENANT_ID; if (NULL == parse_tree) { tenant_id = OB_SYS_TENANT_ID; } else if (T_TENANT_NAME != parse_tree->type_ && T_TENANT_ID != parse_tree->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid parse tree", K(ret), K(parse_tree)); } else { if (T_TENANT_NAME == parse_tree->type_) { ObSchemaGetterGuard schema_guard; ObString tenant_name; tenant_name.assign_ptr(parse_tree->str_value_, static_cast(parse_tree->str_len_)); if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(OB_SYS_TENANT_ID, schema_guard))) { LOG_WARN("failed to get_tenant_schema_guard", KR(ret)); } else if (OB_FAIL(schema_guard.get_tenant_id(tenant_name, tenant_id))) { LOG_WARN("failed to get tenant id from schema guard", KR(ret), K(tenant_name)); } } else { tenant_id = parse_tree->value_; } } return ret; } int ObAlterSystemResolverUtil::resolve_ls_id(const ParseNode *parse_tree, int64_t &ls_id) { int ret = OB_SUCCESS; if (NULL == parse_tree) { ret = OB_ERR_NULL_VALUE; LOG_WARN("node should not be null"); } else if (OB_FAIL(sanity_check(parse_tree, T_LS))) { LOG_WARN("sanity check failed"); } else { ls_id = parse_tree->children_[0]->value_; FLOG_INFO("resolve ls id", K(ls_id)); } return ret; } int ObAlterSystemResolverUtil::resolve_tablet_id(const ParseNode *opt_tablet_id, ObTabletID &tablet_id) { int ret = OB_SUCCESS; if (NULL == opt_tablet_id) { ret = OB_ERR_NULL_VALUE; LOG_WARN("opt_tablet_id should not be null"); } else if (OB_FAIL(sanity_check(opt_tablet_id, T_TABLET_ID))) { LOG_WARN("sanity check failed"); } else { tablet_id = opt_tablet_id->children_[0]->value_; FLOG_INFO("resolve tablet_id", K(tablet_id)); } return ret; } int ObAlterSystemResolverUtil::resolve_force_opt(const ParseNode *parse_tree, bool &force_cmd) { int ret = OB_SUCCESS; force_cmd = false; if (OB_ISNULL(parse_tree)) { //nothing todo } else { force_cmd = true; } return ret; } int ObAlterSystemResolverUtil::resolve_string(const ParseNode *node, ObString &string) { int ret = OB_SUCCESS; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else if (OB_UNLIKELY(T_VARCHAR != node->type_ && T_CHAR != node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node type is not T_VARCHAR/T_CHAR", "type", get_type_name(node->type_)); } else if (OB_UNLIKELY(node->str_len_ <= 0)) { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("empty string"); } else { string = ObString(node->str_len_, node->str_value_); } return ret; } int ObAlterSystemResolverUtil::resolve_relation_name(const ParseNode *node, ObString &string) { int ret = OB_SUCCESS; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else if (OB_UNLIKELY(T_IDENT != node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node type is not T_IDENT", "type", get_type_name(node->type_)); } else if (OB_UNLIKELY(node->str_len_ <= 0)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("empty string"); } else { string = ObString(node->str_len_, node->str_value_); } return ret; } // resolve tenants int ObAlterSystemResolverUtil::resolve_tenant( const ParseNode &tenants_node, const uint64_t tenant_id, common::ObSArray &tenant_ids, bool &affect_all, bool &affect_all_user, bool &affect_all_meta) { int ret = OB_SUCCESS; ObSchemaGetterGuard schema_guard; // Filter duplicate tenant names. hash::ObHashSet tenant_id_set; const int64_t MAX_TENANT_BUCKET = 256; const int64_t ERROR_MSG_LENGTH = 1024; char error_msg[ERROR_MSG_LENGTH] = ""; int tmp_ret = OB_SUCCESS; int64_t pos = 0; if (OB_ISNULL(GCTX.schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema service is empty", KR(ret)); } else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(tenant_id, schema_guard))) { LOG_WARN("get_schema_guard failed", KR(ret)); } else if (OB_FAIL(tenant_id_set.create(MAX_TENANT_BUCKET))) { LOG_WARN("failed to create tenant id set", K(ret)); } else { ObString tenant_name; uint64_t tmp_tenant_id = 0; affect_all = false; affect_all_user = false; affect_all_meta = false; for (int64_t i = 0; OB_SUCC(ret) && (i < tenants_node.num_child_); ++i) { ParseNode *node = tenants_node.children_[i]; if (OB_ISNULL(node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children of server_list should not be null", KR(ret)); } else { tenant_name.assign_ptr(node->str_value_, static_cast(node->str_len_)); if (tenant_name.empty()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret)); } else if (0 == strcasecmp(tenant_name.ptr(), "all")) { affect_all = true; } else if (0 == strcasecmp(tenant_name.ptr(), "all_user")) { affect_all_user = true; } else if (0 == strcasecmp(tenant_name.ptr(), "all_meta")) { affect_all_meta = true; } else if (OB_FAIL(schema_guard.get_tenant_id(tenant_name, tmp_tenant_id))) { LOG_WARN("tenant not exist", K(tenant_name), KR(ret)); } else { int hash_ret = tenant_id_set.exist_refactored(tmp_tenant_id); if (OB_HASH_EXIST == hash_ret) { // duplicate tenant name ret = OB_NOT_SUPPORTED; LOG_WARN("duplicate tanant name", K(tenant_name), K(tmp_tenant_id), KR(ret)); if (OB_SUCCESS != (tmp_ret = databuff_printf(error_msg, ERROR_MSG_LENGTH, pos, "duplicate tenant %s is", tenant_name.ptr()))) { LOG_WARN("failed to set error msg", K(ret), K(tmp_ret), K(error_msg), K(pos)); } else { LOG_USER_ERROR(OB_NOT_SUPPORTED, error_msg); } } else if (OB_HASH_NOT_EXIST == hash_ret) { if (OB_FAIL(tenant_ids.push_back(tmp_tenant_id))) { LOG_WARN("fail to push tenant id ", K(tenant_name), K(tmp_tenant_id), KR(ret)); } else if (OB_FAIL(tenant_id_set.set_refactored(tmp_tenant_id))) { LOG_WARN("fail to push tenant id ", K(tenant_name), K(tmp_tenant_id), KR(ret)); } } else { ret = hash_ret == OB_SUCCESS ? OB_ERR_UNEXPECTED : hash_ret; LOG_WARN("failed to check tenant exist", K(tenant_name), K(tmp_tenant_id), KR(ret)); } } } tenant_name.reset(); } if (OB_SUCC(ret) && (affect_all || affect_all_user || affect_all_meta)) { if (OB_SYS_TENANT_ID != tenant_id) { ret = OB_ERR_NO_PRIVILEGE; LOG_WARN("Only sys tenant can operate all tenants", KR(ret), K(tenant_id)); } else if (tenants_node.num_child_ > 1) { ret = OB_NOT_SUPPORTED; LOG_WARN("all/all_user/all_meta must be used separately", KR(ret), "tenant list count", tenants_node.num_child_); LOG_USER_ERROR(OB_NOT_SUPPORTED, "all/all_user/all_meta in combination with other names is"); } } FLOG_INFO("resolve tenants", K(affect_all), K(affect_all_user), K(affect_all_meta), K(tenant_ids)); } return ret; } int ObFreezeResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObFreezeStmt *freeze_stmt = NULL; if (OB_UNLIKELY(NULL == parse_tree.children_) || OB_UNLIKELY(parse_tree.num_child_ < 2)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("wrong freeze parse tree", KP(parse_tree.children_), K(parse_tree.num_child_)); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else if (NULL == (freeze_stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObFreezeStmt failed"); } else if (OB_ISNULL(parse_tree.children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("wrong freeze type", KP(parse_tree.children_[0])); } else if (T_INT != parse_tree.children_[0]->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("wrong freeze type", K(parse_tree.children_[0]->type_)); } else { stmt_ = freeze_stmt; if (1 == parse_tree.children_[0]->value_) { // MAJOR FREEZE freeze_stmt->set_major_freeze(true); if (OB_UNLIKELY(2 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("wrong freeze parse tree", K(parse_tree.num_child_)); } else { ParseNode *opt_tenant_list_v2 = parse_tree.children_[1]; if (OB_FAIL(resolve_major_freeze_(freeze_stmt, opt_tenant_list_v2))) { LOG_WARN("resolve major freeze failed", KR(ret), KP(opt_tenant_list_v2)); } } } else if (2 == parse_tree.children_[0]->value_) { // MINOR FREEZE freeze_stmt->set_major_freeze(false); if (OB_UNLIKELY(4 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("wrong freeze parse tree", K(parse_tree.num_child_)); } else { ParseNode *opt_tenant_list_or_ls_or_tablet_id = parse_tree.children_[1]; ParseNode *opt_server_list = parse_tree.children_[2]; ParseNode *opt_zone_desc = parse_tree.children_[3]; if (OB_FAIL(resolve_minor_freeze_( freeze_stmt, opt_tenant_list_or_ls_or_tablet_id, opt_server_list, opt_zone_desc))) { LOG_WARN("resolve minor freeze failed", KR(ret), KP(opt_tenant_list_or_ls_or_tablet_id), KP(opt_server_list), KP(opt_zone_desc)); } } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("unknown freeze type", K(parse_tree.children_[0]->value_)); } } return ret; } int ObFreezeResolver::resolve_major_freeze_(ObFreezeStmt *freeze_stmt, ParseNode *opt_tenant_list_v2) { int ret = OB_SUCCESS; const uint64_t cur_tenant_id = session_info_->get_effective_tenant_id(); if (NULL == opt_tenant_list_v2) { // if opt_tenant_list_v2 == NULL, add owned tenant_id if (OB_FAIL(freeze_stmt->get_tenant_ids().push_back(cur_tenant_id))) { LOG_WARN("fail to push owned tenant id ", KR(ret), "owned tenant_id", cur_tenant_id); } } else if (OB_SYS_TENANT_ID != cur_tenant_id) { ret = OB_ERR_NO_PRIVILEGE; LOG_WARN("Only sys tenant can add suffix opt(tenant=name)", KR(ret), K(cur_tenant_id)); } else if ((T_TENANT_LIST == opt_tenant_list_v2->type_)) { // if opt_tenant_list_v2 != NULL && type == T_TENANT_LIST, resolve it if (OB_UNLIKELY(nullptr == opt_tenant_list_v2->children_) || OB_UNLIKELY(0 == opt_tenant_list_v2->num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children of tenant should not be null", KR(ret)); } else { bool affect_all = false; bool affect_all_user = false; bool affect_all_meta = false; if (OB_FAIL(Util::resolve_tenant(*opt_tenant_list_v2, cur_tenant_id, freeze_stmt->get_tenant_ids(), affect_all, affect_all_user, affect_all_meta))) { LOG_WARN("fail to resolve tenant", KR(ret)); } else if (affect_all || affect_all_user || affect_all_meta) { if ((true == affect_all && true == affect_all_user) || (true == affect_all && true == affect_all_meta) || (true == affect_all_user && true == affect_all_meta)) { ret = OB_NOT_SUPPORTED; LOG_WARN("only one of affect_all,affect_all_user,affect_all_meta can be true", KR(ret), K(affect_all), K(affect_all_user), K(affect_all_meta)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "all/all_user/all_meta in combination with other names is"); } else { if (affect_all || affect_all_user) { freeze_stmt->set_freeze_all_user(); } else { freeze_stmt->set_freeze_all_meta(); } } } } } else { LOG_WARN("invalid type when resolve opt_tenant_list_v2", K(T_TENANT_LIST), K(opt_tenant_list_v2->type_)); } return ret; } int ObFreezeResolver::resolve_minor_freeze_(ObFreezeStmt *freeze_stmt, ParseNode *opt_tenant_list_or_ls_or_tablet_id, ParseNode *opt_server_list, ParseNode *opt_zone_desc) { int ret = OB_SUCCESS; const uint64_t cur_tenant_id = session_info_->get_effective_tenant_id(); if (OB_SUCC(ret) && OB_NOT_NULL(opt_tenant_list_or_ls_or_tablet_id) && OB_FAIL(resolve_tenant_ls_tablet_(freeze_stmt, opt_tenant_list_or_ls_or_tablet_id))) { LOG_WARN("resolve tenant ls table failed", KR(ret)); } if (OB_SUCC(ret) && OB_NOT_NULL(opt_server_list) && OB_FAIL(resolve_server_list_(freeze_stmt, opt_server_list))) { LOG_WARN("resolve server list failed", KR(ret)); } if (OB_SUCC(ret) && OB_NOT_NULL(opt_zone_desc) && OB_FAIL(Util::resolve_zone(opt_zone_desc, freeze_stmt->get_zone()))) { LOG_WARN("resolve zone desc failed", KR(ret)); } return ret; } int ObFreezeResolver::resolve_tenant_ls_tablet_(ObFreezeStmt *freeze_stmt, ParseNode *opt_tenant_list_or_ls_or_tablet_id) { int ret = OB_SUCCESS; const uint64_t cur_tenant_id = session_info_->get_effective_tenant_id(); if (OB_ISNULL(opt_tenant_list_or_ls_or_tablet_id->children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children of tenant should not be null", KR(ret)); } else { bool affect_all = false; bool affect_all_user = false; bool affect_all_meta = false; const ParseNode *tenant_list_tuple = nullptr; const ParseNode *opt_tablet_id = nullptr; const ParseNode *ls_id = nullptr; switch (opt_tenant_list_or_ls_or_tablet_id->type_) { case T_TENANT_TABLET: if (opt_tenant_list_or_ls_or_tablet_id->num_child_ != 2) { LOG_WARN("invalid child num", K(opt_tenant_list_or_ls_or_tablet_id->num_child_)); } else { tenant_list_tuple = opt_tenant_list_or_ls_or_tablet_id->children_[0]; opt_tablet_id = opt_tenant_list_or_ls_or_tablet_id->children_[1]; if (OB_ISNULL(tenant_list_tuple)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("tenant list is nullptr", KR(ret), KP(tenant_list_tuple), KP(ls_id), KP(opt_tablet_id)); } } break; case T_TENANT_LS_TABLET: if (opt_tenant_list_or_ls_or_tablet_id->num_child_ != 3) { LOG_WARN("invalid child num", K(opt_tenant_list_or_ls_or_tablet_id->num_child_)); } else { tenant_list_tuple = opt_tenant_list_or_ls_or_tablet_id->children_[0]; ls_id = opt_tenant_list_or_ls_or_tablet_id->children_[1]; opt_tablet_id = opt_tenant_list_or_ls_or_tablet_id->children_[2]; if (OB_ISNULL(tenant_list_tuple) || OB_ISNULL(ls_id)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("tenant_list or ls_id is nullptr", KR(ret), KP(tenant_list_tuple), KP(ls_id), KP(opt_tablet_id)); } } break; default: LOG_WARN("invalid parse node type", K(T_TENANT_TABLET), K(T_TENANT_LS_TABLET), K(opt_tenant_list_or_ls_or_tablet_id->type_)); break; } if (OB_FAIL(ret)) { } else if (OB_NOT_NULL(tenant_list_tuple) && OB_FAIL(Util::resolve_tenant(*tenant_list_tuple, cur_tenant_id, freeze_stmt->get_tenant_ids(), affect_all, affect_all_user, affect_all_meta))) { LOG_WARN("fail to resolve tenant", KR(ret)); } else if (OB_NOT_NULL(ls_id) && OB_FAIL(Util::resolve_ls_id(ls_id, freeze_stmt->get_ls_id()))) { LOG_WARN("fail to resolve tablet id", KR(ret)); } else if (OB_NOT_NULL(opt_tablet_id) && OB_FAIL(Util::resolve_tablet_id(opt_tablet_id, freeze_stmt->get_tablet_id()))) { LOG_WARN("fail to resolve tablet id", KR(ret)); } else if (affect_all || affect_all_user || affect_all_meta) { if ((true == affect_all && true == affect_all_user) || (true == affect_all && true == affect_all_meta) || (true == affect_all_user && true == affect_all_meta)) { ret = OB_NOT_SUPPORTED; LOG_WARN("only one of affect_all,affect_all_user,affect_all_meta can be true", KR(ret), K(affect_all), K(affect_all_user), K(affect_all_meta)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "all/all_user/all_meta in combination with other names is"); } else { if (affect_all || affect_all_user) { freeze_stmt->set_freeze_all_user(); } else { freeze_stmt->set_freeze_all_meta(); } } } } return ret; } int ObFreezeResolver::resolve_server_list_(ObFreezeStmt *freeze_stmt, ParseNode *opt_server_list) { int ret = OB_SUCCESS; if (OB_ISNULL(opt_server_list->children_) || OB_UNLIKELY(0 == opt_server_list->num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children of server_list should not be null"); } else { ObString addr_str; ObAddr server; for (int64_t i = 0; OB_SUCC(ret) && i < opt_server_list->num_child_; ++i) { ParseNode *node = opt_server_list->children_[i]; if (OB_ISNULL(node)) { LOG_WARN("children of server_list should not be null"); } else { addr_str.assign_ptr(node->str_value_, static_cast(node->str_len_)); if (OB_FAIL(server.parse_from_string(addr_str))) { LOG_WARN("parse server from cstring failed", K(addr_str)); } else if (OB_FAIL(freeze_stmt->push_server(server))) { SQL_RESV_LOG(WARN, "push back failed", K(server)); } } server.reset(); addr_str.reset(); } } return ret; } // // This node has six children_ and they are following: // cache_type_: parse_tree.children_[0] // opt_namespace: parse_tree.children_[1] // opt_sql_id: parse_tree.children_[2] // opt_databases: parse_tree.children_[3] // opt_tenant_list: parse_tree.children_[4] // flush_scope: parse_tree.children_[5] // int ObFlushCacheResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObFlushCacheStmt *stmt = NULL; ObSQLSessionInfo* sess = params_.session_info_; /* 无论设置租户级配置项,还是系统参数,都需要alter system权限。 对租户级配置项的修改,算是一种扩展,借用alter system权限进行控制 */ if (OB_ISNULL(sess)) { ret = OB_ERR_UNEXPECTED; SERVER_LOG(WARN, "invalid session"); } else if (OB_UNLIKELY(T_FLUSH_CACHE != parse_tree.type_ || parse_tree.num_child_ != 6)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid argument", "type", get_type_name(parse_tree.type_), "child_num", parse_tree.num_child_); } else if (NULL == parse_tree.children_[0] || NULL == parse_tree.children_[5]) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid parse tree", K(ret)); } else if (NULL == (stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObFlushCacheStmt failed"); } else { ObSchemaGetterGuard schema_guard; // first child: resolve cache type stmt->flush_cache_arg_.cache_type_ = (ObCacheType)parse_tree.children_[0]->value_; // second child: resolve namespace ParseNode *namespace_node = parse_tree.children_[1]; // third child: resolve sql_id ParseNode *sql_id_node = parse_tree.children_[2]; // for adds database id // fourth child: resolve db_list ParseNode *db_node = parse_tree.children_[3]; // for adds tenant ids // fivth child: resolve tenant list ParseNode *t_node = parse_tree.children_[4]; // sixth child: resolve application fields stmt->is_global_ = parse_tree.children_[5]->value_; // whether is coarse granularity plan cache evict. // tenant level(true) / pcv_set level(false) bool is_coarse_granularity = true; ObSEArray db_name_list; // namespace if (OB_FAIL(ret)) { } else if (NULL == namespace_node) { stmt->flush_cache_arg_.ns_type_ = ObLibCacheNameSpace::NS_INVALID; } else if (stmt->flush_cache_arg_.cache_type_ != CACHE_TYPE_LIB_CACHE) { ret = OB_NOT_SUPPORTED; LOG_WARN("only support lib cache's cache evict by namespace", K(stmt->flush_cache_arg_.cache_type_), K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "only support lib cache's cache evict by namespace, other type"); } else { if (OB_UNLIKELY(NULL == namespace_node->children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { ParseNode *node = namespace_node->children_[0]; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else { if (node->str_len_ <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("empty namespace name"); } else { ObString namespce_name(node->str_len_, node->str_value_); ObLibCacheNameSpace ns_type = ObLibCacheRegister::get_ns_type_by_name(namespce_name); if (ns_type <= ObLibCacheNameSpace::NS_INVALID || ns_type >= ObLibCacheNameSpace::NS_MAX) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid namespace type", K(ns_type)); } else { stmt->flush_cache_arg_.ns_type_ = ns_type; } } } } } // sql_id if (OB_FAIL(ret)) { // do nothing } else if (OB_ISNULL(sql_id_node)) { // do nothing // currently, only support plan cache's fine-grained cache evict } else if (stmt->flush_cache_arg_.cache_type_ != CACHE_TYPE_PLAN) { ret = OB_NOT_SUPPORTED; LOG_WARN("only support plan cache's fine-grained cache evict", K(stmt->flush_cache_arg_.cache_type_), K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "only support plan cache's fine-grained cache evict, other type"); } else if (lib::is_oracle_mode()) { ret = OB_NOT_SUPPORTED; LOG_WARN("not supported plan cache's fine-grained cache evict in oracle mode", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "plan cache's fine-grained cache evict in oracle mode is"); } else if (OB_ISNULL(sql_id_node->children_) || OB_ISNULL(sql_id_node->children_[0]) || T_SQL_ID != sql_id_node->type_) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret)); } else if (sql_id_node->children_[0]->str_len_ > (OB_MAX_SQL_ID_LENGTH+1)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret)); } else { stmt->flush_cache_arg_.sql_id_.assign_ptr( sql_id_node->children_[0]->str_value_, static_cast(sql_id_node->children_[0]->str_len_)); stmt->flush_cache_arg_.is_fine_grained_ = true; } // retrive schema guard if (OB_FAIL(ret)) { } else if (OB_ISNULL(GCTX.schema_service_)) { ret = OB_ERR_UNEXPECTED; SERVER_LOG(WARN, "invalid argument", K(GCTX.schema_service_)); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard( session_info_->get_effective_tenant_id(), schema_guard))) { SERVER_LOG(WARN, "get_schema_guard failed", K(ret)); } else { // do nothing } // db names if (OB_FAIL(ret)) { // do nothing } else if (!stmt->flush_cache_arg_.is_fine_grained_) { if (OB_ISNULL(db_node)) { // tenant level plan cache evict // and not needs to specify db_name } else { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "flushing cache in database level at coarse flushing"); } } else if (NULL == db_node) { // db list is empty // empty db list means clear all db's in fine-grained cache evict // do nothing } else if (OB_ISNULL(db_node->children_) || OB_ISNULL(db_node->children_[0]) || T_DATABASE_LIST != db_node->type_) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret)); } else { uint64_t db_id = 0; ObString db_names; ObString db_name; db_names.assign_ptr(db_node->children_[0]->str_value_, static_cast(db_node->children_[0]->str_len_)); while (OB_SUCC(ret) && !db_names.empty()) { db_name = db_names.split_on(',').trim(); if(db_name.empty() && NULL == db_names.find(',')) { db_name = db_names; db_names.reset(); } if(!db_name.empty()) { if (OB_FAIL(db_name_list.push_back(db_name))) { SERVER_LOG(WARN, "failed to add database name", K(ret)); } } } // for database name end } /* * different database belongs to different tenant, * and we will use following logics to retrive db_id: * for (tenant list) { * for (database_name_list) { * // find db_id from schema * args_.push_back(db_id); * } * } * */ // tenant list if (OB_FAIL(ret)) { } else if (NULL == t_node) { //tenant list is empty if (!stmt->flush_cache_arg_.is_fine_grained_) { // coarse grained cache evict // Notes: // tenant level evict, and no tenant list specified means all tenant // for system tenant: empty means flush all tenant's // for normal tenant: this node has been set as NULL in parse phase, // and already adds its tenant id to tenant list in above // Therefore, do nothing if (OB_SYS_TENANT_ID != sess->get_effective_tenant_id() && OB_FAIL(stmt->flush_cache_arg_.push_tenant(sess->get_effective_tenant_id()))) { LOG_WARN("failed to adds tenant for normal tenant", K(sess->get_effective_tenant_id()), K(ret)); } } else { // fine-grained cache evcit // for fine-grained plan evict, we must specify tenant list uint64_t t_id = OB_INVALID_ID; t_id = sess->get_effective_tenant_id(); if (t_id <= OB_MAX_RESERVED_TENANT_ID) {// system tenant will use this path. // system tenant must specify tenant_list; ret = OB_EMPTY_TENANT; SERVER_LOG(WARN, "invalid argument, fine-grained plan evict must specify tenant_list", K(ret)); } else { // normal tenant if (OB_FAIL(stmt->flush_cache_arg_.push_tenant(sess->get_effective_tenant_id()))) { LOG_WARN("failed to adds tenant for normal tenant", K(sess->get_effective_tenant_id()), K(ret)); } else { // normal tenant will use it's tenant_id when t_node is empty for (uint64_t j=0; OB_SUCC(ret) && jflush_cache_arg_.push_database(db_id))) { SERVER_LOG(WARN, "fail to push database id ",K(db_name_list.at(j)), K(db_id), K(ret)); } } // for get db_id ends LOG_INFO("normal tenant flush plan cache ends", K(t_id), K(db_name_list)); } } // normal tenant ends } // fine-grained plan evcit ends } else if (sess->get_effective_tenant_id() != OB_SYS_TENANT_ID) { // tenant node is not null and current tenant is not sys tenant // due to normal tenant cannot specify tenant, and only can purge // their own plan cache ret = OB_ERR_NO_PRIVILEGE; LOG_WARN("Only sys tenant can do this operation", K(ret), K(sess->get_effective_tenant_id())); } else if (NULL == t_node->children_) { ret = OB_ERR_UNEXPECTED; SERVER_LOG(WARN, "invalid argument", K(ret)); } else { uint64_t tenant_id = 0; ObString tenant_name; // adds tenant_ids and get db_ids for (int64_t i = 0; OB_SUCC(ret) && i < t_node->num_child_; ++i) { if (OB_ISNULL(t_node->children_[i])) { ret = OB_ERR_UNEXPECTED; SERVER_LOG(WARN, "invalid argument", K(t_node->children_[i]), K(ret)); } else { tenant_name.assign_ptr(t_node->children_[i]->str_value_, static_cast(t_node->children_[i]->str_len_)); if (OB_FAIL(schema_guard.get_tenant_id(tenant_name, tenant_id))) { SERVER_LOG(WARN, "tenant not exist", K(tenant_name), K(ret)); } else if (OB_FAIL(stmt->flush_cache_arg_.push_tenant(tenant_id))) { SERVER_LOG(WARN, "fail to push tenant id ",K(tenant_name), K(tenant_id), K(ret)); } else { ObSchemaGetterGuard schema_guard_db; if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(tenant_id, schema_guard_db))) { SERVER_LOG(WARN, "get_schema_guard failed", K(ret), K(tenant_id)); } else { for (uint64_t j = 0; OB_SUCC(ret) && j < db_name_list.count(); j++) { uint64_t db_id = 0; if (OB_FAIL(schema_guard_db.get_database_id(tenant_id, db_name_list.at(j), db_id))) { SERVER_LOG(WARN, "database not exist", K(db_name_list.at(j)), K(ret)); } else if ((int64_t)db_id == OB_INVALID_ID) { ret = OB_ERR_BAD_DATABASE; SERVER_LOG(WARN, "database not exist", K(db_name_list.at(j)), K(ret)); } else if (OB_FAIL(stmt->flush_cache_arg_.push_database(db_id))) { SERVER_LOG(WARN, "fail to push database id ",K(db_name_list.at(j)), K(db_id), K(ret)); } } // for get db_id ends } } } // for get tenant_id ends tenant_name.reset(); } //for tenant end } LOG_INFO("resolve flush command finished!", K(ret), K(sess->get_effective_tenant_id()), K(stmt->is_global_), K(stmt->flush_cache_arg_.cache_type_), K(stmt->flush_cache_arg_.sql_id_), K(stmt->flush_cache_arg_.is_fine_grained_), K(stmt->flush_cache_arg_.tenant_ids_), K(stmt->flush_cache_arg_.db_ids_)); } if (OB_SUCC(ret) && ObSchemaChecker::is_ora_priv_check()) { if (OB_ISNULL(schema_checker_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret)); } else if (OB_FAIL(schema_checker_->check_ora_ddl_priv( session_info_->get_effective_tenant_id(), session_info_->get_priv_user_id(), ObString(""), // why use T_ALTER_SYSTEM_SET_PARAMETER? // because T_ALTER_SYSTEM_SET_PARAMETER has following traits: // T_ALTER_SYSTEM_SET_PARAMETER can allow dba to do an operation // and prohibit other user to do this operation // so we reuse this. stmt::T_ALTER_SYSTEM_SET_PARAMETER, session_info_->get_enable_role_array()))) { LOG_WARN("failed to check privilege", K(session_info_->get_effective_tenant_id()), K(session_info_->get_user_id())); } } return ret; } int ObFlushKVCacheResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_FLUSH_KVCACHE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_FLUSH_KVCACHE", "type", get_type_name(parse_tree.type_)); } else { ObFlushKVCacheStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObFlushKVCacheStmt failed"); } else { stmt_ = stmt; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { ParseNode *node = parse_tree.children_[0]; if (NULL == node) { stmt->tenant_name_.reset(); } else { if (OB_UNLIKELY(NULL == node->children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { node = node->children_[0]; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else { if (node->str_len_ <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("empty tenant name"); } else { ObString tenant_name(node->str_len_, node->str_value_); if (OB_FAIL(stmt->tenant_name_.assign(tenant_name))) { LOG_WARN("assign tenant name failed", K(tenant_name), K(ret)); } } } } } if (OB_SUCC(ret)) { node = parse_tree.children_[1]; if (NULL == node) { stmt->cache_name_.reset(); } else { if (OB_UNLIKELY(NULL == node->children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { node = node->children_[0]; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else { if (node->str_len_ <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("empty cache name"); } else { ObString cache_name(node->str_len_, node->str_value_); if (OB_FAIL(stmt->cache_name_.assign(cache_name))) { LOG_WARN("assign cache name failed", K(cache_name), K(ret)); } } } } } } } } } return ret; } int ObFlushIlogCacheResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObFlushIlogCacheStmt *stmt = NULL; if (OB_UNLIKELY(T_FLUSH_ILOGCACHE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type not match T_FLUSH_ILOGCACHE", "type", get_type_name(parse_tree.type_)); } else if (OB_ISNULL(stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("create ObFlushCacheStmt error", K(ret)); } else if (OB_ISNULL(parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children of parse tree is null", K(ret)); } else { ParseNode *opt_file_id_node = parse_tree.children_[0]; ParseNode *file_id_val_node = NULL; if (OB_ISNULL(opt_file_id_node)) { stmt->file_id_ = 0; } else if (OB_ISNULL(opt_file_id_node->children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("opt_file_id_node.children is null", K(ret)); } else if (OB_ISNULL(file_id_val_node = opt_file_id_node->children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("file_id_val_node is null", K(ret)); } else { int64_t file_id_val = file_id_val_node->value_; // type of value_ is int64_t if (file_id_val <= 0 || file_id_val >= INT32_MAX) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid file_id when flush ilogcache", K(ret), K(file_id_val)); } else { stmt->file_id_ = (int32_t)file_id_val; stmt_ = stmt; LOG_INFO("flush ilogcache resolve succ", K(file_id_val)); } } } return ret; } int ObFlushDagWarningsResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObFlushDagWarningsStmt *stmt = NULL; if (OB_UNLIKELY(T_FLUSH_DAG_WARNINGS != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type not match T_FLUSH_DAG_WARNINGS", "type", get_type_name(parse_tree.type_)); } else if (OB_ISNULL(stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("create ObFlushDagWarningsStmt error", K(ret)); } return ret; } int ObAdminServerResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_ADMIN_SERVER != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ADMIN_SERVER", "type", get_type_name(parse_tree.type_)); } else { ObAdminServerStmt *admin_server_stmt = NULL; if (NULL == (admin_server_stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; SQL_RESV_LOG(ERROR, "create ObAdminServerStmt failed"); } else { stmt_ = admin_server_stmt; ParseNode *admin_op = NULL; ParseNode *server_list = NULL; ParseNode *zone_info = NULL; if (3 != parse_tree.num_child_) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "child num not right", "child num", parse_tree.num_child_, K(ret)); } else { admin_op = parse_tree.children_[0]; server_list = parse_tree.children_[1]; zone_info = parse_tree.children_[2]; if (OB_UNLIKELY(NULL == admin_op || NULL == server_list)) { SQL_RESV_LOG(WARN, "admin_op and server_list should not be null"); ret= OB_ERR_UNEXPECTED; } else { admin_server_stmt->set_op( static_cast(admin_op->value_)); ObServerList &servers = admin_server_stmt->get_server_list(); for (int64_t i = 0; OB_SUCC(ret) && i < server_list->num_child_; ++i) { ObString addr_str; ObAddr server; if (OB_UNLIKELY(NULL == server_list->children_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "children of server_list should not be null"); } else if (OB_UNLIKELY(NULL == server_list->children_[i])) { ret = OB_ERR_UNEXPECTED; _SQL_RESV_LOG(WARN, "children[%ld] of server_list should not be null", i); } else { addr_str.assign_ptr(server_list->children_[i]->str_value_, static_cast(server_list->children_[i]->str_len_)); if (OB_FAIL(server.parse_from_string(addr_str))) { SQL_RESV_LOG(WARN, "parse server from string failed", K(addr_str), K(ret)); } else if (OB_FAIL(servers.push_back(server))) { SQL_RESV_LOG(WARN, "push back failed", K(server), K(ret)); } } } if (OB_SUCC(ret)) { if (NULL != zone_info) { ObString zone_str; ObZone zone; if (OB_UNLIKELY(NULL == zone_info->children_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "children of zone_info should not be null"); } else if (OB_UNLIKELY(NULL == zone_info->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "children[0] of zone_info should not be null"); } else { zone_str.assign_ptr(zone_info->children_[0]->str_value_, static_cast(zone_info->children_[0]->str_len_)); if (OB_FAIL(zone.assign(zone_str))) { SQL_RESV_LOG(WARN, "assign failed", K(zone_str), K(ret)); } else { admin_server_stmt->set_zone(zone); } } } } } } } } return ret; } int ObAdminZoneResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObAdminZoneStmt *admin_zone_stmt = NULL; if (OB_UNLIKELY(T_ADMIN_ZONE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ADMIN_ZONE", "type", get_type_name(parse_tree.type_)); } else if (NULL == (admin_zone_stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; SQL_RESV_LOG(ERROR, "create ObAdminZoneStmt failed"); } else { stmt_ = admin_zone_stmt; if (3 != parse_tree.num_child_) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "child num not right", "child num", parse_tree.num_child_, K(ret)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "children should not be null"); } else { ParseNode *admin_op = parse_tree.children_[0]; ParseNode *zone_info = parse_tree.children_[1]; ParseNode *zone_options = parse_tree.children_[2]; ObZone zone; if (OB_UNLIKELY(NULL == admin_op || NULL == zone_info)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "admin_op and zone_info should not be null"); } else if (admin_op->value_ < 1 || admin_op->value_ > 7) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid action code", "action", admin_op->value_); } else if (OB_FAIL(zone.assign(ObString(zone_info->str_len_, zone_info->str_value_)))) { SQL_RESV_LOG(WARN, "assign zone failed", K(zone), K(ret)); } else { admin_zone_stmt->set_zone(zone); ObAdminZoneArg::AdminZoneOp op = static_cast(admin_op->value_); admin_zone_stmt->set_op(op); if (NULL != zone_options) { for (int64_t i = 0; OB_SUCC(ret) && i < zone_options->num_child_; ++i) { if (NULL == zone_options->children_[i]) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "region info is null", K(ret)); } else if (T_REGION == zone_options->children_[i]->type_) { ObRegion region; ParseNode *region_info = zone_options->children_[i]; if (admin_zone_stmt->has_alter_region_option()) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "multiple region option"); } else if (region_info->str_len_ <= 0) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "empty region"); } else if (OB_FAIL(region.assign(ObString( region_info->str_len_, region_info->str_value_)))) { SQL_RESV_LOG(WARN, "assign region failed", K(ret)); } else if (OB_FAIL(admin_zone_stmt->set_alter_region_option())) { SQL_RESV_LOG(WARN, "fail to set alter region option", K(ret)); } else { admin_zone_stmt->set_region(region); } } else if (T_IDC == zone_options->children_[i]->type_) { ObIDC idc; ParseNode *idc_info = zone_options->children_[i]; if (admin_zone_stmt->has_alter_idc_option()) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "multiple idc option"); } else if (idc_info->str_len_ <= 0) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "empty idc"); } else if (OB_FAIL(idc.assign(ObString( idc_info->str_len_, idc_info->str_value_)))) { SQL_RESV_LOG(WARN, "idc assign failed", K(ret)); } else if (OB_FAIL(admin_zone_stmt->set_alter_idc_option())) { SQL_RESV_LOG(WARN, "fail to set alter idc option", K(ret)); } else { admin_zone_stmt->set_idc(idc); } } else if (T_ZONE_TYPE == zone_options->children_[i]->type_) { ParseNode *zone_type_info = zone_options->children_[i]; ObZoneType zone_type = str_to_zone_type(zone_type_info->str_value_); if (admin_zone_stmt->has_alter_zone_type_option()) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "multiple zone_type option"); } else if (zone_type == ObZoneType::ZONE_TYPE_INVALID) { ret = OB_INVALID_ARGUMENT; LOG_WARN("unexpected zone_type info", "info", zone_type_info->value_); } else if (OB_FAIL(admin_zone_stmt->set_alter_zone_type_option())) { SQL_RESV_LOG(WARN, "fail to set alter zone_type option", K(ret)); } else { admin_zone_stmt->set_zone_type(zone_type); } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected zone option", K(ret)); } } } } } } return ret; } int ObSwitchReplicaRoleResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_SWITCH_REPLICA_ROLE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_SWITCH_REPLICA_ROLE", "type", get_type_name(parse_tree.type_)); } else { ObSwitchReplicaRoleStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObSwitchReplicaRoleStmt failed"); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else { stmt_ = stmt; ObAdminSwitchReplicaRoleArg &rpc_arg = stmt->get_rpc_arg(); if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } if (OB_SUCC(ret)) { ParseNode *role = parse_tree.children_[0]; if (OB_UNLIKELY(NULL == role)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("role should not be null"); } else if (OB_UNLIKELY(T_INT != role->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_INT", "type", get_type_name(role->type_)); } else { switch (role->value_) { case 0: { rpc_arg.role_ = ObRole::LEADER; LOG_INFO("switch role to LEADER", K(role->value_)); break; } case 1: { rpc_arg.role_ = ObRole::FOLLOWER; LOG_INFO("switch role to FOLLOWER", K(role->value_)); break; } case 2: { rpc_arg.role_ = ObRole::INVALID_ROLE; LOG_INFO("switch role to ARBITRARY", K(role->value_)); break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected role value", "value", role->value_); break; } } } } if (OB_SUCC(ret)) { ParseNode *node = parse_tree.children_[1]; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else if (OB_UNLIKELY(NULL == node->children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { switch (node->type_) { case T_LS_SERVER_TENANT: { if (OB_FAIL(Util::resolve_ls_id(node->children_[0], rpc_arg.ls_id_))) { LOG_WARN("resolve partition id failed", K(ret)); } else if (OB_FAIL(Util::resolve_server(node->children_[1], rpc_arg.server_))) { LOG_WARN("resolve server failed", K(ret)); } else if (OB_FAIL(Util::resolve_tenant(node->children_[2], rpc_arg.tenant_name_))) { LOG_WARN("resolve tenant failed", K(ret)); } else { if (rpc_arg.ls_id_ < 0 || !rpc_arg.server_.is_valid()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("ls_id or server is invalid", K(rpc_arg)); } LOG_INFO("resolve switch replica arg done", K_(rpc_arg.ls_id), K_(rpc_arg.server), K_(rpc_arg.tenant_name)); } break; } case T_SERVER_TENANT: { if (OB_FAIL(Util::resolve_server(node->children_[0], rpc_arg.server_))) { LOG_WARN("resolve server failed", K(ret)); } else if (OB_FAIL(Util::resolve_tenant(node->children_[1], rpc_arg.tenant_name_))) { LOG_WARN("resolve tenant failed", K(ret)); } break; } case T_ZONE_TENANT: { if (OB_FAIL(Util::resolve_zone(node->children_[0], rpc_arg.zone_))) { LOG_WARN("resolve zone failed", K(ret)); } else if (OB_FAIL(Util::resolve_tenant(node->children_[1], rpc_arg.tenant_name_))) { LOG_WARN("resolve tenant failed", K(ret)); } break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected type", "type", get_type_name(node->type_)); break; } } } } } } return ret; } int ObReportReplicaResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_REPORT_REPLICA != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_REPORT_REPLICA", "type", get_type_name(parse_tree.type_)); } else { ObReportReplicaStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObReportReplicaStmt failed"); } else { stmt_ = stmt; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else if (OB_FAIL(Util::resolve_server_or_zone(parse_tree.children_[0], stmt->get_rpc_arg()))) { LOG_WARN("resolve server or zone failed", K(ret)); } } } return ret; } int ObRecycleReplicaResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_RECYCLE_REPLICA != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_RECYCLE_REPLICA", "type", get_type_name(parse_tree.type_)); } else { ObRecycleReplicaStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObRecycleReplicaStmt failed"); } else { stmt_ = stmt; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else if (OB_FAIL(Util::resolve_server_or_zone(parse_tree.children_[0], stmt->get_rpc_arg()))) { LOG_WARN("resolve server or zone failed", K(ret)); } } } return ret; } int ObAdminMergeResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObSQLSessionInfo* sess = params_.session_info_; if (OB_UNLIKELY(T_MERGE_CONTROL != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_MERGE_CONTROL", "type", get_type_name(parse_tree.type_)); } else { ObAdminMergeStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObAdminMergeStmt failed"); } else { stmt_ = stmt; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { ParseNode *node = parse_tree.children_[0]; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else if (OB_UNLIKELY(T_INT != node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_INT", "type", get_type_name(node->type_)); } else { switch (node->value_) { case 1: { stmt->get_rpc_arg().type_ = ObAdminMergeArg::START_MERGE; break; } case 2: { stmt->get_rpc_arg().type_ = ObAdminMergeArg::SUSPEND_MERGE; break; } case 3: { stmt->get_rpc_arg().type_ = ObAdminMergeArg::RESUME_MERGE; break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected merge admin type", "value", node->value_); break; } } } } if (OB_SUCC(ret)) { const uint64_t cur_tenant_id = sess->get_effective_tenant_id(); ParseNode *tenants_node = parse_tree.children_[1]; if (NULL != tenants_node) { if (OB_SYS_TENANT_ID != cur_tenant_id) { ret = OB_ERR_NO_PRIVILEGE; LOG_WARN("Only sys tenant can add suffix opt(tenant=name)", KR(ret), K(cur_tenant_id)); } else if (T_TENANT_LIST != tenants_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_TENANT_LIST", "type", get_type_name(tenants_node->type_)); } else { bool affect_all = false; bool affect_all_user = false; bool affect_all_meta = false; const int64_t child_num = tenants_node->num_child_; if (OB_UNLIKELY(nullptr == tenants_node->children_) || OB_UNLIKELY(0 == child_num)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children of tenant should not be null", KR(ret), K(child_num)); } else if (OB_FAIL(Util::resolve_tenant(*tenants_node, cur_tenant_id, stmt->get_rpc_arg().tenant_ids_, affect_all, affect_all_user, affect_all_meta))) { LOG_WARN("fail to resolve tenant", KR(ret), K(cur_tenant_id)); } else if (affect_all || affect_all_user || affect_all_meta) { if ((true == affect_all && true == affect_all_user) || (true == affect_all && true == affect_all_meta) || (true == affect_all_user && true == affect_all_meta)) { ret = OB_NOT_SUPPORTED; LOG_WARN("only one of affect_all,affect_all_user,affect_all_meta can be true", KR(ret), K(affect_all), K(affect_all_user), K(affect_all_meta)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "all/all_user/all_meta in combination with other names is"); } else { if (affect_all || affect_all_user) { stmt->get_rpc_arg().affect_all_user_ = true; } else { stmt->get_rpc_arg().affect_all_meta_ = true; } } } } } else { if (OB_FAIL(stmt->get_rpc_arg().tenant_ids_.push_back(cur_tenant_id))) { LOG_WARN("fail to push back own tenant id"); } } } } } return ret; } int ObAdminRecoveryResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_RECOVERY_CONTROL != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_RECOVERY_CONTROL", "type", get_type_name(parse_tree.type_)); } else { ObAdminRecoveryStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObAdminRecoveryStmt failed"); } else { stmt_ = stmt; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { ParseNode *node = parse_tree.children_[0]; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else if (OB_UNLIKELY(T_INT != node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_INT", "type", get_type_name(node->type_)); } else { switch (node->value_) { case 2: { stmt->get_rpc_arg().type_ = ObAdminRecoveryArg::SUSPEND_RECOVERY; break; } case 3: { stmt->get_rpc_arg().type_ = ObAdminRecoveryArg::RESUME_RECOVERY; break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected recovery admin type", "value", node->value_); break; } } } } if (OB_SUCC(ret)) { if (OB_FAIL(Util::resolve_zone(parse_tree.children_[1], stmt->get_rpc_arg().zone_))) { LOG_WARN("resolve zone failed", K(ret)); } } } } return ret; } int ObClearRootTableResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_CLEAR_ROOT_TABLE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_CLEAR_ROOT_TABLE", "type", get_type_name(parse_tree.type_)); } else { ObClearRoottableStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObClearRoottableStmt failed"); } else { stmt_ = stmt; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { ParseNode *node = parse_tree.children_[0]; if (NULL == node) { stmt->get_rpc_arg().tenant_name_.reset(); } else { if (OB_UNLIKELY(NULL == node->children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { node = node->children_[0]; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else { if (node->str_len_ <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("empty tenant name"); } else { ObString tenant_name(node->str_len_, node->str_value_); if (OB_FAIL(stmt->get_rpc_arg().tenant_name_.assign(tenant_name))) { LOG_WARN("assign tenant name failed", K(tenant_name), K(ret)); } } } } } } } } return ret; } int ObRefreshSchemaResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_REFRESH_SCHEMA != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_REFRESH_SCHEMA", "type", get_type_name(parse_tree.type_)); } else { ObRefreshSchemaStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObRefreshSchemaStmt failed"); } else { stmt_ = stmt; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else if (OB_FAIL(Util::resolve_server_or_zone(parse_tree.children_[0], stmt->get_rpc_arg()))) { LOG_WARN("resolve server or zone failed", K(ret)); } } } return ret; } int ObRefreshMemStatResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_REFRESH_MEMORY_STAT != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_REFRESH_MEMORY_STAT", "type", get_type_name(parse_tree.type_)); } else { ObRefreshMemStatStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObRefreshMemStatStmt failed"); } else { stmt_ = stmt; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else if (OB_FAIL(Util::resolve_server_or_zone(parse_tree.children_[0], stmt->get_rpc_arg()))) { LOG_WARN("resolve server or zone failed", K(ret)); } } } return ret; } int ObWashMemFragmentationResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_WASH_MEMORY_FRAGMENTATION != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_WASH_MEMORY_FRAGMENTATION", "type", get_type_name(parse_tree.type_)); } else { ObWashMemFragmentationStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObWashMemFragmentationStmt failed"); } else { stmt_ = stmt; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else if (OB_FAIL(Util::resolve_server_or_zone(parse_tree.children_[0], stmt->get_rpc_arg()))) { LOG_WARN("resolve server or zone failed", K(ret)); } } } return ret; } int ObRefreshIOCalibrationResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObRefreshIOCalibraitonStmt *stmt = nullptr; obrpc::ObAdminRefreshIOCalibrationArg *arg = nullptr; if (OB_UNLIKELY(T_REFRESH_IO_CALIBRATION != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_REFRESH_IO_CALIBRATION", "type", get_type_name(parse_tree.type_)); } else if (OB_ISNULL(stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObRefreshIOCalibraitonStmt failed"); } else if (FALSE_IT(stmt_ = stmt)) { } else if (OB_UNLIKELY(NULL == parse_tree.children_ || 3 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("parse tree children is invalid", K(ret), K(parse_tree.num_child_)); } else { arg = &stmt->get_rpc_arg(); } if (OB_SUCC(ret)) { // parse storage_name from child[0] const ParseNode *storage_name_node = parse_tree.children_[0]; if (OB_ISNULL(storage_name_node) || storage_name_node->num_child_ <= 0) { // allow null, do nothing } else if (OB_FAIL(Util::resolve_string(storage_name_node->children_[0], arg->storage_name_))) { LOG_WARN("resolve storage name failed", K(ret)); } } if (OB_SUCC(ret)) { // parse calibration_list from child[1] const ParseNode *calibration_list_node = parse_tree.children_[1]; if (OB_ISNULL(calibration_list_node)) { // null means refresh arg->only_refresh_ = true; } else if (nullptr == calibration_list_node->children_ || calibration_list_node->num_child_ <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("calibration list node has no children", K(ret)); } else { for (int64_t i = 0; OB_SUCC(ret) && i < calibration_list_node->num_child_; ++i) { common::ObIOBenchResult item; const ParseNode *calibration_info_node = calibration_list_node->children_[i]; ObString calibration_string; if (OB_ISNULL(calibration_info_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children of calibration_list should not be null", K(ret), KP(calibration_info_node), K(i)); } else if (OB_FAIL(Util::resolve_string(calibration_info_node, calibration_string))) { LOG_WARN("resolve calibration info node failed", K(ret)); if (0 == i && calibration_info_node->str_len_ <= 0) { // empty means reset, do nothing arg->only_refresh_ = false; ret = OB_SUCCESS; break; } } else if (OB_FAIL(ObIOCalibration::parse_calibration_string(calibration_string, item))) { LOG_WARN("parse calibration info failed", K(ret), K(calibration_string), K(i)); } else if (OB_FAIL(arg->calibration_list_.push_back(item))) { LOG_WARN("push back calibration item failed", K(ret), K(i), K(item)); } } } } if (OB_SUCC(ret)) { // parse server or zone from child[2] if (OB_FAIL(Util::resolve_server_or_zone(parse_tree.children_[2], *arg))) { LOG_WARN("resolve server or zone failed", K(ret)); } } return ret; } int check_backup_region(const ObString &backup_region) { int ret = OB_SUCCESS; ObArray backup_region_array; ObArray region_array; const int64_t ERROR_MSG_LENGTH = 1024; char error_msg[ERROR_MSG_LENGTH] = ""; int tmp_ret = OB_SUCCESS; int64_t pos = 0; if (OB_FAIL(ObBackupUtils::parse_backup_format_input(backup_region, MAX_REGION_LENGTH, backup_region_array))) { LOG_WARN("failed to parse backup format input", K(ret), K(backup_region)); } else if (OB_FAIL(share::ObZoneTableOperation::get_region_list(*GCTX.sql_proxy_, region_array))) { LOG_WARN("failed to get region list", K(ret)); } else { for (int64_t i = 0; i < backup_region_array.count(); ++i) { const ObRegion &tmp_region = backup_region_array.at(i).region_; bool found = false; for (int64_t j = 0; !found && j < region_array.count(); ++j) { const ObRegion ®ion = region_array.at(j); if (tmp_region == region) { found = true; } } if (!found) { ret = OB_CANNOT_SET_BACKUP_REGION; LOG_WARN("backup region is not exist in region list", K(ret), K(backup_region), K(region_array)); if (OB_SUCCESS != (tmp_ret = databuff_printf(error_msg, ERROR_MSG_LENGTH, pos, "backup region do not exist in region list. backup region : %s.", backup_region.ptr()))) { LOG_WARN("failed to set error msg", K(tmp_ret), K(error_msg), K(pos)); } else { LOG_USER_ERROR(OB_CANNOT_SET_BACKUP_REGION, error_msg); } } } } return ret; } int check_backup_zone(const ObString &backup_zone) { int ret = OB_SUCCESS; ObArray backup_zone_array; ObArray zone_array; const int64_t ERROR_MSG_LENGTH = 1024; char error_msg[ERROR_MSG_LENGTH] = ""; int tmp_ret = OB_SUCCESS; int64_t pos = 0; if (OB_FAIL(ObBackupUtils::parse_backup_format_input(backup_zone, MAX_REGION_LENGTH, backup_zone_array))) { LOG_WARN("failed to parse backup format input", K(ret), K(backup_zone)); } else if (OB_FAIL(share::ObZoneTableOperation::get_zone_list(*GCTX.sql_proxy_, zone_array))) { LOG_WARN("failed to get region list", K(ret)); } else { for (int64_t i = 0; OB_SUCC(ret) && i < backup_zone_array.count(); ++i) { const ObZone &tmp_zone = backup_zone_array.at(i).zone_; bool found = false; for (int64_t j = 0; !found && j < zone_array.count(); ++j) { const ObZone &zone = zone_array.at(j); if (tmp_zone == zone) { found = true; } } if (!found) { ret = OB_CANNOT_SET_BACKUP_ZONE; LOG_WARN("backup zone is not exist in zone list", K(ret), K(backup_zone), K(zone_array)); if (OB_SUCCESS != (tmp_ret = databuff_printf(error_msg, ERROR_MSG_LENGTH, pos, "backup zone do not exist in zone list. backup zone : %s.", backup_zone.ptr()))) { LOG_WARN("failed to set error msg", K(tmp_ret), K(error_msg), K(pos)); } else { LOG_USER_ERROR(OB_CANNOT_SET_BACKUP_ZONE, error_msg); } } } } return ret; } /* for mysql mode */ int ObSetConfigResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_ALTER_SYSTEM_SET_PARAMETER != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ALTER_SYSTEM_SET_PARAMETER", "type", get_type_name(parse_tree.type_)); } else { if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { const ParseNode *list_node = parse_tree.children_[0]; if (OB_UNLIKELY(NULL == list_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("list_node should not be null"); } else { ObSetConfigStmt *stmt = create_stmt(); if (OB_UNLIKELY(NULL == stmt)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create stmt failed"); } else { HEAP_VAR(ObCreateTableResolver, ddl_resolver, params_) { for (int64_t i = 0; OB_SUCC(ret) && i < list_node->num_child_; ++i) { if (OB_UNLIKELY(NULL == list_node->children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); break; } const ParseNode *action_node = list_node->children_[i]; if (NULL == action_node) { continue; } // config name HEAP_VAR(ObAdminSetConfigItem, item) { if (OB_LIKELY(session_info_ != NULL)) { item.exec_tenant_id_ = session_info_->get_effective_tenant_id(); } else { LOG_WARN("session is null"); item.exec_tenant_id_ = OB_INVALID_TENANT_ID; } if (OB_UNLIKELY(NULL == action_node->children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); break; } if (OB_UNLIKELY(NULL == action_node->children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children[0] should not be null"); break; } ObString name(action_node->children_[0]->str_len_, action_node->children_[0]->str_value_); ObCharset::casedn(CS_TYPE_UTF8MB4_GENERAL_CI, name); if (OB_FAIL(item.name_.assign(name))) { LOG_WARN("assign config name failed", K(name), K(ret)); break; } // config value ObObjParam val; if (OB_UNLIKELY(NULL == action_node->children_[1])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children[1] should not be null"); break; } else if (OB_FAIL(ddl_resolver.resolve_default_value(action_node->children_[1], val))) { LOG_WARN("resolve config value failed", K(ret)); break; } ObString str_val; ObCollationType cast_coll_type = CS_TYPE_INVALID; if (OB_LIKELY(session_info_ != NULL)) { if (OB_SUCCESS != session_info_->get_collation_connection(cast_coll_type)) { LOG_WARN("fail to get collation_connection"); cast_coll_type = ObCharset::get_default_collation(ObCharset::get_default_charset()); } else {} } else { LOG_WARN("session is null"); cast_coll_type = ObCharset::get_system_collation(); } ObArenaAllocator allocator(ObModIds::OB_SQL_COMPILE); ObCastCtx cast_ctx(&allocator, NULL,//to varchar. this field will not be used. 0,//to varchar. this field will not be used. CM_NONE, cast_coll_type, NULL); EXPR_GET_VARCHAR_V2(val, str_val); if (OB_FAIL(ret)) { LOG_WARN("get varchar value failed", K(ret), K(val)); break; } else if (OB_FAIL(item.value_.assign(str_val))) { LOG_WARN("assign config value failed", K(ret), K(str_val)); break; } else if (session_info_ != NULL && action_node->children_[4] == NULL && OB_FAIL(check_param_valid(session_info_->get_effective_tenant_id(), ObString(item.name_.size(), item.name_.ptr()), ObString(item.value_.size(), item.value_.ptr())))) { LOG_WARN("fail to check param valid", K(ret)); } else if (NULL != action_node->children_[2]) { ObString comment(action_node->children_[2]->str_len_, action_node->children_[2]->str_value_); if (OB_FAIL(item.comment_.assign(comment))) { LOG_WARN("assign comment failed", K(comment), K(ret)); break; } } // ignore config scope // server or zone if (OB_SUCC(ret) && NULL != action_node->children_[3]) { const ParseNode *n = action_node->children_[3]; if (OB_FAIL(Util::resolve_server_or_zone(n, item))) { LOG_WARN("resolve server or zone failed", K(ret)); break; } } // if // tenant if (OB_SUCC(ret) && NULL != action_node->children_[4]) { const ParseNode *n = action_node->children_[4]; if (T_TENANT_NAME == n->type_) { uint64_t tenant_id = item.exec_tenant_id_; if (OB_SYS_TENANT_ID != tenant_id) { ret = OB_ERR_NO_PRIVILEGE; LOG_WARN("non sys tenant", K(tenant_id), K(ret)); break; } else { uint64_t tenant_node_id = OB_INVALID_ID; ObString tenant_name(n->children_[0]->str_len_, n->children_[0]->str_value_); ObString config_name(item.name_.size(), item.name_.ptr()); if (OB_FAIL(item.tenant_name_.assign(tenant_name))) { LOG_WARN("assign tenant name failed", K(tenant_name), K(ret)); break; #ifdef OB_BUILD_TDE_SECURITY } else if (0 == config_name.case_compare(TDE_METHOD) || 0 == config_name.case_compare(EXTERNAL_KMS_INFO)) { if (OB_ISNULL(schema_checker_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema checker is null", K(ret)); } else if (OB_FAIL(schema_checker_->get_tenant_id(tenant_name, tenant_node_id))) { LOG_WARN("fail to get tenant id", K(ret)); } else if (OB_FAIL(check_param_valid(tenant_node_id, config_name, ObString(item.value_.size(), item.value_.ptr())))) { LOG_WARN("fail to check param valid", K(ret)); } #endif } } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("resolve tenant name failed", K(ret)); break; } } // if if (OB_SUCC(ret)) { bool is_backup_config = false; bool can_set_trace_control_info = false; int tmp_ret = OB_SUCCESS; tmp_ret = OB_E(EventTable::EN_ENABLE_SET_TRACE_CONTROL_INFO) OB_SUCCESS; if (OB_SUCCESS != tmp_ret) { can_set_trace_control_info = true; } share::ObBackupConfigChecker backup_config_checker; if (OB_FAIL(backup_config_checker.check_config_name(item.name_.ptr(), is_backup_config))) { LOG_WARN("fail to check is valid backup config", K(ret), "config_name", item.name_.ptr(), "config value", item.value_.ptr()); } else if (is_backup_config) { if (stmt->get_rpc_arg().is_valid() && !stmt->get_rpc_arg().is_backup_config_) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "backup configuration items cannot be set together with non data backup configuration items"); LOG_WARN("backup configuration items cannot be set together with non data backup configuration items", K(ret)); } else { stmt->get_rpc_arg().is_backup_config_ = true; } } else if (stmt->get_rpc_arg().is_valid() && stmt->get_rpc_arg().is_backup_config_) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "backup configuration items cannot be set together with non data backup configuration items"); LOG_WARN("backup configuration items cannot be set together with non data backup configuration items", K(ret)); } if (OB_FAIL(ret)) { } else if (OB_FAIL(stmt->get_rpc_arg().items_.push_back(item))) { LOG_WARN("add config item failed", K(ret), K(item)); } else if (0 == STRCMP(item.name_.ptr(), Ob_STR_BACKUP_REGION)) { if (OB_FAIL(check_backup_region(item.value_.str()))) { LOG_WARN("failed to check backup dest", K(ret)); } } else if (0 == STRCMP(item.name_.ptr(), OB_STR_BACKUP_ZONE)) { if (OB_FAIL(check_backup_zone(item.value_.str()))) { LOG_WARN("failed to check backup dest", K(ret)); } } else if (0 == STRCMP(item.name_.ptr(), CLUSTER_ID)) { ret = OB_OP_NOT_ALLOW; LOG_WARN("cluster_id is not allowed to modify"); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "alter the parameter cluster_id"); } else if (0 == STRCMP(item.name_.ptr(), QUERY_RESPPONSE_TIME_FLUSH)) { if(OB_FAIL(observer::ObRSTCollector::get_instance().flush_query_response_time(item.exec_tenant_id_, item.value_.str()))){ LOG_WARN("set query response time flush", K(ret)); } } else if (0 == STRCMP(item.name_.ptr(), QUERY_RESPPONSE_TIME_STATS)) { if(OB_FAIL(observer::ObRSTCollector::get_instance().control_query_response_time(item.exec_tenant_id_, item.value_.str()))){ LOG_WARN("set query response time stats", K(ret)); } } else if (!can_set_trace_control_info && session_info_ != NULL && 0 == STRCMP(item.name_.ptr(), OB_STR_TRC_CONTROL_INFO) && !session_info_->is_inner()) { ret = OB_OP_NOT_ALLOW; LOG_WARN("_trace_control_info is not allowed to modify"); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "alter the parameter _trace_control_info"); } } } } } } } } } return ret; } int ObSetConfigResolver::check_param_valid(int64_t tenant_id , const ObString &name, const ObString &value) { int ret = OB_SUCCESS; if (tenant_id == OB_SYS_TENANT_ID) { if (0 == name.case_compare(SSL_EXTERNAL_KMS_INFO)) { #ifndef OB_BUILD_TDE_SECURITY ret = OB_NOT_SUPPORTED; #else share::ObSSLClient client; if (OB_FAIL(client.init(value.ptr(), value.length()))) { OB_LOG(WARN, "ssl client init", K(ret), K(value)); } else if (OB_FAIL(client.check_param_valid())) { OB_LOG(WARN, "ssl client param is not valid", K(ret)); } #endif } else if (0 == name.case_compare("ssl_client_authentication") && (0 == value.case_compare("1") || 0 == value.case_compare("ON") || 0 == value.case_compare("TRUE"))) { ObString ssl_config(GCONF.ssl_external_kms_info.str()); if (!ssl_config.empty()) { #ifndef OB_BUILD_TDE_SECURITY ret = OB_NOT_SUPPORTED; #else share::ObSSLClient client; if (OB_FAIL(client.init(ssl_config.ptr(), ssl_config.length()))) { OB_LOG(WARN, "kms client init", K(ret), K(ssl_config)); } else if (OB_FAIL(client.check_param_valid())) { OB_LOG(WARN, "kms client param is not valid", K(ret)); } #endif } else { if (EASY_OK != easy_ssl_ob_config_check(OB_SSL_CA_FILE, OB_SSL_CERT_FILE, OB_SSL_KEY_FILE, NULL, NULL, true, false)) { ret = OB_INVALID_CONFIG; LOG_WARN("key and cert not match", K(ret)); LOG_USER_ERROR(OB_INVALID_CONFIG, "key and cert not match"); } } } else if (0 == name.case_compare("_ob_ssl_invited_nodes")) { if (OB_ISNULL(GCTX.locality_manager_)) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("locality manager is null", K(ret), KP(GCTX.locality_manager_)); } else if (FALSE_IT(GCTX.locality_manager_->set_ssl_invited_nodes(value))) { } #ifdef ERRSIM if (OB_SUCCESS != (ret = OB_E(EventTable::EN_SSL_INVITE_NODES_FAILED) OB_SUCCESS)) { LOG_WARN("ERRSIM, fail to set ssl invite node", K(ret)); } #endif } else if (0 == name.case_compare("_load_tde_encrypt_engine")) { if (OB_FAIL(share::ObTdeEncryptEngineLoader::get_instance().load(value))) { LOG_WARN("load antsm-engine failed", K(ret)); } } } #ifdef OB_BUILD_TDE_SECURITY if (OB_SUCC(ret)) { if (0 == name.case_compare("tde_method")) { ObString tde_method; uint64_t compat_version = 0; if (!ObTdeMethodUtil::is_valid(value)) { ret = OB_NOT_SUPPORTED; LOG_WARN("not supported other method", K(value), K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "alter invalid tde_method"); } else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) { LOG_WARN("fail to get data version", KR(ret), K(tenant_id)); } else if (compat_version < DATA_VERSION_4_2_1_0 && ObTdeMethodUtil::is_aes256_algorithm(value)) { ret = OB_NOT_SUPPORTED; LOG_WARN("encrypt table key with aes256 is not supported", K(ret), K(value)); } else if (OB_FAIL(share::ObEncryptionUtil::get_tde_method(tenant_id, tde_method))) { LOG_WARN("fail to check tenant is method internal", K(ret)); } else if (0 != tde_method.case_compare("none") && 0 != value.case_compare(tde_method)) { // tde_method修改规则 // 当主密钥已经存在于租户内, 不允许修改为其他类型. // 主备库场景放开此限制, 检查主密钥的类型是否和要修改的类型一致. ObSchemaGetterGuard schema_guard; const share::schema::ObKeystoreSchema *keystore_schema = NULL; if (OB_ISNULL(GCTX.schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema service is empty"); } else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard( tenant_id, schema_guard))) { LOG_WARN("get_schema_guard failed"); } else if (OB_FAIL(schema_guard.get_keystore_schema(tenant_id, keystore_schema))) { LOG_WARN("fail get keystore schema", K(ret)); } else if (OB_ISNULL(keystore_schema)) { ret = OB_OBJECT_NAME_NOT_EXIST; LOG_WARN("fail to get keystore schema", K(ret)); } else if (0 != keystore_schema->get_master_key_id()) { if (!GCTX.is_standby_cluster()) { ret = OB_NOT_SUPPORTED; LOG_WARN("alter tde method is not support", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "alter tde method with master key exists"); } else if (0 == keystore_schema->get_master_key().case_compare("kms") && 0 == value.case_compare("bkmi")) { /*do nothing*/ } else if (0 == keystore_schema->get_master_key().case_compare(value)) { /*do nothing*/ } else if (0 == value.case_compare("internal")) { /*do nothing*/ } else { ret = OB_NOT_SUPPORTED; LOG_WARN("alter tde method is not support", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "alter tde method with master key exists"); } } } } else if (0 == name.case_compare(EXTERNAL_KMS_INFO)) { ObString tde_method; ObKmsClient *client = NULL; ObArenaAllocator allocator(ObModIds::OB_SQL_COMPILE); if (OB_FAIL(share::ObEncryptionUtil::get_tde_method(tenant_id, tde_method))) { LOG_WARN("fail to get method internal", K(ret)); } else if (OB_FAIL(ObKmsClientUtil::get_kms_client(allocator, tde_method, client))) { LOG_WARN("fail to get kms client", K(tde_method), K(ret)); } else if (OB_ISNULL(client)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("kms_client is null", K(tde_method), K(ret)); } else if (OB_FAIL(client->init(value.ptr(), value.length()))) { LOG_WARN("the json str is not valid", K(ret)); } } } #endif return ret; } int ObSetTPResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_ALTER_SYSTEM_SETTP != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ALTER_SYSTEM", "type", get_type_name(parse_tree.type_)); } else { if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { const ParseNode *list_node = parse_tree.children_[0]; if (OB_UNLIKELY(NULL == list_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("list_node should not be null"); } else { ObSetTPStmt *stmt = create_stmt(); if (OB_UNLIKELY(NULL == stmt)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create stmt failed"); } else { for (int64_t i = 0; OB_SUCC(ret) && i < list_node->num_child_; ++i) { if (OB_UNLIKELY(NULL == list_node->children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); break; } const ParseNode *action_node = list_node->children_[i]; if (OB_ISNULL(action_node) || OB_ISNULL(action_node->children_) || OB_ISNULL(action_node->children_[0])) { continue; } const ParseNode *value = action_node->children_[0]; switch (action_node->type_) { case T_TP_NO: { // event no stmt->get_rpc_arg().event_no_ = value->value_; } break; case T_TP_NAME: { stmt->get_rpc_arg().event_name_.assign_ptr( value->str_value_, static_cast(value->str_len_)); break; } case T_OCCUR: { // occurrence if (value->value_ > 0) { stmt->get_rpc_arg().occur_ = value->value_; } else { ret = OB_INVALID_ARGUMENT; } } break; case T_TRIGGER_MODE: { // trigger frequency if (T_INT == value->type_) { if (value->value_ < 0) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid argument", K(value->value_)); } else { stmt->get_rpc_arg().trigger_freq_ = value->value_; } } } break; case T_ERROR_CODE: { // error code if (value->value_ > 0) { stmt->get_rpc_arg().error_code_ = -value->value_; } else { stmt->get_rpc_arg().error_code_ = value->value_; } } break; case T_TP_COND: { // condition stmt->get_rpc_arg().cond_ = value->value_; } break; default: break; } } if (OB_SUCC(ret) && (2 <= parse_tree.num_child_) && (NULL != parse_tree.children_[1])) { if (OB_FAIL(Util::resolve_server_or_zone(parse_tree.children_[1], stmt->get_rpc_arg()))) { LOG_WARN("failed to resolve_server_or_zone", K(ret)); } } } LOG_INFO("set tp", K(stmt->get_rpc_arg())); } } } return ret; } int ObClearLocationCacheResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_CLEAR_LOCATION_CACHE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_CLEAR_LOCATION_CACHE", "type", get_type_name(parse_tree.type_)); } else { ObClearLocationCacheStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObClearLocationCacheStmt failed"); } else { stmt_ = stmt; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("dhildren should not be null"); } else if (OB_FAIL(Util::resolve_server_or_zone(parse_tree.children_[0], stmt->get_rpc_arg()))) { LOG_WARN("resolve server or zone failed", K(ret)); } } } return ret; } int ObReloadGtsResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_RELOAD_GTS != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_RELOAD_GTS", "type", get_type_name(parse_tree.type_)); } else { ret = OB_NOT_SUPPORTED; LOG_WARN("reload gts not supported", KR(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "reload gts command"); } return ret; } int ObReloadUnitResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_RELOAD_UNIT != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_RELOAD_UNIT", "type", get_type_name(parse_tree.type_)); } else { ObReloadUnitStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObReloadUnitStmt failed"); } else { stmt_ = stmt; } } return ret; } int ObReloadServerResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_RELOAD_SERVER != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_RELOAD_SERVER", "type", get_type_name(parse_tree.type_)); } else { ObReloadServerStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObReloadServerStmt failed"); } else { stmt_ = stmt; } } return ret; } int ObReloadZoneResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_RELOAD_ZONE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_RELOAD_ZONE", "type", get_type_name(parse_tree.type_)); } else { ObReloadZoneStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObReloadZoneStmt failed"); } else { stmt_ = stmt; } } return ret; } int ObClearMergeErrorResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObSQLSessionInfo* sess = params_.session_info_; if (OB_UNLIKELY(T_CLEAR_MERGE_ERROR != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_CLEAR_MERGE_ERROR", "type", get_type_name(parse_tree.type_)); } else { ObClearMergeErrorStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObClearMergeErrorStmt failed"); } else { stmt_ = stmt; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { const uint64_t cur_tenant_id = sess->get_effective_tenant_id(); ParseNode *tenants_node = parse_tree.children_[0]; if (NULL != tenants_node) { if (OB_SYS_TENANT_ID != cur_tenant_id) { ret = OB_ERR_NO_PRIVILEGE; LOG_WARN("Only sys tenant can add suffix opt(tenant=name)", KR(ret), K(cur_tenant_id)); } else if (T_TENANT_LIST != tenants_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_TENANT_LIST", "type", get_type_name(tenants_node->type_)); } else { bool affect_all = false; bool affect_all_user = false; bool affect_all_meta = false; const int64_t child_num = tenants_node->num_child_; if (OB_UNLIKELY(nullptr == tenants_node->children_) || OB_UNLIKELY(0 == child_num)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children of tenant should not be null", KR(ret), K(child_num)); } else if (OB_FAIL(Util::resolve_tenant(*tenants_node, cur_tenant_id, stmt->get_rpc_arg().tenant_ids_, affect_all, affect_all_user, affect_all_meta))) { LOG_WARN("fail to resolve tenant", KR(ret), K(cur_tenant_id)); } else if (affect_all || affect_all_user || affect_all_meta) { if ((true == affect_all && true == affect_all_user) || (true == affect_all && true == affect_all_meta) || (true == affect_all_user && true == affect_all_meta)) { ret = OB_NOT_SUPPORTED; LOG_WARN("only one of affect_all,affect_all_user,affect_all_meta can be true", KR(ret), K(affect_all), K(affect_all_user), K(affect_all_meta)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "all/all_user/all_meta in combination with other names is"); } else { if (affect_all || affect_all_user) { stmt->get_rpc_arg().affect_all_user_ = true; } else { stmt->get_rpc_arg().affect_all_meta_ = true; } } } } } else { if (OB_FAIL(stmt->get_rpc_arg().tenant_ids_.push_back(cur_tenant_id))) { LOG_WARN("fail to push back own tenant id"); } } } } } return ret; } int ObMigrateUnitResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_MIGRATE_UNIT != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_MIGRATE_UNIT", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { ObMigrateUnitStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObMigrateUnitStmt failed"); } else { stmt_ = stmt; ParseNode *node = parse_tree.children_[0]; if (OB_UNLIKELY(NULL == node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null"); } else { stmt->get_rpc_arg().unit_id_ = node->value_; if (NULL == parse_tree.children_[1] ) { stmt->get_rpc_arg().is_cancel_ = true ; } else if (OB_FAIL(Util::resolve_server_value(parse_tree.children_[1], stmt->get_rpc_arg().destination_))) { LOG_WARN("resolve server failed", K(ret)); } } } } return ret; } int ObAddArbitrationServiceResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; #ifndef OB_BUILD_ARBITRATION UNUSEDx(parse_tree); ret = OB_NOT_SUPPORTED; LOG_WARN("not supported in CE version", KR(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "add arbitration service in CE version"); #else if (OB_UNLIKELY(T_ADD_ARBITRATION_SERVICE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ADD_ARBITRATION_SERVICE", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { ObAddArbitrationServiceStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObAddArbitrationServiceStmt failed"); } else { stmt_ = stmt; ObString dest(""); if (OB_FAIL(Util::resolve_string(parse_tree.children_[0], dest))) { LOG_WARN("resolve string failed", K(ret)); } else if (OB_FAIL(stmt->get_rpc_arg().init(dest))) { LOG_WARN("fail to init arg", K(ret), K(dest)); } } } #endif return ret; } int ObRemoveArbitrationServiceResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; #ifndef OB_BUILD_ARBITRATION UNUSEDx(parse_tree); ret = OB_NOT_SUPPORTED; LOG_WARN("not supported in CE version", KR(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "remove arbitration service in CE version"); #else if (OB_UNLIKELY(T_REMOVE_ARBITRATION_SERVICE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_REMOVE_ARBITRATION_SERVICE", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { ObRemoveArbitrationServiceStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObRemoveArbitrationServiceStmt failed"); } else { stmt_ = stmt; ObString dest(""); if (OB_FAIL(Util::resolve_string(parse_tree.children_[0], dest))) { LOG_WARN("resolve string failed", K(ret)); } else if (OB_FAIL(stmt->get_rpc_arg().init(dest))) { LOG_WARN("fail to init arg", K(ret), K(dest)); } } } #endif return ret; } int ObReplaceArbitrationServiceResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; #ifndef OB_BUILD_ARBITRATION UNUSEDx(parse_tree); ret = OB_NOT_SUPPORTED; LOG_WARN("not supported in CE version", KR(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "replace arbitration service in CE version"); #else if (OB_UNLIKELY(T_REPLACE_ARBITRATION_SERVICE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_REPLACE_ARBITRATION_SERVICE", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { ObReplaceArbitrationServiceStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObReplaceArbitrationServiceStmt failed"); } else { stmt_ = stmt; ObString arbitration_service(""); ObString previous_arbitration_service(""); if (OB_FAIL(Util::resolve_string(parse_tree.children_[0], previous_arbitration_service))) { LOG_WARN("resolve string failed", K(ret)); } else if (OB_FAIL(Util::resolve_string(parse_tree.children_[1], arbitration_service))) { LOG_WARN("resolve string for previous arb service failed", K(ret)); } else if (OB_FAIL(stmt->get_rpc_arg().init(arbitration_service, previous_arbitration_service))) { LOG_WARN("fail to init arg", KR(ret), K(arbitration_service), K(previous_arbitration_service)); } } } #endif return ret; } int ObUpgradeVirtualSchemaResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_UPGRADE_VIRTUAL_SCHEMA != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_UPGRADE_VIRTUAL_SCHEMA", "type", get_type_name(parse_tree.type_)); } else { ObUpgradeVirtualSchemaStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObUpgradeVirtualSchemaStmt failed"); } else { stmt_ = stmt; } } return ret; } int ObAdminUpgradeCmdResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_ADMIN_UPGRADE_CMD != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_UPGRADE_CMD", "type", get_type_name(parse_tree.type_)); } else { ObAdminUpgradeCmdStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObAdminUpgradeCmdStmt failed", K(ret)); } else { stmt_ = stmt; if (OB_ISNULL(parse_tree.children_) || 1 != parse_tree.num_child_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be NULL and number of children should be one", K(ret)); } else { ParseNode *op = parse_tree.children_[0]; if (OB_ISNULL(op)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("cmd should not be NULL", K(ret)); } else if (OB_UNLIKELY(T_INT != op->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_INT", K(ret), "type", get_type_name(op->type_)); } else { stmt->set_op(static_cast(op->value_)); } } } } return ret; } int ObAdminRollingUpgradeCmdResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_ADMIN_ROLLING_UPGRADE_CMD != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ROLLING_UPGRADE_CMD", "type", get_type_name(parse_tree.type_)); } else { ObAdminRollingUpgradeCmdStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObAdminRollingUpgradeCmdStmt failed", K(ret)); } else { stmt_ = stmt; if (OB_ISNULL(parse_tree.children_) || 1 != parse_tree.num_child_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be NULL and number of children should be one", K(ret)); } else { ParseNode *op = parse_tree.children_[0]; if (OB_ISNULL(op)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("cmd should not be NULL", K(ret)); } else if (OB_UNLIKELY(T_INT != op->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_INT", K(ret), "type", get_type_name(op->type_)); } else { stmt->set_op(static_cast(op->value_)); } } } } return ret; } int ObPhysicalRestoreTenantResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObPhysicalRestoreTenantStmt *stmt = nullptr; if (OB_UNLIKELY(T_PHYSICAL_RESTORE_TENANT != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_PHYSICAL_RESTORE_TENANT", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else if (OB_UNLIKELY(7 != parse_tree.num_child_ && 2 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("num of children not match", K(ret), "child_num", parse_tree.num_child_); } else if (OB_ISNULL(stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObPhysicalRestoreTenantStmt failed"); } else if (OB_FALSE_IT(stmt_ = stmt)) { } else if (2 == parse_tree.num_child_) { // parse preview stmt->set_is_preview(true); stmt->get_rpc_arg().initiator_tenant_id_ = OB_SYS_TENANT_ID; const ParseNode *time_node = parse_tree.children_[1]; if (OB_FAIL(Util::resolve_string(parse_tree.children_[0], stmt->get_rpc_arg().uri_))) { LOG_WARN("resolve string failed", K(ret)); } else if (OB_ISNULL(parse_tree.children_[1])) { stmt->get_rpc_arg().with_restore_scn_ = false; } else if (0/*timestamp*/ == time_node->children_[0]->value_) { stmt->get_rpc_arg().restore_timestamp_.assign_ptr(time_node->children_[1]->str_value_, time_node->children_[1]->str_len_); stmt->get_rpc_arg().with_restore_scn_ = false; } else if (1/*timestamp*/ == time_node->children_[0]->value_) { if (share::OB_BASE_SCN_TS_NS >= time_node->children_[1]->value_) { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "until scn, it should be positive integer"); LOG_WARN("until scn, it should be positive integer", KR(ret), K(time_node->children_[1]->value_)); } else if (OB_FAIL(stmt->get_rpc_arg().restore_scn_.convert_for_sql(time_node->children_[1]->value_))) { LOG_WARN("failed to convert scn", K(ret)); } else { stmt->get_rpc_arg().with_restore_scn_ = true; } } } else { stmt->set_is_preview(false); stmt->get_rpc_arg().initiator_tenant_id_ = OB_SYS_TENANT_ID; if(OB_FAIL(Util::resolve_relation_name(parse_tree.children_[0], stmt->get_rpc_arg().tenant_name_))) { LOG_WARN("resolve tenant_name failed", K(ret)); } else { const ObString &tenant_name = stmt->get_rpc_arg().tenant_name_; if (OB_FAIL(ObResolverUtils::check_not_supported_tenant_name(tenant_name))) { LOG_WARN("since 4.2.1, naming a tenant as all/all_user/all_meta is not supported", KR(ret), K(tenant_name)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "since 4.2.1, naming a tenant as all/all_user/all_meta is"); } else if (OB_NOT_NULL(parse_tree.children_[1])) { if (session_info_->user_variable_exists(OB_RESTORE_SOURCE_NAME_SESSION_STR)) { ret = OB_NOT_SUPPORTED; LOG_WARN("invalid sql syntax", KR(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "should not have backup_dest and restore_source at the same time"); } else if (OB_FAIL(Util::resolve_string(parse_tree.children_[1], stmt->get_rpc_arg().uri_))) { LOG_WARN("resolve string failed", K(ret)); } } } if (OB_FAIL(ret)) { // do nothing } else if (OB_NOT_NULL(parse_tree.children_[4]) && OB_FAIL(Util::resolve_string(parse_tree.children_[4], stmt->get_rpc_arg().encrypt_key_))) { LOG_WARN("failed to resolve encrypt key", K(ret)); } else if (OB_NOT_NULL(parse_tree.children_[5])) { ParseNode *kms_node = parse_tree.children_[5]; if (2 != kms_node->num_child_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("num of children not match", K(ret), "child_num", kms_node->num_child_); } else if (OB_ISNULL(kms_node->children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("kms uri should not be NULL", K(ret)); } else if (OB_FAIL(Util::resolve_string(kms_node->children_[0], stmt->get_rpc_arg().kms_uri_))) { LOG_WARN("failed to resolve kms uri", K(ret)); } else if (OB_NOT_NULL(kms_node->children_[1]) && OB_FAIL(Util::resolve_string(kms_node->children_[1], stmt->get_rpc_arg().kms_encrypt_key_))) { LOG_WARN("failed to resolve kms encrypt key", K(ret)); } } ParseNode *description_node = parse_tree.children_[6]; if (OB_FAIL(ret)) { // do nothing } else if (OB_FAIL(Util::resolve_string(parse_tree.children_[3], stmt->get_rpc_arg().restore_option_))) { LOG_WARN("resolve string failed", K(ret)); } else if (OB_NOT_NULL(description_node) && OB_FAIL(Util::resolve_string(description_node, stmt->get_rpc_arg().description_))) { LOG_WARN("fail to resolve description", K(ret)); #ifdef OB_BUILD_TDE_SECURITY } else if (OB_FAIL(resolve_kms_encrypt_info(stmt->get_rpc_arg().restore_option_))) { LOG_WARN("fail to resolve encrypt info", K(ret)); #endif } else if (OB_FAIL(resolve_decryption_passwd(stmt->get_rpc_arg()))) { LOG_WARN("failed to resolve decrytion passwd", K(ret)); } else if (OB_FAIL(resolve_restore_source_array(stmt->get_rpc_arg()))) { LOG_WARN("failed to resolve restore source array", K(ret)); } else { // resolve datetime const ParseNode *time_node = parse_tree.children_[2]; if (OB_ISNULL(parse_tree.children_[2])) { stmt->get_rpc_arg().with_restore_scn_ = false; } else if (0/*timestamp*/ == time_node->children_[0]->value_) { stmt->get_rpc_arg().restore_timestamp_.assign_ptr(time_node->children_[1]->str_value_, time_node->children_[1]->str_len_); stmt->get_rpc_arg().with_restore_scn_ = false; } else if (1/*timestamp*/ == time_node->children_[0]->value_) { if (share::OB_BASE_SCN_TS_NS >= time_node->children_[1]->value_) { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "until scn, it should be positive integer"); LOG_WARN("until scn, it should be positive integer", KR(ret), K(time_node->children_[1]->value_)); } else if (OB_FAIL(stmt->get_rpc_arg().restore_scn_.convert_for_sql(time_node->children_[1]->value_))) { LOG_WARN("failed to convert scn", K(ret)); } else { stmt->get_rpc_arg().with_restore_scn_ = true; } } } } return ret; } #ifdef OB_BUILD_TDE_SECURITY int ObPhysicalRestoreTenantResolver::resolve_kms_encrypt_info(common::ObString store_option) { int ret = OB_SUCCESS; const char *encrypt_option_str = "kms_encrypt=true"; ObString kms_var("kms_encrypt_info"); int64_t encrypt_opt_str_len = strlen(encrypt_option_str); bool is_kms_encrypt = false; for (int i = 0; i <= store_option.length() - encrypt_opt_str_len; ++i) { if (0 == STRNCASECMP(store_option.ptr() + i, encrypt_option_str, encrypt_opt_str_len)) { is_kms_encrypt = true; break; } } if (is_kms_encrypt) { ObObj value; if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session is null" , K(ret)); } else if (OB_FAIL(session_info_->get_user_variable_value(kms_var, value))) { LOG_WARN("fail to get user variable", K(ret)); } else { ObPhysicalRestoreTenantStmt *stmt = static_cast(stmt_); stmt->get_rpc_arg().kms_info_ = value.get_varchar(); //浅拷贝即可 bool is_valid = false; if (OB_FAIL(check_kms_info_valid(stmt->get_rpc_arg().kms_info_, is_valid))) { LOG_WARN("fail to check kms info valid", K(ret)); } else if (!is_valid) { ret = OB_INVALID_ARGUMENT; LOG_WARN("kms info is not valid", K(ret)); } } } return ret; } int ObPhysicalRestoreTenantResolver::check_kms_info_valid(const ObString &kms_info, bool &is_valid) { int ret = OB_SUCCESS; if (kms_info.length() > 4000 || kms_info.length() < 0) { is_valid = false; } else { is_valid = true; } return ret; } #endif int ObPhysicalRestoreTenantResolver::resolve_decryption_passwd( ObPhysicalRestoreTenantArg &arg) { int ret = OB_SUCCESS; ObObj value; if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session is null" , K(ret)); } else if (!session_info_->user_variable_exists(OB_BACKUP_DECRYPTION_PASSWD_ARRAY_SESSION_STR)) { LOG_INFO("no decryption passwd is specified"); arg.passwd_array_.reset(); } else if (OB_FAIL(session_info_->get_user_variable_value( OB_BACKUP_DECRYPTION_PASSWD_ARRAY_SESSION_STR, value))) { LOG_WARN("fail to get user variable", K(ret)); } else { arg.passwd_array_ = value.get_varchar(); LOG_INFO("succeed to resolve_decryption_passwd", "passwd", arg.passwd_array_); } return ret; } int ObPhysicalRestoreTenantResolver::resolve_restore_source_array( obrpc::ObPhysicalRestoreTenantArg &arg) { int ret = OB_SUCCESS; ObObj value; if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session is null" , K(ret)); } else if (!session_info_->user_variable_exists(OB_RESTORE_SOURCE_NAME_SESSION_STR)) { LOG_INFO("no restore source is specified"); arg.multi_uri_.reset(); } else if (OB_FAIL(session_info_->get_user_variable_value( OB_RESTORE_SOURCE_NAME_SESSION_STR, value))) { LOG_WARN("failed to get user variable", KR(ret)); } else { arg.multi_uri_ = value.get_varchar(); LOG_INFO("succeed to resolve_restore_source_array", "multi_uri", arg.multi_uri_); } return ret; } int ObRunJobResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_RUN_JOB != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_RUN_JOB", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { ObRunJobStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObRunJobStmt failed"); } else { stmt_ = stmt; if (OB_FAIL(Util::resolve_string(parse_tree.children_[0], stmt->get_rpc_arg().job_))) { LOG_WARN("resolve string failed", K(ret)); } else if (OB_FAIL(Util::resolve_server_or_zone(parse_tree.children_[1], stmt->get_rpc_arg()))) { LOG_WARN("resolve server or zone failed", K(ret)); } } } return ret; } int ObRunUpgradeJobResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_ADMIN_RUN_UPGRADE_JOB != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ADMIN_RUN_UPGRADE_JOB", KR(ret), "type", get_type_name(parse_tree.type_)); } else if (OB_ISNULL(parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", KR(ret)); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info is null", KR(ret)); } else { ObRunUpgradeJobStmt *stmt = create_stmt(); if (OB_ISNULL(stmt)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObRunUpgradeJobStmt failed", KR(ret)); } else { stmt_ = stmt; // 1. parse action ObString str; uint64_t version = OB_INVALID_VERSION; if (OB_FAIL(Util::resolve_string(parse_tree.children_[0], str))) { LOG_WARN("resolve string failed", KR(ret)); } else if (0 == str.case_compare(rootserver::ObRsJobTableOperator::get_job_type_str( rootserver::JOB_TYPE_UPGRADE_BEGIN))) { stmt->get_rpc_arg().action_ = obrpc::ObUpgradeJobArg::UPGRADE_BEGIN; } else if (0 == str.case_compare(rootserver::ObRsJobTableOperator::get_job_type_str( rootserver::JOB_TYPE_UPGRADE_SYSTEM_VARIABLE))) { stmt->get_rpc_arg().action_ = obrpc::ObUpgradeJobArg::UPGRADE_SYSTEM_VARIABLE; } else if (0 == str.case_compare(rootserver::ObRsJobTableOperator::get_job_type_str( rootserver::JOB_TYPE_UPGRADE_SYSTEM_TABLE))) { stmt->get_rpc_arg().action_ = obrpc::ObUpgradeJobArg::UPGRADE_SYSTEM_TABLE; } else if (0 == str.case_compare(rootserver::ObRsJobTableOperator::get_job_type_str( rootserver::JOB_TYPE_UPGRADE_VIRTUAL_SCHEMA))) { stmt->get_rpc_arg().action_ = obrpc::ObUpgradeJobArg::UPGRADE_VIRTUAL_SCHEMA; } else if (0 == str.case_compare(rootserver::ObRsJobTableOperator::get_job_type_str( rootserver::JOB_TYPE_UPGRADE_SYSTEM_PACKAGE))) { stmt->get_rpc_arg().action_ = obrpc::ObUpgradeJobArg::UPGRADE_SYSTEM_PACKAGE; } else if (0 == str.case_compare(rootserver::ObRsJobTableOperator::get_job_type_str( rootserver::JOB_TYPE_UPGRADE_ALL_POST_ACTION))) { stmt->get_rpc_arg().action_ = obrpc::ObUpgradeJobArg::UPGRADE_ALL_POST_ACTION; } else if (0 == str.case_compare(rootserver::ObRsJobTableOperator::get_job_type_str( rootserver::JOB_TYPE_UPGRADE_INSPECTION))) { stmt->get_rpc_arg().action_ = obrpc::ObUpgradeJobArg::UPGRADE_INSPECTION; } else if (0 == str.case_compare(rootserver::ObRsJobTableOperator::get_job_type_str( rootserver::JOB_TYPE_UPGRADE_END))) { stmt->get_rpc_arg().action_ = obrpc::ObUpgradeJobArg::UPGRADE_END; } else if (0 == str.case_compare(rootserver::ObRsJobTableOperator::get_job_type_str( rootserver::JOB_TYPE_UPGRADE_ALL))) { stmt->get_rpc_arg().action_ = obrpc::ObUpgradeJobArg::UPGRADE_ALL; } else { // UPGRADE_POST_ACTION if (OB_FAIL(ObClusterVersion::get_version(str, version))) { LOG_WARN("fail to get version", KR(ret), K(str)); } else { stmt->get_rpc_arg().action_ = obrpc::ObUpgradeJobArg::UPGRADE_POST_ACTION; stmt->get_rpc_arg().version_ = static_cast(version); } } // 2. parse tenant_ids if (OB_SUCC(ret) && parse_tree.num_child_ >= 2 && OB_NOT_NULL(parse_tree.children_[1])) { ParseNode *tenants_node = parse_tree.children_[1]; bool affect_all = false; bool affect_all_user = false; bool affect_all_meta = false; const int64_t child_num = tenants_node->num_child_; const uint64_t cur_tenant_id = session_info_->get_effective_tenant_id(); ObSArray &tenant_ids = stmt->get_rpc_arg().tenant_ids_; if (T_TENANT_LIST != tenants_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_TENANT_LIST", KR(ret), "type", get_type_name(tenants_node->type_)); } else if (OB_ISNULL(tenants_node->children_) || OB_UNLIKELY(0 == child_num)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children of tenant should not be null", KR(ret), K(child_num)); } else if (OB_FAIL(Util::resolve_tenant(*tenants_node, cur_tenant_id, tenant_ids, affect_all, affect_all_user, affect_all_meta))) { LOG_WARN("fail to resolve tenant", KR(ret), K(cur_tenant_id)); } else if (affect_all_user || affect_all_meta) { ret = OB_NOT_SUPPORTED; LOG_WARN("all_user/all_meta is not supported by ALTER SYSTEM RUN UPGRADE JOB", KR(ret), K(affect_all_user), K(affect_all_meta)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "use all_user/all_meta in 'ALTER SYSTEM RUN UPGRADE JOB' syntax is"); } else if (affect_all && 0 != tenant_ids.count()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("tenant_ids should be empty when specify tenant = all", KR(ret)); } else if (obrpc::ObUpgradeJobArg::UPGRADE_SYSTEM_PACKAGE == stmt->get_rpc_arg().action_) { if ((tenant_ids.count() > 1) || (1 == tenant_ids.count() && !is_sys_tenant(tenant_ids.at(0)))) { ret = OB_NOT_SUPPORTED; LOG_WARN("Only system tenant can run UPGRADE_SYSTEM_PACKAGE Job", KR(ret), K(tenant_ids)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Non-sys tenant run UPGRADE_SYSTEM_PACKAGE job"); } } } } } return ret; } int ObStopUpgradeJobResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_ADMIN_STOP_UPGRADE_JOB != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ADMIN_STOP_UPGRADE_JOB", KR(ret), "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", KR(ret)); } else { ObStopUpgradeJobStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObStopUpgradeJobStmt failed", KR(ret)); } else { stmt_ = stmt; stmt->get_rpc_arg().action_ = obrpc::ObUpgradeJobArg::STOP_UPGRADE_JOB; } } return ret; } int ObSwitchRSRoleResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_SWITCH_RS_ROLE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_SWITCH_RS_ROLE", K(ret), "type", get_type_name(parse_tree.type_)); } else if (OB_ISNULL(parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("childern should noto be null", K(ret)); } else { ObSwitchRSRoleStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObSwitchRSRoleStmt failed", K(ret)); } else { stmt_ = stmt; ObAdminSwitchRSRoleArg &rpc_arg = stmt->get_rpc_arg(); ParseNode *role = parse_tree.children_[0]; if (OB_ISNULL(role)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("role should not be null", K(ret)); } else if (OB_UNLIKELY(T_INT != role->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_INT", K(ret), "type", get_type_name(role->type_)); } else { switch (role->value_) { case 0: { rpc_arg.role_ = LEADER; break; } case 1: { rpc_arg.role_ = FOLLOWER; break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected role value", K(ret), "value", role->value_); break; } } } if (OB_SUCC(ret)) { ParseNode *node = parse_tree.children_[1]; if (OB_ISNULL(node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node should not be null", K(ret)); } else { switch (node->type_) { case T_IP_PORT: { if (OB_FAIL(Util::resolve_server(node, rpc_arg.server_))) { LOG_WARN("resolve server failed", K(ret)); } break; } case T_ZONE: { if (OB_FAIL(Util::resolve_zone(node, rpc_arg.zone_))) { LOG_WARN("resolve zone failed", K(ret)); } break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected type", K(ret), "type", get_type_name(node->type_)); break; } } } } } } return ret; } int ObRefreshTimeZoneInfoResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_REFRESH_TIME_ZONE_INFO != parse_tree.type_) || OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_REFRESH_TIME_ZONE_INFO", "type", get_type_name(parse_tree.type_), K(session_info_)); } else { ObRefreshTimeZoneInfoStmt *refresh_time_zone_info_stmt = create_stmt(); if (OB_UNLIKELY(NULL == refresh_time_zone_info_stmt)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObRefreshTimeZoneInfoStmt failed", K(ret)); } else { refresh_time_zone_info_stmt->set_tenant_id(session_info_->get_effective_tenant_id()); stmt_ = refresh_time_zone_info_stmt; } } return ret; } // // /- T_INT(priority) // /| // T_ENABLE_SQL_THROTTLE -< // \| // \- T_SQL_THROTTLE_METRICS -< [ T_RT -> (decimal) // | T_CPU -> (decimal) // | T_IO -> (int) // | T_NETWORK -> (decimal) // | T_LOGICAL_READS -> (int) // ]+ // int ObEnableSqlThrottleResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObEnableSqlThrottleStmt *stmt = nullptr; if (OB_UNLIKELY(T_ENABLE_SQL_THROTTLE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ENABLE_SQL_THROTTLE", "type", get_type_name(parse_tree.type_)); } else if (OB_ISNULL(parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("parse_tree's children is null", K(ret)); } else if (2 != parse_tree.num_child_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("parse_tree's number of children doesn't match", K(ret)); } else { stmt = create_stmt(); if (nullptr == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObEnableSqlThrottleStmt failed"); } } if (OB_SUCC(ret)) { ParseNode *priority_node = parse_tree.children_[0]; if (nullptr != priority_node) { stmt->set_priority(priority_node->value_); } ParseNode *metrics_node = parse_tree.children_[1]; if (metrics_node != nullptr) { for (int i = 0; i < metrics_node->num_child_; i++) { ParseNode *node = metrics_node->children_[i]; ParseNode *valNode = node->children_[0]; switch (node->type_) { case T_RT: if (valNode->type_ == T_INT) { stmt->set_rt(static_cast(valNode->value_)); } else if (valNode->type_ == T_NUMBER) { stmt->set_rt(atof(valNode->str_value_)); } break; case T_CPU: if (valNode->type_ == T_INT) { stmt->set_cpu(static_cast(valNode->value_)); } else if (valNode->type_ == T_NUMBER) { stmt->set_cpu(atof(valNode->str_value_)); } break; case T_IO: stmt->set_io(valNode->value_); break; case T_NETWORK: if (valNode->type_ == T_INT) { stmt->set_network(static_cast(valNode->value_)); } else if (valNode->type_ == T_NUMBER) { stmt->set_network(atof(valNode->str_value_)); } break; case T_LOGICAL_READS: stmt->set_logical_reads(valNode->value_); break; case T_QUEUE_TIME: if (valNode->type_ == T_INT) { stmt->set_queue_time(static_cast(valNode->value_)); } else if (valNode->type_ == T_NUMBER) { stmt->set_queue_time(atof(valNode->str_value_)); } break; default: break; } } } } if (OB_SUCC(ret)) { stmt_ = stmt; } return ret; } int ObDisableSqlThrottleResolver::resolve(const ParseNode &parse_tree) { UNUSED(parse_tree); int ret = OB_SUCCESS; stmt_ = create_stmt(); return ret; } int ObCancelTaskResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_CANCEL_TASK != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_CANCEL_TASK", "type", get_type_name(parse_tree.type_)); } else if (OB_ISNULL(parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("parse_tree's children is null", K(ret)); } else { ObCancelTaskStmt *cancel_task = create_stmt(); if (NULL == cancel_task) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObCancelTaskStmt failed"); } else { stmt_ = cancel_task; ParseNode *cancel_type_node = parse_tree.children_[0]; ParseNode *task_id = parse_tree.children_[1]; share::ObSysTaskType task_type = MAX_SYS_TASK_TYPE; ObString task_id_str; if (OB_ISNULL(task_id)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("task_id node is null", K(ret)); } else if (OB_FAIL(Util::resolve_string(task_id, task_id_str))) { LOG_WARN("resolve string failed", K(ret)); } else if (NULL == cancel_type_node) { task_type = MAX_SYS_TASK_TYPE; } else { switch (cancel_type_node->value_) { case 1: { task_type = GROUP_MIGRATION_TASK; break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected cancel task type", K(ret), "value", cancel_type_node->value_); break; } } } if (OB_SUCC(ret)) { if (OB_FAIL(cancel_task->set_param(task_type, task_id_str))) { LOG_WARN("failed to set cancel task param", K(ret), K(task_type), K(task_id_str)); } } } } return ret; } int ObSetDiskValidResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_SET_DISK_VALID != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_SET_DISK_VALID", "type", get_type_name(parse_tree.type_)); } else { ObSetDiskValidStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObSetDiskValidStmt failed"); } else { stmt_ = stmt; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else { if (OB_FAIL(Util::resolve_server(parse_tree.children_[0], stmt->server_))) { LOG_WARN("resolve server failed", K(ret)); } else { // do nothing } } } } return ret; } int ObAlterDiskgroupAddDiskResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_ALTER_DISKGROUP_ADD_DISK != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ALTER_DISKGROUP_ADD_DISK", "type", get_type_name(parse_tree.type_)); } else { ObAddDiskStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObAddDiskStmt failed"); } else { stmt_ = stmt; ObAdminAddDiskArg &arg = stmt->arg_; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else if (OB_FAIL(Util::resolve_relation_name(parse_tree.children_[0], arg.diskgroup_name_))) { LOG_WARN("failed to resolve diskgroup_name", K(ret)); } else if (OB_FAIL(Util::resolve_string(parse_tree.children_[1], arg.disk_path_))) { LOG_WARN("failed to resolve disk_path", K(ret)); } else if (NULL != parse_tree.children_[2] && OB_FAIL(Util::resolve_string(parse_tree.children_[2], arg.alias_name_))) { LOG_WARN("failed to resolve alias name", K(ret)); } else if (OB_FAIL(Util::resolve_server(parse_tree.children_[3], arg.server_))) { LOG_WARN("failed to resolve server", K(ret)); } else if (NULL != parse_tree.children_[4] && OB_FAIL(Util::resolve_zone(parse_tree.children_[4], arg.zone_))) { LOG_WARN("failed to resolve zone", K(ret)); } else { LOG_INFO("succeed to resolve add disk arg", K(arg)); } } } return ret; } int ObAlterDiskgroupDropDiskResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_ALTER_DISKGROUP_DROP_DISK != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ALTER_DISKGROUP_DROP_DISK", "type", get_type_name(parse_tree.type_)); } else { ObDropDiskStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObDropDiskStmt failed"); } else { stmt_ = stmt; ObAdminDropDiskArg &arg = stmt->arg_; if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else if (OB_FAIL(Util::resolve_relation_name(parse_tree.children_[0], arg.diskgroup_name_))) { LOG_WARN("failed to resolve diskgroup_name", K(ret)); } else if (OB_FAIL(Util::resolve_string(parse_tree.children_[1], arg.alias_name_))) { LOG_WARN("failed to resolve alias name", K(ret)); } else if (OB_FAIL(Util::resolve_server(parse_tree.children_[2], arg.server_))) { LOG_WARN("failed to resolve server", K(ret)); } else if (NULL != parse_tree.children_[3] && OB_FAIL(Util::resolve_zone(parse_tree.children_[3], arg.zone_))) { LOG_WARN("failed to resolve zone", K(ret)); } else { LOG_INFO("succeed to resolve drop disk arg", K(arg)); } } } return ret; } int ObClearBalanceTaskResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ParseNode *tenants_node = NULL; ParseNode *zone_node = NULL; ParseNode *task_type_node = NULL; ObClearBalanceTaskStmt *clear_task_stmt = NULL; if (OB_UNLIKELY(T_CLEAR_BALANCE_TASK != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_CLEAR_BALANCE_TASK", "type", get_type_name(parse_tree.type_)); } else if (OB_ISNULL(parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("parse_tree's children is null", K(ret)); } else { clear_task_stmt = create_stmt(); if (NULL == clear_task_stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObClearBalanceTaskStmt failed"); } else { stmt_ = clear_task_stmt; tenants_node = parse_tree.children_[0]; zone_node = parse_tree.children_[1]; task_type_node = parse_tree.children_[2]; } } ObSchemaGetterGuard schema_guard; if (OB_SUCC(ret) && NULL != tenants_node) {//以租户为单位 if (T_TENANT_LIST != tenants_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get invalid tenant_name node", K(ret)); } else if (OB_UNLIKELY(NULL == tenants_node->children_) || OB_UNLIKELY(0 == tenants_node->num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children of tenant should not be null"); } else if (OB_ISNULL(GCTX.schema_service_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema service is empty"); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard( session_info_->get_effective_tenant_id(), schema_guard))) { LOG_WARN("get_schema_guard failed"); } else { common::ObIArray &tenant_ids = clear_task_stmt->get_tenant_ids(); uint64_t tenant_id = 0; ObString tenant_name; for (int64_t i = 0; OB_SUCC(ret) && i < tenants_node->num_child_; ++i) { ParseNode *node = tenants_node->children_[i]; if (OB_ISNULL(node)) { LOG_WARN("children of server_list should not be null"); } else { tenant_name.assign_ptr(node->str_value_, static_cast(node->str_len_)); if (OB_FAIL(schema_guard.get_tenant_id(tenant_name, tenant_id))) { LOG_WARN("tenant not exist", K(tenant_name)); } else if (OB_FAIL(tenant_ids.push_back(tenant_id))) { LOG_WARN("fail to push tenant id ", K(tenant_name), K(tenant_id)); } } tenant_name.reset(); } // end for } } //end if (NULL != tenants_node) if (OB_SUCC(ret) && NULL != zone_node) {//以zone为单位 if (T_ZONE_LIST != zone_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get invalid zone_name node", K(ret)); } else if (OB_UNLIKELY(NULL == zone_node->children_) || OB_UNLIKELY(0 == zone_node->num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children of zone should not be null"); } else { common::ObIArray &zone_names = clear_task_stmt->get_zone_names(); ObZone zone_name ; ObString parse_zone_name; for (int64_t i = 0; OB_SUCC(ret) && i < zone_node->num_child_; ++i) { ParseNode *node = zone_node->children_[i]; if (OB_ISNULL(node)) { LOG_WARN("children of server_list should not be null"); } else { parse_zone_name.assign_ptr(node->str_value_, static_cast(node->str_len_)); if (OB_FAIL(zone_name.assign(parse_zone_name))) { LOG_WARN("failed to assign zone name", K(ret), K(parse_zone_name)); } else if (OB_FAIL(zone_names.push_back(zone_name))) { LOG_WARN("failed to push back zone name", K(ret), K(zone_name)); } } parse_zone_name.reset(); zone_name.reset(); }//end for } }// end if (NULL != zone_node) if (OB_SUCC(ret)) { if (NULL == task_type_node) { clear_task_stmt->set_type(ObAdminClearBalanceTaskArg::ALL); } else if (T_BALANCE_TASK_TYPE != task_type_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get invalid type node", K(ret)); } else if (OB_UNLIKELY(NULL == task_type_node->children_) || OB_UNLIKELY(0 == task_type_node->num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children of node_type should not be null"); } else { clear_task_stmt->set_type(static_cast(task_type_node->children_[0]->value_)); } } return ret; } int ObChangeTenantResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_CHANGE_TENANT != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_CHANGE_TENANT", "type", get_type_name(parse_tree.type_)); } else if (OB_ISNULL(schema_checker_) || OB_ISNULL(schema_checker_->get_schema_guard())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema_checker or schema_guard is null", K(ret)); } else { ObChangeTenantStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObChangeTenantStmt failed"); } else { if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else if (OB_UNLIKELY(T_TENANT_NAME != parse_tree.children_[0]->type_ && T_TENANT_ID != parse_tree.children_[0]->type_)) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid parse_tree", K(ret)); } else { if (T_TENANT_ID == parse_tree.children_[0]->type_) { uint64_t tenant_id = static_cast(parse_tree.children_[0]->value_); bool is_exist = false; ObSchemaGetterGuard *schema_guard = schema_checker_->get_schema_guard(); if (OB_FAIL(schema_guard->check_tenant_exist(tenant_id, is_exist))) { LOG_WARN("check tenant exist failed", K(ret), K(tenant_id)); } else if (!is_exist) { ret = OB_TENANT_NOT_EXIST; LOG_WARN("tenant not exist", K(ret), K(tenant_id)); } else { stmt->set_tenant_id(tenant_id); stmt_ = stmt; } } else if (T_TENANT_NAME == parse_tree.children_[0]->type_) { ObString tenant_name; uint64_t tenant_id = OB_INVALID_TENANT_ID; tenant_name.assign_ptr((char *)(parse_tree.children_[0]->str_value_), static_cast(parse_tree.children_[0]->str_len_)); if (tenant_name.length() >= OB_MAX_TENANT_NAME_LENGTH) { ret = OB_ERR_TOO_LONG_IDENT; LOG_USER_ERROR(OB_ERR_TOO_LONG_IDENT, tenant_name.length(), tenant_name.ptr()); } else if (OB_FAIL(schema_checker_->get_tenant_id(tenant_name, tenant_id))) { LOG_WARN("fail to get tenant_id", K(ret), K(tenant_name)); } else { stmt->set_tenant_id(tenant_id); stmt_ = stmt; } } } } } return ret; } int ObDropTempTableResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_ALTER_SYSTEM_DROP_TEMP_TABLE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ALTER_SYSTEM_DROP_TEMP_TABLE", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else { ObDropTableStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObDropTableStmt failed"); } else { stmt_ = stmt; obrpc::ObDropTableArg &drop_table_arg = stmt->get_drop_table_arg(); drop_table_arg.if_exist_ = true; drop_table_arg.to_recyclebin_ = false; drop_table_arg.tenant_id_ = session_info_->get_login_tenant_id(); drop_table_arg.table_type_ = share::schema::TMP_TABLE_ALL; drop_table_arg.session_id_ = static_cast(parse_tree.children_[0]->value_); } } return ret; } int ObRefreshTempTableResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_ALTER_SYSTEM_REFRESH_TEMP_TABLE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ALTER_SYSTEM_REFRESH_TEMP_TABLE", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session_info_ should not be null"); } else { ObAlterTableStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObAlterTableStmt failed"); } else if (OB_FAIL(stmt->set_tz_info_wrap(session_info_->get_tz_info_wrap()))) { LOG_WARN("failed to set_tz_info_wrap", "tz_info_wrap", session_info_->get_tz_info_wrap(), K(ret)); } else if (OB_FAIL(stmt->set_nls_formats( session_info_->get_local_nls_date_format(), session_info_->get_local_nls_timestamp_format(), session_info_->get_local_nls_timestamp_tz_format()))) { SQL_RESV_LOG(WARN, "failed to set_nls_formats", K(ret)); } else { stmt_ = stmt; stmt->set_is_alter_system(true); obrpc::ObAlterTableArg &alter_table_arg = stmt->get_alter_table_arg(); alter_table_arg.session_id_ = static_cast(parse_tree.children_[0]->value_); alter_table_arg.alter_table_schema_.alter_type_ = OB_DDL_ALTER_TABLE; //compat for old server alter_table_arg.tz_info_ = session_info_->get_tz_info_wrap().get_tz_info_offset(); if (OB_FAIL(alter_table_arg.tz_info_wrap_.deep_copy(session_info_->get_tz_info_wrap()))) { LOG_WARN("failed to deep_copy tz info wrap", "tz_info_wrap", session_info_->get_tz_info_wrap(), K(ret)); } else if (OB_FAIL(alter_table_arg.set_nls_formats( session_info_->get_local_nls_date_format(), session_info_->get_local_nls_timestamp_format(), session_info_->get_local_nls_timestamp_tz_format()))) { LOG_WARN("failed to set_nls_formats", K(ret)); } else if (OB_FAIL(alter_table_arg.alter_table_schema_.alter_option_bitset_.add_member(obrpc::ObAlterTableArg::SESSION_ACTIVE_TIME))) { LOG_WARN("failed to add member SESSION_ACTIVE_TIME for alter table schema", K(ret), K(alter_table_arg)); } } } return ret; } int ObAlterSystemSetResolver::check_param_valid(int64_t tenant_id , const ObString &name, const ObString &value) { int ret = OB_SUCCESS; #ifdef OB_BUILD_TDE_SECURITY if (0 == name.case_compare("tde_method")) { ObString tde_method; uint64_t compat_version = 0; if (!ObTdeMethodUtil::is_valid(value)) { ret = OB_NOT_SUPPORTED; LOG_WARN("not supported other method", K(value), K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "alter invalid tde_method"); } else if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) { LOG_WARN("fail to get data version", KR(ret), K(tenant_id)); } else if (compat_version < DATA_VERSION_4_2_1_0 && ObTdeMethodUtil::is_aes256_algorithm(value)) { ret = OB_NOT_SUPPORTED; LOG_WARN("encrypt table key with aes256 is not supported", K(ret), K(value)); } else if (OB_FAIL(share::ObEncryptionUtil::get_tde_method(tenant_id, tde_method))) { LOG_WARN("fail to check tenant is method internal", K(ret)); } else if (0 != tde_method.case_compare("none") && 0 != value.case_compare(tde_method)) { // tde_method修改规则 // 当主密钥已经存在于租户内, 不允许修改为其他类型. // 主备库场景放开此限制, 检查主密钥的类型是否和要修改的类型一致. const share::schema::ObKeystoreSchema *keystore_schema = NULL; if (OB_FAIL(schema_checker_->get_keystore_schema(tenant_id, keystore_schema))) { LOG_WARN("fail get keystore schema", K(ret)); } else if (OB_ISNULL(keystore_schema)) { ret = OB_OBJECT_NAME_NOT_EXIST; LOG_WARN("fail to get keystore schema", K(ret)); } else if (0 != keystore_schema->get_master_key_id()) { if (!GCTX.is_standby_cluster()) { ret = OB_NOT_SUPPORTED; LOG_WARN("alter tde method is not support", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "alter tde method with master key exists"); } else if (0 == keystore_schema->get_master_key().case_compare("kms") && 0 == value.case_compare("bkmi")) { /*do nothing*/ } else if (0 == keystore_schema->get_master_key().case_compare(value)) { /*do nothing*/ } else if (ObTdeMethodUtil::is_internal(value)) { /*do nothing*/ } else { ret = OB_NOT_SUPPORTED; LOG_WARN("alter tde method is not support", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "alter tde method with master key exists"); } } } } else if (0 == name.case_compare(EXTERNAL_KMS_INFO)) { ObString tde_method; ObKmsClient *client = NULL; ObArenaAllocator allocator(ObModIds::OB_SQL_COMPILE); if (OB_FAIL(share::ObEncryptionUtil::get_tde_method(tenant_id, tde_method))) { LOG_WARN("fail to get method internal", K(ret)); } else if (OB_FAIL(ObKmsClientUtil::get_kms_client(allocator, tde_method, client))) { LOG_WARN("fail to get kms client", K(tde_method), K(ret)); } else if (OB_ISNULL(client)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("kms_client is null", K(tde_method), K(ret)); } else if (OB_FAIL(client->init(value.ptr(), value.length()))) { LOG_WARN("the json str is not valid", K(ret)); } } #endif return ret; } // for oracle mode grammer: alter system set sys_var = val int ObAlterSystemSetResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; bool set_parameters = false; uint64_t tenant_id = OB_INVALID_TENANT_ID; if (OB_UNLIKELY(T_ALTER_SYSTEM_SET != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("parse_tree.type_ must be T_ALTER_SYSTEM_SET", K(ret), K(parse_tree.type_)); } else if (OB_ISNULL(session_info_) || OB_ISNULL(allocator_)) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("session_info_ or allocator_ is NULL", K(ret), K(session_info_), K(allocator_)); } else { tenant_id = session_info_->get_effective_tenant_id(); /* first round: detect set variables or parameters */ for (int64_t i = 0; OB_SUCC(ret) && i < parse_tree.num_child_; ++i) { ParseNode *set_node = nullptr, *set_param_node = nullptr; if (OB_ISNULL(set_node = parse_tree.children_[i])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("set_node should not be null", K(ret)); } else if (T_ALTER_SYSTEM_SET_PARAMETER != set_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("set_node->type_ must be T_ALTER_SYSTEM_SET_PARAMETER", K(ret), K(set_node->type_)); } else if (OB_ISNULL(set_param_node = set_node->children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("set_node is null", K(ret)); } else if (OB_UNLIKELY(T_VAR_VAL != set_param_node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_VAR_VAL", K(ret), K(set_param_node->type_)); } else { ParseNode *var = nullptr; if (OB_ISNULL(var = set_param_node->children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("var is NULL", K(ret)); } else if (T_IDENT != var->type_) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "Variable name isn't identifier type"); } else { ObString name(var->str_len_, var->str_value_); share::ObBackupConfigChecker backup_config_checker; bool is_backup_config = false; if (OB_FAIL(backup_config_checker.check_config_name(name, is_backup_config))) { LOG_WARN("fail to check config name", K(ret), K(name)); } else if (is_backup_config) { set_parameters = true; break; } else { omt::ObTenantConfigGuard tenant_config(TENANT_CONF(tenant_id)); if (tenant_config.is_valid() && nullptr != tenant_config->get_container().get(ObConfigStringKey(name))) { set_parameters = true; break; } } } } } // for } /* second round: gen stmt */ if (OB_SUCC(ret)) { if (set_parameters) { FLOG_WARN("set parameters"); ObSetConfigStmt *setconfig_stmt = create_stmt(); if (OB_ISNULL(setconfig_stmt)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create set config stmt failed"); } else { HEAP_VAR(ObCreateTableResolver, ddl_resolver, params_) { for (int64_t i = 0; OB_SUCC(ret) && i < parse_tree.num_child_; ++i) { ParseNode *set_node = nullptr, *set_param_node = nullptr; if (OB_ISNULL(set_node = parse_tree.children_[i])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("set_node should not be null", K(ret)); } else if (T_ALTER_SYSTEM_SET_PARAMETER != set_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("set_node->type_ must be T_ALTER_SYSTEM_SET_PARAMETER", K(ret), K(set_node->type_)); } else if (OB_ISNULL(set_param_node = set_node->children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("set_node is null", K(ret)); } else if (OB_UNLIKELY(T_VAR_VAL != set_param_node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_VAR_VAL", K(ret), K(set_param_node->type_)); } else { ParseNode *name_node = nullptr, *value_node = nullptr; HEAP_VAR(ObAdminSetConfigItem, item) { item.exec_tenant_id_ = tenant_id; /* name */ if (OB_ISNULL(name_node = set_param_node->children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("var is NULL", K(ret)); } else if (T_IDENT != name_node->type_) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "Variable name isn't identifier type"); } else { ObString name(name_node->str_len_, name_node->str_value_); ObCharset::casedn(CS_TYPE_UTF8MB4_GENERAL_CI, name); if (OB_FAIL(item.name_.assign(name))) { LOG_WARN("assign config name failed", K(name), K(ret)); } } if (OB_FAIL(ret)) { break; } /* value */ if (OB_ISNULL(value_node = set_param_node->children_[1])) { ret = OB_INVALID_ARGUMENT; LOG_WARN("value node is NULL", K(ret)); } else { ObObjParam val; if (OB_FAIL(ddl_resolver.resolve_default_value(value_node, val))) { LOG_WARN("resolve config value failed", K(ret)); break; } ObString str_val; ObCollationType cast_coll_type = CS_TYPE_INVALID; if (OB_SUCCESS != session_info_->get_collation_connection(cast_coll_type)) { LOG_WARN("fail to get collation_connection"); cast_coll_type = ObCharset::get_default_collation( ObCharset::get_default_charset()); } ObArenaAllocator allocator(ObModIds::OB_SQL_COMPILE); ObCastCtx cast_ctx(&allocator, NULL, //to varchar. this field will not be used. 0, //to varchar. this field will not be used. CM_NONE, cast_coll_type, NULL); EXPR_GET_VARCHAR_V2(val, str_val); if (OB_FAIL(ret)) { LOG_WARN("get varchar value failed", K(ret), K(val)); break; } else if (OB_FAIL(item.value_.assign(str_val))) { LOG_WARN("assign config value failed", K(ret), K(str_val)); break; } } if (OB_SUCC(ret)) { share::ObBackupConfigChecker backup_config_checker; bool is_backup_config = false; if (OB_FAIL(backup_config_checker.check_config_name(item.name_.ptr(), is_backup_config))) { LOG_WARN("fail to check is valid backup config", K(ret), "config_name", item.name_.ptr(), "config value", item.value_.ptr()); } else if (is_backup_config) { if (setconfig_stmt->get_rpc_arg().is_valid() && !setconfig_stmt->get_rpc_arg().is_backup_config_) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "backup configuration items cannot be set together with non data backup configuration items"); LOG_WARN("backup configuration items cannot be set together with non data backup configuration items", K(ret)); } else { setconfig_stmt->get_rpc_arg().is_backup_config_ = true; } } else if (setconfig_stmt->get_rpc_arg().is_valid() && setconfig_stmt->get_rpc_arg().is_backup_config_) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "backup configuration items cannot be set together with non data backup configuration items"); LOG_WARN("backup configuration items cannot be set together with non data backup configuration items", K(ret)); } if (OB_FAIL(ret)) { } else if (OB_FAIL(check_param_valid( tenant_id, ObString(item.name_.size(), item.name_.ptr()), ObString(item.value_.size(), item.value_.ptr())))) { LOG_WARN("fail to check param valid", K(ret)); } else if (OB_FAIL( setconfig_stmt->get_rpc_arg().items_.push_back( item))) { LOG_WARN("add config item failed", K(ret), K(item)); } } } } } // for } } } else { ObVariableSetStmt *variable_set_stmt = create_stmt(); if (OB_ISNULL(variable_set_stmt)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create variable set stmt failed", K(OB_ALLOCATE_MEMORY_FAILED)); } else { variable_set_stmt->set_actual_tenant_id(session_info_->get_effective_tenant_id()); ParseNode *set_node = nullptr, *set_param_node = NULL; ObVariableSetStmt::VariableSetNode var_node; for (int64_t i = 0; OB_SUCC(ret) && i < parse_tree.num_child_; ++i) { if (OB_ISNULL(set_node = parse_tree.children_[i])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("set_node should not be null", K(ret)); } else if (T_ALTER_SYSTEM_SET_PARAMETER != set_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("set_node->type_ must be T_ALTER_SYSTEM_SET_PARAMETER", K(ret), K(set_node->type_)); } else if (OB_ISNULL(set_param_node = set_node->children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("set_node is null", K(ret)); } else if (OB_UNLIKELY(T_VAR_VAL != set_param_node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_VAR_VAL", K(ret), K(set_param_node->type_)); } else { ParseNode *var = NULL; var_node.set_scope_ = ObSetVar::SET_SCOPE_GLOBAL; variable_set_stmt->set_has_global_variable(true); /* resolve var_name */ if (OB_ISNULL(var = set_param_node->children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("var is NULL", K(ret)); } else { ObString var_name; if (T_IDENT != var->type_) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "Variable name isn't identifier type"); } else { var_node.is_system_variable_ = true; var_name.assign_ptr(var->str_value_, static_cast(var->str_len_)); } if (OB_SUCC(ret)) { if (OB_FAIL(ob_write_string(*allocator_, var_name, var_node.variable_name_))) { LOG_WARN("Can not malloc space for variable name", K(ret)); } else { ObCharset::casedn(CS_TYPE_UTF8MB4_GENERAL_CI, var_node.variable_name_); } } /* resolve value */ if (OB_SUCC(ret)) { if (OB_ISNULL(set_param_node->children_[1])) { ret = OB_INVALID_ARGUMENT; LOG_WARN("value node is NULL", K(ret)); } else if (var_node.is_system_variable_) { ParseNode value_node; MEMCPY(&value_node, set_param_node->children_[1], sizeof(ParseNode)); if (OB_FAIL(ObResolverUtils::resolve_const_expr(params_, value_node, var_node.value_expr_, NULL))) { LOG_WARN("resolve variable value failed", K(ret)); } } } if (OB_SUCC(ret) && OB_FAIL(variable_set_stmt->add_variable_node(var_node))) { LOG_WARN("Add set entry failed", K(ret)); } } } // end resolve variable and value } // end for } } /* 无论设置租户级配置项,还是系统参数,都需要alter system权限。 对租户级配置项的修改,算是一种扩展,借用alter system权限进行控制 */ if (OB_SUCC(ret) && ObSchemaChecker::is_ora_priv_check()) { CK (OB_NOT_NULL(schema_checker_)); OZ (schema_checker_->check_ora_ddl_priv( session_info_->get_effective_tenant_id(), session_info_->get_priv_user_id(), ObString(""), stmt::T_ALTER_SYSTEM_SET_PARAMETER, session_info_->get_enable_role_array()), session_info_->get_effective_tenant_id(), session_info_->get_user_id()); } } // if return ret; } int ObArchiveLogResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_ARCHIVE_LOG != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ARCHIVE_LOG", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(3 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else { ObArchiveLogStmt *stmt = create_stmt(); const int64_t is_enable = parse_tree.children_[0]->value_; const uint64_t tenant_id = session_info_->get_login_tenant_id(); ObSArray archive_tenant_ids; ParseNode *t_node = parse_tree.children_[1]; if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObArchiveLogStmt failed"); } else if (NULL != t_node) { if (OB_SYS_TENANT_ID != tenant_id) { ret = OB_ERR_NO_PRIVILEGE; LOG_WARN("Only sys tenant can add suffix opt(tenant=name)", KR(ret), K(tenant_id)); } else if (T_TENANT_LIST != t_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_TENANT_LIST", "type", get_type_name(t_node->type_)); } else { bool affect_all = false; bool affect_all_user = false; bool affect_all_meta = false; const int64_t child_num = t_node->num_child_; if (OB_UNLIKELY(nullptr == t_node->children_) || OB_UNLIKELY(0 == child_num)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children of tenant should not be null", KR(ret), K(child_num)); } else if (OB_FAIL(Util::resolve_tenant(*t_node, tenant_id, archive_tenant_ids, affect_all, affect_all_user, affect_all_meta))) { LOG_WARN("fail to resolve tenant", KR(ret), K(tenant_id)); } else if (affect_all_user || affect_all_meta) { ret = OB_NOT_SUPPORTED; LOG_WARN("all_user/all_meta is not supported by ALTER SYSTEM ARCHIVELOG", KR(ret), K(affect_all_user), K(affect_all_meta)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "use all_user/all_meta in 'ALTER SYSTEM ARCHIVELOG' syntax is"); } else if (affect_all) { } else if (archive_tenant_ids.empty()) { ret = OB_NOT_SUPPORTED; LOG_WARN("No valid tenant name given", K(ret), K(tenant_id)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "No valid tenant name given"); } } } if (OB_FAIL(ret)) { } else if (OB_FAIL(stmt->set_param(is_enable, tenant_id, archive_tenant_ids))) { LOG_WARN("Failed to set archive tenant ids", K(ret), K(is_enable), K(tenant_id), K(archive_tenant_ids)); } else { stmt_ = stmt; } } return ret; } int ObBackupDatabaseResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_BACKUP_DATABASE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_BACKUP_DATABASE", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(5 != parse_tree.num_child_ && 6 != parse_tree.num_child_ )) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else { const uint64_t tenant_id = session_info_->get_login_tenant_id(); const int64_t with_tenant = parse_tree.children_[0]->value_; common::ObSArray backup_tenant_ids; ObBackupPathString backup_dest; ObBackupDescription backup_description; if (0 == with_tenant && OB_SYS_TENANT_ID != tenant_id) { // user tenant backup ParseNode *dest_node = parse_tree.children_[3]; ParseNode *description_node = parse_tree.children_[4]; if (nullptr != dest_node && OB_FAIL(backup_dest.assign(dest_node->str_value_))) { LOG_WARN("failed to assign backup_dest", K(ret)); } else if (nullptr != description_node && OB_FAIL(backup_description.assign(description_node->str_value_))) { LOG_WARN("failed to assign backup_description", K(ret)); } } else if (0 == with_tenant && OB_SYS_TENANT_ID == tenant_id) { ParseNode *dest_node = parse_tree.children_[3]; ParseNode *description_node = parse_tree.children_[4]; if (nullptr != dest_node && OB_FAIL(backup_dest.assign(dest_node->str_value_))) { LOG_WARN("failed to assign backup_dest", K(ret)); } else if (nullptr != description_node && OB_FAIL(backup_description.assign(description_node->str_value_))) { LOG_WARN("failed to assign backup_description", K(ret)); } } else if (1 == with_tenant && OB_SYS_TENANT_ID != tenant_id) { ret = OB_NOT_SUPPORTED; LOG_WARN("user tenant cannot specify tenant names", K(ret), K(tenant_id)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "user tenant cannot specify tenant names"); } else if (1 == with_tenant/*tenant level*/ && OB_SYS_TENANT_ID == tenant_id) { ParseNode *t_node = parse_tree.children_[3]; ParseNode *dest_node = parse_tree.children_[4]; ParseNode *description_node = parse_tree.children_[5]; if (nullptr == t_node) { ret = OB_NOT_SUPPORTED; LOG_WARN("No tenant name specified", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "No tenant name specified"); } else if (OB_FAIL(Util::get_tenant_ids(*t_node, backup_tenant_ids))) { LOG_WARN("failed to get tenant ids"); } else if (nullptr != dest_node && OB_FAIL(backup_dest.assign(dest_node->str_value_))) { LOG_WARN("failed to assign backup_dest", K(ret)); } else if (nullptr != description_node && OB_FAIL(backup_description.assign(description_node->str_value_))) { LOG_WARN("failed to assign backup_description", K(ret)); } } if (OB_FAIL(ret)) { } else if (!backup_dest.is_empty()) { // TODO(chognrong.th) support specify path in 4.1 ret = OB_NOT_SUPPORTED; LOG_WARN("backup do not support using specify path ", K(ret), K(backup_dest), K(backup_tenant_ids)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "backup do not support using specify path"); } const int64_t compl_log = parse_tree.children_[1]->value_; const int64_t incremental = parse_tree.children_[2]->value_; ObBackupDatabaseStmt *stmt = create_stmt(); if (OB_FAIL(ret)) { } else if (nullptr == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObBackupDatabaseStmt failed"); } else if (OB_FAIL(stmt->set_param(tenant_id, incremental, compl_log, backup_dest, backup_description, backup_tenant_ids))) { LOG_WARN("Failed to set param", K(ret), K(tenant_id), K(incremental)); } else { stmt_ = stmt; } } return ret; } int ObCancelRestoreResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_CANCEL_RESTORE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_CANCEL_RESTORE", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(1 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_2_0_0) { ret = OB_NOT_SUPPORTED; LOG_WARN("cancel restore is not supported under cluster version 4_2_0_0", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "cancel restore is"); } else { ObCancelRestoreStmt *stmt = NULL; if (OB_ISNULL(stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("failed to create stmt", K(ret)); } else if (OB_UNLIKELY(T_IDENT != parse_tree.children_[0]->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid node", K(ret)); } else { ObString tenant_name; tenant_name.assign_ptr(parse_tree.children_[0]->str_value_, parse_tree.children_[0]->str_len_); stmt->get_drop_tenant_arg().exec_tenant_id_ = OB_SYS_TENANT_ID; stmt->get_drop_tenant_arg().if_exist_ = false; stmt->get_drop_tenant_arg().force_drop_ = true; stmt->get_drop_tenant_arg().delay_to_drop_ = false; stmt->get_drop_tenant_arg().open_recyclebin_ = false; stmt->get_drop_tenant_arg().tenant_name_ = tenant_name; stmt->get_drop_tenant_arg().drop_only_in_restore_ = true; } } return ret; } int ObCancelRecoverTableResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; uint64_t session_tenant_id = session_info_->get_effective_tenant_id(); uint64_t tenant_id = OB_INVALID_TENANT_ID; ObRecoverTableStmt *stmt = nullptr; ObSchemaGetterGuard schema_guard; ObString tenant_name; if (OB_UNLIKELY(T_CANCEL_RECOVER_TABLE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_CANCEL_RESTORE", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(1 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (!is_sys_tenant(session_tenant_id)) { ret = OB_OP_NOT_ALLOW; LOG_WARN("user tenant cancel recover table is not allowed", K(ret), K(session_tenant_id)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "user tenant cancel recover table is"); } else if (OB_ISNULL(stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("failed to create stmt", K(ret)); } else if (OB_UNLIKELY(T_IDENT != parse_tree.children_[0]->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid node", K(ret)); } else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(session_tenant_id, schema_guard))) { LOG_WARN("failed to get_tenant_schema_guard", KR(ret)); } else if (OB_FALSE_IT(tenant_name.assign_ptr(parse_tree.children_[0]->str_value_, parse_tree.children_[0]->str_len_))) { } else if (OB_FAIL(schema_guard.get_tenant_id(tenant_name, tenant_id))) { LOG_WARN("failed to get tenant id from schema guard", KR(ret), K(tenant_name)); } else if (OB_FAIL(ObRecoverTableUtil::check_compatible(tenant_id))) { LOG_WARN("check recover table compatible failed", K(ret)); } else { stmt->get_rpc_arg().tenant_id_ = tenant_id; stmt->get_rpc_arg().tenant_name_ = tenant_name; stmt->get_rpc_arg().action_ = ObRecoverTableArg::CANCEL; } return ret; } int ObAlterSystemResolverUtil::get_tenant_ids(const ParseNode &t_node, ObIArray &tenant_ids) { int ret = OB_SUCCESS; ObSchemaGetterGuard schema_guard; hash::ObHashSet tenant_id_set; const int64_t MAX_TENANT_BUCKET = 256; if (T_TENANT_LIST != t_node.type_ || NULL == t_node.children_) { ret = OB_ERR_UNEXPECTED; SERVER_LOG(WARN, "invalid argument", K(ret), K(t_node.type_), KP(t_node.children_)); } else if (OB_ISNULL(GCTX.schema_service_)) { ret = OB_ERR_UNEXPECTED; SERVER_LOG(WARN, "invalid argument", K(GCTX.schema_service_)); } else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard( OB_SYS_TENANT_ID, schema_guard))) { SERVER_LOG(WARN, "get_schema_guard failed", K(ret)); } else if (OB_FAIL(tenant_id_set.create(MAX_TENANT_BUCKET))) { SERVER_LOG(WARN, "failed to create tenant id set", K(ret)); } else { uint64_t tenant_id = 0; ObString tenant_name; const char *const ALL_TENANT = "ALL"; for (int64_t i = 0; OB_SUCC(ret) && i < t_node.num_child_; ++i) { if (OB_ISNULL(t_node.children_[i])) { ret = OB_ERR_UNEXPECTED; SERVER_LOG(WARN, "invalid argument", KP(t_node.children_[i]), K(ret)); } else { tenant_name.assign_ptr(t_node.children_[i]->str_value_, static_cast(t_node.children_[i]->str_len_)); if (OB_FAIL(schema_guard.get_tenant_id(tenant_name, tenant_id))) { SERVER_LOG(WARN, "tenant not exist", K(tenant_name), K(ret), K(i), K(t_node.num_child_)); } else if (OB_SYS_TENANT_ID == tenant_id) { ret = OB_ERR_UNEXPECTED; LOG_WARN("tenant id list is unexpected", K(ret), K(tenant_id)); } else { int hash_ret = tenant_id_set.exist_refactored(tenant_id); if (OB_HASH_EXIST == hash_ret) { //do nothing } else if (OB_HASH_NOT_EXIST == hash_ret) { if (OB_FAIL(tenant_ids.push_back(tenant_id))) { SERVER_LOG(WARN, "failed to push tenant id into array", K(ret)); } else if (OB_FAIL(tenant_id_set.set_refactored(tenant_id))) { SERVER_LOG(WARN, "failed to push tenant id into set", K(ret)); } } else { ret = hash_ret == OB_SUCCESS ? OB_ERR_UNEXPECTED : hash_ret; SERVER_LOG(WARN, "failed to check tenant exist", K(ret)); } } } tenant_name.reset(); } //for tenant end } return ret; } int ObTableTTLResolver::resolve(const ParseNode& parse_tree) { int ret = OB_SUCCESS; uint64_t tenant_data_version = 0;; const uint64_t cur_tenant_id = session_info_->get_effective_tenant_id(); if (OB_FAIL(GET_MIN_DATA_VERSION(cur_tenant_id, tenant_data_version))) { LOG_WARN("get tenant data version failed", K(ret)); } else if (tenant_data_version < DATA_VERSION_4_2_1_0) { ret = OB_NOT_SUPPORTED; LOG_WARN("TTL command is not supported in data version less than 4.2.1", K(ret), K(tenant_data_version)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "TTL command is not supported in data version less than 4.2.1"); } else if (!ObKVFeatureModeUitl::is_ttl_enable()) { ret = OB_NOT_SUPPORTED; LOG_WARN("ttl is disable", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "ttl is disable, set by config item _obkv_feature_mode"); } else if (OB_UNLIKELY(T_TABLE_TTL != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_TABLE_TTL", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(2 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else { ObTableTTLStmt* ttl_stmt = create_stmt(); const int64_t type = parse_tree.children_[0]->value_; ParseNode *opt_tenant_list_v2 = parse_tree.children_[1]; if (NULL == ttl_stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObTableTTLStmt failed"); } else if (OB_FAIL(ttl_stmt->set_type(type))) { LOG_WARN("fail to set param", K(ret), K(type)); } else { if (NULL == opt_tenant_list_v2) { if (OB_SYS_TENANT_ID == cur_tenant_id) { ttl_stmt->set_ttl_all(true); } else if (OB_FAIL(ttl_stmt->get_tenant_ids().push_back(cur_tenant_id))) { LOG_WARN("fail to push owned tenant id ", KR(ret), "owned tenant_id", cur_tenant_id); } } else if (OB_SYS_TENANT_ID != cur_tenant_id) { ret = OB_ERR_NO_PRIVILEGE; LOG_WARN("only sys tenant can add suffix opt(tenant=name)", KR(ret), K(cur_tenant_id)); } else { bool affect_all = false; bool affect_all_user = false; bool affect_all_meta = false; if (OB_FAIL(Util::resolve_tenant(*opt_tenant_list_v2, cur_tenant_id, ttl_stmt->get_tenant_ids(), affect_all, affect_all_user, affect_all_meta))) { LOG_WARN("fail to resolve tenant", KR(ret), KP(opt_tenant_list_v2), K(cur_tenant_id)); } else if (affect_all_meta) { ret = OB_NOT_SUPPORTED; LOG_WARN("affect_all_meta and affect_all_user is not supported", KR(ret), K(affect_all_meta), K(affect_all_user)); LOG_USER_WARN(OB_NOT_SUPPORTED, "affect_all_meta and affect_all_user"); } else if (affect_all || affect_all_user) { ttl_stmt->set_ttl_all(true); } } } if (OB_SUCC(ret)) { stmt_ = ttl_stmt; } } return ret; } int ObBackupManageResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_BACKUP_MANAGE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_BACKUP_MANAGE", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(3 != parse_tree.num_child_ && 2 != parse_tree.num_child_ && 4 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else { ObBackupManageStmt *stmt = create_stmt(); common::ObSArray managed_tenants; int64_t copy_id = 0; const uint64_t tenant_id = session_info_->get_login_tenant_id(); const int64_t type = parse_tree.children_[0]->value_; const int64_t value = parse_tree.children_[1]->value_; if (2 == parse_tree.num_child_) { // do nothing } else if (3 == parse_tree.num_child_) { copy_id = NULL == parse_tree.children_[2] ? 0 : parse_tree.children_[2]->children_[0]->value_; } else if (4 == parse_tree.num_child_) { const int64_t tenant_flag = parse_tree.children_[2]->value_; if (1 != tenant_flag) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid tenant id or tenant flag", K(ret), K(tenant_flag)); } else { ParseNode *t_node = parse_tree.children_[3]; if (OB_ISNULL(t_node)) { } else if (!is_sys_tenant(tenant_id)) { ret = OB_NOT_SUPPORTED; LOG_WARN("only sys tenant can cancel specify tenant backup", K(ret), K(tenant_id)); } else if (OB_FAIL(Util::get_tenant_ids(*t_node, managed_tenants))) { LOG_WARN("failed to get tenant ids", K(ret)); } } } if (OB_FAIL(ret)) { } else if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObBackupManageResolver failed"); } else if (OB_FAIL(stmt->set_param(tenant_id, type, value, copy_id, managed_tenants))) { LOG_WARN("Failed to set param", K(ret), K(tenant_id), K(type), K(value), K(copy_id)); } else { stmt_ = stmt; } } return ret; } int ObBackupCleanResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_BACKUP_CLEAN != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_BACKUP_CLEAN", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(4 != parse_tree.num_child_ && 5 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else { const uint64_t tenant_id = session_info_->get_login_tenant_id(); const int64_t type = parse_tree.children_[0]->value_; const int64_t value = parse_tree.children_[1]->value_; ObBackupDescription description; ParseNode *t_node = NULL; common::ObSArray clean_tenant_ids; int64_t copy_id = 0; ObBackupCleanStmt *stmt = create_stmt(); if (share::ObNewBackupCleanType::TYPE::CANCEL_DELETE != static_cast(type)) { ret = OB_NOT_SUPPORTED; LOG_WARN("unsupported function ", K(ret), K(type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "function is"); } else if (5 == parse_tree.num_child_) { copy_id = NULL == parse_tree.children_[3] ? 0 : parse_tree.children_[3]->children_[0]->value_; t_node = parse_tree.children_[4]; } else { t_node = parse_tree.children_[3]; } if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObBackupCleanResolver failed"); } else if (NULL != parse_tree.children_[2] && OB_FAIL(description.assign(parse_tree.children_[2]->str_value_))) { LOG_WARN("failed to assign description", K(ret)); } else if (NULL != t_node && OB_SYS_TENANT_ID != tenant_id) { ret = OB_NOT_SUPPORTED; LOG_WARN("user tenant cannot specify tenant names", K(ret), K(tenant_id)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "user tenant cannot specify tenant names"); } else if (NULL != t_node && OB_SYS_TENANT_ID == tenant_id) { if (OB_FAIL(Util::get_tenant_ids(*t_node, clean_tenant_ids))) { LOG_WARN("failed to get tenant ids", K(ret)); } else if (clean_tenant_ids.empty()) { ret = OB_NOT_SUPPORTED; LOG_WARN("No valid tenant name given", K(ret), K(tenant_id)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "No valid tenant name given"); } else if (5 == parse_tree.num_child_ && clean_tenant_ids.count() > 1) { ret = OB_NOT_SUPPORTED; LOG_WARN("To initiate cleanup set or piece under the system tenant, only one tenant name can be specified", K(ret), K(tenant_id), K(clean_tenant_ids)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Too many tenant names specified, only one tenant name can be specified"); } } else if (NULL == t_node && OB_SYS_TENANT_ID == tenant_id) { if (1 == type || 2 == type) { // type=1 is BACKUPSET and type=2 is BACKUPPIECE ret = OB_NOT_SUPPORTED; LOG_WARN("To initiate cleanup set or piece under the system tenant, need to specify one tenant name", K(ret), K(tenant_id), K(clean_tenant_ids)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "need to specify a tenant name"); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(stmt->set_param(tenant_id, type, value, copy_id, description, clean_tenant_ids))) { LOG_WARN("Failed to set param", K(ret), K(tenant_id), K(type), K(value), K(copy_id)); } else { stmt_ = stmt; } } return ret; } int ObDeletePolicyResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_DELETE_POLICY != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_DELETE_POLICY", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(3 != parse_tree.num_child_ && 6 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else { const uint64_t tenant_id = session_info_->get_login_tenant_id(); const int64_t type = parse_tree.children_[0]->value_; const ObString policy_name = parse_tree.children_[2]->str_value_; common::ObSArray clean_tenant_ids; ObDeletePolicyStmt *stmt = create_stmt(); ParseNode *t_node = parse_tree.children_[1]; if (0 != STRCMP(policy_name.ptr(), "default")) { ret = OB_NOT_SUPPORTED; LOG_WARN("the policy name is not \'default\'", K(ret), K(policy_name)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "The policy name is not \'default\', it is"); } else if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObDeletePolicyStmt failed"); } else if (NULL != t_node && OB_SYS_TENANT_ID != tenant_id) { ret = OB_NOT_SUPPORTED; LOG_WARN("user tenant cannot specify tenant names", K(ret), K(tenant_id)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "user tenant cannot specify tenant names"); } else if (NULL != t_node && OB_SYS_TENANT_ID == tenant_id) { if (OB_FAIL(Util::get_tenant_ids(*t_node, clean_tenant_ids))) { LOG_WARN("failed to get tenant ids", K(ret)); } else if (clean_tenant_ids.empty()) { ret = OB_NOT_SUPPORTED; LOG_WARN("No valid tenant name given", K(ret), K(tenant_id)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "No valid tenant name given"); } else if (clean_tenant_ids.count() > 1) { ret = OB_NOT_SUPPORTED; LOG_WARN("To handle deleted policy under the system tenant, only one tenant name can be specified", K(ret), K(tenant_id), K(clean_tenant_ids)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Too many tenant names specified, only one tenant name can be specified"); } } else if (NULL == t_node && OB_SYS_TENANT_ID == tenant_id) { ret = OB_NOT_SUPPORTED; LOG_WARN("To handle deleted policy under the system tenant, only one tenant name can be specified", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Too little tenant names specified, only one tenant name can be specified"); } if (OB_SUCC(ret) && 6 == parse_tree.num_child_) { const ObString recovery_window = OB_ISNULL(parse_tree.children_[3]) ? "" : parse_tree.children_[3]->str_value_; const int64_t redundancy = OB_ISNULL(parse_tree.children_[4]) ? 1 : parse_tree.children_[4]->value_; const int64_t backup_copies = OB_ISNULL(parse_tree.children_[5]) ? 0 : parse_tree.children_[5]->value_; if (OB_ISNULL(parse_tree.children_[3]) && OB_ISNULL(parse_tree.children_[4])) { ret = OB_NOT_SUPPORTED; LOG_WARN("recovery_window and redundancy must set one", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Neither recovery_window nor redundancy is set"); } else if (0 !=recovery_window.length()) { bool is_valid = true; int64_t val = 0; val = ObConfigTimeParser::get(recovery_window.ptr(), is_valid); if (!is_valid) { ret = OB_NOT_SUPPORTED; LOG_WARN("invalid time interval str", K(ret), K(recovery_window)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "recovery window is not be time string"); } } else if (1 != redundancy) { ret = OB_NOT_SUPPORTED; LOG_WARN("redundancy is not equal to 1", K(ret), K(redundancy)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Redundancy not equal to 1 is"); } if (OB_FAIL(ret)) { } else if (OB_FAIL(stmt->set_delete_policy(recovery_window, redundancy, backup_copies))) { LOG_WARN("failed to set delete policy", K(ret), K(recovery_window), K(redundancy), K(backup_copies)); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(stmt->set_param(tenant_id, type, policy_name, clean_tenant_ids))) { LOG_WARN("failed to set param", K(ret), K(tenant_id), K(type), K(policy_name)); } else { stmt_ = stmt; } } return ret; } int ObBackupKeyResolver::resolve(const ParseNode &parse_tree) { #ifndef OB_BUILD_TDE_SECURITY int ret = OB_ERR_PARSE_SQL; #else int ret = OB_SUCCESS; if (OB_UNLIKELY(T_BACKUP_KEY != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_BACKUP_KEY", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(4 != parse_tree.num_child_ && 3 != parse_tree.num_child_ )) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else { uint64_t tenant_id = session_info_->get_login_tenant_id(); const int64_t with_tenant = parse_tree.children_[0]->value_; common::ObSArray backup_tenant_ids; ObBackupPathString backup_dest; ObString encrypt_key; if (0 == with_tenant) { ParseNode *dest_node = parse_tree.children_[1]; ParseNode *encrypt_key_node = parse_tree.children_[2]; if (nullptr != dest_node && OB_FAIL(backup_dest.assign(dest_node->str_value_))) { LOG_WARN("failed to assign backup_dest", K(ret)); } else if (nullptr != encrypt_key_node) { encrypt_key.assign_ptr(encrypt_key_node->str_value_, static_cast(encrypt_key_node->str_len_)); } } else if (1 == with_tenant && OB_SYS_TENANT_ID != tenant_id) { ret = OB_NOT_SUPPORTED; LOG_WARN("user tenant cannot specify tenant names", K(ret), K(tenant_id)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "user tenant cannot specify tenant names"); } else if (1 == with_tenant/*tenant level*/ && OB_SYS_TENANT_ID == tenant_id) { ParseNode *t_node = parse_tree.children_[1]; ParseNode *dest_node = parse_tree.children_[2]; ParseNode *encrypt_key_node = parse_tree.children_[3]; if (nullptr == t_node) { ret = OB_NOT_SUPPORTED; LOG_WARN("No tenant name specified", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "No tenant name specified"); } else if (OB_FAIL(Util::get_tenant_ids(*t_node, backup_tenant_ids))) { LOG_WARN("failed to get tenant ids"); } else if (backup_tenant_ids.count() != 1) { ret = common::OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "tenant list, count of tenants must be 1"); } else if (FALSE_IT(tenant_id = backup_tenant_ids.at(0))) { } else if (nullptr != dest_node && OB_FAIL(backup_dest.assign(dest_node->str_value_))) { LOG_WARN("failed to assign backup_dest", K(ret)); } else if (nullptr != encrypt_key_node) { encrypt_key.assign_ptr(encrypt_key_node->str_value_, static_cast(encrypt_key_node->str_len_)); } } ObBackupKeyStmt *stmt = create_stmt(); if (OB_FAIL(ret)) { } else if (nullptr == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObBackupKeyStmt failed"); } else if (OB_FAIL(stmt->set_param(tenant_id, backup_dest, encrypt_key))) { LOG_WARN("Failed to set param", K(ret), K(tenant_id)); } else { stmt_ = stmt; } } #endif return ret; } int ObBackupArchiveLogResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_BACKUP_ARCHIVELOG != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_BACKUP_ARCHIVELOG", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(1 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else { ObBackupArchiveLogStmt *stmt = create_stmt(); const int64_t is_enable = parse_tree.children_[0]->value_; if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObBackupArchiveLogStmt failed"); } else { stmt->set_is_enable(is_enable); stmt_ = stmt; } } return ret; } int ObBackupSetEncryptionResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObBackupSetEncryptionStmt *stmt = nullptr; if (OB_UNLIKELY(T_BACKUP_SET_ENCRYPTION != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_BACKUP_SET_ENCRYPTION", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(2 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else { const int64_t mode = parse_tree.children_[0]->value_; const ObString passwd(parse_tree.children_[1]->str_len_, parse_tree.children_[1]->str_value_); const uint64_t tenant_id = session_info_->get_login_tenant_id(); LOG_INFO("resolve set encryption", K(mode), K(passwd)); if (NULL == (stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObBackupSetEncryptionStmt failed", K(ret)); } else if (OB_FAIL(stmt->set_param(mode, passwd))) { LOG_WARN("Failed to set param", K(ret), K(mode), K(passwd), KP(session_info_)); } stmt_ = stmt; } return ret; } int ObBackupSetDecryptionResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; const ParseNode *passwd_list = NULL; ObBackupSetDecryptionStmt *stmt = nullptr; if (OB_UNLIKELY(T_BACKUP_SET_DECRYPTION != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_BACKUP_SET_DECRYPTION", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(1 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (OB_ISNULL(passwd_list = parse_tree.children_[0])) { ret= OB_ERR_UNEXPECTED; LOG_ERROR("passwd_ist must not null", K(ret)); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else if (NULL == (stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObBackupSetEncryptionStmt failed", K(ret)); } else { const uint64_t tenant_id = session_info_->get_login_tenant_id(); if (tenant_id != OB_SYS_TENANT_ID) { ret = OB_NOT_SUPPORTED; LOG_WARN("only sys tenant can set decryption", K(ret), K(tenant_id)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "non-sys tenant set decryption is"); } } for (int64_t i = 0; OB_SUCC(ret) && i < passwd_list->num_child_; ++i) { ParseNode *node = passwd_list->children_[i]; const ObString passwd(node->str_len_, node->str_value_); if (OB_FAIL(stmt->add_passwd(passwd))) { LOG_WARN("failed to add passwd", K(ret), K(i), K(passwd)); } } stmt_ = stmt; return ret; } int ObSetRegionBandwidthResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; const ParseNode *src_region_node = NULL; const ParseNode *dst_region_node = NULL; const ParseNode *max_bw_node = NULL; common::ObSqlString max_bw_str; int64_t max_bw = 0; bool valid = false; ObSetRegionBandwidthStmt *stmt = nullptr; // refer to ObResourceUnitOptionResolver::resolve_option; if (OB_UNLIKELY(T_SET_REGION_NETWORK_BANDWIDTH != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_SET_REGION_NETWORK_BANDWIDTH", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(3 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (NULL == (stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObSetRegionBandwidthStmt failed", K(ret)); } else { src_region_node = parse_tree.children_[0]; dst_region_node = parse_tree.children_[1]; max_bw_node = parse_tree.children_[2]; if (T_INT == max_bw_node->type_) { max_bw = static_cast(max_bw_node->value_); if (OB_UNLIKELY(0 == max_bw)) { ret = common::OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "param, max_bw can't be zero"); } } else if (T_VARCHAR == max_bw_node->type_) { if (OB_FAIL(max_bw_str.append(max_bw_node->str_value_, max_bw_node->str_len_))) { SQL_RESV_LOG(WARN, "fail to assign child str", K(ret)); } else { max_bw = common::ObConfigCapacityParser::get(max_bw_str.ptr(), valid); if (!valid) { ret = common::OB_ERR_PARSE_SQL; } else if (OB_UNLIKELY(0 == max_bw)) { ret = common::OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "param, max_bw can't be zero"); } } } /* else if (T_NUMBER == max_bw_node->type_) { } */ else { ret = common::OB_ERR_PARSE_SQL; } if (OB_SUCC(ret)) { stmt->set_param(src_region_node->str_value_, dst_region_node->str_value_, max_bw); } } return ret; } int ObAddRestoreSourceResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObAddRestoreSourceStmt *stmt = NULL; if (OB_UNLIKELY(T_ADD_RESTORE_SOURCE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_ADD_RESTORE_SOURCE", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", KR(ret)); } else if (1 != parse_tree.num_child_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info should not be null", K(ret)); } else { const uint64_t tenant_id = session_info_->get_login_tenant_id(); const ObString source(parse_tree.children_[0]->str_len_, parse_tree.children_[0]->str_value_); if (tenant_id != OB_SYS_TENANT_ID) { ret = OB_NOT_SUPPORTED; LOG_WARN("only sys tenant can set add restore source", K(ret), K(tenant_id)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "non-sys tenant set add restore source is"); } else if (OB_ISNULL(stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("failed to create ObAddRestoreSourceStmt", K(ret)); } else if (OB_FAIL(stmt->add_restore_source(source))) { LOG_WARN("Failed to set param", K(ret), K(source)); } else { stmt_ = stmt; } } return ret; } int ObClearRestoreSourceResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObClearRestoreSourceStmt *stmt = NULL; if (OB_UNLIKELY(T_CLEAR_RESTORE_SOURCE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_CLEAR_RESTORE_SOURCE", "type", get_type_name(parse_tree.type_)); } else if (OB_ISNULL(stmt = create_stmt())) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObClearRestoreSource failed", KR(ret)); } else { stmt_ = stmt; } return ret; } int ObCheckpointSlogResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_CHECKPOINT_SLOG != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_CHECKPOINT_SLOG", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(NULL == parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", K(ret)); } else if (OB_UNLIKELY(2 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else if (OB_ISNULL(parse_tree.children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("should sepecify tenant", K(ret)); } else if (OB_ISNULL(parse_tree.children_[1])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("should sepecify server", K(ret)); } else { ObCheckpointSlogStmt *stmt = create_stmt(); if (NULL == stmt) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObCheckpointSlogStmt failed"); } else { stmt_ = stmt; if (OB_FAIL(Util::resolve_tenant_id(parse_tree.children_[0], stmt->tenant_id_))) { LOG_WARN("resolve tenant_id failed", K(ret)); } else if (OB_FAIL(Util::resolve_server(parse_tree.children_[1], stmt->server_))) { LOG_WARN("resolve server failed", K(ret)); } } } return ret; } int ObRecoverTableResolver::resolve(const ParseNode &parse_tree) { int ret = OB_NOT_SUPPORTED; if (OB_UNLIKELY(T_RECOVER_TABLE != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_RECOVER_TABLE", "type", get_type_name(parse_tree.type_)); } else if (OB_UNLIKELY(9 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", parse_tree.num_child_); } else { ObRecoverTableStmt *stmt = create_stmt(); Worker::CompatMode compat_mode = Worker::CompatMode::INVALID; ObNameCaseMode case_mode = ObNameCaseMode::OB_NAME_CASE_INVALID; if (OB_ISNULL(stmt)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObRecoverTableStmt failed", K(ret)); } else if (OB_FAIL(resolve_tenant_( parse_tree.children_[0], stmt->get_rpc_arg().tenant_id_, stmt->get_rpc_arg().tenant_name_, compat_mode, case_mode))) { LOG_WARN("failed to resolve tenant id", K(ret)); } else if (OB_FAIL(ObRecoverTableUtil::check_compatible(stmt->get_rpc_arg().tenant_id_))) { LOG_WARN("check recover table compatible failed", K(ret)); } else if (OB_FAIL(Util::resolve_string(parse_tree.children_[1], stmt->get_rpc_arg().restore_tenant_arg_.uri_))) { LOG_WARN("failed to resolve backup dest", K(ret)); } else if (OB_FAIL(resolve_scn_(parse_tree.children_[2], stmt->get_rpc_arg().restore_tenant_arg_))) { LOG_WARN("failed to resolve restore scn", K(ret)); } else if (OB_FAIL(Util::resolve_string(parse_tree.children_[3], stmt->get_rpc_arg().restore_tenant_arg_.restore_option_))) { LOG_WARN("failed to resolve restore option", K(ret)); } else if (OB_FAIL(resolve_recover_tables_( parse_tree.children_[4], compat_mode, case_mode, stmt->get_rpc_arg().import_arg_.get_import_table_arg()))) { LOG_WARN("failed to resolve recover table list", K(ret)); } else if (OB_NOT_NULL(parse_tree.children_[5]) && OB_FAIL(Util::resolve_string(parse_tree.children_[5], stmt->get_rpc_arg().restore_tenant_arg_.encrypt_key_))) { LOG_WARN("failed to resolve encrypt key", K(ret)); } else if (OB_NOT_NULL(parse_tree.children_[6])) { ParseNode *kms_node = parse_tree.children_[6]; if (2 != kms_node->num_child_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("num of children not match", K(ret), "child_num", kms_node->num_child_); } else if (OB_ISNULL(kms_node->children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("kms uri should not be NULL", K(ret)); } else if (OB_FAIL(Util::resolve_string(kms_node->children_[0], stmt->get_rpc_arg().restore_tenant_arg_.kms_uri_))) { LOG_WARN("failed to resolve kms uri", K(ret)); } else if (OB_NOT_NULL(kms_node->children_[1]) && OB_FAIL(Util::resolve_string(kms_node->children_[1], stmt->get_rpc_arg().restore_tenant_arg_.kms_encrypt_key_))) { LOG_WARN("failed to resolve kms encrypt key", K(ret)); } } if (OB_FAIL(ret)) { } else if (OB_NOT_NULL(parse_tree.children_[7]) && OB_FAIL(resolve_remap_(parse_tree.children_[7], compat_mode, case_mode, stmt->get_rpc_arg().import_arg_.get_remap_table_arg()))) { LOG_WARN("failed to resolve remap", K(ret)); } else if (OB_NOT_NULL(parse_tree.children_[8]) && OB_FAIL(Util::resolve_string(parse_tree.children_[8], stmt->get_rpc_arg().restore_tenant_arg_.description_))) { LOG_WARN("failed to resolve desc", K(ret)); #ifdef OB_BUILD_TDE_SECURITY } else if (OB_FAIL(resolve_kms_info_( stmt->get_rpc_arg().restore_tenant_arg_.restore_option_, stmt->get_rpc_arg().restore_tenant_arg_.kms_info_))) { LOG_WARN("failed to resolve kms info", K(ret)); #endif } else if (OB_FAIL(resolve_backup_set_pwd_(stmt->get_rpc_arg().restore_tenant_arg_.passwd_array_))) { LOG_WARN("failed to resolve backup set pwd", K(ret)); } else if (OB_FAIL(resolve_restore_source_(stmt->get_rpc_arg().restore_tenant_arg_.multi_uri_))) { LOG_WARN("failed to resolve restore source", K(ret)); } if (OB_SUCC(ret)) { stmt->get_rpc_arg().action_ = ObRecoverTableArg::INITIATE; } } return ret; } int ObRecoverTableResolver::resolve_remap_( const ParseNode *node, const lib::Worker::CompatMode &compat_mode, const ObNameCaseMode &case_mode, share::ObImportRemapArg &remap_arg) { int ret = OB_SUCCESS; if (OB_ISNULL(node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node must not be null", K(ret)); } else if (node->num_child_ > 3) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children num not match", K(ret), "num_child", node->num_child_); } else { bool parsed_remap_table = false; bool parsed_remap_tablegroup = false; bool parsed_remap_tablespace = false; const int DEFAULT_ERROR_MSG_LEN = 16; for (int64_t i = 0; i < node->num_child_ && OB_SUCC(ret); i++) { const ParseNode *child_node = node->children_[i]; if (T_REMAP_TABLE == child_node->type_) { if (parsed_remap_table) { ret = OB_OP_NOT_ALLOW; LOG_WARN("duplicate remap table is not allowed", K(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "duplicate REMAP TABLE is"); } else if (OB_FAIL(resolve_remap_tables_(child_node, compat_mode, case_mode, remap_arg))) { LOG_WARN("failed to resolve remap tables", K(ret)); } else { parsed_remap_table = true; } } else if (T_REMAP_TABLEGROUP == child_node->type_) { if (parsed_remap_tablegroup) { ret = OB_OP_NOT_ALLOW; LOG_WARN("duplicate remap tablegroup is not allowed", K(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "duplicate REMAP TABLEGROUP is"); } else if (OB_FAIL(resolve_remap_tablegroups_(child_node, remap_arg))) { LOG_WARN("failed to resolve remap tablegroups", K(ret)); } else { parsed_remap_tablegroup = true; } } else if (T_REMAP_TABLESPACE == child_node->type_) { if (parsed_remap_tablespace) { ret = OB_OP_NOT_ALLOW; LOG_WARN("duplicate remap tablespace is not allowed", K(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "duplicate REMAP TABLESPACE is"); } else if (OB_FAIL(resolve_remap_tablespaces_(child_node, remap_arg))) { LOG_WARN("failed to resolve remap tablespaces", K(ret)); } else { parsed_remap_tablespace = true; } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid remap", K(ret)); } } } return ret; } int ObRecoverTableResolver::resolve_restore_source_(common::ObString &restore_source) { int ret = OB_SUCCESS; ObObj value; if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info must not be nullptr", K(ret)); } else if (session_info_->user_variable_exists(OB_RESTORE_SOURCE_NAME_SESSION_STR)) { if (OB_FAIL(session_info_->get_user_variable_value(OB_RESTORE_SOURCE_NAME_SESSION_STR, value))) { LOG_WARN("failed to get user variable value", K(ret)); } else { restore_source = value.get_char(); LOG_INFO("succeed to resolve restore source", K(restore_source)); } } return ret; } int ObRecoverTableResolver::resolve_remap_tablespaces_( const ParseNode *node, share::ObImportRemapArg &remap_arg) { int ret = OB_SUCCESS; if (OB_ISNULL(node)) {// no need to remap tablegroups } else if (OB_UNLIKELY(T_REMAP_TABLESPACE != node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_REMAP_TABLESPACE", "type", get_type_name(node->type_)); } else { share::ObRemapTablespaceItem item; const ObNameCaseMode case_mode = OB_ORIGIN_AND_SENSITIVE; for (int64_t i = 0; OB_SUCC(ret) && i < node->num_child_; ++i) { const ParseNode *remap_ts_node = node->children_[i]; if (OB_ISNULL(remap_ts_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("remap table group node must not be null", K(ret)); } else if (OB_UNLIKELY(T_RELATION_FACTOR != remap_ts_node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid parse node type", K(ret)); } else if (OB_UNLIKELY(2 != remap_ts_node->num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid child num", K(ret)); } else { const ParseNode *src = remap_ts_node->children_[0]; const ParseNode *dst = remap_ts_node->children_[1]; if (OB_ISNULL(src) || OB_ISNULL(dst)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("remap tablegroup must not be null", K(ret)); } else { ObString src_name(src->str_len_, src->str_value_), dst_name(dst->str_len_, dst->str_value_); item.reset(); if (src_name.length() > OB_MAX_TABLESPACE_NAME_LENGTH || src_name.length() <= 0) { ret = OB_ERR_WRONG_VALUE; LOG_WARN("invalid src name or dst name", K(ret), K(src_name)); LOG_USER_ERROR(OB_ERR_WRONG_VALUE, "REMAP TABLESPACE", to_cstring(src_name)); } else if (dst_name.length() > OB_MAX_TABLESPACE_NAME_LENGTH || dst_name.length() <= 0) { ret = OB_ERR_WRONG_VALUE; LOG_WARN("invalid src name or dst name", K(ret), K(dst_name)); LOG_USER_ERROR(OB_ERR_WRONG_VALUE, "REMAP TABLESPACE", to_cstring(dst_name)); } else if (OB_FALSE_IT(item.src_.mode_ = case_mode)) { } else if (OB_FALSE_IT(item.target_.mode_ = case_mode)) { } else if (OB_FALSE_IT(item.src_.name_.assign_ptr(src_name.ptr(), src_name.length()))) { } else if (OB_FALSE_IT(item.target_.name_.assign_ptr(dst_name.ptr(), dst_name.length()))) { LOG_WARN("failed to assign", K(dst_name)); } else if (OB_FAIL(remap_arg.add_remap_tablespace(item))) { LOG_WARN("failed to add remap tablespace", K(ret), K(item)); } } } } } return ret; } int ObRecoverTableResolver::resolve_remap_tablegroups_( const ParseNode *node, share::ObImportRemapArg &remap_arg) { int ret = OB_SUCCESS; if (OB_ISNULL(node)) {// no need to remap tablegroups } else if (OB_UNLIKELY(T_REMAP_TABLEGROUP != node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_REMAP_TABLEGROUP", "type", get_type_name(node->type_)); } else { share::ObRemapTablegroupItem item; const ObNameCaseMode case_mode = OB_ORIGIN_AND_SENSITIVE; for (int64_t i = 0; OB_SUCC(ret) && i < node->num_child_; ++i) { const ParseNode *remap_tg_node = node->children_[i]; if (OB_ISNULL(remap_tg_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("remap table group node must not be null", K(ret)); } else if (OB_UNLIKELY(T_RELATION_FACTOR != remap_tg_node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid parse node type", K(ret)); } else if (OB_UNLIKELY(2 != remap_tg_node->num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid child num", K(ret)); } else { const ParseNode *src = remap_tg_node->children_[0]; const ParseNode *dst = remap_tg_node->children_[1]; if (OB_ISNULL(src) || OB_ISNULL(dst)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("remap tablegroup must not be null", K(ret)); } else { ObString src_name(src->str_len_, src->str_value_), dst_name(dst->str_len_, dst->str_value_); item.reset(); if (src_name.length() > OB_MAX_TABLEGROUP_NAME_LENGTH || src_name.length() <= 0) { ret = OB_ERR_WRONG_VALUE; LOG_WARN("invalid src name", K(ret), K(src_name)); LOG_USER_ERROR(OB_ERR_WRONG_VALUE, "REMAP TABLEGROUP", to_cstring(src_name)); } else if (dst_name.length() > OB_MAX_TABLEGROUP_NAME_LENGTH || dst_name.length() <= 0) { ret = OB_ERR_WRONG_VALUE; LOG_WARN("invalid dst name", K(ret), K(dst_name)); LOG_USER_ERROR(OB_ERR_WRONG_VALUE, "REMAP TABLEGROUP", to_cstring(dst_name)); } else if (OB_FALSE_IT(item.src_.mode_ = case_mode)) { } else if (OB_FALSE_IT(item.target_.mode_ = case_mode)) { } else if (OB_FALSE_IT(item.src_.name_.assign_ptr(src_name.ptr(), src_name.length()))) { } else if (OB_FALSE_IT(item.target_.name_.assign_ptr(dst_name.ptr(), dst_name.length()))) { LOG_WARN("failed to assign", K(dst_name)); } else if (OB_FAIL(remap_arg.add_remap_tablegroup(item))) { LOG_WARN("failed to add remap tablegroup", K(ret), K(item)); } } } } } return ret; } int ObRecoverTableResolver::resolve_remap_tables_( const ParseNode *node, const lib::Worker::CompatMode &compat_mode, const ObNameCaseMode &case_mode, share::ObImportRemapArg &remap_arg) { int ret = OB_SUCCESS; if (OB_ISNULL(node)) { // no need to remap tables } else if (OB_UNLIKELY(T_REMAP_TABLE != node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_REMAP_TABLE", "type", get_type_name(node->type_)); } else { share::ObRemapDatabaseItem remap_db_item; share::ObRemapTableItem remap_table_item; ObCollationType cs_type = CS_TYPE_INVALID; bool perserve_lettercase = Worker::CompatMode::ORACLE == compat_mode ? true : (case_mode != OB_LOWERCASE_AND_INSENSITIVE); bool is_oracle_mode = Worker::CompatMode::ORACLE == compat_mode; // No matter what name case mode is of target tenant, the names of remap tables are case sensitive. const ObNameCaseMode sensitive_case_mode = OB_ORIGIN_AND_SENSITIVE; for (int64_t i = 0; OB_SUCC(ret) && i < node->num_child_; ++i) { bool is_remap_db = false; remap_db_item.reset(); remap_table_item.reset(); remap_db_item.src_.mode_ = sensitive_case_mode; remap_db_item.target_.mode_ = sensitive_case_mode; remap_table_item.src_.mode_ = sensitive_case_mode; remap_table_item.target_.mode_ = sensitive_case_mode; const ParseNode *remap_table_node = node->children_[i]; if (OB_ISNULL(remap_table_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("remap table group node must not be null", K(ret)); } else if (OB_UNLIKELY(T_RELATION_FACTOR != remap_table_node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid parse node type", K(ret)); } else if (5 == remap_table_node->num_child_) { // remap table const ParseNode *src_db_node = remap_table_node->children_[0]; const ParseNode *src_tb_node = remap_table_node->children_[1]; const ParseNode *src_pt_node = remap_table_node->children_[2]; const ParseNode *dst_db_node = remap_table_node->children_[3]; const ParseNode *dst_tb_node = remap_table_node->children_[4]; ObString src_db_name, src_tb_name, src_pt_name, dst_db_name, dst_tb_name; if (OB_NOT_NULL(src_db_node) && OB_FALSE_IT(src_db_name.assign_ptr(src_db_node->str_value_, src_db_node->str_len_))) { } else if (OB_NOT_NULL(src_tb_node) && OB_FALSE_IT(src_tb_name.assign_ptr(src_tb_node->str_value_, src_tb_node->str_len_))) { } else if (OB_NOT_NULL(src_pt_node) && OB_FALSE_IT(src_pt_name.assign_ptr(src_pt_node->str_value_, src_pt_node->str_len_))) { } else if (OB_NOT_NULL(dst_db_node) && OB_FALSE_IT(dst_db_name.assign_ptr(dst_db_node->str_value_, dst_db_node->str_len_))) { } else if (OB_NOT_NULL(dst_tb_node) && OB_FALSE_IT(dst_tb_name.assign_ptr(dst_tb_node->str_value_, dst_tb_node->str_len_))) { } if (!src_db_name.empty() && OB_FAIL(ObSQLUtils::check_and_convert_db_name(cs_type, perserve_lettercase, src_db_name))) { LOG_WARN("failed to check and convert db name", K(ret), K(cs_type), K(perserve_lettercase), K(src_db_name)); } else if (!src_tb_name.empty() && OB_FAIL(ObSQLUtils::check_and_convert_table_name(cs_type, perserve_lettercase, src_tb_name, is_oracle_mode))) { LOG_WARN("failed to check and convert table name", K(ret), K(cs_type), K(perserve_lettercase), K(src_tb_name)); } else if (!dst_db_name.empty() && OB_FAIL(ObSQLUtils::check_and_convert_db_name(cs_type, perserve_lettercase, dst_db_name))) { LOG_WARN("failed to check and convert db name", K(ret), K(cs_type), K(perserve_lettercase), K(dst_db_name)); } else if (!dst_tb_name.empty() && OB_FAIL(ObSQLUtils::check_and_convert_table_name(cs_type, perserve_lettercase, dst_tb_name, is_oracle_mode))) { LOG_WARN("failed to check and convert table name", K(ret), K(cs_type), K(perserve_lettercase), K(dst_tb_name)); } else if (!src_pt_name.empty() && src_pt_name.length() > OB_MAX_PARTITION_NAME_LENGTH) { ret = OB_ERR_WRONG_VALUE; LOG_WARN("invalid partition name", K(ret)); LOG_USER_ERROR(OB_ERR_WRONG_VALUE, "INVALID PARTITION NAME", to_cstring(src_pt_name)); } if (OB_FAIL(ret)) { } else if (OB_NOT_NULL(src_db_node) && OB_ISNULL(src_tb_node) && OB_ISNULL(src_pt_node) && OB_NOT_NULL(dst_db_node) && OB_ISNULL(dst_tb_node)) { // db_name.'*':new_db_name.'*'; remap_db_item.src_.name_.assign_ptr(src_db_name.ptr(), src_db_name.length()); remap_db_item.target_.name_.assign_ptr(dst_db_name.ptr(), dst_db_name.length()); is_remap_db = true; } else if (OB_NOT_NULL(src_db_node) && OB_NOT_NULL(src_tb_node) && OB_ISNULL(src_pt_node) && OB_ISNULL(dst_db_node) && OB_NOT_NULL(dst_tb_node)) { // db_name.tb_name:new_tb_name; remap_table_item.src_.database_name_.assign_ptr(src_db_name.ptr(), src_db_name.length()); remap_table_item.src_.table_name_.assign_ptr(src_tb_name.ptr(), src_tb_name.length()); remap_table_item.target_.database_name_.assign_ptr(src_db_name.ptr(), src_db_name.length()); remap_table_item.target_.table_name_.assign_ptr(dst_tb_name.ptr(), dst_tb_name.length()); } else if (OB_NOT_NULL(src_db_node) && OB_NOT_NULL(src_tb_node) && OB_ISNULL(src_pt_node) && OB_NOT_NULL(dst_db_node) && OB_NOT_NULL(dst_tb_node)) { // db_name.tb_name:new_db_name.new_tb_name remap_table_item.src_.database_name_.assign_ptr(src_db_name.ptr(), src_db_name.length()); remap_table_item.src_.table_name_.assign_ptr(src_tb_name.ptr(), src_tb_name.length()); remap_table_item.target_.database_name_.assign_ptr(dst_db_name.ptr(), dst_db_name.length()); remap_table_item.target_.table_name_.assign_ptr(dst_tb_name.ptr(), dst_tb_name.length()); } else if (OB_NOT_NULL(src_db_node) && OB_NOT_NULL(src_tb_node) && OB_NOT_NULL(src_pt_node) && OB_ISNULL(dst_db_node) && OB_NOT_NULL(dst_tb_node)) { // db_name.tb_name:part_name:new_tb_name; int ret = OB_NOT_SUPPORTED; LOG_WARN("remap partition is not supported", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "remap partition"); } else if (OB_NOT_NULL(src_db_node) && OB_NOT_NULL(src_tb_node) && OB_NOT_NULL(src_pt_node) && OB_NOT_NULL(dst_db_node) && OB_NOT_NULL(dst_tb_node)) { int ret = OB_NOT_SUPPORTED; LOG_WARN("remap partition is not supported", K(ret)); } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid remap tables", K(ret)); } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid remap tables", K(ret)); } if (OB_FAIL(ret)) { } else if (!is_remap_db && OB_FAIL(remap_arg.add_remap_table(remap_table_item))) { LOG_WARN("fail to push backup", K(ret), K(remap_table_item)); } else if (is_remap_db && OB_FAIL(remap_arg.add_remap_database(remap_db_item))) { LOG_WARN("fail to push backup", K(ret), K(remap_db_item)); } } } return ret; } int ObRecoverTableResolver::resolve_backup_set_pwd_(common::ObString &pwd) { int ret = OB_SUCCESS; ObObj value; if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session is null" , K(ret)); } else if (!session_info_->user_variable_exists(OB_BACKUP_DECRYPTION_PASSWD_ARRAY_SESSION_STR)) { LOG_INFO("no decryption passwd is specified"); pwd.reset(); } else if (OB_FAIL(session_info_->get_user_variable_value( OB_BACKUP_DECRYPTION_PASSWD_ARRAY_SESSION_STR, value))) { LOG_WARN("fail to get user variable", K(ret)); } else { pwd = value.get_varchar(); LOG_INFO("succeed to resolve_decryption_passwd", "passwd", pwd); } return ret; } #ifdef OB_BUILD_TDE_SECURITY int ObRecoverTableResolver::resolve_kms_info_(const common::ObString &restore_option, common::ObString &kms_info) { int ret = OB_SUCCESS; const char *encrypt_option_str = "kms_encrypt=true"; ObString kms_var("kms_encrypt_info"); int64_t encrypt_opt_str_len = strlen(encrypt_option_str); bool is_kms_encrypt = false; for (int i = 0; i <= restore_option.length() - encrypt_opt_str_len; ++i) { if (0 == STRNCASECMP(restore_option.ptr() + i, encrypt_option_str, encrypt_opt_str_len)) { is_kms_encrypt = true; break; } } if (is_kms_encrypt) { ObObj value; if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session is null" , K(ret)); } else if (OB_FAIL(session_info_->get_user_variable_value(kms_var, value))) { LOG_WARN("fail to get user variable", K(ret)); } else { kms_info = value.get_varchar(); if (kms_info.length() > 4000 || kms_info.length() < 0) { ret = OB_INVALID_ARGUMENT; LOG_WARN("kms info is not valid", K(ret)); } } } return ret; } #endif int ObRecoverTableResolver::resolve_recover_tables_( const ParseNode *node, const lib::Worker::CompatMode &compat_mode, const ObNameCaseMode &case_mode, share::ObImportTableArg &import_arg) { int ret = OB_SUCCESS; ObCollationType cs_type = CS_TYPE_INVALID; bool perserve_lettercase = Worker::CompatMode::ORACLE == compat_mode ? true : (case_mode != OB_LOWERCASE_AND_INSENSITIVE); bool is_oracle_mode = Worker::CompatMode::ORACLE == compat_mode; // No matter what name case mode is of target tenant, the names of recover tables are case sensitive. const ObNameCaseMode sensitive_case_mode = OB_ORIGIN_AND_SENSITIVE; if (OB_ISNULL(node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table list node must not be null", K(ret)); } else if (OB_FAIL(session_info_->get_collation_connection(cs_type))) { LOG_WARN("failed to get collation connection", K(ret)); } for (int64_t i = 0; OB_SUCC(ret) && i < node->num_child_; ++i) { const ParseNode *table_relation_node = node->children_[i]; if (OB_ISNULL(table_relation_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table relation node must not be null", K(ret)); } else if (OB_UNLIKELY(T_RELATION_FACTOR != table_relation_node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid parse node type", K(ret)); } else if (3 == table_relation_node->num_child_) { const ParseNode *db_node = table_relation_node->children_[0]; const ParseNode *tb_node = table_relation_node->children_[1]; const ParseNode *pt_node = table_relation_node->children_[2]; if (OB_ISNULL(db_node) && OB_ISNULL(tb_node) && OB_ISNULL(pt_node)) { // '*'.'*' recover all table of all all database. if (OB_FAIL(import_arg.set_import_all())) { LOG_WARN("failed to set import all", K(ret)); } } else if (OB_NOT_NULL(db_node) && OB_ISNULL(tb_node) && OB_ISNULL(pt_node)) { // db_name.'*' recover all tables of db_name ObString db_name(db_node->str_len_, db_node->str_value_); share::ObImportDatabaseItem db_item(sensitive_case_mode, db_node->str_value_, db_node->str_len_); if (OB_FAIL(ObSQLUtils::check_and_convert_db_name(cs_type, perserve_lettercase, db_name))) { LOG_WARN("failed to check and convert db name", K(ret), K(cs_type), K(perserve_lettercase), K(db_name)); } else if (OB_FAIL(import_arg.add_database(db_item))) { LOG_WARN("failed to add database", K(ret), K(db_item)); } } else if (OB_NOT_NULL(db_node) && OB_NOT_NULL(tb_node) && OB_ISNULL(pt_node)) { // db_name.tb_name recover tb_name of db_name ObString db_name(db_node->str_len_, db_node->str_value_), tb_name(tb_node->str_len_, tb_node->str_value_); if (OB_FAIL(ObSQLUtils::check_and_convert_table_name(cs_type, perserve_lettercase, tb_name, is_oracle_mode))) { LOG_WARN("failed to check and convert table name", K(ret), K(cs_type), K(perserve_lettercase), K(tb_name)); } else if (OB_FAIL(ObSQLUtils::check_and_convert_db_name(cs_type, perserve_lettercase, db_name))) { LOG_WARN("failed to check and convert db name", K(ret), K(cs_type), K(perserve_lettercase), K(db_name)); } else { share::ObImportTableItem table_item(sensitive_case_mode, db_name.ptr(), db_name.length(), tb_name.ptr(), tb_name.length()); if (OB_FAIL(import_arg.add_table(table_item))) { LOG_WARN("failed to add table", K(ret), K(table_item)); } } } else if (OB_NOT_NULL(db_node) && OB_NOT_NULL(tb_node) && OB_NOT_NULL(pt_node)) { ret = OB_NOT_SUPPORTED; LOG_WARN("recover partition is not support", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "recover partition"); } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid recover table list", K(ret)); LOG_USER_ERROR(OB_ERR_UNEXPECTED, "invalid recover table list"); } } else if (5 == table_relation_node->num_child_) { const ParseNode *db_node = table_relation_node->children_[0]; const ParseNode *tb_node = table_relation_node->children_[1]; const ParseNode *pt_node = table_relation_node->children_[4]; if (OB_NOT_NULL(db_node) && OB_NOT_NULL(tb_node) && OB_NOT_NULL(pt_node)) { // db_name.tb_name:pt_name reocver the partion of tb_name ret = OB_NOT_SUPPORTED; LOG_WARN("recover partition is not supported", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "recover partition"); } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid recover table list", K(ret)); LOG_USER_ERROR(OB_ERR_UNEXPECTED, "invalid recover table list"); } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid recover table list", K(ret)); LOG_USER_ERROR(OB_ERR_UNEXPECTED, "invalid recover table list"); } } return ret; } int ObRecoverTableResolver::resolve_scn_( const ParseNode *node, obrpc::ObPhysicalRestoreTenantArg &arg) { int ret = OB_SUCCESS; const ParseNode *time_node = nullptr; if (OB_ISNULL(node)) { //restore to latest, scn = 0; } else if (OB_FALSE_IT(time_node = node)) { } else if (OB_UNLIKELY(T_PHYSICAL_RESTORE_UNTIL != time_node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_PHYSICAL_RESTORE_UNTIL", "type", get_type_name(time_node->type_)); } else if (OB_UNLIKELY(2 != time_node->num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("num of children not match", K(ret), "child_num", time_node->num_child_); } else if (0/*timestamp*/ == time_node->children_[0]->value_) { arg.restore_timestamp_.assign_ptr(time_node->children_[1]->str_value_, time_node->children_[1]->str_len_); arg.with_restore_scn_ = false; } else if (1/*scn*/ == time_node->children_[0]->value_) { if (share::OB_BASE_SCN_TS_NS >= time_node->children_[1]->value_) { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "until scn, it should be positive integer"); LOG_WARN("until scn, it should be positive integer", KR(ret), K(time_node->children_[1]->value_)); } else if (OB_FAIL(arg.restore_scn_.convert_for_sql(time_node->children_[1]->value_))) { LOG_WARN("failed to convert scn", K(ret)); } else { arg.with_restore_scn_ = true; } } else { ret = OB_ERR_UNEXPECTED; LOG_INFO("invalid until", K(ret)); LOG_USER_ERROR(OB_ERR_UNEXPECTED, "invalid until type"); } return ret; } int ObRecoverTableResolver::resolve_tenant_( const ParseNode *node, uint64_t &tenant_id, common::ObString &tenant_name, lib::Worker::CompatMode &compat_mode, ObNameCaseMode &case_mode) { int ret = OB_SUCCESS; uint64_t session_tenant_id = OB_INVALID_TENANT_ID; if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session is NULL", K(ret)); } else if (OB_FALSE_IT(session_tenant_id = session_info_->get_effective_tenant_id())) { } else if (is_sys_tenant(session_tenant_id) && OB_NOT_NULL(node)) { // System tenant initiates recover table. if (OB_UNLIKELY(T_TENANT_NAME != node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_TENANT_NAME", "type", get_type_name(node->type_)); } else if (OB_UNLIKELY(1 != node->num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("tenant name node must not be null", K(ret)); } else { ObSchemaGetterGuard schema_guard; ObString tmp_tenant_name(node->children_[0]->str_len_, node->children_[0]->str_value_); if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(session_tenant_id, schema_guard))) { LOG_WARN("failed to get_tenant_schema_guard", KR(ret)); } else if (OB_FAIL(schema_guard.get_tenant_id(tmp_tenant_name, tenant_id))) { LOG_WARN("failed to get tenant id from schema guard", KR(ret), K(tmp_tenant_name)); } else { tenant_name = tmp_tenant_name; } } } else { ret = OB_OP_NOT_ALLOW; LOG_WARN("can't initiate table recover", K(ret), K(session_tenant_id)); if (is_sys_tenant(session_tenant_id)) { LOG_USER_ERROR(OB_OP_NOT_ALLOW, "no target tenant specified"); } else { LOG_USER_ERROR(OB_OP_NOT_ALLOW, "user tenant initiate recover table is"); } } if (OB_SUCC(ret)) { ObSchemaGetterGuard schema_guard; if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(tenant_id, schema_guard))) { LOG_WARN("failed to get tenant schema guard", K(ret), K(tenant_id)); } else if (OB_FAIL(schema_guard.get_tenant_compat_mode(tenant_id, compat_mode))) { LOG_WARN("failed to get compat mode", K(ret), K(tenant_id)); } else if (OB_FAIL(schema_guard.get_tenant_name_case_mode(tenant_id, case_mode))) { LOG_WARN("failed to get name case mode", K(ret), K(tenant_id)); } } return ret; } int ObRecoverTenantResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; share::SCN recovery_until_scn = SCN::min_scn(); obrpc::ObRecoverTenantArg::RecoverType type = obrpc::ObRecoverTenantArg::RecoverType::INVALID; ObString tenant_name; bool with_restore_scn = false; if (OB_UNLIKELY(T_RECOVER != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_RECOVER", "type", get_type_name(parse_tree.type_)); } else if (OB_ISNULL(parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else if (OB_UNLIKELY(2 != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("num of children not match", KR(ret), "child_num", parse_tree.num_child_); } else { ObRecoverTenantStmt *stmt = create_stmt(); if (OB_ISNULL(stmt)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create ObRecoverTenantStmt failed"); } else { if (OB_FAIL(resolve_tenant_name(parse_tree.children_[0], session_info_->get_effective_tenant_id(), tenant_name))) { LOG_WARN("resolve_tenant_name", KR(ret), KP(parse_tree.children_[0]), K(session_info_->get_effective_tenant_id()), K(tenant_name)); } else if (OB_ISNULL(parse_tree.children_[1])) { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "restore until, should specify restore until point"); LOG_WARN("should specify restore until point", KR(ret)); } else if (T_PHYSICAL_RESTORE_UNTIL == parse_tree.children_[1]->type_) { if (OB_FAIL(resolve_restore_until(*parse_tree.children_[1], session_info_, recovery_until_scn, with_restore_scn))) { LOG_WARN("failed to resolve restore until", KR(ret), KP(parse_tree.children_[1]), K(recovery_until_scn), K(with_restore_scn)); } else { type = obrpc::ObRecoverTenantArg::RecoverType::UNTIL; } } else if (T_RECOVER_UNLIMITED == parse_tree.children_[1]->type_) { //TODO(yaoying):need check recovery_until_scn recovery_until_scn.set_max(); type = obrpc::ObRecoverTenantArg::RecoverType::UNTIL; } else if (T_RECOVER_CANCEL == parse_tree.children_[1]->type_) { recovery_until_scn.set_min(); type = obrpc::ObRecoverTenantArg::RecoverType::CANCEL; } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected node type", KR(ret), "type", get_type_name(parse_tree.children_[1]->type_)); } } if (OB_SUCC(ret)) { if (OB_FAIL(stmt->get_rpc_arg().init(session_info_->get_effective_tenant_id(), tenant_name, type, recovery_until_scn))) { LOG_WARN("fail to init arg", KR(ret), K(stmt->get_rpc_arg()), K(session_info_->get_effective_tenant_id()), K(tenant_name), K(type), K(recovery_until_scn)); } else { stmt_ = stmt; } } } return ret; } int resolve_restore_until(const ParseNode &time_node, const ObSQLSessionInfo *session_info, share::SCN &recovery_until_scn, bool &with_restore_scn) { int ret = OB_SUCCESS; recovery_until_scn.set_min(); with_restore_scn = false; if (OB_UNLIKELY(T_PHYSICAL_RESTORE_UNTIL != time_node.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type is not T_PHYSICAL_RESTORE_UNTIL", "type", get_type_name(time_node.type_)); } else if (OB_ISNULL(session_info)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("arg should not be null", KP(session_info)); } else if (OB_ISNULL(time_node.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null"); } else if (OB_UNLIKELY(2 != time_node.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("num of children not match", K(ret), "child_num", time_node.num_child_); } else if (OB_ISNULL(time_node.children_[0]) || OB_ISNULL(time_node.children_[1])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be null", KP(time_node.children_[0]), KP(time_node.children_[1])); } else if (0/*timestamp*/ == time_node.children_[0]->value_) { uint64_t time_val = 0; ObString time_str; ObString sys_time_zone; ObTimeZoneInfoWrap tz_info_wrap; const ObTimeZoneInfo *time_zone_info = nullptr; const ObTimeZoneInfo *sys_tz_info = nullptr; if (OB_ISNULL(time_zone_info = session_info->get_timezone_info())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("time zone info is null", K(ret), KP(session_info), KP(time_zone_info)); } else if (OB_FAIL(session_info->get_sys_variable(share::SYS_VAR_SYSTEM_TIME_ZONE, sys_time_zone))) { LOG_WARN("Get sys variable error", K(ret)); } else if (OB_ISNULL(time_zone_info->get_tz_info_map())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("should not be null", KP(time_zone_info->get_tz_info_map())); } else if (OB_FAIL(tz_info_wrap.init_time_zone(sys_time_zone, OB_INVALID_VERSION, *(const_cast(time_zone_info->get_tz_info_map()))))) { LOG_WARN("tz_info_wrap init_time_zone fail", KR(ret), K(sys_time_zone)); } else if (OB_ISNULL(sys_tz_info = tz_info_wrap.get_time_zone_info())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("sys time zone info is null", K(ret)); } else if (OB_FAIL(ObAlterSystemResolverUtil::resolve_string(time_node.children_[1], time_str))) { LOG_WARN("resolve string failed", K(ret)); } else if (OB_FAIL(ObTimeConverter::str_to_scn_value(time_str, sys_tz_info, time_zone_info, ObTimeConverter::COMPAT_OLD_NLS_TIMESTAMP_FORMAT, true/*oracle mode*/, time_val))) { ret = OB_ERR_WRONG_VALUE; LOG_USER_ERROR(OB_ERR_WRONG_VALUE, "TIMESTAMP", to_cstring(time_str)); } else if (OB_FAIL(recovery_until_scn.convert_for_sql(time_val))) { LOG_WARN("fail to set scn", K(ret)); } else { with_restore_scn = true; } } else if (1/*scn*/ == time_node.children_[0]->value_) { if (share::OB_BASE_SCN_TS_NS >= time_node.children_[1]->value_) { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "until scn, it should be positive integer"); LOG_WARN("until scn, it should be positive integer", KR(ret), K(time_node.children_[1]->value_)); } else if (OB_FAIL(recovery_until_scn.convert_for_sql(time_node.children_[1]->value_))) { LOG_WARN("fail to set scn", K(ret)); } else { with_restore_scn = true; } } return ret; } } // end namespace sql } // end namespace oceanbase