/** * 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/ddl/ob_create_view_resolver.h" #include "sql/resolver/ob_resolver_utils.h" #include "sql/resolver/ddl/ob_create_table_stmt.h" // share CREATE TABLE stmt #include "sql/resolver/dml/ob_select_stmt.h" // resolve select clause #include "sql/resolver/dml/ob_dml_stmt.h" // PartExprItem #include "sql/ob_sql_context.h" #include "sql/ob_select_stmt_printer.h" #include "sql/session/ob_sql_session_info.h" #include "lib/json/ob_json_print_utils.h" // for SJ #include "lib/hash/ob_hashset.h" namespace oceanbase { using namespace common; using namespace obrpc; using namespace share::schema; namespace sql { ObCreateViewResolver::ObCreateViewResolver(ObResolverParams& params) : ObDDLResolver(params) {} ObCreateViewResolver::~ObCreateViewResolver() {} int ObCreateViewResolver::resolve(const ParseNode& parse_tree) { int ret = OB_SUCCESS; if (OB_UNLIKELY(T_CREATE_VIEW != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected type of parse_tree", K(parse_tree.type_), K(ret)); } else if (OB_ISNULL(parse_tree.children_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("children should not be NULL", K(ret)); } else if (OB_UNLIKELY(ROOT_NUM_CHILD != parse_tree.num_child_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected num_child of parse_tree", K(parse_tree.num_child_), K(ret)); } else if (OB_ISNULL(allocator_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("allocator_ should not be 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 (OB_ISNULL(params_.query_ctx_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("query_ctx should not be NULL", K(ret)); } else { ObString view_name; ObString synonym_name; ObString view_define; ObCreateTableStmt* stmt = NULL; if (OB_UNLIKELY(NULL == (stmt = create_stmt()))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("create view stmt failed", K(ret)); } else { stmt->set_allocator(*allocator_); stmt_ = stmt; stmt->set_is_view_stmt(true); } bool is_sync_ddl_user = false; if (OB_SUCC(ret)) { if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(session_info_, is_sync_ddl_user))) { LOG_WARN("Failed to check sync_dll_user", K(ret)); } } ObSelectStmt* select_stmt = NULL; // resolve view name; create view [ or replace] view [column_list] [table_id] if (OB_SUCC(ret)) { ObString db_name; if (OB_UNLIKELY(T_CREATE_VIEW != parse_tree.type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("parse_tree type should be T_CREATE_VIEW", K(parse_tree.type_), K(ret)); } else { ObCreateTableArg& create_arg = stmt->get_create_table_arg(); ObTableSchema& table_schema = create_arg.schema_; create_arg.if_not_exist_ = (NULL != parse_tree.children_[IF_NOT_EXISTS_NODE]); // TODO ParseNode* view_node = parse_tree.children_[VIEW_NODE]; if (OB_ISNULL(view_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("view node should not be NULL", K(ret)); } else { // uint64_t database_id = OB_INVALID_ID; // if (OB_FAIL(resolve_table_relation_factor(view_node, database_id, view_name, synonym_name, db_name))) { // if (OB_TABLE_NOT_EXIST == ret) { // ret = OB_SUCCESS; // } else { // LOG_WARN("resolve table relation failed", K(ret)); // } // } if (OB_FAIL(resolve_table_relation_node(view_node, view_name, db_name))) { LOG_WARN("failed to resolve table relation node!", K(ret)); } if (OB_SUCC(ret)) { if (OB_FAIL(normalize_table_or_database_names(view_name))) { LOG_WARN("fail to normalize table name", K(view_name), K(ret)); } else if (OB_FAIL(ob_write_string(*allocator_, db_name, stmt->get_non_const_db_name()))) { LOG_WARN("failed to deep copy database name", K(ret), K(db_name)); } else { } } if (OB_SUCC(ret)) { ObNameCaseMode mode = OB_NAME_CASE_INVALID; bool perserve_lettercase = false; if (OB_FAIL(session_info_->get_name_case_mode(mode))) { LOG_WARN("fail to get name case mode", K(ret), K(mode)); } else if (FALSE_IT(perserve_lettercase = share::is_oracle_mode() ? true : (mode != OB_LOWERCASE_AND_INSENSITIVE))) { } else if (OB_FAIL(ObSQLUtils::check_and_convert_table_name(CS_TYPE_UTF8MB4_GENERAL_CI, perserve_lettercase, view_name))) { LOG_WARN("fail to check and convert view_name", K(ret), K(view_name)); } else { table_schema.set_tenant_id(session_info_->get_effective_tenant_id()); table_schema.set_tablegroup_id(combine_id(OB_SYS_TENANT_ID, OB_SYS_TABLEGROUP_ID)); // table_schema.set_database_id(database_id); ParseNode* table_id_node = parse_tree.children_[TABLE_ID_NODE]; if (OB_UNLIKELY(NULL != table_id_node && (T_TABLE_ID != table_id_node->type_ || 1 != table_id_node->num_child_))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to resolve table_id", K(ret)); } else { table_schema.set_table_id( table_id_node ? static_cast(table_id_node->children_[0]->value_) : OB_INVALID_ID); if (OB_FAIL(table_schema.set_table_name(view_name))) { LOG_WARN("fail to set table_name", K(view_name), K(ret)); } } } } } } } if (OB_SUCC(ret)) { // resolve select stmt: create ... as