/** * 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 "lib/compress/ob_compressor_pool.h" #include "sql/resolver/ddl/ob_ddl_resolver.h" #include "common/sql_mode/ob_sql_mode_utils.h" #include "common/ob_store_format.h" #include "lib/charset/ob_charset.h" #include "lib/string/ob_sql_string.h" #include "share/schema/ob_table_schema.h" #include "share/schema/ob_part_mgr_util.h" #include "sql/resolver/ddl/ob_create_table_stmt.h" #include "sql/resolver/ddl/ob_alter_table_stmt.h" #include "sql/resolver/ddl/ob_create_tablegroup_stmt.h" #include "sql/code_generator/ob_expr_generator_impl.h" #include "sql/code_generator/ob_code_generator_impl.h" #include "sql/session/ob_sql_session_info.h" #include "sql/ob_sql_utils.h" #include "sql/resolver/expr/ob_raw_expr_util.h" #include "sql/resolver/expr/ob_raw_expr_resolver_impl.h" #include "sql/resolver/ob_resolver_utils.h" #include "sql/resolver/expr/ob_raw_expr_printer.h" #include "sql/resolver/expr/ob_raw_expr_part_func_checker.h" #include "share/ob_index_builder_util.h" #include "share/object/ob_obj_cast.h" #include "observer/omt/ob_tenant_config_mgr.h" namespace oceanbase { using namespace common; using namespace share::schema; using namespace share; using namespace obrpc; namespace sql { ObDDLResolver::ObDDLResolver(ObResolverParams& params) : ObStmtResolver(params), block_size_(OB_DEFAULT_SSTABLE_BLOCK_SIZE), consistency_level_(INVALID_CONSISTENCY), index_scope_(NOT_SPECIFIED), replica_num_(0), tablet_size_(-1), pctfree_(OB_DEFAULT_PCTFREE), tablegroup_id_(OB_INVALID_ID), index_attributes_set_(OB_DEFAULT_INDEX_ATTRIBUTES_SET), charset_type_(CHARSET_INVALID), collation_type_(CS_TYPE_INVALID), use_bloom_filter_(false), expire_info_(), compress_method_(), comment_(), tablegroup_name_(), primary_zone_(), row_store_type_(MAX_ROW_STORE), store_format_(OB_STORE_FORMAT_INVALID), progressive_merge_num_(OB_DEFAULT_PROGRESSIVE_MERGE_NUM), storage_format_version_(OB_STORAGE_FORMAT_VERSION_INVALID), table_id_(OB_INVALID_ID), data_table_id_(OB_INVALID_ID), index_table_id_(OB_INVALID_ID), virtual_column_id_(OB_INVALID_ID), read_only_(false), with_rowid_(false), table_name_(), database_name_(), partition_func_type_(PARTITION_FUNC_TYPE_HASH), auto_increment_(1), index_name_(), index_keyname_(NORMAL_KEY), global_(true), store_column_names_(), hidden_store_column_names_(), zone_list_(), sort_column_array_(), storing_column_set_(), has_index_using_type_(false), index_using_type_(share::schema::USING_BTREE), locality_(), is_random_primary_zone_(false), max_used_part_id_(OB_INVALID_ID), duplicate_scope_(share::ObDuplicateScope::DUPLICATE_SCOPE_NONE), enable_row_movement_(false), table_dop_(DEFAULT_TABLE_DOP), hash_subpart_num_(-1) { table_mode_.reset(); } ObDDLResolver::~ObDDLResolver() {} int ObDDLResolver::get_part_str_with_type(ObPartitionFuncType part_func_type, ObString& func_str, ObSqlString& part_str) { int ret = OB_SUCCESS; ObString type_str; if (OB_FAIL(get_part_type_str(part_func_type, type_str))) { LOG_WARN("Failed to get part type str", K(ret)); } else if (OB_FAIL(part_str.append_fmt( "%.*s (%.*s)", type_str.length(), type_str.ptr(), func_str.length(), func_str.ptr()))) { LOG_WARN("Failed to append part str", K(ret)); } else { } // do nothing return ret; } /** * set default value for primary key */ int ObDDLResolver::get_primary_key_default_value(const ObObjType type, ObObj& default_value) { int ret = OB_SUCCESS; switch (type) { case ObTinyIntType: case ObSmallIntType: case ObMediumIntType: case ObInt32Type: case ObIntType: case ObUTinyIntType: case ObUSmallIntType: case ObUMediumIntType: case ObUInt32Type: case ObUInt64Type: default_value.set_int(type, 0); break; case ObFloatType: case ObUFloatType: default_value.set_float(0); break; case ObDoubleType: case ObUDoubleType: default_value.set_double(0); break; case ObNumberType: // set as string case ObUNumberType: case ObNumberFloatType: default_value.set_varchar("0"); default_value.set_type(ObVarcharType); break; case ObYearType: default_value.set_year(ObTimeConverter::ZERO_YEAR); break; case ObDateType: default_value.set_date(ObTimeConverter::ZERO_DATE); break; case ObTimeType: default_value.set_time(ObTimeConverter::ZERO_TIME); break; case ObDateTimeType: default_value.set_datetime(ObTimeConverter::ZERO_DATETIME); break; case ObTimestampTZType: case ObTimestampLTZType: case ObTimestampNanoType: default_value.set_otimestamp_value(type, ObOTimestampData()); break; case ObTimestampType: default_value.set_ext(ObActionFlag::OP_DEFAULT_NOW_FLAG); break; case ObCharType: case ObVarcharType: case ObNVarchar2Type: case ObNCharType: default_value.set_string(type, ObString("").ptr(), 0); break; case ObRawType: default_value.set_raw(ObString("").ptr(), 0); break; case ObIntervalYMType: default_value.set_interval_ym(ObIntervalYMValue()); break; case ObIntervalDSType: default_value.set_interval_ds(ObIntervalDSValue()); break; default: ret = OB_ERR_ILLEGAL_TYPE; SQL_RESV_LOG(WARN, "invalid type of default value", K(type), K(ret)); break; } return ret; } int update_datetime_default_value( ObObjParam& default_value, ParseNode& def_val, const ObObjType datetime_type, const int64_t action_flag) { int ret = OB_SUCCESS; int16_t scale = 0; default_value.set_ext(action_flag); default_value.set_param_meta(); if (def_val.value_ < 0) { scale = ObAccuracy::DDL_DEFAULT_ACCURACY[datetime_type].get_scale(); default_value.set_scale(scale); } else if (OB_ISNULL(def_val.children_) || OB_UNLIKELY(1 != def_val.num_child_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), K(def_val.children_), K(def_val.num_child_)); } else { if (NULL != def_val.children_[0]) { scale = static_cast(def_val.children_[0]->value_); } else if (lib::is_oracle_mode()) { scale = ObAccuracy::DDL_DEFAULT_ACCURACY[datetime_type].get_scale(); } else { scale = 0; } default_value.set_scale(scale); } return ret; } int ObDDLResolver::resolve_default_value(ParseNode* def_node, // const ObObjType column_data_type, ObObjParam& default_value) { int ret = OB_SUCCESS; ObString tmp_str; ObString str; ObObj val; int16_t scale = -1; ObIAllocator* name_pool = NULL; ParseNode* def_val = NULL; if (NULL != def_node) { def_val = def_node; if (def_node->type_ == T_CONSTR_DEFAULT || (def_node->type_ == T_CONSTR_ORIG_DEFAULT)) { def_val = def_node->children_[0]; } if (OB_ISNULL(allocator_) || OB_ISNULL(def_val)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "allocator_ or def_val is null", K(allocator_), K(ret)); } else { name_pool = static_cast(allocator_); if (OB_ISNULL(name_pool)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "name pool is null", K(name_pool), K(ret)); } } if (OB_FAIL(ret)) { // do nothing; } else { switch (def_val->type_) { case T_INT: default_value.set_int(def_val->value_); default_value.set_param_meta(); break; case T_UINT64: default_value.set_uint64(static_cast(def_val->value_)); default_value.set_param_meta(); break; case T_CHAR: case T_VARCHAR: case T_LOB: tmp_str.assign_ptr(const_cast(def_val->str_value_), static_cast(def_val->str_len_)); if ((OB_FAIL(ob_write_string(*name_pool, tmp_str, str)))) { SQL_RESV_LOG(WARN, "Can not malloc space for default value", K(ret)); break; } default_value.set_varchar(str); default_value.set_collation_type(session_info_->get_local_collation_connection()); default_value.set_param_meta(); break; case T_RAW: tmp_str.assign_ptr(const_cast(def_val->str_value_), static_cast(def_val->str_len_)); if ((OB_FAIL(ob_write_string(*name_pool, tmp_str, str)))) { SQL_RESV_LOG(WARN, "Can not malloc space for default value", K(ret)); break; } default_value.set_raw(str); default_value.set_param_meta(); break; case T_HEX_STRING: tmp_str.assign_ptr(const_cast(def_val->str_value_), static_cast(def_val->str_len_)); if ((OB_FAIL(ob_write_string(*name_pool, tmp_str, str)))) { SQL_RESV_LOG(WARN, "Can not malloc space for default value", K(ret)); break; } default_value.set_hex_string(str); default_value.set_scale(0); default_value.set_param_meta(); break; case T_YEAR: default_value.set_year(static_cast(def_val->value_)); default_value.set_scale(0); default_value.set_param_meta(); break; /* * mysql5.6 supports syntax like: c1 date|time|timestamp default date|time|timestamp'xxx' */ case T_DATE: { ObString time_str(static_cast(def_val->str_len_), def_val->str_value_); int32_t time_val = 0; if (OB_FAIL(ObTimeConverter::str_to_date(time_str, time_val))) { ret = OB_ERR_WRONG_VALUE; LOG_USER_ERROR(OB_ERR_WRONG_VALUE, "DATE", to_cstring(time_str)); } else { default_value.set_date(time_val); default_value.set_scale(0); default_value.set_param_meta(); } break; } case T_TIME: { ObString time_str(static_cast(def_val->str_len_), def_val->str_value_); int64_t time_val = 0; if (OB_FAIL(ObTimeConverter::str_to_time(time_str, time_val, &scale))) { ret = OB_ERR_WRONG_VALUE; LOG_USER_ERROR(OB_ERR_WRONG_VALUE, "TIME", to_cstring(time_str)); } else { default_value.set_time(time_val); default_value.set_scale(scale); default_value.set_param_meta(); } break; } case T_TIMESTAMP: { ObString time_str(static_cast(def_val->str_len_), def_val->str_value_); int64_t time_val = 0; ObTimeConvertCtx cvrt_ctx(TZ_INFO(session_info_), false); if (OB_FAIL(ObTimeConverter::str_to_datetime(time_str, cvrt_ctx, time_val, &scale))) { ret = OB_ERR_WRONG_VALUE; LOG_USER_ERROR(OB_ERR_WRONG_VALUE, "TIMESTAMP", to_cstring(time_str)); } else { default_value.set_datetime(time_val); default_value.set_scale(scale); default_value.set_param_meta(); } break; } case T_TIMESTAMP_TZ: { ObObjType value_type = ObMaxType; ObOTimestampData tz_value; ObTimeConvertCtx cvrt_ctx(TZ_INFO(session_info_), false); ObString time_str(static_cast(def_val->str_len_), def_val->str_value_); // if (OB_FAIL(ObTimeConverter::str_to_otimestamp(time_str, cvrt_ctx, tmp_type, ot_data))) { if (OB_FAIL(ObTimeConverter::literal_timestamp_validate_oracle(time_str, cvrt_ctx, value_type, tz_value))) { ret = OB_INVALID_DATE_VALUE; LOG_USER_ERROR(OB_INVALID_DATE_VALUE, "TIMESTAMP", to_cstring(time_str)); } else { /* use max scale bug:#18093350 */ default_value.set_otimestamp_value(value_type, tz_value); default_value.set_scale(OB_MAX_TIMESTAMP_TZ_PRECISION); default_value.set_param_meta(); } break; } case T_DATETIME: { ObString time_str(static_cast(def_val->str_len_), def_val->str_value_); int64_t time_val = 0; ObTimeConvertCtx cvrt_ctx(TZ_INFO(session_info_), false); if (OB_FAIL(ObTimeConverter::literal_date_validate_oracle(time_str, cvrt_ctx, time_val))) { ret = OB_ERR_WRONG_VALUE; LOG_USER_ERROR(OB_ERR_WRONG_VALUE, "DATE", to_cstring(time_str)); } else { default_value.set_datetime(time_val); default_value.set_scale(OB_MAX_DATE_PRECISION); default_value.set_param_meta(); } break; } case T_FLOAT: { int err = 0; double value = 0; char* endptr = NULL; value = ObCharset::strntod(def_val->str_value_, static_cast(def_val->str_len_), &endptr, &err); if (EOVERFLOW == err) { ret = OB_DATA_OUT_OF_RANGE; } else { default_value.set_float(static_cast(value)); default_value.set_param_meta(); } break; } case T_DOUBLE: { int err = 0; double value = 0; char* endptr = NULL; value = ObCharset::strntod(def_val->str_value_, static_cast(def_val->str_len_), &endptr, &err); if (EOVERFLOW == err) { ret = OB_DATA_OUT_OF_RANGE; } else { default_value.set_double(value); default_value.set_param_meta(); } break; } case T_NUMBER: case T_NUMBER_FLOAT: { // set as string ObString number(static_cast(def_val->str_len_), def_val->str_value_); if (OB_FAIL(ob_write_string(*name_pool, number, str))) { SQL_RESV_LOG(WARN, "Can not malloc space for default value", K(ret)); break; } default_value.set_varchar(str); default_value.set_type(ObVarcharType); default_value.set_collation_type(ObCharset::get_system_collation()); default_value.set_param_meta(); break; } case T_BOOL: default_value.set_bool(def_val->value_ == 1 ? true : false); default_value.set_param_meta(); break; case T_NULL: default_value.set_type(ObNullType); default_value.set_param_meta(); break; case T_FUN_SYS_CUR_TIMESTAMP: { ret = update_datetime_default_value( default_value, *def_val, ObTimestampType, ObActionFlag::OP_DEFAULT_NOW_FLAG); break; } case T_OP_POS: ret = resolve_default_value(def_val->children_[0], default_value); break; case T_OP_NEG: { ObObjParam old_obj; ret = resolve_default_value(def_val->children_[0], old_obj); if (OB_FAIL(ret)) { SQL_RESV_LOG(WARN, "Resolve default const value failed", K(ret)); } else if (ObIntType == old_obj.get_type()) { int64_t value = 0; old_obj.get_int(value); default_value.set_int(-value); default_value.set_param_meta(); } else if (ObFloatType == old_obj.get_type()) { float value = 0.0f; if (OB_FAIL(old_obj.get_float(value))) { SQL_RESV_LOG(WARN, "failed to get float value from old_obj", K(ret), K(old_obj)); } else { default_value.set_float(-value); default_value.set_param_meta(); } } else if (ObDoubleType == old_obj.get_type()) { double value = 0.0; if (OB_FAIL(old_obj.get_double(value))) { SQL_RESV_LOG(WARN, "failed to get double value", K(ret)); } else { default_value.set_double(-value); default_value.set_param_meta(); } } else if (T_NUMBER == def_val->children_[0]->type_) { ObString str; old_obj.get_varchar(str); char buffer[number::ObNumber::MAX_PRINTABLE_SIZE]; snprintf(buffer, sizeof(buffer), "-%.*s", str.length(), str.ptr()); if ((OB_FAIL(ob_write_string(*name_pool, ObString::make_string(buffer), str)))) { SQL_RESV_LOG(WARN, "Can not malloc space for default value", K(ret)); break; } default_value.set_varchar(str); default_value.set_collation_type(ObCharset::get_system_collation()); default_value.set_param_meta(); } else { ret = OB_ERR_PARSER_SYNTAX; SQL_RESV_LOG(WARN, "Invalid flag '-' in default value", K(ret)); } break; } case T_INTERVAL_YM: case T_INTERVAL_DS: case T_NVARCHAR2: case T_NCHAR: case T_UROWID: { // oracle's default value is stored as string, won't be here ret = OB_NOT_SUPPORTED; break; } default: ret = OB_ERR_ILLEGAL_TYPE; SQL_RESV_LOG(WARN, "Illegal type of default value", K(ret), K(def_val->type_)); break; } } } else { default_value.set_null(); default_value.set_param_meta(); } if (OB_SUCC(ret)) { _OB_LOG(DEBUG, "resolve default value: %s", to_cstring(default_value)); } return ret; } int ObDDLResolver::set_table_name(const ObString& table_name) { int ret = OB_SUCCESS; if (allocator_) { if (OB_FAIL(ob_write_string(*allocator_, table_name, table_name_))) { SQL_RESV_LOG(WARN, "deep copy table name failed", K(ret)); } } else { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "allocator is null", K(ret)); } return ret; } int ObDDLResolver::set_database_name(const ObString& database_name) { int ret = OB_SUCCESS; if (allocator_) { if (OB_FAIL(ob_write_string(*allocator_, database_name, database_name_))) { SQL_RESV_LOG(WARN, "deep copy table name failed", K(ret)); } } else { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "allocator is null", K(ret)); } return ret; } int ObDDLResolver::resolve_table_id_pre(ParseNode* node) { int ret = OB_SUCCESS; if (NULL != node) { ParseNode* option_node = NULL; int32_t num = 0; if (T_TABLE_OPTION_LIST != node->type_ || node->num_child_ < 1) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid parse node", K(ret)); } else if (OB_ISNULL(node->children_) || OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "node children or session_info_ is null", K(node->children_), K(session_info_), K(ret)); } else { num = node->num_child_; } for (int64_t i = 0; OB_SUCC(ret) && i < num; ++i) { if (OB_ISNULL(option_node = node->children_[i])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "node is null", K(ret)); } else if (option_node->type_ == T_TABLE_ID) { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { table_id_ = static_cast(option_node->children_[0]->value_); } } } } return ret; } int ObDDLResolver::resolve_table_options(ParseNode* node, bool is_index_option) { int ret = OB_SUCCESS; if (NULL != node) { ParseNode* option_node = NULL; int32_t num = 0; if (T_TABLE_OPTION_LIST != node->type_ || node->num_child_ < 1) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid parse node", K(ret)); } else if (OB_ISNULL(node->children_) || OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "node children or session_info_ is null", K(node->children_), K(session_info_), K(ret)); } else { num = node->num_child_; } for (int64_t i = 0; OB_SUCC(ret) && i < num; ++i) { if (OB_ISNULL(option_node = node->children_[i])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "node is null", K(ret)); } else if (OB_FAIL(resolve_table_option(option_node, is_index_option))) { SQL_RESV_LOG(WARN, "resolve table option failed", K(ret)); } } } if (OB_SUCC(ret)) { if (CHARSET_INVALID == charset_type_ && CS_TYPE_INVALID == collation_type_) { // The database character set and collation affect these aspects of server operation: // // For CREATE TABLE statements, the database character set and collation are used as default // values for table definitions if the table character set and collation are not specified. // To override this, provide explicit CHARACTER SET and COLLATE table options. int64_t coll_cs_db_int64 = -1; int64_t coll_db_int64 = -1; if (OB_FAIL(session_info_->get_sys_variable(share::SYS_VAR_CHARACTER_SET_DATABASE, coll_cs_db_int64))) { SQL_RESV_LOG(WARN, "fail to get sys variable character_set_database", K(ret)); } else if (OB_FAIL(session_info_->get_sys_variable(share::SYS_VAR_COLLATION_DATABASE, coll_db_int64))) { SQL_RESV_LOG(WARN, "fail to get sys variable collation_database", K(ret)); } else if (!ObCharset::is_valid_collation(coll_cs_db_int64) || !ObCharset::is_valid_collation(coll_db_int64)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid collation type", K(ret), K(coll_cs_db_int64), K(coll_db_int64)); } else { charset_type_ = ObCharset::charset_type_by_coll(static_cast(coll_cs_db_int64)); collation_type_ = static_cast(coll_db_int64); } } else if (OB_FAIL(ObCharset::check_and_fill_info(charset_type_, collation_type_))) { SQL_RESV_LOG(WARN, "fail to fill collation info", K(ret)); } } return ret; } /** * @param check_column_exist is used for 'alter table add index'/'create index' to ignore schema check * check_column_exist default is true */ int ObDDLResolver::add_storing_column(const ObString& column_name, bool check_column_exist, bool is_hidden) { int ret = OB_SUCCESS; ObString col_name; if (OB_ISNULL(schema_checker_) || OB_ISNULL(stmt_) || OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "schema checker or stmt cat not be null", K(ret)); } if (OB_SUCCESS == ret && check_column_exist) { ObColumnSchemaV2* column_schema = NULL; if (stmt::T_CREATE_TABLE == stmt_->get_stmt_type()) { ObCreateTableStmt* create_table_stmt = static_cast(stmt_); ObTableSchema& tbl_schema = create_table_stmt->get_create_table_arg().schema_; if (NULL == (column_schema = tbl_schema.get_column_schema(column_name))) { ret = OB_ERR_BAD_FIELD_ERROR; LOG_USER_ERROR( OB_ERR_BAD_FIELD_ERROR, column_name.length(), column_name.ptr(), table_name_.length(), table_name_.ptr()); } else if (ob_is_text_tc(column_schema->get_data_type())) { ret = OB_ERR_WRONG_KEY_COLUMN; LOG_USER_ERROR(OB_ERR_WRONG_KEY_COLUMN, column_name.length(), column_name.ptr()); } else if (ObTimestampTZType == column_schema->get_data_type()) { ret = OB_ERR_WRONG_KEY_COLUMN; LOG_USER_ERROR(OB_ERR_WRONG_KEY_COLUMN, column_name.length(), column_name.ptr()); } } if (OB_SUCC(ret)) { if (OB_ISNULL(column_schema)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "column schema is null", K(ret)); } else if (column_schema->get_rowkey_position() > 0) { // rowkey can't be used as storing column, so ignore it } else { // do nothing; } } } if (OB_SUCC(ret)) { ObColumnNameHashWrapper column_name_key(column_name); ObColumnNameWrapper column_key(column_name, 0); // prefix length of storing column is 0 bool check_prefix_len = true; if (is_column_exists(sort_column_array_, column_key, check_prefix_len)) { // column exists in sort columns, so ignore it } else if (OB_HASH_EXIST == storing_column_set_.exist_refactored(column_name_key)) { if (is_hidden) { // try add storing column by observer, and column is duplicate, just ignore } else { ret = OB_ERR_COLUMN_DUPLICATE; LOG_USER_ERROR(OB_ERR_COLUMN_DUPLICATE, column_name.length(), column_name.ptr()); } } else if (OB_FAIL(storing_column_set_.set_refactored(column_name_key))) { SQL_RESV_LOG(WARN, "set column name to storing column set failed", K(ret)); } else if (!is_hidden && OB_FAIL(store_column_names_.push_back(column_name))) { SQL_RESV_LOG(WARN, "add column name failed", K(column_name), K(ret)); } else if (is_hidden && OB_FAIL(hidden_store_column_names_.push_back(column_name))) { SQL_RESV_LOG(WARN, "add column name failed", K(column_name), K(ret)); } } return ret; } int ObDDLResolver::add_fulltext_column(const ObString& column_name) { int ret = OB_SUCCESS; ObColumnNameHashWrapper key_name(column_name); ObColumnNameWrapper key_column_name(column_name, 0); bool check_prefix_len = false; if (!is_column_exists(sort_column_array_, key_column_name, check_prefix_len)) { ret = OB_ERR_KEY_COLUMN_DOES_NOT_EXITS; LOG_USER_ERROR(OB_ERR_KEY_COLUMN_DOES_NOT_EXITS, column_name.length(), column_name.ptr()); } else if (OB_HASH_EXIST == (ret = fulltext_column_set_.exist_refactored(key_name))) { ret = OB_ERR_COLUMN_DUPLICATE; LOG_USER_ERROR(OB_ERR_COLUMN_DUPLICATE, column_name.length(), column_name.ptr()); } else if (OB_HASH_NOT_EXIST != ret) { LOG_WARN("check column name whether in fulltext columns failed", K(ret), K(column_name)); } else if (OB_FAIL(fulltext_column_set_.set_refactored(key_name))) { LOG_WARN("set column name to fulltext column set failed", K(ret), K(column_name)); } else if (OB_FAIL(fulltext_column_names_.push_back(column_name))) { LOG_WARN("add column name to fulltext columns failed", K(ret), K(column_name)); } return ret; } int ObDDLResolver::resolve_table_option(const ParseNode* option_node, const bool is_index_option) { int ret = OB_SUCCESS; const uint64_t tenant_id = session_info_->get_effective_tenant_id(); ObString database_name; uint64_t database_id = OB_INVALID_ID; if (OB_ISNULL(stmt_) || OB_ISNULL(allocator_) || OB_ISNULL(schema_checker_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "allocator_ or stmt_ or schema_checker_ cat not be null", K(ret)); } else { database_name = database_name_; } CHECK_COMPATIBILITY_MODE(session_info_); if (OB_FAIL(ret)) { // do nothing } else if (OB_FAIL(schema_checker_->get_database_id(tenant_id, database_name, database_id))) { SQL_RESV_LOG(WARN, "fail to get database_id.", K(ret), K(database_name), K(tenant_id)); } if (OB_SUCCESS == ret && NULL != option_node) { switch (option_node->type_) { case T_EXPIRE_INFO: { // //not supported in version(1.0) // ret = OB_NOT_SUPPORTED; // LOG_USER_ERROR(ret, "expire info in version(1.0)"); // if (stmt::T_CREATE_INDEX == stmt_->get_stmt_type()) { // ret = OB_ERR_PARSE_SQL; // SQL_RESV_LOG(WARN, "Expire info can not be specified in index option", K(ret)); // } // const bool is_index_table = false; // if (OB_ISNULL(option_node->children_)) { // ret = OB_ERR_UNEXPECTED; // SQL_RESV_LOG(WARN, "(the children of option_node is null", K(option_node->children_), K(ret)); // } else if (NULL != option_node->children_[0] && T_NULL == option_node->children_[0]->type_) { // //drop expire info // expire_info_.assign_ptr(NULL, 0); // } else { // ObRawExpr *expr = NULL; // ObString expire_info; // expire_info.assign_ptr(const_cast(option_node->str_value_), // static_cast(option_node->str_len_)); // if (OB_ISNULL(option_node->children_[0])) { // ret = OB_ERR_UNEXPECTED; // SQL_RESV_LOG(ERROR,"children can't be null", K(ret)); // } else if (OB_FAIL(ob_write_string(*allocator_, expire_info, expire_info_))) { // SQL_RESV_LOG(WARN, "write string failed", K(ret)); // } else { // if (stmt::T_ALTER_TABLE != stmt_->get_stmt_type()) { // if (OB_FAIL(schema_checker_->get_table_schema(tenant_id, database_id, table_name_, // is_index_table, &tab_schema))) { // SQL_RESV_LOG(WARN, "table is not exist", K(tenant_id), K(database_id), K_(table_name), // K(ret)); // } else if (OB_ISNULL(tab_schema)) { // ret = OB_ERR_UNEXPECTED; // SQL_RESV_LOG(WARN, "tab schema is null", K(tab_schema), K(ret)); // } else if ((tab_schema->get_progressive_merge_num() > 1 || progressive_merge_num_ > 1) // && tab_schema->get_index_tid_count() > 0) { // ret = OB_OP_NOT_ALLOW; // SQL_RESV_LOG(WARN, "this progressive merge num > 1 and contain index table", K(ret)); // } else if (OB_FAIL(resolve_sql_expr(*(option_node->children_[0]), expr, T_EXPIRE_SCOPE)) // || OB_FAIL(stmt_->get_condition_exprs().push_back(expr))) { // if (OB_ERR_BAD_FIELD_ERROR != ret) { // SQL_RESV_LOG(WARN, "Resolve expire info failed", K(ret)); // } // } // } else { // //mark alter table option // if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::EXPIRE_INFO))) { // SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); // } // } // } // } break; } case T_BLOCK_SIZE: { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { const int64_t block_size = option_node->children_[0]->value_; if (block_size < MIN_BLOCK_SIZE || block_size > MAX_BLOCK_SIZE) { ret = OB_ERR_INVALID_BLOCK_SIZE; SQL_RESV_LOG(WARN, "block size should between 1024 and 1048576", K(block_size), K(ret)); } else { block_size_ = block_size; } } if (OB_SUCCESS == ret && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::BLOCK_SIZE))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } break; } case T_REPLICA_NUM: { if (!is_index_option) { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { replica_num_ = static_cast(option_node->children_[0]->value_); if (replica_num_ <= 0 || MAX_REPLICA_NUM < replica_num_) { ret = OB_NOT_SUPPORTED; SQL_RESV_LOG(WARN, "Invalid replica_num", K_(replica_num), K(ret)); } } if (ret == OB_SUCCESS && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::REPLICA_NUM))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("index option should not specify replica num", K(ret)); } break; } case T_TABLET_SIZE: { if (!is_index_option) { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { tablet_size_ = option_node->children_[0]->value_; if (tablet_size_ < 0 || tablet_size_ & ((1 << 21) - 1)) { ret = OB_INVALID_CONFIG; SQL_RESV_LOG(WARN, "tablet_size must be a multiple of 2M", K_(tablet_size), K(ret)); } } if (ret == OB_SUCCESS && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::TABLET_SIZE))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("index option should not specify tablet size", K(ret)); } break; } case T_PCTFREE: { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(ret), K(option_node->children_[0])); } else { pctfree_ = static_cast(option_node->children_[0]->value_); if (pctfree_ < 0 || pctfree_ >= OB_MAX_PCTFREE) { if (share::is_oracle_mode()) { ret = OB_ERR_INVALID_PCTFREE_OR_PCTUSED_VALUE; } else { ret = OB_INVALID_CONFIG; } SQL_RESV_LOG(WARN, "invalid pctfree value", K(ret), K_(pctfree)); } } if (ret == OB_SUCCESS && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::PCTFREE))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } break; } case T_PCTUSED: { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(ret), K(option_node->children_[0])); } else { int64_t pctused = static_cast(option_node->children_[0]->value_); if (pctused <= 0 || pctused > OB_MAX_PCTUSED) { ret = OB_ERR_INVALID_PCTFREE_OR_PCTUSED_VALUE; SQL_RESV_LOG(WARN, "invalid pctused value", K(ret), K(pctused)); } } break; } case T_INITRANS: { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(ret), K(option_node->children_[0])); } else { int64_t initrans = static_cast(option_node->children_[0]->value_); if (initrans <= 0 || initrans > OB_MAX_TRANS) { ret = OB_ERR_INVALID_INITRANS_VALUE; SQL_RESV_LOG(WARN, "invalid initrans value", K(ret), K(initrans)); } } break; } case T_MAXTRANS: { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(ret), K(option_node->children_[0])); } else { int64_t maxtrans = static_cast(option_node->children_[0]->value_); if (maxtrans < 0 || maxtrans > OB_MAX_TRANS) { ret = OB_ERR_INVALID_MAXTRANS_VALUE; SQL_RESV_LOG(WARN, "invalid initrans value", K(ret), K(maxtrans)); } } break; } case T_STORAGE_OPTIONS: { if (0 == option_node->num_child_) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node's num child can not be 0", K(ret), K(option_node->num_child_)); } for (int64_t i = 0; OB_SUCC(ret) && i < option_node->num_child_; ++i) { if (OB_ISNULL(option_node->children_[i])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null!", K(ret), K(i)); } else { // TODO: only support storage syntax } } break; } case T_COMPRESSION: { if (!is_index_option) { ObString tmp_str; if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { tmp_str.assign_ptr(const_cast(option_node->children_[0]->str_value_), static_cast(option_node->children_[0]->str_len_)); compress_method_ = tmp_str.trim(); } bool is_find = false; const char* find_compress_name = NULL; for (int i = 0; OB_SUCC(ret) && i < ARRAYSIZEOF(common::compress_funcs) && !is_find; i++) { if (0 == ObString::make_string(compress_funcs[i]).case_compare(compress_method_)) { is_find = true; find_compress_name = compress_funcs[i]; } } if (OB_FAIL(ret)) { // do nothing } else if (OB_ISNULL(find_compress_name)) { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, to_cstring(compress_method_)); } else if (OB_FAIL(ob_write_string(*allocator_, find_compress_name, compress_method_))) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "write string failed", K(ret)); } else { } if (ret == OB_SUCCESS && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::COMPRESS_METHOD))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("index option should not specify compress method", K(ret)); } break; } case T_STORE_FORMAT: { if (GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_2100) { ret = OB_NOT_SUPPORTED; LOG_WARN("Create table with store format option not supported in old version", K(ret)); } else if (!is_index_option) { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { store_format_ = static_cast(option_node->children_[0]->value_); if (!ObStoreFormat::is_store_format_valid(store_format_, share::is_oracle_mode())) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "Unexpected invalid store format value", K_(store_format), K(ret)); } else { row_store_type_ = ObStoreFormat::get_row_store_type(store_format_); } if (OB_SUCC(ret) && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::STORE_FORMAT))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } else if (share::is_oracle_mode()) { const char* compress_name = ObStoreFormat::get_store_format_compress_name(store_format_); if (OB_ISNULL(compress_name)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "Unexpected null compress_name", K_(store_format), K(ret)); } else if (OB_FAIL( ob_write_string(*allocator_, ObString::make_string(compress_name), compress_method_))) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "write string failed", K(ret)); } else if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::COMPRESS_METHOD))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("index option should not specify compress format", K(ret)); } break; } case T_PROGRESSIVE_MERGE_NUM: { if (!is_index_option) { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { progressive_merge_num_ = option_node->children_[0]->value_; } if (OB_FAIL(ret)) { // do nothing } else if (progressive_merge_num_ < 0 || progressive_merge_num_ > MAX_PROGRESSIVE_MERGE_NUM) { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "progressive_merge_num"); } else { if (stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::PROGRESSIVE_MERGE_NUM))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } else if (stmt::T_CREATE_TABLE == stmt_->get_stmt_type()) { ObCreateTableStmt* create_table_stmt = static_cast(stmt_); ObTableSchema& tbl_schema = create_table_stmt->get_create_table_arg().schema_; if (!tbl_schema.is_user_table()) { ret = OB_OP_NOT_ALLOW; SQL_RESV_LOG(WARN, "only allow to set progressive merge num for data table", K(ret)); } } else { ret = OB_ERR_PARSE_SQL; SQL_RESV_LOG(WARN, "PROGRESSIVE_MERGE_NUM can not be specified in creating index", K(ret)); } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("index option should not specify progressive merge num", K(ret)); } break; } case T_STORAGE_FORMAT_VERSION: { if (!is_index_option) { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { storage_format_version_ = option_node->children_[0]->value_; } if (OB_FAIL(ret)) { // do nothing } else if (storage_format_version_ < OB_STORAGE_FORMAT_VERSION_V1 || storage_format_version_ >= OB_STORAGE_FORMAT_VERSION_MAX) { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "invalid storage format version"); } else { if (stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::STORAGE_FORMAT_VERSION))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } else if (stmt::T_CREATE_TABLE == stmt_->get_stmt_type()) { ObCreateTableStmt* create_table_stmt = static_cast(stmt_); ObTableSchema& tbl_schema = create_table_stmt->get_create_table_arg().schema_; if (!tbl_schema.is_user_table()) { ret = OB_OP_NOT_ALLOW; SQL_RESV_LOG(WARN, "only allow to set storage format version for data table", K(ret)); } } else { ret = OB_ERR_PARSE_SQL; SQL_RESV_LOG(WARN, "STORAGE_FORMAT_VERSION can not be specified in creating index", K(ret)); } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("index option should be be specified storage_format_version", K(ret)); } break; } case T_USE_BLOOM_FILTER: { if (!is_index_option) { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { use_bloom_filter_ = option_node->children_[0]->value_ ? true : false; } if (OB_SUCCESS == ret && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::USE_BLOOM_FILTER))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("index option should not specify use bloom filter", K(ret)); } break; } case T_INDEX_SCOPE: { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { index_scope_ = option_node->children_[0]->value_ == 0 ? LOCAL_INDEX : GLOBAL_INDEX; } if (OB_SUCCESS == ret && GLOBAL_INDEX == index_scope_) { if (OB_ISNULL(option_node->children_[1])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[1]), K(ret)); } else if (0 != STRNCMP("GLOBAL", static_cast(option_node->children_[1]->str_value_), option_node->children_[1]->str_len_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "invalid index type!", K(ret)); } } if (OB_SUCCESS == ret && LOCAL_INDEX == index_scope_) { if (OB_ISNULL(option_node->children_[1])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[1]), K(ret)); } else if (0 != STRNCMP("LOCAL", static_cast(option_node->children_[1]->str_value_), option_node->children_[1]->str_len_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "invalid index type!", K(ret)); } } break; } case T_REVERSE: { // support dummy syntax only break; } case T_STORING_COLUMN_LIST: { ParseNode* cur_node = NULL; ObString column_name; if (OB_ISNULL(option_node->children_[0]) || T_STORING_COLUMN_LIST != option_node->type_ || option_node->num_child_ < 1) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "invalid node type and node child!", K(ret)); } for (int64_t i = 0; OB_SUCCESS == ret && i < option_node->num_child_; i++) { if (OB_ISNULL(option_node->children_[i])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid node type and node child!", K(ret)); } else { cur_node = option_node->children_[i]; if (OB_ISNULL(cur_node)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "invalid node type and node child!", K(cur_node), K(ret)); } else { int32_t len = static_cast(cur_node->str_len_); column_name = ObString(len, len, cur_node->str_value_); } } if (OB_FAIL(ret)) { } else if (stmt::T_ALTER_TABLE == stmt_->get_stmt_type() || stmt::T_CREATE_INDEX == stmt_->get_stmt_type()) { bool check_column_exist = false; if (OB_FAIL(add_storing_column(column_name, check_column_exist))) { SQL_RESV_LOG(WARN, "Add storing column failed", K(ret), K(column_name)); } } else { if (OB_FAIL(add_storing_column(column_name))) { SQL_RESV_LOG(WARN, "Add storing column failed", K(ret), K(column_name)); } if (OB_SUCCESS == ret && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::TABLEGROUP_NAME))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } } } break; } case T_PARSER_NAME: { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("option_node child is null"); } else { int32_t str_len = static_cast(option_node->children_[0]->str_len_); parser_name_.assign_ptr(option_node->children_[0]->str_value_, str_len); } break; } case T_WITH_ROWID: { with_rowid_ = true; break; } case T_COMMENT: { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { comment_ = ObString(option_node->children_[0]->str_len_, option_node->children_[0]->str_value_); ObCollationType client_cs_type = session_info_->get_local_collation_connection(); if (OB_FAIL(ObSQLUtils::copy_and_convert_string_charset( *allocator_, comment_, comment_, client_cs_type, CS_TYPE_UTF8MB4_BIN))) { LOG_WARN("fail to convert comment to utf8", K(ret)); } } if (OB_SUCC(ret)) { if (comment_.length() > MAX_TABLE_COMMENT_LENGTH) { comment_ = ""; if (is_index_option) { ret = OB_ERR_TOO_LONG_INDEX_COMMENT; LOG_USER_ERROR(OB_ERR_TOO_LONG_INDEX_COMMENT, MAX_INDEX_COMMENT_LENGTH); } else { ret = OB_ERR_TOO_LONG_TABLE_COMMENT; LOG_USER_ERROR(OB_ERR_TOO_LONG_TABLE_COMMENT, MAX_TABLE_COMMENT_LENGTH); } } } if (OB_SUCCESS == ret && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::COMMENT))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } break; } case T_TABLEGROUP: { if (!is_index_option) { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { tablegroup_name_.assign_ptr((char*)(option_node->children_[0]->str_value_), static_cast(option_node->children_[0]->str_len_)); tablegroup_id_ = OB_INVALID_ID; } if (OB_SUCCESS == ret && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::TABLEGROUP_NAME))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("index option should not specify tablegrouop", K(ret)); } break; } case T_TABLE_MODE: { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { bool is_sync_ddl_user = false; ObString table_mode_str(static_cast(option_node->children_[0]->str_len_), (char*)(option_node->children_[0]->str_value_)); if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(session_info_, is_sync_ddl_user))) { LOG_WARN("Failed to check sync_ddl_user", K(ret)); } else if (is_sync_ddl_user) { // in backup mode if (OB_FAIL(ObBackUpTableModeOp::get_table_mode(table_mode_str, table_mode_))) { LOG_WARN("Failed to get table mode from string", K(ret), K(table_mode_str)); } } else if (0 == table_mode_str.case_compare("normal")) { table_mode_.mode_flag_ = TABLE_MODE_NORMAL; } else { ret = OB_ERR_PARSER_SYNTAX; } if (OB_FAIL(ret)) { SQL_RESV_LOG(WARN, "failed to resolve table mode str!", K(ret)); } } if (OB_SUCCESS == ret && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::TABLE_MODE))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } else { ObTableSchema tmp_table_schema; if (OB_FAIL(get_table_schema_for_check(tmp_table_schema))) { LOG_WARN("get table schema failed", K(ret)); } else if (table_mode_.mode_flag_ != TABLE_MODE_NORMAL) { // alter table change PK_MODE not suppoted ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "Unsupported table mode"); SQL_RESV_LOG(WARN, "Unsupported table mode", K(ret), K(table_mode_)); } else { table_mode_.pk_mode_ = tmp_table_schema.get_table_mode_struct().pk_mode_; } } } break; } case T_CHARSET: { if (!is_index_option) { if (stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { ret = OB_NOT_SUPPORTED; SQL_RESV_LOG(WARN, "Not support to alter charset", K(ret)); } else if (CHARSET_INVALID == charset_type_) { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { ObString node_value(option_node->children_[0]->str_len_, option_node->children_[0]->str_value_); ObString charset = node_value.trim(); ObCharsetType charset_type = ObCharset::charset_type(charset); if (CHARSET_INVALID == charset_type) { ret = OB_ERR_UNKNOWN_CHARSET; LOG_USER_ERROR(OB_ERR_UNKNOWN_CHARSET, charset.length(), charset.ptr()); } else { charset_type_ = charset_type; } } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("index option should not specify charset"); } break; } case T_COLLATION: { if (!is_index_option) { if (stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { ret = OB_ERR_PARSE_SQL; SQL_RESV_LOG(WARN, "Not support to alter collation", K(ret)); } else if (CS_TYPE_INVALID == collation_type_) { ObString node_value(option_node->str_len_, option_node->str_value_); ObString collation = node_value.trim(); ObCollationType collation_type = ObCharset::collation_type(collation); if (CS_TYPE_INVALID == collation_type) { ret = OB_ERR_UNKNOWN_COLLATION; LOG_USER_ERROR(OB_ERR_UNKNOWN_COLLATION, collation.length(), collation.ptr()); } else { collation_type_ = collation_type; } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("index option should not specify collation", K(ret)); } break; } case T_TABLE_ID: { if (!is_index_option) { if (stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { ret = OB_ERR_PARSE_SQL; SQL_RESV_LOG(WARN, "Not support to alter table id", K(ret)); break; } if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { table_id_ = static_cast(option_node->children_[0]->value_); if (is_cte_table(table_id_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("This table cann't be a cte table", K(ret)); } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("index option should not specify table_id", K(ret)); } break; } case T_DATA_TABLE_ID: { if (is_index_option && stmt::T_CREATE_INDEX == stmt_->get_stmt_type()) { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { uint64_t table_id = static_cast(option_node->children_[0]->value_); // bool is_sync_ddl_user = false; // if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(session_info_, is_sync_ddl_user))) { // LOG_WARN("Failed to check check_sync_ddl_user", K(ret)); // } else if (!is_sync_ddl_user) { // ret = OB_ERR_PARSE_SQL; // LOG_WARN("Only support for sync ddl user to specify data_table_id", K(ret), // K(session_info_->get_user_name())); // } else { data_table_id_ = table_id; // } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("only create index can specify data_table_id for restore purpose", K(ret)); } break; } case T_INDEX_TABLE_ID: { if (is_index_option && stmt::T_CREATE_INDEX == stmt_->get_stmt_type()) { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { uint64_t table_id = static_cast(option_node->children_[0]->value_); // bool is_sync_ddl_user = false; // if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(session_info_, is_sync_ddl_user))) { // LOG_WARN("Failed to check check_sync_ddl_user", K(ret)); // } else if (!is_sync_ddl_user) { // ret = OB_ERR_PARSE_SQL; // LOG_WARN("Only support for sync ddl user to specify index_table_id", K(ret), // K(session_info_->get_user_name())); // } else { index_table_id_ = table_id; // } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("only create index can specify index_table_id for restore purpose", K(ret)); } break; } case T_VIRTUAL_COLUMN_ID: { if (is_index_option && stmt::T_CREATE_INDEX == stmt_->get_stmt_type()) { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option node child is null", K(option_node->children_[0]), K(ret)); } else { bool is_sync_ddl_user = false; if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(session_info_, is_sync_ddl_user))) { LOG_WARN("Failed to check check_sync_ddl_user", K(ret)); } else if (!is_sync_ddl_user) { ret = OB_ERR_PARSE_SQL; LOG_WARN("Only support for sync ddl user to specify index_table_id", K(ret), K(session_info_->get_user_name())); } else { virtual_column_id_ = static_cast(option_node->children_[0]->value_); } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("only create index can sepcify virtual column id for restore purpose", K(ret)); } break; } case T_MAX_USED_PART_ID: { bool is_sync_ddl_user = false; if (stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { ret = OB_ERR_PARSE_SQL; SQL_RESV_LOG(WARN, "not support alter table with max_used_part_id", K(ret)); } else if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(session_info_, is_sync_ddl_user))) { SQL_RESV_LOG(WARN, "Failed to check sync_dll_user", K(ret)); } else if (!is_sync_ddl_user) { ret = OB_ERR_PARSE_SQL; SQL_RESV_LOG(WARN, "only support for sync ddl user to create table with max_used_part_id", K(ret), K(session_info_->get_user_name())); } else { max_used_part_id_ = static_cast(option_node->children_[0]->value_); } break; } case T_PRIMARY_ZONE: { if (!is_index_option) { ObString tmp_str; if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else if (T_DEFAULT == option_node->children_[0]->type_) { if (GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_2000) { ret = OB_OP_NOT_ALLOW; SQL_RESV_LOG(WARN, "set primary_zone DEFAULT is not allowed now", K(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "set primary_zone DEFAULT"); } } else if (T_RANDOM == option_node->children_[0]->type_) { if (GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_2000) { ret = OB_OP_NOT_ALLOW; SQL_RESV_LOG(WARN, "set primary_zone RANDOM is not allowed now", K(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "set primary_zone RANDOM"); } else { primary_zone_.assign_ptr( common::OB_RANDOM_PRIMARY_ZONE, static_cast(strlen(common::OB_RANDOM_PRIMARY_ZONE))); } } else { tmp_str.assign_ptr(const_cast(option_node->children_[0]->str_value_), static_cast(option_node->children_[0]->str_len_)); primary_zone_ = tmp_str.trim(); if (GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_2000 && primary_zone_.empty()) { ret = OB_OP_NOT_ALLOW; SQL_RESV_LOG(WARN, "set primary_zone empty is not allowed now", K(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "set primary_zone empty"); } } if (OB_SUCCESS == ret && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { bool is_sync_ddl_user = false; if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(session_info_, is_sync_ddl_user))) { LOG_WARN("Failed to check check_sync_ddl_user", K(ret)); } else if (is_sync_ddl_user) { ret = OB_IGNORE_SQL_IN_RESTORE; LOG_WARN( "Cannot support for sync ddl user to alter primary zone", K(ret), K(session_info_->get_user_name())); } else if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::PRIMARY_ZONE))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("index option should not specify primary zone", K(ret)); } break; } case T_READ_ONLY: { if (!is_index_option) { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "read only options can not be null", K(ret)); } else if (T_ON == option_node->children_[0]->type_) { read_only_ = true; } else if (T_OFF == option_node->children_[0]->type_) { read_only_ = false; } else { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "unknown read only options", K(ret)); } if (OB_SUCCESS == ret && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(obrpc::ObAlterTableArg::READ_ONLY))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("index option should not specify read only", K(ret)); } break; } case T_AUTO_INCREMENT: { if (!is_index_option) { // parser filters negative value errno = 0; int err = 0; uint64_t auto_increment = 0; if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "read only options can not be null", K(ret)); } else { auto_increment = ObCharset::strntoull(option_node->children_[0]->str_value_, static_cast(option_node->children_[0]->str_len_), 10, &err); } /* If the value read is out of the range of representable values by a long long int, * the function returns LLONG_MAX or LLONG_MIN, and errno is set to ERANGE. */ if (OB_FAIL(ret)) { // do nothing } else if (ERANGE == err && (UINT_MAX == auto_increment || 0 == auto_increment)) { ret = OB_DATA_OUT_OF_RANGE; } else if (EDOM == err) { ObString node_str( static_cast(option_node->children_[0]->str_len_), option_node->children_[0]->str_value_); ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD; SQL_RESV_LOG(WARN, "failed, invalid value", K(auto_increment), K(node_str), K(err), K(ret)); LOG_USER_ERROR(OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD, node_str.length(), node_str.ptr()); } else { auto_increment_ = auto_increment; } if (OB_SUCCESS == ret && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::AUTO_INCREMENT))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("index option should not specify autoincrement id", K(ret)); } break; } case T_TABLE_RENAME: { if (!is_index_option) { if (stmt::T_ALTER_TABLE != stmt_->get_stmt_type()) { ret = OB_ERR_RESOLVE_SQL; SQL_RESV_LOG(WARN, "Can't alter table name when creating table", K(ret)); } else { ParseNode* relation_node = NULL; ObString new_database_name; if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "read only options can not be null", K(ret)); } else { relation_node = option_node->children_[0]; } if (OB_FAIL(ret)) { } else if (OB_ISNULL(relation_node)) { ret = OB_ERR_PARSE_SQL; SQL_RESV_LOG(WARN, "table relation node should not be null!", K(ret)); } else if (OB_FAIL(resolve_table_relation_node(relation_node, table_name_, new_database_name))) { } else if (table_name_.empty()) { ret = OB_WRONG_TABLE_NAME; LOG_USER_ERROR(OB_WRONG_TABLE_NAME, table_name_.length(), table_name_.ptr()); } else if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::TABLE_NAME))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } else if (share::is_oracle_mode()) { ParseNode* new_db_node = relation_node->children_[0]; if (OB_ISNULL(new_db_node)) { database_name_ = static_cast(stmt_)->get_org_database_name(); } else { ret = OB_ERR_ALTER_TABLE_RENAME_WITH_OPTION; SQL_RESV_LOG(WARN, "new_db_node should be null in oracle mode", K(ret)); } } else { database_name_ = new_database_name; } } } else { ret = OB_NOT_SUPPORTED; LOG_WARN("index option should not rename table", K(ret)); } break; } case T_USING_BTREE: { has_index_using_type_ = true; index_using_type_ = USING_BTREE; break; } case T_USING_HASH: { has_index_using_type_ = true; index_using_type_ = USING_HASH; break; } case T_ENGINE: { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "engine node can not be null", K(ret)); } else { ObString engine_name( static_cast(option_node->children_[0]->str_len_), option_node->children_[0]->str_value_); LOG_USER_WARN(OB_ERR_UNKNOWN_STORAGE_ENGINE, engine_name.length(), engine_name.ptr()); SQL_RESV_LOG(WARN, "unknown engine", K(engine_name), K(ret)); ret = OB_SUCCESS; } break; } case T_INVISIBLE: { index_attributes_set_ |= (uint64_t)1 << ObTableSchema::INDEX_VISIBILITY; break; } case T_VISIBLE: { /*do nothing default is visible*/ index_attributes_set_ &= ~((uint64_t)1 << ObTableSchema::INDEX_VISIBILITY); break; } case T_DUPLICATE_SCOPE: { ObString duplicate_scope_str; share::ObDuplicateScope my_duplicate_scope = share::ObDuplicateScope::DUPLICATE_SCOPE_MAX; if (nullptr == option_node->children_ || 1 != option_node->num_child_) { ret = common::OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid replicate scope arg", K(ret), "num_child", option_node->num_child_); } else if (nullptr == option_node->children_[0]) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option node child is null", K(ret)); } else { duplicate_scope_str.assign_ptr(const_cast(option_node->children_[0]->str_value_), static_cast(option_node->children_[0]->str_len_)); duplicate_scope_str = duplicate_scope_str.trim(); if (OB_FAIL( ObDuplicateScopeChecker::convert_duplicate_scope_string(duplicate_scope_str, my_duplicate_scope))) { SQL_RESV_LOG(WARN, "fail to convert replicate scope string", K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "duplicate_scope"); } else { duplicate_scope_ = my_duplicate_scope; } if (OB_SUCC(ret) && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::DUPLICATE_SCOPE))) { LOG_WARN("fail to add member to bitset!", K(ret)); } } } break; } case T_LOCALITY: { if (NULL == option_node->children_ || option_node->num_child_ != 2) { ret = common::OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid locality argument", K(ret), "num_child", option_node->num_child_); } else if (T_DEFAULT == option_node->children_[0]->type_) { if (GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_2000) { ret = OB_OP_NOT_ALLOW; SQL_RESV_LOG(WARN, "set locality DEFAULT is not allowed now", K(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "set locality DEFAULT"); } } else { int64_t locality_length = option_node->children_[0]->str_len_; const char* locality_str = option_node->children_[0]->str_value_; common::ObString locality(locality_length, locality_str); if (OB_UNLIKELY(locality_length > common::MAX_LOCALITY_LENGTH)) { ret = common::OB_ERR_TOO_LONG_IDENT; SQL_RESV_LOG(WARN, "locality length is beyond limit", K(ret), K(locality)); LOG_USER_ERROR(OB_ERR_TOO_LONG_IDENT, locality.length(), locality.ptr()); } else if (GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_2000 && 0 == locality_length) { ret = OB_OP_NOT_ALLOW; SQL_RESV_LOG(WARN, "set locality empty is not allowed now", K(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "set locality empty"); } else { locality_.assign_ptr(locality_str, static_cast(locality_length)); } } if (OB_SUCC(ret) && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { bool is_sync_ddl_user = false; if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(session_info_, is_sync_ddl_user))) { LOG_WARN("Failed to check sync_dll_user", K(ret)); } else if (is_sync_ddl_user) { ret = OB_IGNORE_SQL_IN_RESTORE; LOG_WARN("Cannot support for sync ddl user to alter locality", K(ret), K(session_info_->get_user_name())); } else if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::LOCALITY))) { SQL_RESV_LOG(WARN, "fail to add member to bitset!", K(ret)); } else if (nullptr == option_node->children_[1]) { // not force alter locality } else if (option_node->children_[1]->type_ != T_FORCE) { ret = common::OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "invalid node", K(ret)); } else if (OB_FAIL(alter_table_bitset_.add_member(obrpc::ObAlterTableArg::FORCE_LOCALITY))) { SQL_RESV_LOG(WARN, "fail to add force locality member to bitset", K(ret)); } } break; } case T_ENABLE_ROW_MOVEMENT: { if (NULL == option_node->children_ || 1 != option_node->num_child_ || T_BOOL != option_node->children_[0]->type_) { ret = common::OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid row movement argument", K(ret), "num_child", option_node->num_child_); } else { enable_row_movement_ = static_cast(option_node->children_[0]->value_); if (stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::ENABLE_ROW_MOVEMENT))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } } break; } case T_PARALLEL: { if (OB_ISNULL(option_node->children_[0])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "option_node child is null", K(option_node->children_[0]), K(ret)); } else { const int64_t table_dop = option_node->children_[0]->value_; if (table_dop <= 0) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid table dop", K(table_dop), K(ret)); } else { table_dop_ = table_dop; } } if (OB_SUCC(ret) && stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(alter_table_bitset_.add_member(ObAlterTableArg::TABLE_DOP))) { SQL_RESV_LOG(WARN, "failed to add member to bitset!", K(ret)); } } break; } default: { /* won't be here */ ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "should not reach here", K(option_node->type_), K(ret)); break; } } } return ret; } int ObDDLResolver::resolve_column_definition_ref( ObColumnSchemaV2& column, ParseNode* node /* column_definition_def */, bool is_resolve_for_alter_table) { int ret = OB_SUCCESS; ObString name; int32_t name_length = 0; const char* name_ptr = nullptr; if (OB_ISNULL(node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid parser tree!", K(ret), K(node)); } else if (T_COLUMN_REF != node->type_ || 3 != node->num_child_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid parser tree!", K(ret), K(node->type_), K(node->num_child_)); } else { ParseNode* db_name_node = node->children_[0]; ParseNode* table_name_node = node->children_[1]; if (is_oracle_mode()) { if (OB_NOT_NULL(table_name_node) || OB_NOT_NULL(db_name_node)) { ret = OB_ERR_ONLY_SIMPLE_COLUMN_NAME_ALLOWED; LOG_WARN("only simple column names allowed here", K(ret)); } } else { if (NULL != db_name_node) { ObString dbname(db_name_node->str_len_, db_name_node->str_value_); if (0 != dbname.compare(database_name_)) { ret = OB_WRONG_DB_NAME; LOG_WARN("invalid database name", K(ret)); LOG_USER_ERROR(OB_WRONG_DB_NAME, dbname.length(), dbname.ptr()); } } if (OB_FAIL(ret)) { } else if (NULL != table_name_node) { ObString table_name(table_name_node->str_len_, table_name_node->str_value_); if (0 != table_name.compare(table_name_)) { ret = OB_WRONG_TABLE_NAME; LOG_WARN("invalid table name", K(ret)); LOG_USER_ERROR(OB_WRONG_TABLE_NAME, table_name.length(), table_name.ptr()); } } } } if (OB_FAIL(ret)) { } else if (OB_FAIL(resolve_column_name(name, node->children_[2]))) { LOG_WARN("resolve column name failed", K(ret)); } else if (is_resolve_for_alter_table) { AlterColumnSchema& alter_column_schema = static_cast(column); if (OB_FAIL(alter_column_schema.set_origin_column_name(name))) { SQL_RESV_LOG(WARN, "fail to set origin column name", K(name), K(ret)); } } else if (OB_FAIL(column.set_column_name(name))) { SQL_RESV_LOG(WARN, "fail to set column name", K(name), K(ret)); } return ret; } int ObDDLResolver::resolve_column_name(common::ObString& col_name, ParseNode* node /* column_name */) { int ret = OB_SUCCESS; if (OB_ISNULL(node) || T_IDENT != node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid parser tree", K(ret)); } else { col_name.assign_ptr(node->str_value_, node->str_len_); int32_t name_length = col_name.length(); const char* name_ptr = col_name.ptr(); if (name_length > OB_MAX_COLUMN_NAME_LENGTH) { ret = OB_ERR_TOO_LONG_IDENT; _SQL_RESV_LOG( WARN, "identifier name '%.*s' is too long, ret=%d", static_cast(name_length), name_ptr, ret); LOG_USER_ERROR(OB_ERR_TOO_LONG_IDENT, static_cast(name_length), name_ptr); } else if (0 == name_length) { ret = OB_WRONG_COLUMN_NAME; _SQL_RESV_LOG(WARN, "identifier name '%.*s' is empty, ret=%d", static_cast(name_length), name_ptr, ret); LOG_USER_ERROR(OB_WRONG_COLUMN_NAME, static_cast(name_length), name_ptr); } else { ObCollationType cs_type = CS_TYPE_INVALID; if (share::is_oracle_mode() && 0 == col_name.case_compare(OB_HIDDEN_LOGICAL_ROWID_COLUMN_NAME)) { ret = OB_ERR_BAD_FIELD_ERROR; LOG_USER_ERROR(OB_ERR_BAD_FIELD_ERROR, name_length, name_ptr, table_name_.length(), table_name_.ptr()); LOG_WARN("invalid rowid column", K(ret)); } else if (OB_FAIL(session_info_->get_collation_connection(cs_type))) { LOG_WARN("fail to get collation_connection", K(ret)); } else if (OB_FAIL(ObSQLUtils::check_column_name(cs_type, col_name))) { SQL_RESV_LOG(WARN, "fail to check column name", K(col_name), K(ret)); } } } return ret; } int ObDDLResolver::resolve_column_definition(ObColumnSchemaV2& column, ParseNode* node, /* column_definition */ ObColumnResolveStat& resolve_stat, bool& is_modify_column_visibility, common::ObString& pk_name, const bool is_add_column, const bool is_modify_column, const bool is_oracle_temp_table, const bool is_create_table_as) { int ret = OB_SUCCESS; ParseNode* column_definition_ref_node = NULL; if (T_COLUMN_DEFINITION != node->type_ || node->num_child_ < COLUMN_DEFINITION_NUM_CHILD || OB_ISNULL(allocator_) || OB_ISNULL(node->children_) || OB_ISNULL(node->children_[0]) || T_COLUMN_REF != node->children_[0]->type_ || COLUMN_DEF_NUM_CHILD != node->children_[0]->num_child_ || OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG( WARN, "invalid parse node", K(ret), K(node->type_), K(node->num_child_), K_(allocator), K_(session_info)); } else { resolve_stat.reset(); column_definition_ref_node = node->children_[0]; ParseNode* table_node = column_definition_ref_node->children_[1]; if (is_oracle_mode() && OB_NOT_NULL(table_node)) { ret = OB_ERR_ONLY_SIMPLE_COLUMN_NAME_ALLOWED; LOG_WARN("only simple column names allowed here", K(ret)); } else if (OB_SUCC(resolve_column_definition_ref(column, column_definition_ref_node, false))) { // empty } else { SQL_RESV_LOG(WARN, "fail to resolve column_definition_ref", K(ret)); } } ParseNode* type_node = NULL; if (OB_SUCC(ret)) { type_node = node->children_[1]; if (OB_ISNULL(type_node)) { if (share::is_oracle_mode() && (is_modify_column || GEN_COLUMN_DEFINITION_NUM_CHILD == node->num_child_ || is_create_table_as)) { // allow data_type node to be null in Oracle mode // 1. alter table column // 2. generated column def // 3. create table as if (is_create_table_as) { // mock a dummy data_type, will override in resolve subquery phase ObDataType data_type; column.set_data_type(ObUInt64Type); column.set_charset_type(CHARSET_BINARY); column.set_collation_type(CS_TYPE_BINARY); } } else { ret = OB_ERR_INVALID_DATATYPE; LOG_WARN("type_node is invalid", K(ret)); } } else if (OB_UNLIKELY(!ob_is_valid_obj_type(static_cast(type_node->type_)))) { ret = OB_ERR_INVALID_DATATYPE; SQL_RESV_LOG(WARN, "type_node or stmt_ or datatype is invalid", K(ret)); } } if (OB_SUCC(ret) && type_node != NULL) { ObDataType data_type; if (OB_FAIL(ObResolverUtils::resolve_data_type(*type_node, column.get_column_name_str(), data_type, (OB_NOT_NULL(session_info_) && is_oracle_mode()), session_info_->get_session_nls_params()))) { LOG_WARN("resolve data type failed", K(ret), K(column.get_column_name_str())); } else if (ObExtendType == data_type.get_obj_type()) { ret = OB_NOT_SUPPORTED; } else { column.set_meta_type(data_type.get_meta_type()); column.set_accuracy(data_type.get_accuracy()); column.set_charset_type(data_type.get_charset_type()); column.set_collation_type(data_type.get_collation_type()); if (data_type.is_binary_collation()) { column.set_binary_collation(true); column.set_collation_type(CS_TYPE_INVALID); } if (data_type.get_meta_type().is_integer_type() || data_type.get_meta_type().is_numeric_type()) { column.set_zero_fill(data_type.is_zero_fill()); } if (ob_is_nstring_type(column.get_meta_type().get_type())) { CK(OB_NOT_NULL(session_info_)); if (OB_SUCC(ret)) { ObCollationType coll_type = session_info_->get_nls_collation_nation(); column.set_collation_type(coll_type); column.set_charset_type(ObCharset::charset_type_by_coll(coll_type)); } } if (OB_SUCC(ret) && column.is_string_type() && stmt::T_CREATE_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(check_and_fill_column_charset_info(column, charset_type_, collation_type_))) { SQL_RESV_LOG(WARN, "fail to check and fill column charset info", K(ret)); } else if (data_type.get_meta_type().is_lob()) { if (OB_FAIL(check_text_column_length_and_promote(column, table_id_))) { SQL_RESV_LOG(WARN, "fail to check text or blob column length", K(ret), K(column)); } } else if (OB_FAIL(check_string_column_length(column, lib::is_oracle_mode()))) { SQL_RESV_LOG(WARN, "fail to check string column length", K(ret), K(column)); } } if (OB_SUCC(ret) && ObRawType == column.get_data_type() && stmt::T_CREATE_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(ObDDLResolver::check_raw_column_length(column))) { SQL_RESV_LOG(WARN, "failed to check raw column length", K(ret), K(column)); } } if (OB_SUCC(ret) && ObURowIDType == column.get_data_type() && stmt::T_CREATE_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(ObDDLResolver::check_urowid_column_length(column))) { SQL_RESV_LOG(WARN, "failed to check rowid column length", K(ret)); } } if (OB_SUCC(ret) && column.is_enum_or_set()) { if (OB_FAIL(resolve_enum_or_set_column(type_node, column))) { LOG_WARN("fail to resolve set column", K(ret), K(column)); } } } } if (OB_SUCC(ret) && GEN_COLUMN_DEFINITION_NUM_CHILD == node->num_child_) { ParseNode* expr_node = NULL; if (share::is_oracle_mode() && (column.get_meta_type().is_blob() || column.get_meta_type().is_clob())) { ret = OB_ERR_INVALID_VIRTUAL_COLUMN_TYPE; LOG_WARN("invalid use of blob/clob type with generate defnition", K(ret), K(column.get_meta_type())); LOG_USER_ERROR(OB_NOT_SUPPORTED, "generate column with blob type"); } else if (share::is_oracle_mode() && is_create_table_as) { ret = OB_NOT_SUPPORTED; LOG_WARN("generate column in create table as not support", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "generate column in create table as"); } else if (OB_ISNULL(expr_node = node->children_[3])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr_node is null"); } else { ObString expr_str(expr_node->str_len_, expr_node->str_value_); ObObj default_value; default_value.set_varchar(expr_str); default_value.set_collation_type(ObCharset::get_system_collation()); if (OB_FAIL(column.set_cur_default_value(default_value))) { LOG_WARN("set current default value failed", K(ret)); } else if (node->children_[4] != NULL && node->children_[4]->type_ == T_STORED_COLUMN) { column.add_column_flag(STORED_GENERATED_COLUMN_FLAG); } else { column.add_column_flag(VIRTUAL_GENERATED_COLUMN_FLAG); } } } if (OB_SUCC(ret)) { ParseNode* attrs_node = node->children_[2]; if (attrs_node != NULL) { if (OB_UNLIKELY(6 == node->num_child_)) { if (OB_FAIL(resolve_generated_column_attribute(column, attrs_node, resolve_stat))) { LOG_WARN("resolve generated column attribute failed", K(ret)); } } else if (OB_FAIL(resolve_normal_column_attribute(column, attrs_node, resolve_stat, pk_name))) { LOG_WARN("resolve normal column attribute failed", K(ret)); } } // specify column pos, only supported in add column syntax within MySQL Mode if (OB_SUCC(ret) && share::is_mysql_mode()) { ParseNode* pos_node = NULL; if (OB_UNLIKELY(GEN_COLUMN_DEFINITION_NUM_CHILD == node->num_child_)) { // generated column with pos_column pos_node = node->children_[5]; } else { // normal column with pos_column pos_node = node->children_[3]; } if (NULL != pos_node) { if (!is_add_column) { ret = OB_NOT_SUPPORTED; SQL_RESV_LOG(WARN, "unsupport for first or before or after column", K(ret)); } } } // visibility_option, Oracle mode only if (OB_SUCC(ret) && share::is_oracle_mode()) { ParseNode* visiblity_node = NULL; if (OB_UNLIKELY(GEN_COLUMN_DEFINITION_NUM_CHILD == node->num_child_)) { visiblity_node = node->children_[5]; } else { visiblity_node = node->children_[3]; } if (NULL != visiblity_node) { if (is_modify_column) { // Column visibility modifications can not be combined with any other modified column DDL option. if (OB_UNLIKELY(GEN_COLUMN_DEFINITION_NUM_CHILD == node->num_child_)) { visiblity_node = node->children_[5]; if (OB_NOT_NULL(node->children_[1]) || OB_NOT_NULL(node->children_[2]) || OB_NOT_NULL(node->children_[3]) || OB_NOT_NULL(node->children_[4])) { ret = OB_ERR_MODIFY_COL_VISIBILITY_COMBINED_WITH_OTHER_OPTION; SQL_RESV_LOG(WARN, "Column visibility modifications can not be combined with any other modified column DDL option.", K(ret)); } else { is_modify_column_visibility = true; } } else { if (OB_NOT_NULL(node->children_[1]) || OB_NOT_NULL(node->children_[2])) { ret = OB_ERR_MODIFY_COL_VISIBILITY_COMBINED_WITH_OTHER_OPTION; SQL_RESV_LOG(WARN, "Column visibility modifications can not be combined with any other modified column DDL option.", K(ret)); } else { is_modify_column_visibility = true; } } } if (OB_SUCC(ret)) { if (T_INVISIBLE == visiblity_node->type_) { const ObTableSchema* table_schema = NULL; if (is_oracle_temp_table) { ret = OB_ERR_INVISIBLE_COL_ON_UNSUPPORTED_TABLE_TYPE; LOG_WARN("Invisible column is not supported on temp table.", K(ret)); } else if (OB_ISNULL(schema_checker_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema checker ptr is null", K(ret)); } else if (is_modify_column && OB_FAIL(schema_checker_->get_table_schema(column.get_table_id(), table_schema))) { LOG_WARN("get_table_schema failed", K(ret), K(column.get_table_id())); } else if (is_modify_column && is_sys_database_id(table_schema->get_database_id())) { // The visibility of a column from a table owned by a SYS user cannot be modified to invisible, but can be // modified to visible ret = OB_ERR_MODIFY_COL_VISIBILITY_BY_SYS_USER; SQL_RESV_LOG( WARN, "The visibility of a column from a table owned by a SYS user cannot be changed.", K(ret)); } else { column.add_column_flag(INVISIBLE_COLUMN_FLAG); } } else { // T_VISIBLE == visiblity_node->type_ column.del_column_flag(INVISIBLE_COLUMN_FLAG); } } } } } return ret; } // only use in oracle mode int ObDDLResolver::resolve_uk_name_from_column_attribute(ParseNode* attrs_node, common::ObString& uk_name) { int ret = OB_SUCCESS; if (OB_ISNULL(attrs_node)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("attrs_node is invalid"); } for (int64_t i = 0; OB_SUCC(ret) && i < attrs_node->num_child_; ++i) { ParseNode* attr_node = attrs_node->children_[i]; if (T_CONSTR_UNIQUE_KEY != attr_node->type_) { continue; } else { ParseNode* uk_name_node = attr_node->children_[0]; if (OB_ISNULL(uk_name_node)) { // do nothing } else { uk_name.assign_ptr(uk_name_node->str_value_, static_cast(uk_name_node->str_len_)); } break; } } return ret; } int ObDDLResolver::resolve_normal_column_attribute( ObColumnSchemaV2& column, ParseNode* attrs_node, ObColumnResolveStat& resolve_stat, ObString& pk_name) { int ret = OB_SUCCESS; ObObjParam default_value; default_value.set_null(); bool is_set_cur_default = false; bool is_set_orig_default = false; ObCreateTableStmt* create_table_stmt = static_cast(stmt_); if (OB_ISNULL(attrs_node)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("attrs_node is invalid"); } for (int64_t i = 0; OB_SUCC(ret) && i < attrs_node->num_child_; ++i) { ParseNode* attr_node = attrs_node->children_[i]; switch (attr_node->type_) { case T_CONSTR_NOT_NULL: column.set_nullable(false); resolve_stat.is_set_not_null_ = true; break; case T_CONSTR_NULL: // set non_primary_key_column to nullable if (!resolve_stat.is_primary_key_) { column.set_nullable(true); } resolve_stat.is_set_null_ = true; break; case T_CONSTR_PRIMARY_KEY: { resolve_stat.is_primary_key_ = true; // primary key should not be nullable column.set_nullable(false); if (ob_is_text_tc(column.get_data_type())) { ret = OB_ERR_WRONG_KEY_COLUMN; LOG_USER_ERROR( OB_ERR_WRONG_KEY_COLUMN, column.get_column_name_str().length(), column.get_column_name_str().ptr()); SQL_RESV_LOG(WARN, "BLOB, TEXT column can't be primary key", K(column), K(ret)); } else if (ObTimestampTZType == column.get_data_type()) { ret = OB_ERR_WRONG_KEY_COLUMN; LOG_USER_ERROR( OB_ERR_WRONG_KEY_COLUMN, column.get_column_name_str().length(), column.get_column_name_str().ptr()); SQL_RESV_LOG(WARN, "TIMESTAMP WITH TIME ZONE column can't be primary key", K(column), K(ret)); } if (OB_FAIL(ret)) { } else if (share::is_oracle_mode()) { ParseNode* pk_name_node = attr_node->children_[0]; if (OB_ISNULL(pk_name_node)) { // do nothing } else { pk_name.assign_ptr(pk_name_node->str_value_, static_cast(pk_name_node->str_len_)); } } break; } case T_CONSTR_UNIQUE_KEY: { resolve_stat.is_unique_key_ = true; if (ob_is_text_tc(column.get_data_type())) { ret = OB_ERR_WRONG_KEY_COLUMN; LOG_USER_ERROR( OB_ERR_WRONG_KEY_COLUMN, column.get_column_name_str().length(), column.get_column_name_str().ptr()); SQL_RESV_LOG(WARN, "BLOB, TEXT column can't be unique key", K(column), K(ret)); } else if (ObTimestampTZType == column.get_data_type()) { ret = OB_ERR_WRONG_KEY_COLUMN; LOG_USER_ERROR( OB_ERR_WRONG_KEY_COLUMN, column.get_column_name_str().length(), column.get_column_name_str().ptr()); SQL_RESV_LOG(WARN, "TIMESTAMP WITH TIME ZONE column can't be unique key", K(column), K(ret)); } break; } case T_CONSTR_ORIG_DEFAULT: case T_CONSTR_DEFAULT: { if (share::is_oracle_mode()) { resolve_stat.is_set_default_value_ = true; ObString expr_str(attr_node->str_len_, attr_node->str_value_); if (OB_FAIL(ObSQLUtils::copy_and_convert_string_charset(*allocator_, expr_str, expr_str, session_info_->get_local_collation_connection(), CS_TYPE_UTF8MB4_BIN))) { LOG_WARN("fail to copy and convert string charset", K(ret)); } else { default_value.set_varchar(expr_str); default_value.set_collation_type(CS_TYPE_UTF8MB4_BIN); default_value.set_param_meta(); if (T_CONSTR_ORIG_DEFAULT == attr_node->type_) { ret = OB_NOT_SUPPORTED; // TODO: do it next LOG_WARN("not support set orig default now", K(ret)); } else if (OB_FAIL(column.set_cur_default_value(default_value))) { LOG_WARN("set current default value failed", K(ret)); } else { column.add_column_flag(DEFAULT_EXPR_V2_COLUMN_FLAG); } } } else { if (1 != attr_node->num_child_ || NULL == attr_node->children_[0]) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "resolve default value failed", K(ret)); } else if (OB_FAIL(resolve_default_value(attr_node, default_value))) { SQL_RESV_LOG(WARN, "resolve default value failed", K(ret)); } else if (IS_DEFAULT_NOW_OBJ(default_value)) { if ((ObDateTimeTC != column.get_data_type_class() && ObOTimestampTC != column.get_data_type_class()) || default_value.get_scale() != column.get_accuracy().get_scale()) { ret = OB_INVALID_DEFAULT; LOG_USER_ERROR( OB_INVALID_DEFAULT, column.get_column_name_str().length(), column.get_column_name_str().ptr()); SQL_RESV_LOG(WARN, "Invalid default value", K(column), K(default_value), K(ret)); } else { default_value.set_scale(column.get_accuracy().get_scale()); } } if (OB_FAIL(ret)) { // do nothing } else if (!default_value.is_null() && ob_is_text_tc(column.get_data_type())) { ret = OB_INVALID_DEFAULT; LOG_USER_ERROR( OB_INVALID_DEFAULT, column.get_column_name_str().length(), column.get_column_name_str().ptr()); SQL_RESV_LOG(WARN, "BLOB, TEXT column can't have a default value", K(column), K(default_value), K(ret)); } else { if (T_CONSTR_DEFAULT == attr_node->type_) { resolve_stat.is_set_default_value_ = true; if (is_set_cur_default) { ret = OB_ERR_PARSER_SYNTAX; SQL_RESV_LOG(WARN, "cannot set current default value twice", K(ret)); } else { is_set_cur_default = true; column.set_cur_default_value(default_value); } } else { // T_CONSTR_ORIG_DEFAULT == column.get_data_type_class() resolve_stat.is_set_orig_default_value_ = true; bool is_sync_ddl_user = false; if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(session_info_, is_sync_ddl_user))) { LOG_WARN("Failed to check sync_dll_user", K(ret)); } else if (!is_sync_ddl_user || stmt::T_CREATE_TABLE != stmt_->get_stmt_type()) { ret = OB_ERR_PARSER_SYNTAX; SQL_RESV_LOG(WARN, "Only support for sync ddl user to specify the orig_default_value", K(ret)); } else if (is_set_orig_default) { ret = OB_ERR_PARSER_SYNTAX; SQL_RESV_LOG(WARN, "cannot set orig default value twice", K(ret)); } else { is_set_orig_default = true; column.set_orig_default_value(default_value); } } } } LOG_DEBUG("finish resolve default value", K(ret), K(default_value), K(column), K(attr_node->num_child_), K(attr_node->param_num_)); break; } case T_CONSTR_AUTO_INCREMENT: if (ob_is_text_tc(column.get_data_type())) { ret = OB_ERR_COLUMN_SPEC; LOG_USER_ERROR(OB_ERR_COLUMN_SPEC, column.get_column_name_str().length(), column.get_column_name_str().ptr()); SQL_RESV_LOG(WARN, "BLOB, TEXT column can't set autoincrement", K(column), K(default_value), K(ret)); } else { column.set_autoincrement(true); resolve_stat.is_autoincrement_ = true; } break; case T_COLUMN_ID: { bool is_sync_ddl_user = false; if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(session_info_, is_sync_ddl_user))) { LOG_WARN("Failed to check sync_dll_user", K(ret)); } else if (!is_sync_ddl_user && !GCONF.enable_sys_table_ddl) { ret = OB_ERR_PARSE_SQL; LOG_WARN("Only support for sync ddl user or inner_table add column to specify column id", K(ret), K(session_info_->get_user_name())); } else if (attr_node->num_child_ != 1 || OB_ISNULL(attr_node->children_[0]) || T_INT != attr_node->children_[0]->type_) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid node", K(attr_node->children_[0]), K(ret)); } else { const uint64_t column_id = static_cast(attr_node->children_[0]->value_); // 1. column id must start with 16 // 2. shadow column for uniq index must start with 32768(32767+1) if (column_id < OB_APP_MIN_COLUMN_ID || column_id > OB_MIN_SHADOW_COLUMN_ID) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid column id", K(column_id), K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "column id"); } else { column.set_column_id(column_id); } } break; } case T_COMMENT: { if (attr_node->num_child_ != 1 || OB_ISNULL(attr_node->children_[0]) || T_VARCHAR != attr_node->children_[0]->type_) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid node!", K(ret)); } else { ObString comment(attr_node->children_[0]->str_len_, attr_node->children_[0]->str_value_); ObCollationType client_cs_type = session_info_->get_local_collation_connection(); if (OB_FAIL(ObSQLUtils::copy_and_convert_string_charset( *allocator_, comment, comment, client_cs_type, CS_TYPE_UTF8MB4_BIN))) { LOG_WARN("fail to convert comment to utf8", K(ret), K(comment)); } else if (comment.length() >= MAX_COLUMN_COMMENT_LENGTH) { ret = OB_ERR_TOO_LONG_FIELD_COMMENT; LOG_USER_ERROR(OB_ERR_TOO_LONG_FIELD_COMMENT, MAX_COLUMN_COMMENT_LENGTH); } else { column.set_comment(comment); } } break; } case T_ON_UPDATE: if (ObDateTimeType == column.get_data_type() || ObTimestampType == column.get_data_type()) { if (T_FUN_SYS_CUR_TIMESTAMP != attr_node->children_[0]->type_) { ret = OB_ERR_PARSER_SYNTAX; SQL_RESV_LOG(WARN, "on_update attribute can only be timestamp or synonyms type", "node_type", attr_node->children_[0]->type_, K(column), K(ret)); } else { int16_t scale = 0; if (OB_UNLIKELY(NULL == attr_node->children_[0] || 1 != attr_node->children_[0]->num_child_)) { ret = OB_INVALID_ON_UPDATE; LOG_WARN("invalid argument", K(ret), K(attr_node->children_[0])); } else { if (NULL != attr_node->children_[0]->children_[0]) { scale = static_cast(attr_node->children_[0]->children_[0]->value_); } else { // defaule value } if (column.get_accuracy().get_scale() != scale) { ret = OB_INVALID_ON_UPDATE; LOG_USER_ERROR(OB_INVALID_ON_UPDATE, column.get_column_name()); SQL_RESV_LOG(WARN, "Invalid ON UPDATE clause for ", K(column), K(ret)); } else { column.set_on_update_current_timestamp(true); } } } } else { ret = OB_INVALID_ON_UPDATE; LOG_USER_ERROR(OB_INVALID_ON_UPDATE, column.get_column_name()); SQL_RESV_LOG(WARN, "only ObDateTimeType and ObTimeStampType column can have attribute" " of on_update", K(column), K(ret)); } break; case T_CHECK_CONSTRAINT: { if (stmt::T_CREATE_TABLE != stmt_->get_stmt_type()) { ret = OB_NOT_SUPPORTED; SQL_RESV_LOG( WARN, "Adding column-level check cst while altering table not supported", K(ret), K(stmt_->stmt_type_)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Add column-level check cst while altering table"); } else { ObSEArray& csts = create_table_stmt->get_create_table_arg().constraint_list_; if (OB_FAIL(resolve_check_constraint_node(*attr_node, csts, &column))) { SQL_RESV_LOG(WARN, "resolve constraint failed", K(ret)); } } break; } case T_FOREIGN_KEY: { if (stmt::T_CREATE_TABLE != stmt_->get_stmt_type()) { ret = OB_NOT_SUPPORTED; SQL_RESV_LOG( WARN, "Adding a column-level fk while altering table is not supported", K(ret), K(stmt_->stmt_type_)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Adding column-level foreign key constraints while altering table"); } else { ObCreateForeignKeyArg foreign_key_arg; if (OB_FAIL(resolve_foreign_key_node(attr_node, foreign_key_arg, false, &column))) { SQL_RESV_LOG(WARN, "failed to resolve foreign key node", K(ret)); } else if (OB_FAIL(create_table_stmt->get_foreign_key_arg_list().push_back(foreign_key_arg))) { SQL_RESV_LOG(WARN, "failed to push back foreign key arg", K(ret)); } } break; } default: // won't be here ret = OB_ERR_PARSER_SYNTAX; SQL_RESV_LOG(WARN, "Wrong column constraint", K(ret)); break; } } if (OB_SUCC(ret) && column.get_cur_default_value().is_null() && resolve_stat.is_set_default_value_ && (!column.is_nullable() || resolve_stat.is_primary_key_)) { ret = OB_INVALID_DEFAULT; LOG_USER_ERROR(OB_INVALID_DEFAULT, column.get_column_name_str().length(), column.get_column_name_str().ptr()); SQL_RESV_LOG(WARN, "Invalid default value", K(column), K(ret)); } // can't set both null & not null attribute at the same time // mysql did not throw error, but it is mysql's bug: // http://bugs.mysql.com/bug.php?id=79645 if (OB_SUCC(ret) && resolve_stat.is_set_null_ && resolve_stat.is_set_not_null_) { ret = OB_ERR_COLUMN_DEFINITION_AMBIGUOUS; LOG_USER_ERROR( OB_ERR_COLUMN_DEFINITION_AMBIGUOUS, column.get_column_name_str().length(), column.get_column_name_str().ptr()); } if (OB_SUCC(ret) && column.is_autoincrement()) { if (column.get_cur_default_value().get_type() != ObNullType) { ret = OB_INVALID_DEFAULT; LOG_USER_ERROR(OB_INVALID_DEFAULT, column.get_column_name_str().length(), column.get_column_name_str().ptr()); SQL_RESV_LOG(WARN, "can not set default value for auto_increment column", K(ret)); } if (OB_SUCC(ret)) { // for show create table // set auto-increment column default null => still not null column.set_nullable(false); } if (OB_SUCC(ret)) { if (column.get_data_type() < ObTinyIntType || column.get_data_type() > ObUDoubleType) { ret = OB_ERR_COLUMN_SPEC; LOG_USER_ERROR(OB_ERR_COLUMN_SPEC, column.get_column_name_str().length(), column.get_column_name_str().ptr()); SQL_RESV_LOG(WARN, "wrong column type for auto_increment", K(ret)); } } } return ret; } int ObDDLResolver::resolve_generated_column_attribute( ObColumnSchemaV2& column, ParseNode* attrs_node, ObColumnResolveStat& resolve_stat) { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && attrs_node && i < attrs_node->num_child_; ++i) { ParseNode* attr_node = attrs_node->children_[i]; switch (attr_node->type_) { case T_CONSTR_NOT_NULL: column.set_nullable(false); resolve_stat.is_set_not_null_ = true; break; case T_CONSTR_NULL: // set non_primary_key_column to nullable if (!resolve_stat.is_primary_key_) { column.set_nullable(true); } resolve_stat.is_set_null_ = true; break; case T_CONSTR_PRIMARY_KEY: { // if (column.is_stored_generated_column()) { // resolve_stat.is_primary_key_ = true; // primary key should not be nullable // column.set_nullable(false); // } else { ret = OB_ERR_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN; LOG_USER_ERROR(OB_ERR_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN, "Defining a generated column as primary key"); // } break; } case T_CONSTR_UNIQUE_KEY: { resolve_stat.is_unique_key_ = true; break; } case T_COMMENT: { if (attr_node->num_child_ != 1 || OB_ISNULL(attr_node->children_[0]) || T_VARCHAR != attr_node->children_[0]->type_) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid node!", K(ret)); } else { ObString comment(attr_node->children_[0]->str_len_, attr_node->children_[0]->str_value_); ObCollationType client_cs_type = session_info_->get_local_collation_connection(); if (OB_FAIL(ObSQLUtils::copy_and_convert_string_charset( *allocator_, comment, comment, client_cs_type, CS_TYPE_UTF8MB4_BIN))) { LOG_WARN("fail to convert comment to utf8", K(ret), K(comment)); } else if (comment.length() >= MAX_COLUMN_COMMENT_LENGTH) { ret = OB_ERR_TOO_LONG_FIELD_COMMENT; LOG_USER_ERROR(OB_ERR_TOO_LONG_FIELD_COMMENT, MAX_COLUMN_COMMENT_LENGTH); } else { column.set_comment(comment); } } break; } case T_COLUMN_ID: { bool is_sync_ddl_user = false; if (attr_node->num_child_ != 1 || OB_ISNULL(attr_node->children_[0]) || T_INT != attr_node->children_[0]->type_) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid node", K(attr_node->children_[0]), K(ret)); } else if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(session_info_, is_sync_ddl_user))) { LOG_WARN("Failed to check sync_dll_user", K(ret)); } else if (!is_sync_ddl_user) { ret = OB_ERR_PARSE_SQL; LOG_WARN("Only support for sync ddl user to specify column id", K(ret), K(session_info_->get_user_name())); } else { const uint64_t column_id = static_cast(attr_node->children_[0]->value_); // 1. column id must start with 16 // 2. shadow column for uniq index must start with 32768(32767+1) if (column_id < OB_APP_MIN_COLUMN_ID || column_id > OB_MIN_SHADOW_COLUMN_ID) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid column id", K(column_id), K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "column id"); } else { column.set_column_id(column_id); } } break; } default: // won't be here ret = OB_ERR_PARSER_SYNTAX; SQL_RESV_LOG(WARN, "Wrong column constraint", K(ret)); break; } } // http://bugs.mysql.com/bug.php?id=79645 if (OB_SUCCESS == ret && resolve_stat.is_set_null_ && resolve_stat.is_set_not_null_) { ret = OB_ERR_COLUMN_DEFINITION_AMBIGUOUS; LOG_USER_ERROR( OB_ERR_COLUMN_DEFINITION_AMBIGUOUS, column.get_column_name_str().length(), column.get_column_name_str().ptr()); } return ret; } /* int ObDDLResolver::resolve_generated_column_definition(ObColumnSchemaV2 &column, ParseNode *node, ObColumnResolveStat &resolve_stat) { int ret = OB_SUCCESS; ParseNode *name_node = NULL; if (T_COLUMN_DEFINITION != node->type_ || node->num_child_ != 6 || OB_ISNULL(allocator_) || OB_ISNULL(node->children_) || OB_ISNULL(node->children_[0]) || T_COLUMN_REF != node->children_[0]->type_ || COLUMN_DEF_NUM_CHILD != node->children_[0]->num_child_){ ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "invalid parse node",K(ret)); } else { resolve_stat.reset(); name_node = node->children_[0]->children_[2]; if (OB_ISNULL(name_node)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "name node can not be null", K(ret)); } else if (OB_FAIL(resolve_column_definition_ref(column, name_node))) { SQL_RESV_LOG(WARN, "fail to resolve column_definition_ref", K(ret)); } } ParseNode *type_node = NULL; if (OB_SUCC(ret)) { type_node = node->children_[1]; } if (OB_SUCC(ret) && type_node != NULL) { ObDataType data_type; const ObLengthSemantics default_length_semantics = LS_BYTE; if (OB_FAIL(ObResolverUtils::resolve_data_type(*type_node, column.get_column_name_str(), data_type, (session_info_ != NULL && is_oracle_mode()), default_length_semantics))) { LOG_WARN("resolve data type failed", K(ret), K(column.get_column_name_str())); } else if (ObExtendType == data_type.get_obj_type()) { const ParseNode *name_node = type_node->children_[0]; CK (OB_NOT_NULL(session_info_) && OB_NOT_NULL(schema_checker_)); CK (OB_NOT_NULL(name_node)); CK (T_SP_TYPE == name_node->type_); if (OB_SUCC(ret)) { uint64_t udt_id = OB_INVALID_ID; uint64_t db_id = session_info_->get_database_id(); if (NULL != name_node->children_[0]) { OZ (schema_checker_->get_database_id(session_info_->get_effective_tenant_id(), ObString(name_node->children_[0]->str_len_, name_node->children_[0]->str_value_), db_id)); } OZ (schema_checker_->get_udt_id(session_info_->get_effective_tenant_id(), db_id, OB_INVALID_ID, ObString(name_node->children_[1]->str_len_, name_node->children_[1]->str_value_), udt_id)); if (OB_SUCC(ret)) { data_type.set_udt_id(udt_id); } } } else { } if (OB_SUCC(ret)) { column.set_meta_type(data_type.get_meta_type()); column.set_accuracy(data_type.get_accuracy()); column.set_charset_type(data_type.get_charset_type()); if (data_type.is_binary_collation()) { column.set_binary_collation(true); column.set_collation_type(CS_TYPE_INVALID); } if (OB_SUCC(ret) && column.is_string_type() && stmt::T_CREATE_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(check_and_fill_column_charset_info(column, charset_type_, collation_type_))) { SQL_RESV_LOG(WARN, "fail to check and fill column charset info", K(ret)); } else if (data_type.get_meta_type().is_lob()) { if (OB_FAIL(check_text_column_length_and_promote(column))) { SQL_RESV_LOG(WARN, "fail to check text or blob column length", K(ret), K(column)); } } else if (OB_FAIL(check_string_column_length(column, lib::is_oracle_mode()))) { SQL_RESV_LOG(WARN, "fail to check string column length", K(ret), K(column)); } } if (OB_SUCC(ret) && ObRawType == column.get_data_type() && stmt::T_CREATE_TABLE == stmt_->get_stmt_type()) { if (OB_FAIL(ObDDLResolver::check_raw_column_length(column))) { SQL_RESV_LOG(WARN, "failed to check raw column length", K(ret), K(column)); } } } } return ret; } */ int ObDDLResolver::cast_default_value(ObObj& default_value, const ObTimeZoneInfo* tz_info, const common::ObString* nls_formats, ObIAllocator& allocator, ObColumnSchemaV2& column_schema) { // cast default value int ret = OB_SUCCESS; const int64_t CUR_TIME = 0; bool need_cast = false; if (default_value.is_null()) { need_cast = false; } else if (column_schema.get_data_type() != default_value.get_type()) { need_cast = true; } else if (column_schema.is_string_type() && default_value.is_string_type() && column_schema.get_collation_type() != default_value.get_collation_type()) { need_cast = true; } if (need_cast) { ObAccuracy res_accuracy; const ObDataTypeCastParams dtc_params( tz_info, nls_formats, CS_TYPE_INVALID, CS_TYPE_INVALID, CS_TYPE_UTF8MB4_GENERAL_CI); ObCastCtx cast_ctx(&allocator, &dtc_params, CUR_TIME, share::is_oracle_mode() ? CM_ORACLE_MODE : CM_COLUMN_CONVERT, column_schema.get_collation_type(), NULL, &res_accuracy); if (ob_is_enumset_tc(column_schema.get_data_type())) { if (OB_FAIL(cast_enum_or_set_default_value(column_schema, cast_ctx, default_value))) { LOG_WARN("fail to cast enum or set default value", K(default_value), K(column_schema), K(ret)); } } else if (IS_DEFAULT_NOW_OBJ(default_value)) { if (ObDateTimeTC == column_schema.get_data_type_class()) { if (OB_FAIL(column_schema.set_cur_default_value(default_value))) { SQL_RESV_LOG(WARN, "set current default value failed", K(ret)); } } else { ret = OB_INVALID_DEFAULT; LOG_USER_ERROR(OB_INVALID_DEFAULT, column_schema.get_column_name_str().length(), column_schema.get_column_name_str().ptr()); } } else { // so cool. cast in place. if (OB_FAIL(ObObjCaster::to_type(column_schema.get_data_type(), cast_ctx, default_value, default_value))) { SQL_RESV_LOG(WARN, "cast default value failed", K(ret), "src_type", default_value.get_type(), "dst_type", column_schema.get_data_type(), K(ret)); } else if (ObNumberTC == column_schema.get_data_type_class()) { number::ObNumber nmb; nmb = default_value.get_number(); if (share::is_oracle_mode()) { const ObObj* res_obj = &default_value; const common::ObAccuracy& accuracy = column_schema.get_accuracy(); if (OB_FAIL(common::obj_accuracy_check( cast_ctx, accuracy, column_schema.get_collation_type(), *res_obj, default_value, res_obj))) { SQL_RESV_LOG(WARN, "check and round number failed on oracle mode", K(ret), K(default_value), K(*res_obj)); } } else { if (OB_FAIL(nmb.check_and_round(column_schema.get_data_precision(), column_schema.get_data_scale()))) { SQL_RESV_LOG(WARN, "check and round number failed", K(ret)); } } if (OB_SUCC(ret)) { default_value.set_number(column_schema.get_data_type(), nmb); } } if (OB_FAIL(ret)) { ret = OB_INVALID_DEFAULT; LOG_USER_ERROR(OB_INVALID_DEFAULT, column_schema.get_column_name_str().length(), column_schema.get_column_name_str().ptr()); } } } return ret; } int ObDDLResolver::check_default_value_length(const ObObj& default_value, const ObColumnSchemaV2& column) { int ret = OB_SUCCESS; int64_t strlen = -1; if (ObStringTC == column.get_data_type_class()) { if (CS_TYPE_INVALID == column.get_collation_type()) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "invaild default data type", K(ret)); } else { // get characters of default value under specified charset ObString str; const bool is_byte_length = is_oracle_byte_length(share::is_oracle_mode(), column.get_length_semantics()); if (default_value.is_null()) { strlen = 0; } else if (OB_FAIL(default_value.get_varchar(str))) { SQL_RESV_LOG(WARN, "invalid default data", K(ret), K(str), K(default_value)); } else { strlen = is_byte_length ? str.length() : ObCharset::strlen_char(column.get_collation_type(), str.ptr(), str.length()); } if (OB_SUCC(ret) && strlen > column.get_data_length()) { ret = OB_INVALID_DEFAULT; SQL_RESV_LOG(WARN, "Invalid default value: length is larger than data length", "default_value", str, "length", strlen, "data_length", column.get_data_length(), K(is_byte_length)); LOG_USER_ERROR(OB_INVALID_DEFAULT, column.get_column_name_str().length(), column.get_column_name_str().ptr()); } } } else if (ObBitTC == column.get_data_type_class()) { int32_t bit_len = 0; if (default_value.is_null()) { // do nothing } else if (OB_FAIL(get_bit_len(default_value.get_bit(), bit_len))) { SQL_RESV_LOG(WARN, "fail to get bit length", K(ret), K(default_value), K(bit_len)); } else if (bit_len > column.get_data_precision()) { ret = OB_INVALID_DEFAULT; SQL_RESV_LOG(WARN, "default value length is larger than column length", K(ret), K(default_value), K(bit_len), K(column.get_data_precision())); LOG_USER_ERROR(OB_INVALID_DEFAULT, column.get_column_name_str().length(), column.get_column_name_str().ptr()); } else { /*do nothing*/ } } else { /*do nothing*/ } return ret; } int ObDDLResolver::build_partition_key_info( ObTableSchema& table_schema, const bool is_subpart, const bool is_key_implicit_v2) { int ret = OB_SUCCESS; ObSEArray qualified_names; ObRawExpr* partition_key_expr = NULL; if (OB_FAIL(ObResolverUtils::build_partition_key_expr( params_, table_schema, partition_key_expr, &qualified_names, is_key_implicit_v2))) { LOG_WARN("failed to build partition key expr!", K(ret)); } else if (OB_UNLIKELY(qualified_names.count() <= 0)) { // no primary key, error now ret = OB_ERR_FIELD_NOT_FOUND_PART; LOG_WARN("Field in list of fields for partition function not found in table", K(ret)); } else { for (int64_t i = 0; OB_SUCC(ret) && i < qualified_names.count(); ++i) { ObQualifiedName& q_name = qualified_names.at(i); if (is_subpart) { if (OB_FAIL(table_schema.add_subpartition_key(q_name.col_name_))) { LOG_WARN("Failed to add subpartition key", K(ret)); } } else if (OB_FAIL(table_schema.add_partition_key(q_name.col_name_))) { LOG_WARN("Failed to add partition key", K(ret)); } else { } // do nothing } } return ret; } int ObDDLResolver::set_partition_keys( ObTableSchema& table_schema, ObIArray& partition_keys, const bool is_subpart) { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < partition_keys.count(); ++i) { if (is_subpart) { if (OB_FAIL(table_schema.add_subpartition_key(partition_keys.at(i)))) { LOG_WARN("Failed to add subpartition key", K(ret), "key_name", partition_keys.at(i)); } } else if (OB_FAIL(table_schema.add_partition_key(partition_keys.at(i)))) { LOG_WARN("Failed to add partition key", K(ret), "key_name", partition_keys.at(i)); } else { } // do nothing } return ret; } void ObDDLResolver::reset() { block_size_ = OB_DEFAULT_SSTABLE_BLOCK_SIZE; consistency_level_ = INVALID_CONSISTENCY; index_scope_ = NOT_SPECIFIED; replica_num_ = 0; tablet_size_ = -1; charset_type_ = CHARSET_INVALID; collation_type_ = CS_TYPE_INVALID; use_bloom_filter_ = false; expire_info_.reset(); compress_method_.reset(); parser_name_.reset(); comment_.reset(); tablegroup_name_.reset(); primary_zone_.reset(); row_store_type_ = MAX_ROW_STORE; store_format_ = OB_STORE_FORMAT_INVALID; progressive_merge_num_ = OB_DEFAULT_PROGRESSIVE_MERGE_NUM; storage_format_version_ = OB_STORAGE_FORMAT_VERSION_INVALID; table_id_ = OB_INVALID_ID; data_table_id_ = OB_INVALID_ID; index_table_id_ = OB_INVALID_ID; partition_func_type_ = PARTITION_FUNC_TYPE_HASH; auto_increment_ = 1; index_name_.reset(); index_keyname_ = NORMAL_KEY; global_ = true; store_column_names_.reset(); hidden_store_column_names_.reset(); sort_column_array_.reset(); storing_column_set_.reset(); fulltext_column_names_.reset(); fulltext_column_set_.reset(); locality_.reset(); is_random_primary_zone_ = false; max_used_part_id_ = OB_INVALID_ID; enable_row_movement_ = false; table_mode_.reset(); table_dop_ = DEFAULT_TABLE_DOP; hash_subpart_num_ = -1; } bool ObDDLResolver::is_valid_prefix_key_type(const ObObjTypeClass column_type_class) { return column_type_class == ObStringTC || column_type_class == ObTextTC; } int ObDDLResolver::check_prefix_key(const int32_t prefix_len, const ObColumnSchemaV2& column_schema) { int ret = OB_SUCCESS; if (prefix_len > 0) { if (!is_valid_prefix_key_type(column_schema.get_data_type_class())) { ret = OB_WRONG_SUB_KEY; SQL_RESV_LOG( WARN, "The used key part isn't a string", "data_type_class", column_schema.get_data_type_class(), K(ret)); } else if (column_schema.get_data_length() < prefix_len) { ret = OB_WRONG_SUB_KEY; LOG_USER_ERROR(OB_WRONG_SUB_KEY); SQL_RESV_LOG(WARN, "The used length is longer than the key part", K(prefix_len), K(ret)); } } return ret; } int ObDDLResolver::check_string_column_length(const ObColumnSchemaV2& column, const bool is_oracle_mode) { int ret = OB_SUCCESS; if (ObStringTC != column.get_data_type_class() || CHARSET_INVALID == column.get_charset_type() || CS_TYPE_INVALID == column.get_collation_type()) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "column infomation is error", K(column), K(ret)); } else if (ObCharType == column.get_data_type() || ObNCharType == column.get_data_type()) { /* compatiable with mysql * char & binary : 255 charaters at most * varchar & varbinary : 65536 bytes at most * varchar(N)&varbinary(N): N is character count, N's upper bound is defined by its charset. * char(N)&binary(N): N is charactor count, upper limit is 255 characters. * oralce * char(N)&raw(N): N is byte count, upper limit is 2000 bytes */ const int64_t max_char_length = is_oracle_mode ? OB_MAX_ORACLE_CHAR_LENGTH_BYTE : OB_MAX_CHAR_LENGTH; const int64_t data_len = column.get_data_length(); if (data_len < 0 || data_len > max_char_length) { ret = OB_ERR_TOO_LONG_COLUMN_LENGTH; LOG_WARN( "column data length is invalid", K(ret), K(max_char_length), "real_data_length", column.get_data_length()); LOG_USER_ERROR(OB_ERR_TOO_LONG_COLUMN_LENGTH, column.get_column_name(), static_cast(max_char_length)); } else if (is_oracle_mode && 0 == data_len) { ret = OB_ERR_ZERO_LEN_COL; LOG_WARN("column data length cannot be zero on oracle mode", K(ret), K(data_len)); } } else if (ObVarcharType == column.get_data_type() || ObNVarchar2Type == column.get_data_type()) { int64_t mbmaxlen = 0; if (OB_FAIL(ObCharset::get_mbmaxlen_by_coll(column.get_collation_type(), mbmaxlen))) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "fail to get mbmaxlen", K(ret), K(column.get_collation_type())); } else { const int64_t data_len = column.get_data_length(); if (0 == mbmaxlen) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "mbmaxlen can not be 0", K(ret)); } else if (data_len < 0 || (is_oracle_mode ? data_len > OB_MAX_ORACLE_VARCHAR_LENGTH : data_len * mbmaxlen > OB_MAX_VARCHAR_LENGTH)) { ret = OB_ERR_TOO_LONG_COLUMN_LENGTH; const uint64_t real_data_length = static_cast(data_len); LOG_WARN("column data length is invalid", K(ret), K(data_len), K(real_data_length), K(mbmaxlen)); LOG_USER_ERROR(OB_ERR_TOO_LONG_COLUMN_LENGTH, column.get_column_name(), static_cast(is_oracle_mode ? OB_MAX_ORACLE_VARCHAR_LENGTH : OB_MAX_VARCHAR_LENGTH / mbmaxlen)); } else if (is_oracle_mode && 0 == data_len) { ret = OB_ERR_ZERO_LEN_COL; LOG_WARN("column data length cannot be zero on oracle mode", K(ret), K(data_len)); } } } else { ret = OB_ERR_UNEXPECTED; } return ret; } // raw(N): N byte: upper bound: 2000 byte int ObDDLResolver::check_raw_column_length(const share::schema::ObColumnSchemaV2& column) { int ret = OB_SUCCESS; if (ObRawType != column.get_data_type()) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "column infomation is error", K(column), K(ret)); } else { const int64_t data_len = column.get_data_length(); if (data_len < 0 || data_len > OB_MAX_ORACLE_RAW_SQL_COL_LENGTH) { ret = OB_ERR_TOO_LONG_COLUMN_LENGTH; LOG_WARN("column data length is invalid", K(ret), K(OB_MAX_ORACLE_RAW_SQL_COL_LENGTH), "real_data_length", column.get_data_length()); LOG_USER_ERROR( OB_ERR_TOO_LONG_COLUMN_LENGTH, column.get_column_name(), static_cast(OB_MAX_ORACLE_RAW_SQL_COL_LENGTH)); } else if (0 == data_len) { ret = OB_ERR_ZERO_LEN_COL; LOG_WARN("column data length cannot be zero on oracle mode", K(ret), K(data_len)); } } return ret; } int ObDDLResolver::check_urowid_column_length(const share::schema::ObColumnSchemaV2& column) { int ret = OB_SUCCESS; if (ObURowIDType != column.get_data_type()) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "column information is error", K(ret), K(column)); } else { const int64_t data_len = column.get_data_length(); if (data_len < 0 || data_len > OB_MAX_USER_ROW_KEY_LENGTH) { // create table t (a urwoid(int_num)); // int_num is urowid's decoded max length. i.e primary key's max length ret = OB_ERR_TOO_LONG_COLUMN_LENGTH; LOG_WARN("column data length is invalid", K(ret), K(OB_MAX_USER_ROW_KEY_LENGTH), "real_data_length", column.get_data_length()); LOG_USER_ERROR( OB_ERR_TOO_LONG_COLUMN_LENGTH, column.get_column_name(), static_cast(OB_MAX_USER_ROW_KEY_LENGTH)); } else if (0 == data_len) { ret = OB_ERR_ZERO_LEN_COL; LOG_WARN("column data length cannot be zero on oracle mode", K(ret), K(data_len)); } } return ret; } int ObDDLResolver::check_text_length(ObCharsetType cs_type, ObCollationType co_type, const char* name, ObObjType& type, int32_t& length, bool need_rewrite_length) { int ret = OB_SUCCESS; int64_t mbmaxlen = 0; int32_t default_length = ObAccuracy::DDL_DEFAULT_ACCURACY[type].get_length(); if (!ob_is_text_tc(type) || CHARSET_INVALID == cs_type || CS_TYPE_INVALID == co_type) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "column infomation is error", K(cs_type), K(co_type), K(ret)); } else if (OB_FAIL(ObCharset::get_mbmaxlen_by_coll(co_type, mbmaxlen))) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "fail to get mbmaxlen", K(ret), K(co_type)); } else if (0 == mbmaxlen) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(ERROR, "mbmaxlen can not be 0", K(ret), K(co_type), K(mbmaxlen)); } else if (share::is_oracle_mode() || 0 == length) { length = default_length; } else if (0 > length) { ret = OB_ERR_TOO_LONG_COLUMN_LENGTH; LOG_USER_ERROR(OB_ERR_TOO_LONG_COLUMN_LENGTH, name, static_cast(ObAccuracy::DDL_DEFAULT_ACCURACY[ObLongTextType].get_length() / mbmaxlen)); SQL_RESV_LOG(WARN, "fail to check column data length", K(ret), K(length), K(ObAccuracy::DDL_DEFAULT_ACCURACY[ObLongTextType].get_length()), K(mbmaxlen)); } else { // eg. text(128) will be tinytext in mysql, and text(65537) will be mediumtext if (ObTextType == type) { if (length * mbmaxlen > ObAccuracy::DDL_DEFAULT_ACCURACY[ObLongTextType].get_length()) { ret = OB_ERR_TOO_LONG_COLUMN_LENGTH; LOG_USER_ERROR(OB_ERR_TOO_LONG_COLUMN_LENGTH, name, static_cast(ObAccuracy::DDL_DEFAULT_ACCURACY[ObLongTextType].get_length() / mbmaxlen)); SQL_RESV_LOG(WARN, "fail to check column data length", K(ret), K(ObAccuracy::DDL_DEFAULT_ACCURACY[ObLongTextType].get_length()), K(mbmaxlen)); } else { for (int64_t i = ObTinyTextType; i <= ObLongTextType; ++i) { default_length = ObAccuracy::DDL_DEFAULT_ACCURACY[i].get_length(); if (length * mbmaxlen <= default_length) { type = static_cast(i); length = default_length; break; } } } } else if (share::is_mysql_mode() && length * mbmaxlen > default_length) { ret = OB_ERR_TOO_LONG_COLUMN_LENGTH; LOG_USER_ERROR(OB_ERR_TOO_LONG_COLUMN_LENGTH, name, static_cast(default_length / mbmaxlen)); SQL_RESV_LOG(WARN, "fail to check column data length", K(ret), K(default_length), K(length), K(mbmaxlen)); } else { length = default_length; } } if (OB_SUCC(ret) && share::is_mysql_mode() && need_rewrite_length) { if (OB_FAIL(rewrite_text_length_mysql(type, length))) { LOG_WARN("check_text_length_mysql fails", K(ret), K(type), K(length)); } } return ret; } // old version ObTinyTextType, ObTextType, ObMediumTextType, ObLongTextType max_length is incorrect // correct max_legth is ObTinyTextType:255 etc. // so when create new user table, must rewrite max column length int ObDDLResolver::rewrite_text_length_mysql(ObObjType& type, int32_t& length) { int ret = OB_SUCCESS; int32_t max_length = ObAccuracy::MAX_ACCURACY[type].get_length(); if (length < 0 || length > max_length) { ret = OB_ERR_UNEXPECTED; LOG_WARN("length can not be less than 0 or larger than max_length", K(ret), K(type), K(length), K(max_length)); } else if (ob_is_text_tc(type) && max_length == length) { length = length - 1; } return ret; } // TODO texttc should care about the the defined length not the actual length int ObDDLResolver::check_text_column_length_and_promote(ObColumnSchemaV2& column, int64_t table_id) { int ret = OB_SUCCESS; bool need_check_length = true; ObObjType type = column.get_data_type(); int32_t length = column.get_data_length(); if (OB_INVALID_ID != table_id && is_inner_table(table_id)) { // inner table don't need to rewrite // if table_id == OB_INVALID_ID, this is not inner_table need_check_length = false; } if (OB_FAIL(check_text_length(column.get_charset_type(), column.get_collation_type(), column.get_column_name(), type, length, need_check_length))) { LOG_WARN("failed to check text length", K(ret), K(column)); } else { column.set_data_type(type); column.set_data_length(length); } return ret; } int ObDDLResolver::check_and_fill_column_charset_info( ObColumnSchemaV2& column, const ObCharsetType table_charset_type, const ObCollationType table_collation_type) { int ret = OB_SUCCESS; ObCharsetType charset_type = CHARSET_INVALID; ObCollationType collation_type = CS_TYPE_INVALID; ; if (CHARSET_INVALID == table_charset_type || CS_TYPE_INVALID == table_collation_type) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid column charset info!", K(ret)); } else { charset_type = column.get_charset_type(); collation_type = column.get_collation_type(); } if (OB_FAIL(ret)) { // empty } else if (column.is_binary_collation() && CS_TYPE_INVALID == collation_type) { if (CHARSET_INVALID == charset_type) { column.set_charset_type(table_charset_type); column.set_collation_type(ObCharset::get_bin_collation(table_charset_type)); } else { column.set_charset_type(charset_type); column.set_collation_type(ObCharset::get_bin_collation(charset_type)); } } else if (CHARSET_INVALID == charset_type && CS_TYPE_INVALID == collation_type) { column.set_charset_type(table_charset_type); column.set_collation_type(table_collation_type); } else if (OB_FAIL(ObCharset::check_and_fill_info(charset_type, collation_type))) { SQL_RESV_LOG(WARN, "fail to fill charset and collation info", K(collation_type), K(ret)); } else { column.set_charset_type(charset_type); column.set_collation_type(collation_type); } return ret; } int ObDDLResolver::resolve_part_func(ObResolverParams& params, const ParseNode* node, const ObPartitionFuncType partition_func_type, const ObTableSchema& table_schema, ObIArray& part_func_exprs, ObIArray& partition_keys) { int ret = OB_SUCCESS; part_func_exprs.reset(); partition_keys.reset(); if (OB_ISNULL(node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("NULL ptr", K(ret)); } else if (T_EXPR_LIST == node->type_) { if (node->num_child_ < 1) { ret = OB_ERR_UNEXPECTED; LOG_WARN("Partition fun node should not less than 1", K(ret)); } else if (node->num_child_ > OB_MAX_PART_COLUMNS) { ret = OB_ERR_TOO_MANY_PARTITION_FUNC_FIELDS; LOG_WARN("Too may partition func fields", K(ret)); } else { ObRawExpr* func_expr = NULL; for (int64_t i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { func_expr = NULL; if (OB_ISNULL(node->children_[i]) || T_EXPR_LIST == node->children_[i]->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null or node type error", K(ret)); } else if (OB_FAIL(ObResolverUtils::resolve_partition_expr( params, *(node->children_[i]), table_schema, partition_func_type, func_expr, &partition_keys))) { LOG_WARN("resolve partition expr failed", K(ret)); } else if (OB_FAIL(part_func_exprs.push_back(func_expr))) { LOG_WARN("array push back fail", K(ret)); } else { LOG_DEBUG("succ to resolve_part_func", KPC(func_expr)); } // do nothing } // end of for } } else { ObRawExpr* func_expr = NULL; if (OB_FAIL(ObResolverUtils::resolve_partition_expr( params, *node, table_schema, partition_func_type, func_expr, &partition_keys))) { LOG_WARN("resolve partition expr failed", K(ret)); } else if (OB_FAIL(part_func_exprs.push_back(func_expr))) { LOG_WARN("array push back fail", K(ret)); } else if (partition_keys.count() > OB_MAX_PART_COLUMNS) { ret = OB_ERR_TOO_MANY_PARTITION_FUNC_FIELDS; LOG_WARN("too may partition func fields", K(ret)); } } if (OB_SUCC(ret)) { // check duplicate of PARTITION_FUNC_TYPE_RANGE_COLUMNS if (partition_func_type == PARTITION_FUNC_TYPE_RANGE_COLUMNS) { for (int64_t idx = 0; OB_SUCC(ret) && idx < partition_keys.count(); ++idx) { const ObString& key_name = partition_keys.at(idx); for (int64_t b_idx = 0; OB_SUCC(ret) && b_idx < idx; ++b_idx) { if (ObCharset::case_insensitive_equal(key_name, partition_keys.at(b_idx))) { ret = OB_ERR_SAME_NAME_PARTITION_FIELD; LOG_USER_ERROR(OB_ERR_SAME_NAME_PARTITION_FIELD, key_name.length(), key_name.ptr()); } } } } } return ret; } int ObDDLResolver::resolve_list_partition_elements(const ObDDLStmt* stmt, ParseNode* node, const bool is_subpartition, const ObPartitionFuncType part_type, const ObIArray& part_func_exprs, ObDDLStmt::array_t& list_value_exprs, ObIArray& partitions, ObIArray& subpartitions, int64_t max_used_part_id, const bool& in_tablegroup) { int ret = OB_SUCCESS; if (OB_ISNULL(node) || OB_ISNULL(stmt_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null or stmt is null", K(ret), K(node), K(stmt_)); } else if (!is_subpartition && max_used_part_id >= 0 && max_used_part_id < node->num_child_ - 1) { ret = OB_INVALID_ARGUMENT; LOG_WARN("max_used_part_id is invalid", K(ret), K(max_used_part_id), K(node->num_child_)); } else { int64_t partition_num = node->num_child_; ParseNode* partition_expr_list = node; ObPartition partition; ObSubPartition subpartition; int64_t part_id = OB_INVALID_PARTITION_ID; bool use_part_id = false; bool has_empty_name = false; for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; i++) { subpartition.reset(); partition.reset(); ParseNode* element_node = partition_expr_list->children_[i]; if (OB_ISNULL(element_node) || OB_ISNULL(element_node->children_[PARTITION_ELEMENT_NODE])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition expr list node is null", K(ret), K(element_node)); } else if ((OB_ISNULL(element_node->children_[PARTITION_NAME_NODE]) || OB_ISNULL(element_node->children_[PARTITION_NAME_NODE]->children_[NAMENODE])) && !is_oracle_mode()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition expr list node is null", K(ret), K(element_node)); } else { ObString partition_name; if (OB_NOT_NULL(element_node->children_[PARTITION_NAME_NODE])) { ParseNode* partition_name_node = element_node->children_[PARTITION_NAME_NODE]->children_[NAMENODE]; partition_name.assign_ptr( partition_name_node->str_value_, static_cast(partition_name_node->str_len_)); } else if (is_subpartition) { subpartition.set_is_empty_partition_name(true); has_empty_name = true; } else { partition.set_is_empty_partition_name(true); has_empty_name = true; } ParseNode* expr_list_node = element_node->children_[PARTITION_ELEMENT_NODE]; if (partition_name.length() > OB_MAX_PARTITION_NAME_LENGTH) { ret = OB_ERR_TOO_LONG_IDENT; } else if (T_EXPR_LIST != expr_list_node->type_ && T_DEFAULT != expr_list_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr_list_node->type_ is not T_EXPR_LIST or T_DEFAULT", K(ret), "expr_list_node type", expr_list_node->type_); } else if (use_part_id) { // special case for backup-restore module if (OB_ISNULL(element_node->children_[PART_ID_NODE])) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Should speicify part id for all parts", K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "partition id which should include either none or all partition ids"); } } // add list partition elements to table schema if (OB_SUCC(ret)) { part_id = OB_INVALID_PARTITION_ID; if (is_subpartition) { subpartition.set_part_id(ObSubPartition::TEMPLATE_PART_ID); subpartition.set_sub_part_id(i); if (OB_FAIL(subpartition.set_part_name(partition_name))) { LOG_WARN("Failed to set part name", K(ret)); } else { ret = subpartitions.push_back(subpartition); } } else if (OB_ISNULL(element_node->children_[PART_ID_NODE])) { part_id = max_used_part_id >= 0 ? max_used_part_id - partition_num + 1 + i : i; } else { bool valid = false; part_id = static_cast(element_node->children_[PART_ID_NODE]->children_[0]->value_); if (OB_FAIL(check_partid_valid(stmt, part_id, max_used_part_id, valid))) { LOG_WARN("part id not valid", K(ret)); } else if (!valid) { ret = OB_ERR_UNEXPECTED; LOG_WARN("part id not valid", K(ret)); } else if (0 == i) { use_part_id = true; } else if (!use_part_id) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Should speicify part id for all parts", K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "partition id which should include either none or all partition ids"); } } } if (OB_SUCC(ret)) { if (part_id < 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition id is invalid", K(ret), K(part_id)); } else { partition.set_part_id(part_id); if (OB_FAIL(partition.set_part_name(partition_name))) { LOG_WARN("Failed to set part name", K(ret)); } else { ret = partitions.push_back(partition); } } } if (OB_SUCC(ret)) { if (OB_FAIL(resolve_list_partition_value_node( *expr_list_node, partition_name, part_type, part_func_exprs, list_value_exprs, in_tablegroup))) { LOG_WARN("failed to resolve list partition value node", K(ret)); } } } } if (OB_UNLIKELY(has_empty_name) && (stmt::T_CREATE_TABLE == stmt->get_stmt_type() || stmt::T_CREATE_TABLEGROUP == stmt->get_stmt_type() || stmt::T_CREATE_INDEX == stmt->get_stmt_type())) { if (OB_FAIL(create_name_for_empty_partition(is_subpartition, partitions, subpartitions))) { LOG_WARN("failed to create name for empty [sub]partitions", K(ret)); } } } return ret; } int ObDDLResolver::resolve_range_partition_elements(const ObDDLStmt* stmt, ParseNode* node, const bool is_subpartition, const ObPartitionFuncType part_type, const ObIArray& part_func_exprs, ObIArray& range_value_exprs, ObIArray& partitions, ObIArray& subpartitions, int64_t max_used_part_id, const bool& in_tablegroup) { int ret = OB_SUCCESS; if (OB_ISNULL(node) || OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null or stmt is null", K(ret), K(node), K(stmt)); } else if (!is_subpartition && max_used_part_id >= 0 && max_used_part_id < node->num_child_ - 1) { ret = OB_INVALID_ARGUMENT; LOG_WARN("max_used_part_id is invalid", K(ret), K(max_used_part_id), K(node->num_child_)); } else { int64_t partition_num = node->num_child_; ParseNode* partition_expr_list = node; ObPartition partition; ObSubPartition subpartition; bool init_specified = false; bool has_empty_name = false; // ignore alter_table with part_id for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; i++) { subpartition.reset(); partition.reset(); ParseNode* element_node = partition_expr_list->children_[i]; if (OB_ISNULL(element_node) || OB_ISNULL(element_node->children_[PARTITION_ELEMENT_NODE])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition expr list node is null", K(ret), K(element_node)); } else if ((OB_ISNULL(element_node->children_[PARTITION_NAME_NODE]) || OB_ISNULL(element_node->children_[PARTITION_NAME_NODE]->children_[NAMENODE])) && !is_oracle_mode()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition expr list node is null", K(ret), K(element_node)); } else { ObString partition_name; if (OB_NOT_NULL(element_node->children_[PARTITION_NAME_NODE])) { ParseNode* partition_name_node = element_node->children_[PARTITION_NAME_NODE]->children_[NAMENODE]; partition_name.assign_ptr( partition_name_node->str_value_, static_cast(partition_name_node->str_len_)); } else if (is_subpartition) { subpartition.set_is_empty_partition_name(true); has_empty_name = true; } else { partition.set_is_empty_partition_name(true); has_empty_name = true; } ParseNode* expr_list_node = element_node->children_[PARTITION_ELEMENT_NODE]; if (partition_name.length() > OB_MAX_PARTITION_NAME_LENGTH) { ret = OB_ERR_TOO_LONG_IDENT; } else if (T_EXPR_LIST != expr_list_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr_list_node->type_ is not T_EXPR_LIST", K(ret)); } else if (part_func_exprs.count() != expr_list_node->num_child_) { ret = OB_ERR_PARTITION_COLUMN_LIST_ERROR; LOG_WARN("Inconsistency in usage of column lists for partitioning near", K(ret)); } else { // add range partition elements to table schema if (OB_SUCC(ret)) { if (is_subpartition) { subpartition.set_part_id(ObSubPartition::TEMPLATE_PART_ID); subpartition.set_sub_part_id(i); if (OB_FAIL(subpartition.set_part_name(partition_name))) { LOG_WARN("Failed to set part name", K(ret)); } else { ret = subpartitions.push_back(subpartition); } } else { int64_t part_id = OB_INVALID_ID; bool current_spec = false; if (OB_ISNULL(element_node->children_[PART_ID_NODE])) { // part_id not specified part_id = max_used_part_id >= 0 ? max_used_part_id - partition_num + 1 + i : i; current_spec = false; } else { // with part_id part_id = static_cast(element_node->children_[PART_ID_NODE]->children_[0]->value_); if (OB_FAIL(check_partid_valid(stmt, part_id, max_used_part_id, current_spec))) { LOG_WARN("part id not valid", K(ret)); } else if (!current_spec) { ret = OB_ERR_UNEXPECTED; LOG_WARN("part id not valid", K(ret)); } } // all with part id, or all without part id. // otherwise unsupported if (OB_SUCC(ret)) { if (0 == i) { init_specified = current_spec; } else if (current_spec != init_specified) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Should speicify part id for all parts", K(ret)); LOG_USER_ERROR( OB_INVALID_ARGUMENT, "partition id which should include either none or all partition ids"); } } if (OB_FAIL(ret)) { } else if (part_id < 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid part_id", K(ret), K(part_id)); } else if (OB_FAIL(partition.set_part_name(partition_name))) { LOG_WARN("Failed to set part name", K(ret)); } else { partition.set_part_id(part_id); ret = partitions.push_back(partition); } } } for (int64_t j = 0; OB_SUCC(ret) && j < expr_list_node->num_child_; j++) { if (OB_ISNULL(expr_list_node->children_[j])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null", K(ret)); } else if (T_MAXVALUE == expr_list_node->children_[j]->type_) { ObRawExpr* maxvalue_expr = NULL; ObConstRawExpr* c_expr = NULL; c_expr = (ObConstRawExpr*)allocator_->alloc(sizeof(ObConstRawExpr)); if (NULL != c_expr) { c_expr = new (c_expr) ObConstRawExpr(); maxvalue_expr = c_expr; maxvalue_expr->set_data_type(common::ObMaxType); if (OB_FAIL(range_value_exprs.push_back(maxvalue_expr))) { LOG_WARN("array push back fail", K(ret)); } } else { ret = OB_ALLOCATE_MEMORY_FAILED; } } else if (T_NULL == expr_list_node->children_[j]->type_) { ret = OB_EER_NULL_IN_VALUES_LESS_THAN; LOG_WARN("null value is not allowed in less than", K(ret)); } else if (T_EXPR_LIST != expr_list_node->children_[j]->type_) { ObRawExpr* part_value_expr = NULL; ObRawExpr* part_func_expr = NULL; if (OB_FAIL(part_func_exprs.at(j, part_func_expr))) { LOG_WARN("get part expr failed", K(j), "size", part_func_exprs.count(), K(ret)); } else if (OB_ISNULL(part_func_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("part_func_expr is invalid", K(ret)); } else if (OB_FAIL(ObResolverUtils::resolve_partition_range_value_expr(params_, *(expr_list_node->children_[j]), partition_name, part_type, *part_func_expr, part_value_expr, in_tablegroup))) { LOG_WARN("resolve partition expr failed", K(ret)); } else if (OB_FAIL(range_value_exprs.push_back(part_value_expr))) { LOG_WARN("array push back fail", K(ret)); } } else { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("syntax error, expect single expr while expr list got", K(ret)); } } } } } if (OB_UNLIKELY(has_empty_name) && (stmt::T_CREATE_TABLE == stmt->get_stmt_type() || stmt::T_CREATE_TABLEGROUP == stmt->get_stmt_type() || stmt::T_CREATE_INDEX == stmt->get_stmt_type())) { if (OB_FAIL(create_name_for_empty_partition(is_subpartition, partitions, subpartitions))) { LOG_WARN("failed to create name for empty [sub]partitions", K(ret)); } } } return ret; } int ObDDLResolver::check_partid_valid( const ObDDLStmt* stmt, const int64_t part_id, const int64_t max_used_part_id, bool& valid) { int ret = OB_SUCCESS; bool is_sync_ddl_user = false; if (OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt is null", K(ret)); } else if (stmt::T_CREATE_TABLE != stmt->get_stmt_type() && stmt::T_CREATE_TABLEGROUP != stmt->get_stmt_type() && stmt::T_CREATE_INDEX != stmt->get_stmt_type()) { ret = OB_ERR_PARSE_SQL; LOG_WARN( "only support create table or tablegroup or index with part_id", K(ret), "stmt_type", stmt->get_stmt_type()); } else if (OB_FAIL(ObResolverUtils::check_sync_ddl_user(session_info_, is_sync_ddl_user))) { LOG_WARN("Failed to check sync_dll_user", K(ret)); } else if (!is_sync_ddl_user) { ret = OB_ERR_PARSE_SQL; LOG_WARN("Only support for sync ddl user to specify part id", K(ret), "user name", session_info_->get_user_name()); } else if (max_used_part_id < 0) { // must specify max_used_part_id ret = OB_OP_NOT_ALLOW; LOG_WARN("specific part_id without max_used_part_id not allowed", K(max_used_part_id), K(ret)); LOG_USER_ERROR(OB_OP_NOT_ALLOW, "specify part_id without max_used_part_id"); } else if (part_id > max_used_part_id) { // can't larger than max_used_part_id ret = OB_INVALID_ARGUMENT; LOG_WARN("part_id is bigger than max_used_part_id", K(part_id), K(max_used_part_id), K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "part_id or max_used_part_id"); } else { valid = true; } return ret; } int ObDDLResolver::check_max_used_part_id_valid( const share::schema::ObTableSchema& table_schema, int64_t& max_used_part_id) { int ret = OB_SUCCESS; int64_t current_max_part_id = -1; if (table_schema.is_auto_partitioned_table()) { } else if (table_schema.is_range_part() || table_schema.is_list_part()) { // get max part id ObPartition** part_array = table_schema.get_part_array(); if (OB_FAIL(GET_PART_ID(part_array, table_schema.get_first_part_num() - 1, current_max_part_id))) { LOG_WARN("Failed to get part id", K(table_schema.get_first_part_num() - 1), K(ret)); } } else { current_max_part_id = table_schema.get_part_option().get_part_num() - 1; } if (OB_SUCC(ret)) { if (max_used_part_id < 0) { max_used_part_id = current_max_part_id; } else if (PARTITION_LEVEL_ZERO == table_schema.get_part_level()) { ret = OB_NOT_SUPPORTED; SQL_RESV_LOG(WARN, "non-partitioned table with max_used_part_id not support", K(ret), K(max_used_part_id)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "non-partitioned table with max_used_part_id"); } else if (max_used_part_id < current_max_part_id) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid max_used_part_id", K(ret), K(max_used_part_id), K(current_max_part_id)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "max_used_part_id"); } else { // use max_used_part_id_ } } return ret; } int ObDDLResolver::check_partition_name_duplicate(ParseNode* node, bool is_oracle_modle) { int ret = OB_SUCCESS; if (OB_ISNULL(node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null", K(ret)); } else { hash::ObPlacementHashSet* partition_name_set = nullptr; void* buf = nullptr; int64_t partition_num = node->num_child_; ParseNode* partition_expr_list = node; ParseNode* element_node = NULL; if (OB_ISNULL(buf = allocator_->alloc( sizeof(hash::ObPlacementHashSet)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to allocate memory", KR(ret)); } else { partition_name_set = new (buf) hash::ObPlacementHashSet(); } if (OB_FAIL(ret)) { } else if (OB_ISNULL(partition_name_set)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition name hash set is null", KR(ret)); } for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; i++) { element_node = partition_expr_list->children_[i]; if (OB_ISNULL(element_node) || OB_ISNULL(element_node->children_[PARTITION_ELEMENT_NODE])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition expr list node is null", K(ret), K(element_node)); } else if ((OB_ISNULL(element_node->children_[PARTITION_NAME_NODE]) || OB_ISNULL(element_node->children_[PARTITION_NAME_NODE]->children_[NAMENODE])) && !is_oracle_modle) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition expr list node is null", K(ret), K(element_node)); } else { ObString partition_name; if (OB_NOT_NULL(element_node->children_[PARTITION_NAME_NODE])) { ParseNode* partition_name_node = element_node->children_[PARTITION_NAME_NODE]->children_[NAMENODE]; partition_name.assign_ptr( partition_name_node->str_value_, static_cast(partition_name_node->str_len_)); ObPartitionNameHashWrapper partition_name_key(partition_name); if (OB_HASH_EXIST == partition_name_set->exist_refactored(partition_name_key)) { ret = OB_ERR_SAME_NAME_PARTITION; LOG_USER_ERROR(OB_ERR_SAME_NAME_PARTITION, partition_name.length(), partition_name.ptr()); } else { if (OB_FAIL(partition_name_set->set_refactored(partition_name_key))) { LOG_WARN("add partition name to map failed", K(ret), K(ret)); } } } } } } return ret; } int ObDDLResolver::fill_extended_type_info(const ParseNode& str_list_node, ObColumnSchemaV2& column) { int ret = OB_SUCCESS; ObArray type_info_array; CK(NULL != session_info_); CK(NULL != allocator_); if (OB_FAIL(ret)) { } else if (OB_FAIL(ObResolverUtils::resolve_extended_type_info(str_list_node, type_info_array))) { LOG_WARN("failed to resolve extended type info", K(ret)); } else { // The resolved extended type info's collation is session connection collation, // need convert to column collation finally. The converting may be done in RS, // but the session connection collation info is lost in RS, so we convert to a // intermediate collation (system collation) here. Convert from the intermediate // collation to column collation finally in ObResolverUtils::check_extended_type_info(). ObCollationType src = session_info_->get_local_collation_connection(); ObCollationType dst = ObCharset::get_system_collation(); FOREACH_CNT_X(str, type_info_array, OB_SUCC(ret)) { OZ(ObCharset::charset_convert(*allocator_, *str, src, dst, *str)); } } OZ(column.set_extended_type_info(type_info_array)); return ret; } int ObDDLResolver::resolve_enum_or_set_column(const ParseNode* type_node, ObColumnSchemaV2& column) { int ret = OB_SUCCESS; if (OB_ISNULL(type_node) || OB_UNLIKELY(type_node->num_child_ != 4) || OB_ISNULL(allocator_) || OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("type node is NULL", K(ret), K(type_node), K(session_info_)); } else if (OB_ISNULL(type_node->children_[3])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("child is NULL", K(ret)); } else if (OB_FAIL(fill_extended_type_info(*(type_node->children_[3]), column))) { LOG_WARN("fail to fill type info", K(ret), K(column)); } else if (stmt::T_ALTER_TABLE == stmt_->get_stmt_type()) { } else if (OB_FAIL(check_and_fill_column_charset_info(column, charset_type_, collation_type_))) { LOG_WARN("fail to check and fill column charset info", K(ret), K(column), K(charset_type_), K(collation_type_)); } else if (OB_FAIL(check_extended_type_info(column, session_info_->get_sql_mode()))) { LOG_WARN("fail to fill extended type info", K(ret), K(column), K(session_info_->get_sql_mode())); } else if (OB_FAIL(calc_enum_or_set_data_length(column))) { LOG_WARN("fail to calc data length", K(ret), K(column)); } return ret; } int ObDDLResolver::calc_enum_or_set_data_length(const ObIArray& type_info, const ObCollationType& collation_type, const ObObjType& type, int32_t& length) { int ret = OB_SUCCESS; int32_t cur_len = 0; if (OB_UNLIKELY(ObEnumType != type && ObSetType != type)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected column type", K(ret)); } else if (ObEnumType == type) { for (int64_t i = 0; OB_SUCC(ret) && i < type_info.count(); ++i) { const ObString& type_str = type_info.at(i); cur_len = static_cast(ObCharset::strlen_char(collation_type, type_str.ptr(), type_str.length())); length = length < cur_len ? cur_len : length; } } else { for (int64_t i = 0; OB_SUCC(ret) && i < type_info.count(); ++i) { const ObString& type_str = type_info.at(i); cur_len = static_cast(ObCharset::strlen_char(collation_type, type_str.ptr(), type_str.length())); length += cur_len; } length += (static_cast(type_info.count()) - 1) * ObCharsetUtils::get_const_str(collation_type, ',').length(); } return ret; } int ObDDLResolver::calc_enum_or_set_data_length(ObColumnSchemaV2& column) { int ret = OB_SUCCESS; int32_t length = 0; if (OB_FAIL(calc_enum_or_set_data_length( column.get_extended_type_info(), column.get_collation_type(), column.get_data_type(), length))) { LOG_WARN("failed to calc enum or set data length", K(ret)); } else { column.set_data_length(length); } return ret; } int ObDDLResolver::check_extended_type_info(ObColumnSchemaV2& column, ObSQLMode sql_mode) { return ObResolverUtils::check_extended_type_info(*allocator_, column.get_extended_type_info(), ObCharset::get_system_collation(), column.get_column_name_str(), column.get_data_type(), column.get_collation_type(), sql_mode); } int ObDDLResolver::check_duplicates_in_type_infos(const ObColumnSchemaV2& col, ObSQLMode sql_mode, int32_t& dup_cnt) { return ObResolverUtils::check_duplicates_in_type_infos(col.get_extended_type_info(), col.get_column_name_str(), col.get_data_type(), col.get_collation_type(), sql_mode, dup_cnt); } int ObDDLResolver::check_type_info_incremental_change( const ObColumnSchemaV2& ori_schema, const ObColumnSchemaV2& new_schema) { int ret = OB_SUCCESS; const ObIArray& ori_type_info = ori_schema.get_extended_type_info(); const ObIArray& new_type_info = new_schema.get_extended_type_info(); if (OB_UNLIKELY(new_type_info.count() < ori_type_info.count())) { ret = OB_NOT_SUPPORTED; LOG_WARN("not support", K(new_type_info.count()), K(ori_type_info.count()), K(ret)); } else if (OB_UNLIKELY(ori_schema.get_charset_type() != new_schema.get_charset_type())) { ret = OB_NOT_SUPPORTED; LOG_WARN("not support", K(ori_schema.get_collation_type()), K(ori_schema.get_collation_type()), K(ret)); } ObCollationType coll_type = ori_schema.get_collation_type(); for (int64_t i = 0; OB_SUCC(ret) && i < ori_type_info.count(); ++i) { const ObString& ori_str = ori_type_info.at(i); const ObString& new_str = new_type_info.at(i); if (0 != ObCharset::strcmp(coll_type, ori_str.ptr(), ori_str.length(), new_str.ptr(), new_str.length())) { ret = OB_NOT_SUPPORTED; LOG_WARN("not support", K(coll_type), K(ori_str), K(new_str), K(ret)); } } return ret; } int ObDDLResolver::cast_enum_or_set_default_value(const ObColumnSchemaV2& column, ObCastCtx& cast_ctx, ObObj& def_val) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!def_val.is_string_type())) { ret = OB_INVALID_DEFAULT; LOG_WARN("invalid default value type", K(def_val), K(ret)); LOG_USER_ERROR(OB_INVALID_DEFAULT, column.get_column_name_str().length(), column.get_column_name_str().ptr()); } else if (OB_UNLIKELY(!ob_is_enumset_tc(column.get_data_type()))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected column type", K(column), K(ret)); } else { ObExpectType expect_type; expect_type.set_type(column.get_data_type()); expect_type.set_collation_type(column.get_collation_type()); expect_type.set_type_infos(&column.get_extended_type_info()); if (OB_FAIL(ObObjCaster::to_type(expect_type, cast_ctx, def_val, def_val))) { ret = OB_INVALID_DEFAULT; LOG_WARN("fail to cast to enum or set", K(def_val), K(expect_type), K(ret)); LOG_USER_ERROR(OB_INVALID_DEFAULT, column.get_column_name_str().length(), column.get_column_name_str().ptr()); } } return ret; } int ObDDLResolver::print_expr_to_default_value( ObRawExpr& expr, share::schema::ObColumnSchemaV2& column, const ObTimeZoneInfo* tz_info) { int ret = OB_SUCCESS; HEAP_VAR(char[OB_MAX_DEFAULT_VALUE_LENGTH], expr_str_buf) { MEMSET(expr_str_buf, 0, sizeof(expr_str_buf)); int64_t pos = 0; ObString expr_def; ObObj default_value; ObRawExprPrinter expr_printer(expr_str_buf, OB_MAX_DEFAULT_VALUE_LENGTH, &pos, tz_info); if (OB_FAIL(expr_printer.do_print(&expr, T_NONE_SCOPE, true))) { LOG_WARN("print expr definition failed", K(expr), K(ret)); } else if (FALSE_IT(expr_def.assign_ptr(expr_str_buf, static_cast(pos)))) { } else if (FALSE_IT(default_value.set_varchar(expr_def))) { } else if (FALSE_IT(default_value.set_collation_type(ObCharset::get_system_collation()))) { } else if (OB_FAIL(column.set_cur_default_value(default_value))) { LOG_WARN("set orig default value failed", K(ret)); } else { LOG_DEBUG("succ to print_expr_to_default_value", K(expr), K(column), K(default_value), K(expr_def), K(ret)); } } return ret; } int ObDDLResolver::check_default_value(ObObj& default_value, const common::ObTimeZoneInfoWrap& tz_info_wrap, const common::ObString* nls_formats, ObIAllocator& allocator, ObTableSchema& table_schema, ObColumnSchemaV2& column) { int ret = OB_SUCCESS; const ObObj input_default_value = default_value; if (column.is_generated_column()) { ObString expr_str; ObResolverParams params; ObRawExpr* expr = NULL; ObRawExprFactory expr_factory(allocator); ObSQLSessionInfo empty_session; params.expr_factory_ = &expr_factory; params.allocator_ = &allocator; params.session_info_ = &empty_session; if (OB_FAIL(empty_session.test_init(0, 0, 0, &allocator))) { LOG_WARN("init empty session failed", K(ret)); } else if (OB_FAIL(empty_session.load_default_sys_variable(false, false))) { LOG_WARN("session load default system variable failed", K(ret)); } else if (OB_FAIL(input_default_value.get_string(expr_str))) { LOG_WARN("get expr string from default value failed", K(ret), K(input_default_value)); } else if (OB_FAIL(ObResolverUtils::resolve_generated_column_expr( params, expr_str, table_schema, column, expr, ObResolverUtils::CHECK_FOR_GENERATED_COLUMN))) { LOG_WARN("resolve generated column expr failed", K(ret)); } else if (column.get_meta_type().is_null()) { column.set_data_type(expr->get_data_type()); column.set_collation_type(expr->get_collation_type()); column.set_accuracy(expr->get_accuracy()); } } else if (column.is_default_expr_v2_column()) { ObString expr_str; ObResolverParams params; ObRawExpr* expr = NULL; ObRawExprFactory expr_factory(allocator); ObSQLSessionInfo empty_session; ParamStore empty_param_list((ObWrapperAllocator(allocator))); params.expr_factory_ = &expr_factory; params.allocator_ = &allocator; params.session_info_ = &empty_session; params.param_list_ = &empty_param_list; common::ObObj tmp_default_value; common::ObObj tmp_dest_obj; const ObObj* tmp_res_obj = NULL; common::ObObj tmp_dest_obj_null; const bool is_strict = true; // oracle mode const ObObjType data_type = column.get_data_type(); const ObAccuracy& accuracy = column.get_accuracy(); const ObCollationType collation_type = column.get_collation_type(); const ObDataTypeCastParams dtc_params( tz_info_wrap.get_time_zone_info(), nls_formats, CS_TYPE_INVALID, CS_TYPE_INVALID, CS_TYPE_UTF8MB4_GENERAL_CI); ObCastCtx cast_ctx(&allocator, &dtc_params, CM_NONE, column.get_collation_type()); if (OB_FAIL(empty_session.test_init(0, 0, 0, &allocator))) { LOG_WARN("init empty session failed", K(ret)); } else if (OB_FAIL(empty_session.load_default_sys_variable(false, false))) { LOG_WARN("session load default system variable failed", K(ret)); } else if (OB_FAIL(empty_session.set_tz_info_wrap(tz_info_wrap))) { LOG_WARN("fail to set set_tz_info_wrap", K(ret)); } else if (FALSE_IT(empty_session.set_nls_formats(nls_formats))) { } else if (FALSE_IT(empty_session.set_compatibility_mode( share::is_oracle_mode() ? ObCompatibilityMode::ORACLE_MODE : ObCompatibilityMode::MYSQL_MODE))) { } else if (FALSE_IT( empty_session.set_sql_mode(share::is_oracle_mode() ? DEFAULT_ORACLE_MODE : DEFAULT_MYSQL_MODE))) { } else if (OB_FAIL(input_default_value.get_string(expr_str))) { LOG_WARN("get expr string from default value failed", K(ret), K(input_default_value)); } else if (OB_FAIL(ObResolverUtils::resolve_default_expr_v2_column_expr(params, expr_str, column, expr))) { LOG_WARN("resolve expr_default expr failed", K(expr_str), K(column), K(ret)); } else if (OB_FAIL(ObSQLUtils::calc_simple_expr_without_row(stmt::StmtType::T_NONE, params.session_info_, expr, tmp_default_value, params.param_list_, allocator))) { LOG_WARN("Failed to get simple expr value", K(ret)); } else if (OB_FAIL(ObObjCaster::to_type(data_type, cast_ctx, tmp_default_value, tmp_dest_obj, tmp_res_obj))) { LOG_WARN("cast obj failed, ", "src type", tmp_default_value.get_type(), "dest type", data_type, K(tmp_default_value), K(ret)); } else if (OB_ISNULL(tmp_res_obj)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("cast obj failed, ", "src type", tmp_default_value.get_type(), "dest type", data_type, K(tmp_default_value), K(ret)); } else if (OB_FAIL(obj_collation_check(is_strict, collation_type, *const_cast(tmp_res_obj)))) { LOG_WARN("failed to check collation", K(ret), K(collation_type), K(tmp_dest_obj)); } else if (OB_FAIL( obj_accuracy_check(cast_ctx, accuracy, collation_type, *tmp_res_obj, tmp_dest_obj, tmp_res_obj))) { LOG_WARN("failed to check accuracy", K(ret), K(accuracy), K(collation_type), KPC(tmp_res_obj)); } else if (0 == input_default_value.get_string().compare("''")) { // if default is '', we should store '' instead of NULL. // FIXME::when observer differentiate '' and null, we can delete this code tmp_dest_obj_null.set_varchar(input_default_value.get_string()); tmp_dest_obj_null.set_collation_type(ObCharset::get_system_collation()); if (OB_FAIL(column.set_cur_default_value(tmp_dest_obj_null))) { LOG_WARN("set orig default value failed", K(ret)); } } else if (OB_FAIL(print_expr_to_default_value(*expr, column, tz_info_wrap.get_time_zone_info()))) { LOG_WARN("fail to print_expr_to_default_value", KPC(expr), K(column), K(ret)); } LOG_DEBUG("finish check default value", K(input_default_value), K(expr_str), K(tmp_default_value), K(tmp_dest_obj), K(tmp_dest_obj_null), KPC(expr), K(ret)); } else { if (OB_FAIL(cast_default_value(default_value, tz_info_wrap.get_time_zone_info(), nls_formats, allocator, column))) { LOG_WARN( "fail to cast default value!", K(default_value), KPC(tz_info_wrap.get_time_zone_info()), K(column), K(ret)); } else if (OB_FAIL(check_default_value_length(default_value, column))) { LOG_WARN("fail to check default value length", K(default_value), K(column), K(ret)); } else { default_value.set_collation_type(column.get_collation_type()); LOG_DEBUG("succ to set default value", K(input_default_value), K(default_value), K(column), K(ret)); } } return ret; } int ObDDLResolver::calc_default_value(share::schema::ObColumnSchemaV2& column, common::ObObj& default_value, const common::ObTimeZoneInfoWrap& tz_info_wrap, const common::ObString* nls_formats, common::ObIAllocator& allocator) { int ret = OB_SUCCESS; if (IS_DEFAULT_NOW_OBJ(default_value)) { int64_t cur_time = ObTimeUtility::current_time(); ObTimeConverter::round_datetime(column.get_data_scale(), cur_time); switch (column.get_data_type()) { case ObDateTimeType: { int64_t dt_value = 0; if (OB_FAIL(ObTimeConverter::timestamp_to_datetime(cur_time, tz_info_wrap.get_time_zone_info(), dt_value))) { LOG_WARN("failed to convert timestamp to datetime", K(ret)); } else { ObTimeConverter::round_datetime(column.get_data_scale(), dt_value); default_value.set_datetime(dt_value); } break; } case ObTimestampType: { ObTimeConverter::round_datetime(column.get_data_scale(), cur_time); default_value.set_timestamp(cur_time); break; } default: { ret = OB_NOT_SUPPORTED; LOG_WARN("UnKnown type!", "default value type", column.get_data_type(), K(ret)); break; } } } else if (column.is_default_expr_v2_column()) { ObString expr_str; ObResolverParams params; ObRawExpr* expr = NULL; ObRawExprFactory expr_factory(allocator); ObSQLSessionInfo empty_session; ParamStore empty_param_list((ObWrapperAllocator(allocator))); params.expr_factory_ = &expr_factory; params.allocator_ = &allocator; params.session_info_ = &empty_session; params.param_list_ = &empty_param_list; if (OB_FAIL(empty_session.test_init(0, 0, 0, &allocator))) { LOG_WARN("init empty session failed", K(ret)); } else if (OB_FAIL(empty_session.load_default_sys_variable(false, false))) { LOG_WARN("session load default system variable failed", K(ret)); } else if (OB_FAIL(empty_session.set_tz_info_wrap(tz_info_wrap))) { LOG_WARN("fail to set set_tz_info_wrap", K(ret)); } else if (FALSE_IT(empty_session.set_nls_formats(nls_formats))) { } else if (FALSE_IT(empty_session.set_compatibility_mode( share::is_oracle_mode() ? ObCompatibilityMode::ORACLE_MODE : ObCompatibilityMode::MYSQL_MODE))) { } else if (FALSE_IT( empty_session.set_sql_mode(share::is_oracle_mode() ? DEFAULT_ORACLE_MODE : DEFAULT_MYSQL_MODE))) { } else if (OB_FAIL(default_value.get_string(expr_str))) { LOG_WARN("get expr string from default value failed", K(ret), K(default_value)); } else if (OB_FAIL(ObResolverUtils::resolve_default_expr_v2_column_expr(params, expr_str, column, expr))) { LOG_WARN("resolve expr_default expr failed", K(ret)); } else if (OB_FAIL(ObSQLUtils::calc_simple_expr_without_row( stmt::StmtType::T_NONE, params.session_info_, expr, default_value, params.param_list_, allocator))) { LOG_WARN("Failed to get simple expr value", K(ret)); } else { ObObj dest_obj; const ObDataTypeCastParams dtc_params( tz_info_wrap.get_time_zone_info(), nls_formats, CS_TYPE_INVALID, CS_TYPE_INVALID, CS_TYPE_UTF8MB4_GENERAL_CI); ObCastCtx cast_ctx(&allocator, &dtc_params, CM_NONE, column.get_collation_type()); if (OB_FAIL(ObObjCaster::to_type(column.get_data_type(), cast_ctx, default_value, dest_obj))) { LOG_WARN("cast obj failed, ", "src type", default_value.get_type(), "dest type", column.get_data_type(), K(default_value), K(ret)); } else { dest_obj.set_scale(column.get_data_scale()); default_value = dest_obj; } } LOG_DEBUG("finish calc default value", K(column), K(expr_str), K(default_value), KPC(expr), K(ret)); } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("it should not arrive here", K(ret), K(default_value), K(column), K(lbt())); } return ret; } int ObDDLResolver::resolve_range_partition_elements(ParseNode* node, const bool is_subpartition, const ObPartitionFuncType part_type, const int64_t expr_num, ObIArray& range_value_exprs, ObIArray& partitions, ObIArray& subpartitions, const bool& in_tablegroup) { int ret = OB_SUCCESS; if (OB_ISNULL(node) || OB_ISNULL(stmt_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null or stmt is null", K(ret), K(node), KP(stmt_)); } else if (expr_num <= 0) { ret = OB_INVALID_ARGUMENT; LOG_WARN("expr num is invalid", K(ret), K(expr_num)); } else { int64_t partition_num = node->num_child_; ParseNode* partition_expr_list = node; ObPartition partition; ObSubPartition subpartition; bool use_part_id = false; const ObCreateTablegroupStmt* tablegroup_stmt = static_cast(stmt_); bool has_empty_name = false; for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; i++) { subpartition.reset(); partition.reset(); ParseNode* element_node = partition_expr_list->children_[i]; if (OB_ISNULL(element_node) || OB_ISNULL(element_node->children_[PARTITION_ELEMENT_NODE])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition expr list node is null", K(ret), K(element_node)); } else if ((OB_ISNULL(element_node->children_[PARTITION_NAME_NODE]) || OB_ISNULL(element_node->children_[PARTITION_NAME_NODE]->children_[NAMENODE])) && !is_oracle_mode()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition expr list node is null", K(ret), K(element_node)); } else { ObString partition_name; if (OB_NOT_NULL(element_node->children_[PARTITION_NAME_NODE])) { ParseNode* partition_name_node = element_node->children_[PARTITION_NAME_NODE]->children_[NAMENODE]; partition_name.assign_ptr( partition_name_node->str_value_, static_cast(partition_name_node->str_len_)); } else if (is_subpartition) { subpartition.set_is_empty_partition_name(true); has_empty_name = true; } else { partition.set_is_empty_partition_name(true); has_empty_name = true; } ParseNode* expr_list_node = element_node->children_[PARTITION_ELEMENT_NODE]; if (partition_name.length() > OB_MAX_PARTITION_NAME_LENGTH) { ret = OB_ERR_TOO_LONG_IDENT; } else if (T_EXPR_LIST != expr_list_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr_list_node->type_ is not T_EXPR_LIST", K(ret)); } else if (expr_num != expr_list_node->num_child_) { ret = OB_ERR_PARTITION_COLUMN_LIST_ERROR; LOG_WARN("Inconsistency in usage of column lists for partitioning near", K(ret), K(expr_num), "num_child", expr_list_node->num_child_); } else if ((is_subpartition) && OB_NOT_NULL(element_node->children_[PART_ID_NODE])) { ret = OB_ERR_PARSE_SQL; LOG_WARN("not support subpartition with part_id", K(ret), K(is_subpartition), K(in_tablegroup)); } else if (use_part_id && OB_ISNULL(element_node->children_[PART_ID_NODE])) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Should speicify part id for all parts", K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "part id which should speicify part id for all parts"); } else { if (is_subpartition) { subpartition.set_part_id(ObSubPartition::TEMPLATE_PART_ID); subpartition.set_sub_part_id(i); if (OB_FAIL(subpartition.set_part_name(partition_name))) { LOG_WARN("Failed to set part name", K(ret)); } else { ret = subpartitions.push_back(subpartition); } } else { if (nullptr == element_node->children_[PART_ID_NODE]) { partition.set_part_id(i); } else if (OB_ISNULL(tablegroup_stmt) || OB_ISNULL(element_node->children_[PART_ID_NODE]->children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("not create tablegroup stmt or part id node is null", K(ret), "stmt", *stmt_); } else { bool valid = false; const int64_t max_used_part_id = tablegroup_stmt->get_max_used_part_id(); const int64_t part_id = static_cast(element_node->children_[PART_ID_NODE]->children_[0]->value_); partition.set_part_id(part_id); if (OB_FAIL(check_partid_valid(tablegroup_stmt, part_id, max_used_part_id, valid))) { LOG_WARN("part id not valid", K(ret)); } else if (!valid) { ret = OB_ERR_UNEXPECTED; LOG_WARN("part id not valid", K(ret)); } else if (0 == i) { use_part_id = true; } else if (!use_part_id) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Should speicify part id for all parts", K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "part id which should speicify part id for all parts"); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(partition.set_part_name(partition_name))) { LOG_WARN("Failed to set part name", K(ret)); } else { ret = partitions.push_back(partition); } } if (OB_FAIL(ret)) { // do nothing } else if (OB_FAIL(resolve_range_value_exprs( expr_list_node, part_type, partition_name, range_value_exprs, in_tablegroup))) { LOG_WARN("fail to resolve range partition element", K(ret)); } } } } if (OB_UNLIKELY(has_empty_name) && (stmt::T_CREATE_TABLE == stmt_->get_stmt_type() || stmt::T_CREATE_TABLEGROUP == stmt_->get_stmt_type() || stmt::T_CREATE_INDEX == stmt_->get_stmt_type())) { if (OB_FAIL(create_name_for_empty_partition(is_subpartition, partitions, subpartitions))) { LOG_WARN("failed to create name for empty [sub]partitions", K(ret)); } } } return ret; } int ObDDLResolver::resolve_range_partition_elements(ParseNode* node, const bool is_subpartition, const ObPartitionFuncType part_type, ObIArray& range_value_exprs, ObIArray& partitions, ObIArray& subpartitions, int64_t& expr_num, const bool& in_tablegroup) { int ret = OB_SUCCESS; expr_num = OB_INVALID_INDEX; if (OB_ISNULL(node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null or stmt is null", K(ret), K(node)); } else { int64_t partition_num = node->num_child_; ParseNode* partition_expr_list = node; ObPartition partition; ObSubPartition subpartition; bool has_empty_name = false; for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; i++) { subpartition.reset(); partition.reset(); ParseNode* element_node = partition_expr_list->children_[i]; if (OB_ISNULL(element_node) || OB_ISNULL(element_node->children_[PARTITION_ELEMENT_NODE])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition expr list node is null", K(ret), K(element_node)); } else if ((OB_ISNULL(element_node->children_[PARTITION_NAME_NODE]) || OB_ISNULL(element_node->children_[PARTITION_NAME_NODE]->children_[NAMENODE])) && !is_oracle_mode()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition expr list node is null", K(ret), K(element_node)); } else { ObString partition_name; if (OB_NOT_NULL(element_node->children_[PARTITION_NAME_NODE])) { ParseNode* partition_name_node = element_node->children_[PARTITION_NAME_NODE]->children_[NAMENODE]; partition_name.assign_ptr( partition_name_node->str_value_, static_cast(partition_name_node->str_len_)); } else if (is_subpartition) { subpartition.set_is_empty_partition_name(true); bool has_empty_name = false; } else { partition.set_is_empty_partition_name(true); bool has_empty_name = false; } ParseNode* expr_list_node = element_node->children_[PARTITION_ELEMENT_NODE]; if (partition_name.length() > OB_MAX_PARTITION_NAME_LENGTH) { ret = OB_ERR_TOO_LONG_IDENT; } else if (T_EXPR_LIST != expr_list_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr_list_node->type_ is not T_EXPR_LIST", K(ret)); } else if (OB_INVALID_INDEX != expr_num && expr_num != expr_list_node->num_child_) { ret = OB_ERR_PARTITION_COLUMN_LIST_ERROR; LOG_WARN("Inconsistency in usage of column lists for partitioning near", K(ret), K(expr_num), "num_child", expr_list_node->num_child_); } else if ((in_tablegroup || is_subpartition) && OB_NOT_NULL(element_node->children_[PART_ID_NODE])) { ret = OB_ERR_PARSE_SQL; LOG_WARN("not support tablegroup or subpartition with part_id", K(ret), K(is_subpartition), K(in_tablegroup)); } else { if (is_subpartition) { subpartition.set_part_id(ObSubPartition::TEMPLATE_PART_ID); subpartition.set_sub_part_id(i); if (OB_FAIL(subpartition.set_part_name(partition_name))) { LOG_WARN("Failed to set part name", K(ret)); } else { ret = subpartitions.push_back(subpartition); } } else { partition.set_part_id(i); if (OB_FAIL(partition.set_part_name(partition_name))) { LOG_WARN("Failed to set part name", K(ret)); } else { ret = partitions.push_back(partition); } } if (OB_FAIL(ret)) { // do nothing } else if (OB_FAIL(resolve_range_value_exprs( expr_list_node, part_type, partition_name, range_value_exprs, in_tablegroup))) { LOG_WARN("fail to resolve range partition element", K(ret)); } else { expr_num = expr_list_node->num_child_; } } } } if (OB_UNLIKELY(has_empty_name) && (stmt::T_CREATE_TABLE == stmt_->get_stmt_type() || stmt::T_CREATE_TABLEGROUP == stmt_->get_stmt_type() || stmt::T_CREATE_INDEX == stmt_->get_stmt_type())) { if (OB_FAIL(create_name_for_empty_partition(is_subpartition, partitions, subpartitions))) { LOG_WARN("failed to create name for empty [sub]partitions", K(ret)); } } } return ret; } int ObDDLResolver::resolve_range_value_exprs(ParseNode* expr_list_node, const ObPartitionFuncType part_type, const ObString& partition_name, ObIArray& range_value_exprs, const bool& in_tablegroup) { int ret = OB_SUCCESS; if (OB_ISNULL(expr_list_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null or stmt is null", K(ret), K(expr_list_node)); } else { for (int64_t j = 0; OB_SUCC(ret) && j < expr_list_node->num_child_; j++) { if (OB_ISNULL(expr_list_node->children_[j])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null", K(ret)); } else if (T_MAXVALUE == expr_list_node->children_[j]->type_) { ObRawExpr* maxvalue_expr = NULL; ObConstRawExpr* c_expr = NULL; c_expr = (ObConstRawExpr*)allocator_->alloc(sizeof(ObConstRawExpr)); if (NULL != c_expr) { c_expr = new (c_expr) ObConstRawExpr(); maxvalue_expr = c_expr; maxvalue_expr->set_data_type(common::ObMaxType); if (OB_FAIL(range_value_exprs.push_back(maxvalue_expr))) { LOG_WARN("array push back fail", K(ret)); } } else { ret = OB_ALLOCATE_MEMORY_FAILED; } } else if (T_NULL == expr_list_node->children_[j]->type_) { ret = OB_EER_NULL_IN_VALUES_LESS_THAN; LOG_WARN("null value is not allowed in less than", K(ret)); } else if (T_EXPR_LIST != expr_list_node->children_[j]->type_) { ObRawExpr* part_value_expr = NULL; if (OB_FAIL(ObResolverUtils::resolve_partition_range_value_expr( params_, *(expr_list_node->children_[j]), partition_name, part_type, part_value_expr, in_tablegroup))) { LOG_WARN("resolve partition expr failed", K(ret)); } else if (OB_FAIL(range_value_exprs.push_back(part_value_expr))) { LOG_WARN("array push back fail", K(ret)); } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr_node type is error", K(ret)); } } } return ret; } int ObDDLResolver::resolve_list_partition_elements(ParseNode* node, const bool is_subpartition, const ObPartitionFuncType part_type, int64_t& expr_num, ObDDLStmt::array_t& list_value_exprs, ObIArray& partitions, ObIArray& subpartitions, const bool& in_tablegroup) { int ret = OB_SUCCESS; if (OB_ISNULL(node) || OB_ISNULL(stmt_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null or stmt is null", K(ret), K(node), K(stmt_)); } else { int64_t partition_num = node->num_child_; ParseNode* partition_expr_list = node; ObPartition partition; ObSubPartition subpartition; int64_t first_non_default_value_idx = OB_INVALID_INDEX; bool use_part_id = false; const sql::ObCreateTablegroupStmt* tablegroup_stmt = static_cast(stmt_); bool has_empty_name = false; for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; i++) { subpartition.reset(); partition.reset(); ParseNode* element_node = partition_expr_list->children_[i]; if (OB_ISNULL(element_node) || OB_ISNULL(element_node->children_[PARTITION_ELEMENT_NODE])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition expr list node is null", K(ret), K(element_node)); } else if ((OB_ISNULL(element_node->children_[PARTITION_NAME_NODE]) || OB_ISNULL(element_node->children_[PARTITION_NAME_NODE]->children_[NAMENODE])) && !is_oracle_mode()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition expr list node is null", K(ret), K(element_node)); } else if (is_subpartition && OB_NOT_NULL(element_node->children_[PART_ID_NODE])) { ret = OB_ERR_PARSE_SQL; LOG_WARN("subpartition can not specify part id", K(ret), K(i), K(is_subpartition), K(in_tablegroup)); } else { ObString partition_name; if (OB_NOT_NULL(element_node->children_[PARTITION_NAME_NODE])) { ParseNode* partition_name_node = element_node->children_[PARTITION_NAME_NODE]->children_[NAMENODE]; partition_name.assign_ptr( partition_name_node->str_value_, static_cast(partition_name_node->str_len_)); } else if (is_subpartition) { subpartition.set_is_empty_partition_name(true); has_empty_name = true; } else { partition.set_is_empty_partition_name(true); has_empty_name = true; } ParseNode* expr_list_node = element_node->children_[PARTITION_ELEMENT_NODE]; if (partition_name.length() > OB_MAX_PARTITION_NAME_LENGTH) { ret = OB_ERR_TOO_LONG_IDENT; } else if (T_EXPR_LIST != expr_list_node->type_ && T_DEFAULT != expr_list_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr_list_node->type_ is not T_EXPR_LIST or T_DEFAULT", K(ret)); } // add list partition elements to tablegroup schema if (OB_SUCC(ret)) { if (is_subpartition) { subpartition.set_part_id(ObSubPartition::TEMPLATE_PART_ID); subpartition.set_sub_part_id(i); if (OB_FAIL(subpartition.set_part_name(partition_name))) { LOG_WARN("Failed to set part name", K(ret)); } else { ret = subpartitions.push_back(subpartition); } } else { if (use_part_id && OB_ISNULL(element_node->children_[PART_ID_NODE])) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Should speicify part id for all parts", K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "part id which should speicify part id for all parts"); } else if (nullptr == element_node->children_[PART_ID_NODE]) { partition.set_part_id(i); } else if (OB_ISNULL(tablegroup_stmt) || OB_ISNULL(element_node->children_[PART_ID_NODE]->children_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("not create tablegroup stmt or part id node is null", K(ret), "stmt", *stmt_); } else { bool valid = false; const int64_t max_used_part_id = tablegroup_stmt->get_max_used_part_id(); const int64_t part_id = static_cast(element_node->children_[PART_ID_NODE]->children_[0]->value_); partition.set_part_id(part_id); if (OB_FAIL(check_partid_valid(tablegroup_stmt, part_id, max_used_part_id, valid))) { LOG_WARN("part id not valid", K(ret)); } else if (!valid) { ret = OB_ERR_UNEXPECTED; LOG_WARN("part id not valid", K(ret)); } else if (0 == i) { use_part_id = true; } else if (!use_part_id) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Should speicify part id for all parts", K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "part id which should speicify part id for all parts"); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(partition.set_part_name(partition_name))) { LOG_WARN("Failed to set part name", K(ret)); } else { ret = partitions.push_back(partition); } } } if (OB_SUCC(ret)) { ObOpRawExpr* row_expr = NULL; if (OB_ISNULL(params_.expr_factory_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } else if (OB_FAIL(params_.expr_factory_->create_raw_expr(T_OP_ROW, row_expr))) { LOG_WARN("failed to create raw expr", K(ret)); } else if (OB_ISNULL(row_expr)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allcoate memory", K(ret)); } else if (T_DEFAULT == expr_list_node->type_) { // replace default with max ObRawExpr* maxvalue_expr = NULL; ObConstRawExpr* c_expr = NULL; c_expr = (ObConstRawExpr*)allocator_->alloc(sizeof(ObConstRawExpr)); if (OB_ISNULL(c_expr)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allcoate memory", K(ret)); } else { c_expr = new (c_expr) ObConstRawExpr(); maxvalue_expr = c_expr; maxvalue_expr->set_data_type(common::ObMaxType); if (OB_FAIL(row_expr->add_param_expr(maxvalue_expr))) { LOG_WARN("failed add param expr", K(ret)); } else if (OB_FAIL(list_value_exprs.push_back(row_expr))) { LOG_WARN("array push back fail", K(ret)); } } } else { ObSEArray part_value_exprs; bool is_all_expr_list = false; expr_num = OB_INVALID_COUNT; if (expr_list_node->num_child_ > 0) { is_all_expr_list = (expr_list_node->children_[0]->type_ == T_EXPR_LIST); } for (int64_t j = 0; OB_SUCC(ret) && j < expr_list_node->num_child_; j++) { part_value_exprs.reset(); if (OB_ISNULL(expr_list_node->children_[j])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null", K(ret)); } else if ((is_all_expr_list && expr_list_node->children_[j]->type_ != T_EXPR_LIST) || (!is_all_expr_list && expr_list_node->children_[j]->type_ == T_EXPR_LIST)) { ret = OB_ERR_PARTITION_COLUMN_LIST_ERROR; LOG_WARN("Inconsistency in usage of column lists for partitioning near", K(ret)); } else if (OB_FAIL(ObResolverUtils::resolve_partition_list_value_expr(params_, *(expr_list_node->children_[j]), partition_name, part_type, expr_num, part_value_exprs, in_tablegroup))) { LOG_WARN("resolve partition expr failed", K(ret)); } for (int64_t k = 0; OB_SUCC(ret) && k < part_value_exprs.count(); k++) { int64_t idx = row_expr->get_param_count() % expr_num; ObObjType cur_data_type = part_value_exprs.at(k)->get_data_type(); ObObjType pre_data_type = cur_data_type; if (first_non_default_value_idx >= 0) { if (list_value_exprs.at(first_non_default_value_idx)->get_param_count() <= idx) { ret = OB_ERR_UNEXPECTED; LOG_WARN("value expr num in row is invalid", K(ret), K(first_non_default_value_idx), K(idx), K(list_value_exprs.at(first_non_default_value_idx)), KPC(part_value_exprs.at(k))); } else { pre_data_type = list_value_exprs.at(first_non_default_value_idx)->get_param_expr(idx)->get_data_type(); } } else if (row_expr->get_param_count() > idx) { pre_data_type = row_expr->get_param_expr(idx)->get_data_type(); } if (OB_FAIL(ret)) { // do nothing } else if (ObMaxType != cur_data_type && ObMaxType != pre_data_type && cur_data_type != pre_data_type) { ret = OB_ERR_WRONG_TYPE_COLUMN_VALUE_ERROR; LOG_USER_ERROR(OB_ERR_WRONG_TYPE_COLUMN_VALUE_ERROR); LOG_WARN("object type is invalid ", K(ret), K(cur_data_type), K(pre_data_type)); } else if (OB_FAIL(row_expr->add_param_expr(part_value_exprs.at(k)))) { LOG_WARN("array push back fail", K(ret)); } } } if (OB_SUCC(ret)) { if (expr_num > 1 && !is_all_expr_list) { if (row_expr->get_param_count() != expr_num) { ret = OB_ERR_PARTITION_COLUMN_LIST_ERROR; LOG_WARN("Inconsistency in usage of column lists for partitioning near", K(ret), K(expr_num)); } } } if (OB_SUCC(ret)) { if (OB_FAIL(list_value_exprs.push_back(row_expr))) { LOG_WARN("array push back fail", K(ret)); } else if (first_non_default_value_idx < 0) { first_non_default_value_idx = i; } } } } } } if (OB_UNLIKELY(has_empty_name) && (stmt::T_CREATE_TABLE == stmt_->get_stmt_type() || stmt::T_CREATE_TABLEGROUP == stmt_->get_stmt_type() || stmt::T_CREATE_INDEX == stmt_->get_stmt_type())) { if (OB_FAIL(create_name_for_empty_partition(is_subpartition, partitions, subpartitions))) { LOG_WARN("failed to create name for empty [sub]partitions", K(ret)); } } } return ret; } int ObDDLResolver::check_column_in_foreign_key(const ObTableSchema& table_schema, const ObString& column_name) { int ret = OB_SUCCESS; if (table_schema.is_parent_table() || table_schema.is_child_table()) { const ObColumnSchemaV2* alter_column = table_schema.get_column_schema(column_name); if (OB_ISNULL(alter_column)) { // do nothing } else { const ObIArray& foreign_key_infos = table_schema.get_foreign_key_infos(); for (int64_t i = 0; OB_SUCC(ret) && i < foreign_key_infos.count(); i++) { const ObForeignKeyInfo& foreign_key_info = foreign_key_infos.at(i); if (table_schema.get_table_id() == foreign_key_info.parent_table_id_) { for (int64_t j = 0; OB_SUCC(ret) && j < foreign_key_info.parent_column_ids_.count(); j++) { if (alter_column->get_column_id() == foreign_key_info.parent_column_ids_.at(j)) { ret = OB_ERR_ALTER_COLUMN_FK; LOG_USER_ERROR(OB_ERR_ALTER_COLUMN_FK, column_name.length(), column_name.ptr()); } } } if (table_schema.get_table_id() == foreign_key_info.child_table_id_) { for (int64_t j = 0; OB_SUCC(ret) && j < foreign_key_info.child_column_ids_.count(); j++) { if (alter_column->get_column_id() == foreign_key_info.child_column_ids_.at(j)) { ret = OB_ERR_ALTER_COLUMN_FK; LOG_USER_ERROR(OB_ERR_ALTER_COLUMN_FK, column_name.length(), column_name.ptr()); } } } } } } return ret; } int ObDDLResolver::check_column_in_check_constraint_for_oracle( const share::schema::ObTableSchema& table_schema, const ObString& column_name, ObAlterTableStmt* alter_table_stmt) { int ret = OB_SUCCESS; const ObColumnSchemaV2* alter_column = table_schema.get_column_schema(column_name); if (OB_ISNULL(alter_column)) { // do nothing } else { for (ObTableSchema::const_constraint_iterator iter = table_schema.constraint_begin(); OB_SUCC(ret) && (iter != table_schema.constraint_end()); ++iter) { if (CONSTRAINT_TYPE_CHECK == (*iter)->get_constraint_type()) { for (ObConstraint::const_cst_col_iterator cst_col_iter = (*iter)->cst_col_begin(); OB_SUCC(ret) && (cst_col_iter != (*iter)->cst_col_end()); ++cst_col_iter) { if (*cst_col_iter == alter_column->get_column_id()) { if (0 == (*iter)->get_column_cnt()) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "check cst don't have column info", K(ret), K(**iter)); } else if (1 == (*iter)->get_column_cnt()) { // drop check constraint cascaded AlterTableSchema& alter_table_schema = alter_table_stmt->get_alter_table_arg().alter_table_schema_; if (OB_FAIL(alter_table_schema.add_constraint(**iter))) { SQL_RESV_LOG(WARN, "add constraint failed!", K(ret), K(**iter)); } else { alter_table_stmt->get_alter_table_arg().alter_constraint_type_ = ObAlterTableArg::DROP_CONSTRAINT; } } else { // if check constraint includes more than one column, throw ret = OB_ERR_DROP_COL_REFERENCED_MULTI_COLS_CONSTRAINT; SQL_RESV_LOG(WARN, "column is referenced in a multi-column constraint", K(ret), K(alter_column->get_column_name_str()), K((*iter)->get_constraint_name_str()), K((*iter)->get_check_expr_str())); } } } } } } return ret; } int ObDDLResolver::check_column_in_foreign_key_for_oracle( const ObTableSchema& table_schema, const ObString& column_name, ObAlterTableStmt* alter_table_stmt) { int ret = OB_SUCCESS; if (table_schema.is_parent_table() || table_schema.is_child_table()) { const ObColumnSchemaV2* alter_column = table_schema.get_column_schema(column_name); if (OB_ISNULL(alter_column)) { // do full check in RS } else { const ObIArray& foreign_key_infos = table_schema.get_foreign_key_infos(); for (int64_t i = 0; OB_SUCC(ret) && i < foreign_key_infos.count(); i++) { const ObForeignKeyInfo& foreign_key_info = foreign_key_infos.at(i); // column in parent table can't be deleted if (OB_SUCC(ret) && table_schema.get_table_id() == foreign_key_info.parent_table_id_) { for (int64_t j = 0; OB_SUCC(ret) && j < foreign_key_info.parent_column_ids_.count(); j++) { if (alter_column->get_column_id() == foreign_key_info.parent_column_ids_.at(j)) { ret = OB_ERR_DROP_PARENT_KEY_COLUMN; } } } if (OB_SUCC(ret) && table_schema.get_table_id() == foreign_key_info.child_table_id_ && foreign_key_info.child_column_ids_.count() > 1) { for (int64_t j = 0; OB_SUCC(ret) && j < foreign_key_info.child_column_ids_.count(); j++) { if (alter_column->get_column_id() == foreign_key_info.child_column_ids_.at(j)) { ret = OB_ERR_MODIFY_OR_DROP_MULTI_COLUMN_CONSTRAINT; } } } if (OB_SUCC(ret) && table_schema.get_table_id() == foreign_key_info.child_table_id_ && foreign_key_info.child_column_ids_.count() == 1) { if (alter_column->get_column_id() == foreign_key_info.child_column_ids_.at(0)) { ObDropForeignKeyArg* foreign_key_arg = NULL; void* tmp_ptr = NULL; if (OB_ISNULL(tmp_ptr = allocator_->alloc(sizeof(ObDropForeignKeyArg)))) { ret = OB_ALLOCATE_MEMORY_FAILED; SQL_RESV_LOG(ERROR, "failed to allocate memory", K(ret)); } else if (FALSE_IT(foreign_key_arg = new (tmp_ptr) ObDropForeignKeyArg())) { } else if (FALSE_IT(foreign_key_arg->foreign_key_name_.assign_ptr( foreign_key_info.foreign_key_name_.ptr(), foreign_key_info.foreign_key_name_.length()))) { } else if (OB_ISNULL(alter_table_stmt)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "alter table stmt should not be null", K(ret)); } else if (OB_FAIL(alter_table_stmt->add_index_arg(foreign_key_arg))) { SQL_RESV_LOG(WARN, "add index to drop_index_list failed!", K(ret)); } else { alter_table_stmt->set_alter_table_index(); } } } } } } return ret; } bool ObDDLResolver::is_ids_match(const ObIArray& src_list, const ObIArray& dest_list) { bool is_match = true; ObSEArray tmp_src_list; ObSEArray tmp_dest_list; if (src_list.count() != dest_list.count()) { is_match = false; } else { for (int64_t i = 0; i < src_list.count(); ++i) { tmp_src_list.push_back(src_list.at(i)); tmp_dest_list.push_back(dest_list.at(i)); } std::sort(tmp_src_list.begin(), tmp_src_list.end()); std::sort(tmp_dest_list.begin(), tmp_dest_list.end()); for (int64_t i = 0; is_match && i < tmp_src_list.count(); ++i) { if (tmp_src_list.at(i) != tmp_dest_list.at(i)) { is_match = false; } } } return is_match; } int ObDDLResolver::check_index_columns_equal_foreign_key( const ObTableSchema& table_schema, const ObTableSchema& index_table_schema) { int ret = OB_SUCCESS; if (table_schema.is_child_table()) { ObString index_name; ObSEArray index_column_ids; const ObIndexInfo& index_info = index_table_schema.get_index_info(); if (OB_FAIL(index_info.get_column_ids(index_column_ids))) { LOG_WARN("failed to get column ids from ObRowkeyInfo", K(ret)); } else if (OB_FAIL(index_table_schema.get_index_name(index_name))) { LOG_WARN("failed to get index name", K(ret)); } const ObIArray& foreign_key_infos = table_schema.get_foreign_key_infos(); for (int64_t i = 0; OB_SUCC(ret) && i < foreign_key_infos.count(); ++i) { const ObForeignKeyInfo& foreign_key_info = foreign_key_infos.at(i); const int64_t child_column_num = foreign_key_info.child_column_ids_.count(); const uint64_t data_table_id = index_table_schema.get_data_table_id(); if (0 == child_column_num) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expected foreign key columns num", K(ret), K(child_column_num)); } if (OB_SUCC(ret)) { if (data_table_id == foreign_key_info.child_table_id_) { if (child_column_num == index_table_schema.get_index_column_number()) { if (is_ids_match(index_column_ids, foreign_key_info.child_column_ids_)) { ret = OB_ERR_ALTER_COLUMN_FK; LOG_USER_ERROR(OB_ERR_ALTER_COLUMN_FK, index_name.length(), index_name.ptr()); } } } // child_table_id_ } } // for } return ret; } // for mysql mode // in mysql mode: index_1(c1, c2) = index_2(c2, c1) int ObDDLResolver::check_indexes_on_same_cols(const ObTableSchema& table_schema, const share::schema::ObTableSchema& input_index_table_schema, ObSchemaChecker& schema_checker, bool& has_other_indexes_on_same_cols) { int ret = OB_SUCCESS; uint64_t same_indexes_cnt = 0; ObSEArray input_index_columns_name; has_other_indexes_on_same_cols = false; ObSEArray simple_index_infos; if (OB_FAIL(ObResolverUtils::get_columns_name_from_index_table_schema( input_index_table_schema, input_index_columns_name))) { LOG_WARN("get columns name from input index table schema failed", K(ret)); } else if (OB_FAIL(table_schema.get_simple_index_infos_without_delay_deleted_tid(simple_index_infos))) { LOG_WARN("get simple_index_infos without delay_deleted_tid failed", K(ret)); } for (int64_t i = 0; OB_SUCC(ret) && !has_other_indexes_on_same_cols && i < simple_index_infos.count(); ++i) { const ObTableSchema* index_table_schema = NULL; bool is_match = false; if (OB_FAIL(schema_checker.get_table_schema(simple_index_infos.at(i).table_id_, index_table_schema))) { LOG_WARN("get_table_schema failed", K(ret), "table id", simple_index_infos.at(i).table_id_); } else if (OB_ISNULL(index_table_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table schema should not be null", K(ret)); } else { ObSEArray index_columns_name; if (OB_FAIL(ObResolverUtils::get_columns_name_from_index_table_schema(*index_table_schema, index_columns_name))) { LOG_WARN("get columns name from compared index table schema failed", K(ret)); } else if (OB_FAIL( ObResolverUtils::check_match_columns(input_index_columns_name, index_columns_name, is_match))) { LOG_WARN("Failed to check_match_columns", K(ret)); } else if (true == is_match) { ++same_indexes_cnt; if (same_indexes_cnt > 1) { has_other_indexes_on_same_cols = true; } } } } return ret; } // for oracle mode // in oracle mode: index_1(c1, c2) != index_2(c2, c1) int ObDDLResolver::check_indexes_on_same_cols(const ObTableSchema& table_schema, const ObCreateIndexArg& create_index_arg, ObSchemaChecker& schema_checker, bool& has_other_indexes_on_same_cols) { int ret = OB_SUCCESS; has_other_indexes_on_same_cols = false; ObSEArray simple_index_infos; if (OB_FAIL(table_schema.get_simple_index_infos_without_delay_deleted_tid(simple_index_infos))) { LOG_WARN("get simple_index_infos without delay_deleted_tid failed", K(ret)); } for (int64_t i = 0; OB_SUCC(ret) && !has_other_indexes_on_same_cols && i < simple_index_infos.count(); ++i) { const ObTableSchema* index_table_schema = NULL; if (OB_FAIL(schema_checker.get_table_schema(simple_index_infos.at(i).table_id_, index_table_schema))) { LOG_WARN("get_table_schema failed", K(ret), "table id", simple_index_infos.at(i).table_id_); } else if (OB_ISNULL(index_table_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table schema should not be null", K(ret)); } else if (OB_FAIL(ObResolverUtils::check_match_columns_strict_with_order( index_table_schema, create_index_arg, has_other_indexes_on_same_cols))) { LOG_WARN("Failed to check_match_columns", K(ret)); } } return ret; } int ObDDLResolver::check_index_name_duplicate(const ObTableSchema& table_schema, const ObCreateIndexArg& create_index_arg, ObSchemaChecker& schema_checker, bool& has_same_index_name) { int ret = OB_SUCCESS; has_same_index_name = false; ObString index_name; ObSEArray simple_index_infos; if (OB_FAIL(table_schema.get_simple_index_infos_without_delay_deleted_tid(simple_index_infos))) { LOG_WARN("get simple_index_infos without delay_deleted_tid failed", K(ret)); } for (int64_t i = 0; OB_SUCC(ret) && !has_same_index_name && i < simple_index_infos.count(); ++i) { const ObTableSchema* index_table_schema = NULL; if (OB_FAIL(schema_checker.get_table_schema(simple_index_infos.at(i).table_id_, index_table_schema))) { LOG_WARN("get_table_schema failed", K(ret), "table id", simple_index_infos.at(i).table_id_); } else if (OB_ISNULL(index_table_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table schema should not be null", K(ret)); } else if (OB_FAIL(index_table_schema->get_index_name(index_name))) { LOG_WARN("Failed to get_index_name", K(ret)); } else if (0 == index_name.compare(create_index_arg.index_name_)) { has_same_index_name = true; } } return ret; } // child 5 of root node, resolve index partition node, // 1 this index is global, we need to first generate index schema, // than resolve global index partition info // 2 this index is local, an error is raised since we cannot specify // partition info for a local index int ObDDLResolver::resolve_index_partition_node(ParseNode* index_partition_node, ObCreateIndexStmt* crt_idx_stmt) { int ret = OB_SUCCESS; if (OB_UNLIKELY(NULL == index_partition_node) || OB_UNLIKELY(NULL == crt_idx_stmt)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret), KP(index_partition_node), KP(crt_idx_stmt)); } else { ObTableSchema& index_schema = crt_idx_stmt->get_create_index_arg().index_schema_; if (NULL == index_partition_node) { // part method is not specified } else if (!global_) { ret = OB_NOT_SUPPORTED; LOG_WARN("partitioned local index is not supported", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "partitioned local index"); } else if (!index_schema.is_global_index_table()) { ret = OB_NOT_SUPPORTED; LOG_WARN( "non global index with partition option not supported", K(ret), "index_type", index_schema.get_index_type()); LOG_USER_ERROR(OB_NOT_SUPPORTED, "non global index with partition option"); } else { if (OB_FAIL(resolve_partition_node(crt_idx_stmt, index_partition_node, index_schema))) { LOG_WARN("failed to resolve partition node", K(ret)); // check valid max_used_part_id } else if (OB_FAIL(check_max_used_part_id_valid(index_schema, max_used_part_id_))) { LOG_WARN("max used part id valid", K(ret), K(max_used_part_id_), K(index_schema)); } else { crt_idx_stmt->set_max_used_part_id(max_used_part_id_); } if (OB_FAIL(ret)) { } else if (PARTITION_LEVEL_ZERO == index_schema.get_part_level() || PARTITION_LEVEL_ONE == index_schema.get_part_level()) { // good } else if (PARTITION_LEVEL_TWO == index_schema.get_part_level()) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "index table with sub-partitions"); LOG_WARN("index table with two level partitions not support", K(ret)); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(check_key_cover_partition_column(crt_idx_stmt, index_schema))) { LOG_WARN("fail to check key cover partition column", K(ret)); } } return ret; } int ObDDLResolver::check_key_cover_partition_keys(const bool is_range_part, const common::ObPartitionKeyInfo& part_key_info, share::schema::ObTableSchema& index_schema) { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < part_key_info.get_size(); ++i) { ObSEArray cascaded_columns; uint64_t column_id = OB_INVALID_ARGUMENT; const ObColumnSchemaV2* column_schema = NULL; if (OB_FAIL(part_key_info.get_column_id(i, column_id))) { LOG_WARN("fail to get column id", K(ret)); } else if (NULL == (column_schema = index_schema.get_column_schema(column_id))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("column schema is null", K(ret)); } else if (column_schema->get_index_position() > 0) { if (is_range_part) { if (column_schema->get_index_position() != i + 1) { ret = OB_NOT_SUPPORTED; LOG_WARN("partition columns not prefix of index columns not support", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "partition columns not prefix of index columns"); } } } else if (!column_schema->is_generated_column()) { ret = OB_EER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF; LOG_WARN("global index should cover all partition column of global index", K(ret)); LOG_USER_ERROR(OB_EER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF, "GLOBAL INDEX"); } else if (is_range_part) { ret = OB_NOT_SUPPORTED; LOG_WARN("range partition on generated column in global index not support", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "range partition on generated column in global index"); } else if (OB_FAIL(column_schema->get_cascaded_column_ids(cascaded_columns))) { LOG_WARN("fail to get cascaded columns ids", K(ret)); } else { for (int64_t j = 0; OB_SUCC(ret) && j < cascaded_columns.count(); ++j) { uint64_t cascaded_column_id = cascaded_columns.at(j); const ObColumnSchemaV2* cascaded_column = NULL; if (NULL == (cascaded_column = index_schema.get_column_schema(cascaded_column_id))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("column schema is null", K(ret)); } else if (column_schema->get_index_position() > 0) { // good, caccaded column is part the index column } else { ret = OB_EER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF; LOG_WARN("global index should cover all partition column of global index", K(ret)); LOG_USER_ERROR(OB_EER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF, "GLOBAL INDEX"); } } } } return ret; } int ObDDLResolver::check_key_cover_partition_column(ObCreateIndexStmt* crt_idx_stmt, ObTableSchema& index_schema) { int ret = OB_SUCCESS; if (OB_UNLIKELY(NULL == crt_idx_stmt)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret)); } else if (global_) { if (INDEX_TYPE_NORMAL_GLOBAL == crt_idx_stmt->get_create_index_arg().index_type_ || INDEX_TYPE_UNIQUE_GLOBAL == crt_idx_stmt->get_create_index_arg().index_type_) { const common::ObPartitionKeyInfo& part_key_info = index_schema.get_partition_key_info(); const common::ObPartitionKeyInfo& subpart_key_info = index_schema.get_subpartition_key_info(); if (!index_schema.is_partitioned_table()) { // not a partition index, good } else if (OB_FAIL(check_key_cover_partition_keys(index_schema.is_range_part(), part_key_info, index_schema))) { LOG_WARN("fail to check key cover", K(ret)); } else if (OB_FAIL( check_key_cover_partition_keys(index_schema.is_range_subpart(), subpart_key_info, index_schema))) { LOG_WARN("fail to check key cover", K(ret)); } else { } // no more to do } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected index type", K(ret), "index_type", crt_idx_stmt->get_create_index_arg().index_type_); } } else { // no need to check } return ret; } int ObDDLResolver::generate_global_index_schema(ObCreateIndexStmt* crt_idx_stmt) { int ret = OB_SUCCESS; const share::schema::ObTableSchema* table_schema = NULL; ObTableSchema& index_schema = crt_idx_stmt->get_create_index_arg().index_schema_; if (OB_UNLIKELY(NULL == crt_idx_stmt)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret)); } else if (!global_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("should not build global schema on a local index", K(ret)); } else if (OB_UNLIKELY(NULL == schema_checker_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("schema checker ptr is null", K(ret)); } else if (OB_FAIL(schema_checker_->get_table_schema(session_info_->get_effective_tenant_id(), crt_idx_stmt->get_create_index_arg().database_name_, crt_idx_stmt->get_create_index_arg().table_name_, false /* is index table*/, table_schema))) { if (OB_TABLE_NOT_EXIST == ret) { LOG_USER_ERROR(OB_TABLE_NOT_EXIST, to_cstring(crt_idx_stmt->get_create_index_arg().database_name_), to_cstring(crt_idx_stmt->get_create_index_arg().table_name_)); LOG_WARN("table not exist", K(ret), "database_name", crt_idx_stmt->get_create_index_arg().database_name_, "table_name", crt_idx_stmt->get_create_index_arg().table_name_); } else { LOG_WARN("fail to get table schema", K(ret)); } } else if (OB_UNLIKELY(NULL == table_schema)) { ret = OB_TABLE_NOT_EXIST; LOG_USER_ERROR(OB_TABLE_NOT_EXIST, to_cstring(crt_idx_stmt->get_create_index_arg().database_name_), to_cstring(crt_idx_stmt->get_create_index_arg().table_name_)); LOG_WARN("table not exist", K(ret), "database_name", crt_idx_stmt->get_create_index_arg().database_name_, "table_name", crt_idx_stmt->get_create_index_arg().table_name_); } else if (!GCONF.enable_sys_table_ddl && !table_schema->is_user_table() && !table_schema->is_tmp_table()) { ret = OB_ERR_WRONG_OBJECT; LOG_USER_ERROR(OB_ERR_WRONG_OBJECT, to_cstring(crt_idx_stmt->get_create_index_arg().database_name_), to_cstring(crt_idx_stmt->get_create_index_arg().table_name_), "BASE_TABLE"); ObTableType table_type = table_schema->get_table_type(); LOG_WARN("Not support to create index on non-normal table", K(ret), K(table_type), "arg", crt_idx_stmt->get_create_index_arg()); } else { ObArray gen_columns; ObCreateIndexArg& create_index_arg = crt_idx_stmt->get_create_index_arg(); ObCreateIndexArg my_create_index_arg; index_schema.set_table_type(USER_INDEX); index_schema.set_index_type(create_index_arg.index_type_); ObTableSchema new_table_schema; if (OB_FAIL(new_table_schema.assign(*table_schema))) { LOG_WARN("fail to assign schema", K(ret)); } else if (OB_FAIL(my_create_index_arg.assign(create_index_arg))) { LOG_WARN("fail to assign index arg", K(ret)); } else if (OB_FAIL(share::ObIndexBuilderUtil::adjust_expr_index_args( my_create_index_arg, new_table_schema, gen_columns))) { LOG_WARN("fail to adjust expr index args", K(ret)); } else if (OB_FAIL(do_generate_global_index_schema(my_create_index_arg, new_table_schema))) { LOG_WARN("fail to do generate global index schema", K(ret)); } else if (OB_FAIL(index_schema.assign(my_create_index_arg.index_schema_))) { LOG_WARN("fail to assign schema", K(ret)); } } return ret; } int ObDDLResolver::do_generate_global_index_schema( ObCreateIndexArg& create_index_arg, share::schema::ObTableSchema& table_schema) { int ret = OB_SUCCESS; ObTableSchema& index_schema = create_index_arg.index_schema_; if (OB_FAIL(share::ObIndexBuilderUtil::set_index_table_columns(create_index_arg, table_schema, index_schema))) { LOG_WARN("fail to set index table columns", K(ret)); } else { } // no more to do return ret; } int ObDDLResolver::resolve_check_constraint_node( const ParseNode& cst_node, ObSEArray& csts, const share::schema::ObColumnSchemaV2* column_schema) { int ret = OB_SUCCESS; if ((share::is_mysql_mode() && (cst_node.num_child_ != 2)) || (share::is_oracle_mode() && (cst_node.num_child_ != 3))) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "the num_child of constraint_node is wrong.", K(cst_node.num_child_), K(ret)); } else { ObString cst_name; ParseNode* cst_name_node = cst_node.children_[0]; ParseNode* cst_check_expr_node = cst_node.children_[1]; ParseNode* cst_check_state_node = NULL; if (share::is_oracle_mode()) { cst_check_state_node = cst_node.children_[2]; } if (OB_ISNULL(cst_check_expr_node)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "NULL ptr", K(ret), K(cst_check_expr_node)); } else if (OB_ISNULL(cst_name_node)) { if (share::is_mysql_mode()) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "NULL ptr", K(ret), K(cst_name_node)); } else if (share::is_oracle_mode()) { if (OB_FAIL(ObTableSchema::create_cons_name_automatically( cst_name, table_name_, *allocator_, CONSTRAINT_TYPE_CHECK))) { SQL_RESV_LOG(WARN, "create cons name automatically failed", K(ret)); } } } else { cst_name.assign_ptr(cst_name_node->str_value_, static_cast(cst_name_node->str_len_)); } if (OB_SUCC(ret)) { ObConstraint cst; if (cst_name.length() > OB_MAX_CONSTRAINT_NAME_LENGTH) { ret = OB_ERR_TOO_LONG_IDENT; LOG_WARN("constraint_name length overflow", K(ret), K(cst_name.length())); } else { ObTableSchema tmp_table_schema; ObRawExpr* check_expr = NULL; if (OB_FAIL(get_table_schema_for_check(tmp_table_schema))) { LOG_WARN("get table schema failed", K(ret), K(cst_name)); } else { for (uint64_t i = 0; OB_SUCC(ret) && i < csts.count(); ++i) { if (csts.at(i).get_constraint_name_str() == cst_name) { ret = OB_ERR_CONSTRAINT_NAME_DUPLICATE; LOG_WARN("duplicate check constraint name", K(ret), K(cst_name)); } } } if (OB_SUCC(ret)) { if (OB_FAIL(cst.set_constraint_name(cst_name))) { LOG_WARN("set constraint name failed", K(ret), K(cst_name)); } else if (OB_FAIL(resolve_check_constraint_expr( params_, cst_check_expr_node, tmp_table_schema, cst, check_expr, column_schema))) { LOG_WARN("resolver constraint expr failed", K(ret)); } else { // resolve constranit_state in oracle mode if (share::is_oracle_mode()) { if (OB_FAIL(resolve_check_cst_state_node(cst_check_state_node, cst))) { SQL_RESV_LOG(WARN, "fail to resolve check cst state node", K(ret)); } } if (OB_SUCC(ret)) { cst.set_constraint_type(CONSTRAINT_TYPE_CHECK); ret = csts.push_back(cst); } } } } } } return ret; } int ObDDLResolver::resolve_check_cst_state_node(const ParseNode* cst_check_state_node, ObConstraint& cst) { int ret = OB_SUCCESS; if (OB_ISNULL(cst_check_state_node)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "cst_check_state_node is null ptr", K(ret)); } else if (T_CONSTRAINT_STATE != cst_check_state_node->type_) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG( WARN, "cst_check_state_node->type_ must be T_CONSTRAINT_STATE", K(ret), K(cst_check_state_node->type_)); } else if (cst_check_state_node->num_child_ != 4) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "the num_child of cst_check_state_node is wrong.", K(ret), K(cst_check_state_node->num_child_)); } else if (OB_NOT_NULL(cst_check_state_node->children_[1])) { // in oracle mode: check constraint with using index option, report parser error. // https://docs.oracle.com/cd/E11882_01/server.112/e41084/clauses002.htm#SQLRF52180 ret = OB_ERR_PARSER_SYNTAX; SQL_RESV_LOG(WARN, "check constraint can't assign state of using index", K(ret)); } else { if (OB_NOT_NULL(cst_check_state_node->children_[0])) { cst.set_rely_flag(T_RELY_CONSTRAINT == cst_check_state_node->children_[0]->type_ ? true : false); } if (OB_NOT_NULL(cst_check_state_node->children_[2])) { cst.set_enable_flag(T_ENABLE_CONSTRAINT == cst_check_state_node->children_[2]->type_ ? true : false); cst.set_validate_flag(T_ENABLE_CONSTRAINT == cst_check_state_node->children_[2]->type_ ? true : false); } if (OB_NOT_NULL(cst_check_state_node->children_[3])) { cst.set_validate_flag(T_VALIDATE_CONSTRAINT == cst_check_state_node->children_[3]->type_ ? true : false); } } return ret; } int ObDDLResolver::resolve_pk_constraint_node( const ParseNode& pk_cst_node, common::ObString pk_name, ObSEArray& csts) { int ret = OB_SUCCESS; ObString cst_name; if ((T_PRIMARY_KEY != pk_cst_node.type_) && (T_COLUMN_DEFINITION != pk_cst_node.type_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "node type is wrong.", K(ret), K(pk_cst_node.type_)); } else if (T_PRIMARY_KEY == pk_cst_node.type_) { // case: create table t1(c1 int, primary key(c1)); if (pk_cst_node.num_child_ != 2) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "the num_child of constraint_node is wrong.", K(pk_cst_node.num_child_), K(ret)); } else { ParseNode* cst_name_node = pk_cst_node.children_[1]; if (OB_ISNULL(cst_name_node)) { // set default pk constraint name if not specified if (OB_FAIL(ObTableSchema::create_cons_name_automatically( cst_name, table_name_, *allocator_, CONSTRAINT_TYPE_PRIMARY_KEY))) { SQL_RESV_LOG(WARN, "create cons name automatically failed", K(ret)); } } else { cst_name.assign_ptr(cst_name_node->str_value_, static_cast(cst_name_node->str_len_)); } } } else { if (NULL == pk_name.ptr()) { if (OB_FAIL(ObTableSchema::create_cons_name_automatically( cst_name, table_name_, *allocator_, CONSTRAINT_TYPE_PRIMARY_KEY))) { SQL_RESV_LOG(WARN, "create cons name automatically failed", K(ret)); } } else { cst_name.assign_ptr(pk_name.ptr(), pk_name.length()); } } if (OB_SUCC(ret)) { ObConstraint cst; if (cst_name.length() > OB_MAX_CONSTRAINT_NAME_LENGTH) { ret = OB_ERR_TOO_LONG_IDENT; LOG_WARN("constraint_name length overflow", K(ret), K(cst_name.length())); } else { // ObTableSchema tmp_table_schema; if (csts.end() != std::find_if(csts.begin(), csts.end(), [&cst_name](const ObConstraint& cst) { return cst_name == cst.get_constraint_name_str(); })) { ret = OB_ERR_CONSTRAINT_DUPLICATE; LOG_WARN("duplicate constraint name", K(ret), K(cst_name)); } else if (OB_FAIL(cst.set_constraint_name(cst_name))) { } else { cst.set_constraint_type(CONSTRAINT_TYPE_PRIMARY_KEY); ret = csts.push_back(cst); } } } return ret; } int ObDDLResolver::resolve_check_constraint_expr(ObResolverParams& params, const ParseNode* node, ObTableSchema& table_schema, ObConstraint& constraint, ObRawExpr*& check_expr, const share::schema::ObColumnSchemaV2* column_schema) { int ret = OB_SUCCESS; check_expr = NULL; if (OB_ISNULL(node)) { ret = OB_NOT_INIT; LOG_WARN("NULL ptr", K(node)); } else { if (OB_FAIL(ObResolverUtils::resolve_check_constraint_expr( params, node, table_schema, constraint, check_expr, column_schema))) { LOG_WARN("resolve check constraint expr failed", K(ret)); } else if (OB_ISNULL(check_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("check_expr is null", K(ret)); } } return ret; } int ObDDLResolver::check_uniq_allow(ObResolverParams& params, ObTableSchema& table_schema, ObCreateIndexArg& index_arg, ObRawExpr* part_func_expr, ObIArray& constraint_exprs, bool& allow) { int ret = OB_SUCCESS; allow = false; ObColumnRefRawExpr* part_col_expr = NULL; if (!part_func_expr->is_column_ref_expr()) { allow = false; } else if (FALSE_IT(part_col_expr = static_cast(part_func_expr))) { } else { for (int64_t i = 0; OB_SUCC(ret) && i < index_arg.index_columns_.count() && !allow; ++i) { const ObString& index_col_name = index_arg.index_columns_.at(i).column_name_; const ObString& part_col_name = part_col_expr->get_column_name(); if (ObCharset::case_insensitive_equal(index_col_name, part_col_name)) { allow = true; } else { // concern as base-column for (int64_t j = 0; OB_SUCC(ret) && j < constraint_exprs.count() && !allow; ++j) { ObOpRawExpr* check_expr = static_cast(constraint_exprs.at(j)); ObRawExpr* child_exprs[2] = {check_expr->get_param_expr(0), check_expr->get_param_expr(1)}; for (int64_t k = 0; OB_SUCC(ret) && k < 2 && !allow; ++k) { if (child_exprs[k]->is_column_ref_expr()) { ObColumnRefRawExpr* col_expr = static_cast(child_exprs[k]); if (ObCharset::case_insensitive_equal(part_col_name, col_expr->get_column_name())) { ObColumnRefRawExpr* cmp_col_expr = NULL; if (!child_exprs[1 - k]->is_column_ref_expr()) { cmp_col_expr = static_cast(child_exprs[1 - k]->get_param_expr(0)); } else { cmp_col_expr = static_cast(child_exprs[1 - k]); } if (ObCharset::case_insensitive_equal(cmp_col_expr->get_column_name(), index_col_name)) { allow = true; } } } } } // check gen column if (OB_SUCC(ret) && !allow) { ObColumnSchemaV2* column_schema = NULL; if (OB_ISNULL(column_schema = table_schema.get_column_schema(part_col_expr->get_column_id()))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("Failed to get column schema", K(ret), K(part_col_expr->get_column_id())); } else if (column_schema->is_generated_column()) { ObString col_def; ObRawExpr* gen_expr = NULL; if (OB_FAIL(column_schema->get_orig_default_value().get_string(col_def))) { LOG_WARN("get generated column definition failed", K(ret)); } else if (OB_FAIL(ObResolverUtils::resolve_generated_column_expr( params, col_def, table_schema, *column_schema, gen_expr))) { LOG_WARN("resolve generated column expr failed", K(ret)); } else { ObString depend_part_col_name; bool is_expect = true; // check is substring or not if (OB_ISNULL(gen_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("NULL ptr", K(ret)); } else if (T_FUN_SYS_SUBSTR != gen_expr->get_expr_type()) { is_expect = false; } else { ObSysFunRawExpr* sys_expr = static_cast(gen_expr); for (int64_t j = 0; OB_SUCC(ret) && j < sys_expr->get_param_count(); j++) { ObRawExpr* param_expr = sys_expr->get_param_expr(j); if (OB_ISNULL(param_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("NULL ptr", K(ret), K(param_expr)); } else if (0 == j && !param_expr->is_column_ref_expr()) { is_expect = false; } else if (0 != j && !param_expr->is_const_expr()) { is_expect = false; } } if (OB_SUCC(ret) && is_expect) { depend_part_col_name = static_cast(sys_expr->get_param_expr(0))->get_column_name(); } if (OB_SUCC(ret) && !is_expect) { continue; } } for (int64_t j = 0; OB_SUCC(ret) && j < constraint_exprs.count() && !allow; ++j) { ObOpRawExpr* check_expr = static_cast(constraint_exprs.at(j)); ObRawExpr* child_exprs[2] = {check_expr->get_param_expr(0), check_expr->get_param_expr(1)}; ObColumnRefRawExpr* col_exprs[2] = {NULL, NULL}; bool gen_expr_exist = false; bool all_col = true; for (int64_t k = 0; OB_SUCC(ret) && k < 2; ++k) { if (child_exprs[k]->is_column_ref_expr()) { col_exprs[k] = static_cast(child_exprs[k]); } else { all_col = false; col_exprs[k] = static_cast(child_exprs[k]->get_param_expr(0)); if (!gen_expr_exist) { ret = check_same_substr_expr(*child_exprs[k], *gen_expr, gen_expr_exist); } } } if (OB_SUCC(ret)) { if (all_col || gen_expr_exist) { if (ObCharset::case_insensitive_equal(col_exprs[0]->get_column_name(), index_col_name) && ObCharset::case_insensitive_equal(col_exprs[1]->get_column_name(), depend_part_col_name)) { allow = true; } else if (ObCharset::case_insensitive_equal(col_exprs[1]->get_column_name(), index_col_name) && ObCharset::case_insensitive_equal( col_exprs[0]->get_column_name(), depend_part_col_name)) { allow = true; } } } } } } } } } } return ret; } int ObDDLResolver::check_same_substr_expr(ObRawExpr& left, ObRawExpr& right, bool& same) { int ret = OB_SUCCESS; same = true; if (left.get_expr_type() != T_FUN_SYS_SUBSTR || right.get_expr_type() != T_FUN_SYS_SUBSTR) { same = false; } else { ObSysFunRawExpr& sys_left = static_cast(left); ObSysFunRawExpr& sys_right = static_cast(right); if (sys_left.get_param_count() != sys_right.get_param_count()) { same = false; } else { for (int64_t i = 0; OB_SUCC(ret) && i < sys_left.get_param_count() && same; ++i) { ObRawExpr* param_left = sys_left.get_param_expr(i); ObRawExpr* param_right = sys_right.get_param_expr(i); if (0 == i) { if (!param_left->is_column_ref_expr() || !param_right->is_column_ref_expr()) { same = false; } else { ObColumnRefRawExpr* col_left = static_cast(param_left); ObColumnRefRawExpr* col_right = static_cast(param_right); if (!ObCharset::case_insensitive_equal(col_left->get_column_name(), col_right->get_column_name())) { same = false; } } } else { if (!param_left->is_const_expr() || !param_right->is_const_expr()) { same = false; } else if (!param_left->same_as(*param_right)) { same = false; } } } } } return ret; } int ObDDLResolver::check_uniq_allow(ObTableSchema& table_schema, ObCreateIndexArg& index_arg, bool& allow) { int ret = OB_SUCCESS; allow = false; if (table_schema.get_part_level() == PARTITION_LEVEL_ONE && table_schema.get_part_option().is_list_part()) { ObArenaAllocator allocator(ObModIds::OB_TEMP_VARIABLES); ObResolverParams params; ObRawExprFactory expr_factory(allocator); ObSQLSessionInfo empty_session; params.expr_factory_ = &expr_factory; params.allocator_ = &allocator; params.session_info_ = &empty_session; if (OB_FAIL(empty_session.init(0, 0, 0, &allocator))) { LOG_WARN("init empty session failed", K(ret)); } else if (OB_FAIL(empty_session.load_default_sys_variable(false, false))) { LOG_WARN("session load default system variable failed", K(ret)); } else { const share::schema::ObPartitionFuncType part_func_type = table_schema.get_part_option().get_part_func_type(); const ParseNode* node = NULL; common::ObSEArray part_keys; common::ObSEArray part_func_exprs; if (OB_FAIL(ObRawExprUtils::parse_expr_node_from_str( table_schema.get_part_option().get_part_func_expr_str(), *params.allocator_, node))) { LOG_WARN("parse expr node from string failed", K(ret)); } else if (OB_FAIL(resolve_part_func(params, node, part_func_type, table_schema, part_func_exprs, part_keys))) { SQL_RESV_LOG(WARN, "resolve part func failed", K(ret)); } if (OB_SUCC(ret) && part_func_exprs.count() == 1) { ObSEArray check_exprs; for (ObTableSchema::const_constraint_iterator iter = table_schema.constraint_begin(); OB_SUCC(ret) && iter != table_schema.constraint_end(); iter++) { ObConstraint cst; ObRawExpr* check_expr = NULL; if ((*iter)->get_constraint_type() != CONSTRAINT_TYPE_CHECK) { continue; } else if (OB_FAIL(ObRawExprUtils::parse_bool_expr_node_from_str( (*iter)->get_check_expr_str(), *params.allocator_, node))) { LOG_WARN("parse expr node from string failed", K(ret)); } else if (OB_FAIL(resolve_check_constraint_expr(params, node, table_schema, cst, check_expr))) { LOG_WARN("resolver constraint expr failed", K(ret)); } else { ret = check_exprs.push_back(check_expr); } } bool tmp_allow = false; if (OB_FAIL(ret)) { } else if (OB_FAIL(check_uniq_allow( params, table_schema, index_arg, part_func_exprs.at(0), check_exprs, tmp_allow))) { LOG_WARN("check_uniq_allowe failed", K(ret)); } else if (tmp_allow) { allow = tmp_allow; } } } } return ret; } int ObDDLResolver::resolve_split_partition_range_element(const ParseNode* node, const share::schema::ObPartitionFuncType part_type, const ObIArray& part_func_exprs, common::ObIArray& range_value_exprs, const bool& in_tablegroup) { int ret = OB_SUCCESS; if (OB_ISNULL(node) || T_EXPR_LIST != node->type_) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid_argument", K(ret), "type", node->type_); } else if (!in_tablegroup) { if (node->num_child_ != part_func_exprs.count()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid_argument", K(ret), "node num", node->num_child_, "function num", part_func_exprs.count()); } } ObString part_name; for (int i = 0; OB_SUCC(ret) && i < node->num_child_; ++i) { if (OB_ISNULL(node->children_[i])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null", K(ret), K(i), "node", node->children_[i]); } else if (T_MAXVALUE == node->children_[i]->type_) { ObRawExpr* maxvalue_expr = NULL; ObConstRawExpr* c_expr = NULL; c_expr = (ObConstRawExpr*)allocator_->alloc(sizeof(ObConstRawExpr)); if (OB_ISNULL(c_expr)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to alloc raw expr", K(ret), K(c_expr)); } else { c_expr = new (c_expr) ObConstRawExpr(); maxvalue_expr = c_expr; maxvalue_expr->set_data_type(common::ObMaxType); if (OB_FAIL(range_value_exprs.push_back(maxvalue_expr))) { LOG_WARN("array push back fail", K(ret)); } } } else if (T_NULL == node->children_[i]->type_) { ret = OB_EER_NULL_IN_VALUES_LESS_THAN; LOG_WARN("null value is not allowed in less than", K(ret)); } else if (T_EXPR_LIST != node->children_[i]->type_) { ObRawExpr* part_value_expr = NULL; ObRawExpr* part_func_expr = NULL; if (!in_tablegroup) { if (OB_FAIL(part_func_exprs.at(i, part_func_expr))) { LOG_WARN("get part expr failed", K(ret), K(i), "size", part_func_exprs.count()); } else if (OB_ISNULL(part_func_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("part func expr is invalid", K(ret), K(i)); } else if (OB_FAIL(ObResolverUtils::resolve_partition_range_value_expr(params_, *(node->children_[i]), part_name, part_type, *part_func_expr, part_value_expr, in_tablegroup))) { LOG_WARN("failed to resolve at values", K(ret)); } } else { if (OB_FAIL(ObResolverUtils::resolve_partition_range_value_expr( params_, *(node->children_[i]), part_name, part_type, part_value_expr, in_tablegroup))) { LOG_WARN("failed to resolve at values", K(ret)); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(range_value_exprs.push_back(part_value_expr))) { LOG_WARN("failed to push back raw_expr", K(ret), K(part_value_expr)); } } } // end for process t_expr_list return ret; } int ObDDLResolver::resolve_split_partition_list_value(const ParseNode* node, const share::schema::ObPartitionFuncType part_type, const ObIArray& part_func_exprs, ObDDLStmt::array_t& list_value_exprs, int64_t& expr_num, const bool& in_tablegroup) { int ret = OB_SUCCESS; ObString part_name; ObOpRawExpr* row_expr = NULL; if (OB_ISNULL(node) || OB_ISNULL(params_.expr_factory_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(node), K(params_.expr_factory_)); } else if (T_EXPR_LIST != node->type_ && T_DEFAULT != node->type_) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument node type", K(ret), "node type", node->type_); } else if (OB_FAIL(params_.expr_factory_->create_raw_expr(T_OP_ROW, row_expr))) { LOG_WARN("failed to create raw expr", K(ret)); } else if (OB_ISNULL(row_expr)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allcoate memory", K(ret)); } else if (T_DEFAULT == node->type_) { // replace default value with max ObRawExpr* maxvalue_expr = NULL; ObConstRawExpr* c_expr = NULL; c_expr = (ObConstRawExpr*)allocator_->alloc(sizeof(ObConstRawExpr)); if (OB_ISNULL(c_expr)) { ret = OB_ALLOCATE_MEMORY_FAILED; } else { c_expr = new (c_expr) ObConstRawExpr(); maxvalue_expr = c_expr; maxvalue_expr->set_data_type(common::ObMaxType); ObDDLStmt::array_t part_value_expr_array; if (OB_FAIL(row_expr->add_param_expr(maxvalue_expr))) { LOG_WARN("failed to add param expr", K(ret)); } else if (OB_FAIL(list_value_exprs.push_back(row_expr))) { LOG_WARN("array push back fail", K(ret)); } } } else { ObSEArray part_value_exprs; bool is_all_expr_list = false; if (node->num_child_ > 0) { is_all_expr_list = (node->children_[0]->type_ == T_EXPR_LIST); } for (int64_t j = 0; OB_SUCC(ret) && j < node->num_child_; j++) { part_value_exprs.reset(); if (OB_ISNULL(node->children_[j])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null", K(ret)); } else if ((is_all_expr_list && node->children_[j]->type_ != T_EXPR_LIST) || (!is_all_expr_list && node->children_[j]->type_ == T_EXPR_LIST)) { ret = OB_ERR_PARTITION_COLUMN_LIST_ERROR; LOG_WARN("Inconsistency in usage of column lists for partitioning near", K(ret)); } else if (!in_tablegroup && OB_FAIL(ObResolverUtils::resolve_partition_list_value_expr( params_, *(node->children_[j]), part_name, part_type, part_func_exprs, part_value_exprs))) { LOG_WARN("resolve partition expr failed", K(ret)); } else if (in_tablegroup && OB_FAIL(ObResolverUtils::resolve_partition_list_value_expr(params_, *(node->children_[j]), part_name, part_type, expr_num, part_value_exprs, in_tablegroup))) { LOG_WARN("resolve partition expr failed", K(ret)); } for (int64_t k = 0; OB_SUCC(ret) && k < part_value_exprs.count(); k++) { if (OB_FAIL(row_expr->add_param_expr(part_value_exprs.at(k)))) { LOG_WARN("failed to add param expr", K(ret)); } } // end for } // end for if (OB_FAIL(ret)) { } else if (part_func_exprs.count() > 1 && !is_all_expr_list) { if (row_expr->get_param_count() != part_func_exprs.count()) { ret = OB_ERR_PARTITION_COLUMN_LIST_ERROR; LOG_WARN("Inconsistency in usage of column lists for partitioning near", K(ret)); } } if (OB_FAIL(ret)) { } else if (OB_FAIL(list_value_exprs.push_back(row_expr))) { LOG_WARN("array push back fail", K(ret)); } } return ret; } int ObDDLResolver::check_split_type_valid( const ParseNode* split_node, const share::schema::ObPartitionFuncType part_type) { int ret = OB_SUCCESS; if (OB_ISNULL(split_node) || T_SPLIT_ACTION != split_node->type_ || OB_ISNULL(split_node->children_[SPLIT_PARTITION_TYPE_NODE]) || PARTITION_FUNC_TYPE_MAX == part_type) { ret = OB_INVALID_ARGUMENT; LOG_WARN("node type error or partition type node is null", K(ret), "node_type", split_node->type_, "split_partition_type", split_node->children_[SPLIT_PARTITION_TYPE_NODE], K(part_type)); } else if (share::schema::is_list_part(part_type) && T_SPLIT_LIST != split_node->children_[SPLIT_PARTITION_TYPE_NODE]->type_) { ret = OB_ERR_UNEXPECTED; LOG_USER_ERROR(OB_ERR_UNEXPECTED, "VALUES LESS THAN or AT clause cannot be used with List partition"); LOG_WARN("at clause cannot be used with list partition", K(ret), "node_type", split_node->children_[SPLIT_PARTITION_TYPE_NODE]->type_); } else if (share::schema::is_range_part(part_type) && T_SPLIT_RANGE != split_node->children_[SPLIT_PARTITION_TYPE_NODE]->type_) { ret = OB_ERR_UNEXPECTED; LOG_USER_ERROR(OB_ERR_UNEXPECTED, "expecting VALUES LESS THAN or AT clause"); LOG_WARN("values clause cannot be used with range partitioned", K(ret), "node_type", split_node->children_[SPLIT_PARTITION_TYPE_NODE]->type_); } return ret; } int ObDDLResolver::generate_index_name( ObString& index_name, IndexNameSet& current_index_name_set, const common::ObString& first_col_name) { int ret = OB_SUCCESS; // inspect whether first_column_name is exist ObIndexNameHashWrapper index_key(first_col_name); if (OB_ISNULL(allocator_)) { ret = OB_NOT_INIT; SQL_RESV_LOG(WARN, "allocator is null.", K(ret)); } else if (OB_HASH_EXIST != current_index_name_set.exist_refactored(index_key)) { if (OB_FAIL(ob_write_string(*allocator_, first_col_name, index_name))) { SQL_RESV_LOG(WARN, "failed to set index name to first column name", K(ret)); } } else { char buffer[number::ObNumber::MAX_PRINTABLE_SIZE]; ObString str; bool b_flag = false; ObIndexNameHashWrapper tmp_key; for (int32_t i = 2; OB_SUCC(ret) && !b_flag; ++i) { if (snprintf(buffer, sizeof(buffer), "%.*s_%d", first_col_name.length(), first_col_name.ptr(), i) < 0) { ret = OB_SIZE_OVERFLOW; SQL_RESV_LOG(WARN, "failed to generate buffer", K(first_col_name), K(ret)); } else if (OB_FAIL(ob_write_string(*allocator_, ObString::make_string(buffer), str))) { SQL_RESV_LOG(WARN, "Can not malloc space for index name"); } else { tmp_key.set_name(str); if (OB_HASH_EXIST != current_index_name_set.exist_refactored(tmp_key)) { b_flag = true; } } } index_name.assign_ptr(str.ptr(), str.length()); } return ret; } int ObDDLResolver::resolve_foreign_key(const ParseNode* node, ObArray& node_position_list) { int ret = OB_SUCCESS; if (OB_ISNULL(node)) { // do nothing, create table t as select ... will come here } else if (T_TABLE_ELEMENT_LIST != node->type_) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(node->type_)); } else if (OB_ISNULL(stmt_)) { ret = OB_NOT_INIT; SQL_RESV_LOG(WARN, "stmt_ is null", K(ret)); } else if (OB_ISNULL(node->children_)) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(node->children_)); } else { ObCreateTableStmt* create_table_stmt = static_cast(stmt_); for (int64_t i = 0; OB_SUCC(ret) && i < node_position_list.size(); ++i) { int child_pos = node_position_list.at(i); ObCreateForeignKeyArg foreign_key_arg; if (!(0 <= child_pos && child_pos < node->num_child_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "node pos out of range", K(ret), K(child_pos), K(node->num_child_)); } else if (OB_FAIL(resolve_foreign_key_node(node->children_[child_pos], foreign_key_arg, false))) { SQL_RESV_LOG(WARN, "failed to resolve foreign key node", K(ret), K(child_pos)); } else if (OB_FAIL(create_table_stmt->get_foreign_key_arg_list().push_back(foreign_key_arg))) { SQL_RESV_LOG(WARN, "failed to push back foreign key arg", K(ret)); } } if (OB_SUCC(ret) && share::is_oracle_mode() && OB_FAIL(ObResolverUtils::check_dup_foreign_keys_exist(create_table_stmt->get_foreign_key_arg_list()))) { SQL_RESV_LOG(WARN, "failed to check dup foreign keys exist", K(ret)); } current_foreign_key_name_set_.reset(); } return ret; } int ObDDLResolver::resolve_foreign_key_node( const ParseNode* node, obrpc::ObCreateForeignKeyArg& arg, bool is_alter_table, const ObColumnSchemaV2* column) { int ret = OB_SUCCESS; if (OB_ISNULL(node)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "node is null", K(ret)); } else if (!is_oracle_mode()) { // mysql mode if (T_FOREIGN_KEY != node->type_ || 7 != node->num_child_ || OB_ISNULL(node->children_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(node->type_), K(node->num_child_), K(node->children_)); } else { ParseNode* child_columns = node->children_[0]; ParseNode* parent_table = node->children_[1]; ParseNode* parent_columns = node->children_[2]; ParseNode* reference_options = node->children_[3]; ParseNode* constraint_name = node->children_[4]; ParseNode* foreign_key_name = node->children_[5]; UNUSED(foreign_key_name); ParseNode* match_options = node->children_[6]; if (OB_FAIL(resolve_table_relation_node(parent_table, arg.parent_table_, arg.parent_database_))) { LOG_WARN("failed to resolve foreign key parent table", K(ret)); } else if (OB_FAIL(resolve_foreign_key_columns(child_columns, arg.child_columns_))) { LOG_WARN("failed to resolve foreign key child columns", K(ret)); } else if (OB_FAIL(resolve_foreign_key_columns(parent_columns, arg.parent_columns_))) { LOG_WARN("failed to resolve foreign key parent columns", K(ret)); } else if (OB_FAIL(resolve_foreign_key_options(reference_options, arg.update_action_, arg.delete_action_))) { LOG_WARN("failed to resolve foreign key options", K(ret)); } else if (OB_FAIL(resolve_foreign_key_name(constraint_name, arg.foreign_key_name_))) { LOG_WARN("failed to resolve foreign key name", K(ret)); } else if (OB_FAIL(check_foreign_key_reference(arg, is_alter_table, NULL))) { LOG_WARN("failed to check reference columns", K(ret)); } else if (OB_FAIL(resolve_match_options(match_options))) { LOG_WARN("failed to resolve match options", K(ret)); } } } else { // oracle mode if (NULL == column) { // table level foreign key in oracle mode if (T_FOREIGN_KEY != node->type_ || 4 != node->num_child_ || OB_ISNULL(node->children_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(node->type_), K(node->num_child_), K(node->children_)); } else { ParseNode* constraint_name = node->children_[0]; ParseNode* child_columns = node->children_[1]; ParseNode* references_clause_node = node->children_[2]; ParseNode* fk_enable_state_node = node->children_[3]; ParseNode* parent_table = nullptr; ParseNode* parent_columns = nullptr; ParseNode* reference_options = nullptr; if (OB_ISNULL(references_clause_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("failed to resolve references clause, node is null", K(ret)); } else { // resolve references_clause if (T_REFERENCES_CLAUSE != references_clause_node->type_ || 3 != references_clause_node->num_child_ || OB_ISNULL(references_clause_node->children_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(references_clause_node->type_), K(references_clause_node->num_child_), K(references_clause_node->children_)); } else { parent_table = references_clause_node->children_[0]; parent_columns = references_clause_node->children_[1]; reference_options = references_clause_node->children_[2]; } } if (OB_SUCC(ret)) { if (OB_FAIL(resolve_table_relation_node(parent_table, arg.parent_table_, arg.parent_database_))) { LOG_WARN("failed to resolve foreign key parent table", K(ret)); } else if (OB_FAIL(resolve_foreign_key_columns(child_columns, arg.child_columns_))) { LOG_WARN("failed to resolve foreign key child columns", K(ret)); } else if (OB_FAIL(resolve_fk_referenced_columns_oracle( parent_columns, arg, is_alter_table, arg.parent_columns_))) { LOG_WARN("failed to resolve foreign key parent columns in oracle mode", K(ret)); } else if (OB_FAIL(resolve_foreign_key_option(reference_options, arg.update_action_, arg.delete_action_))) { LOG_WARN("failed to resolve foreign key options", K(ret)); } else if (OB_FAIL(resolve_foreign_key_name(constraint_name, arg.foreign_key_name_))) { LOG_WARN("failed to resolve foreign key name", K(ret)); } else if (OB_FAIL(check_foreign_key_reference(arg, is_alter_table, NULL))) { LOG_WARN("failed to check reference columns", K(ret)); } else if (OB_FAIL(resolve_foreign_key_state(fk_enable_state_node, arg))) { LOG_WARN("failed to resolve foreign key enable_state", K(ret)); } } } } else { // column level foreign key in oracle mode if (T_FOREIGN_KEY != node->type_ || 3 != node->num_child_ || OB_ISNULL(node->children_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(node->type_), K(node->num_child_), K(node->children_)); } else { ParseNode* constraint_name = node->children_[0]; ParseNode* references_clause_node = node->children_[1]; ParseNode* fk_enable_state_node = node->children_[2]; ParseNode* parent_table = nullptr; ParseNode* parent_columns = nullptr; ParseNode* reference_options = nullptr; if (OB_ISNULL(references_clause_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("failed to resolve references clause, node is null", K(ret)); } else { // resolve references_clause if (T_REFERENCES_CLAUSE != references_clause_node->type_ || 3 != references_clause_node->num_child_ || OB_ISNULL(references_clause_node->children_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(references_clause_node->type_), K(references_clause_node->num_child_), K(references_clause_node->children_)); } else { parent_table = references_clause_node->children_[0]; parent_columns = references_clause_node->children_[1]; reference_options = references_clause_node->children_[2]; } } if (OB_SUCC(ret)) { if (OB_FAIL(resolve_table_relation_node(parent_table, arg.parent_table_, arg.parent_database_))) { LOG_WARN("failed to resolve foreign key parent table", K(ret)); } else if (OB_FAIL(arg.child_columns_.push_back( ObString(column->get_column_name_str().length(), column->get_column_name_str().ptr())))) { LOG_WARN("failed to push back column name", K(ret)); } else if (OB_FAIL(resolve_fk_referenced_columns_oracle( parent_columns, arg, is_alter_table, arg.parent_columns_))) { LOG_WARN("failed to resolve foreign key parent columns", K(ret)); } else if (OB_FAIL(resolve_foreign_key_option(reference_options, arg.update_action_, arg.delete_action_))) { LOG_WARN("failed to resolve foreign key options", K(ret)); } else if (OB_FAIL(resolve_foreign_key_name(constraint_name, arg.foreign_key_name_))) { LOG_WARN("failed to resolve foreign key name", K(ret)); } else if (OB_FAIL(check_foreign_key_reference(arg, is_alter_table, column))) { LOG_WARN("failed to check reference columns", K(ret)); } else if (OB_FAIL(resolve_foreign_key_state(fk_enable_state_node, arg))) { LOG_WARN("failed to resolve foreign key enable_state", K(ret)); } } } } } // end oracle mode return ret; } int ObDDLResolver::resolve_foreign_key_columns(const ParseNode* node, ObIArray& columns) { int ret = OB_SUCCESS; if (OB_ISNULL(node)) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "node is null", K(ret)); } else if (OB_ISNULL(node->children_)) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(node->type_), K(node->num_child_), K(node->children_)); } else { for (int64_t i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { ParseNode* column = node->children_[i]; if (OB_ISNULL(column)) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "child is null", K(ret)); } else if (OB_ISNULL(column->str_value_)) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(column->type_), K(column->str_value_)); } else if (OB_FAIL(columns.push_back(ObString(column->str_len_, column->str_value_)))) { LOG_WARN("failed to push back column name", K(ret), K(column->str_value_)); } } } return ret; } int ObDDLResolver::resolve_fk_referenced_columns_oracle( const ParseNode* node, const obrpc::ObCreateForeignKeyArg& arg, bool is_alter_table, ObIArray& columns) { int ret = OB_SUCCESS; if (share::is_oracle_mode() && OB_ISNULL(node)) { // oracle mode: ref column can be default, will auto ref parent table's pk column const ObTableSchema* parent_table_schema = NULL; if (0 == arg.parent_table_.case_compare(table_name_) && 0 == arg.parent_database_.case_compare(database_name_) && !is_alter_table) { // create table with self-ref foreign key if (OB_ISNULL(static_cast(stmt_))) { ret = OB_NOT_INIT; SQL_RESV_LOG(WARN, "stmt_ is null.", K(ret)); } else { parent_table_schema = &static_cast(stmt_)->get_create_table_arg().schema_; if (OB_ISNULL(parent_table_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("parent table schema is null", K(ret)); } } } else if (OB_FAIL(schema_checker_->get_table_schema(session_info_->get_effective_tenant_id(), arg.parent_database_, arg.parent_table_, false, parent_table_schema))) { LOG_WARN("table is not exist", K(ret), K(arg.parent_database_), K(arg.parent_table_)); } else if (OB_ISNULL(parent_table_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("parent table schema is null", K(ret)); } if (OB_SUCC(ret)) { const ObRowkeyInfo& rowkey_info = parent_table_schema->get_rowkey_info(); for (int64_t i = 0; OB_SUCC(ret) && i < rowkey_info.get_size(); ++i) { uint64_t column_id = 0; const ObColumnSchemaV2* col_schema = NULL; if (OB_FAIL(rowkey_info.get_column_id(i, column_id))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to get rowkey info", K(ret), K(i), K(rowkey_info)); } else if (NULL == (col_schema = parent_table_schema->get_column_schema(column_id))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get index column schema failed", K(ret)); } else if (col_schema->is_hidden() || col_schema->is_shadow_column()) { // do nothing } else if (OB_FAIL(columns.push_back(col_schema->get_column_name()))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("push back index column failed", K(ret)); } } if (OB_SUCC(ret) && (0 == columns.count())) { ret = OB_ERR_REFERENCED_TABLE_HAS_NO_PK; LOG_WARN("referenced table does not have a primary key", K(ret), KPC(parent_table_schema)); } } } else if (OB_FAIL(resolve_foreign_key_columns(node, columns))) { LOG_WARN("failed to resolve foreign key columns", K(ret)); } return ret; } int ObDDLResolver::resolve_foreign_key_options( const ParseNode* node, ObReferenceAction& update_action, ObReferenceAction& delete_action) { int ret = OB_SUCCESS; if (OB_ISNULL(node)) { // nothing. } else if (T_REFERENCE_OPTION_LIST != node->type_ || node->num_child_ > 2) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(node->type_), K(node->num_child_)); } else if (NULL != node->children_) { update_action = ACTION_INVALID; delete_action = ACTION_INVALID; ParseNode* option_node = NULL; for (int64_t i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { option_node = node->children_[i]; ObReferenceAction action = ACTION_INVALID; if (OB_ISNULL(option_node)) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "option node is null", K(ret), K(i)); } else { switch (option_node->int32_values_[1]) { case T_RESTRICT: action = ACTION_RESTRICT; break; case T_CASCADE: action = ACTION_CASCADE; break; case T_SET_NULL: // action = ACTION_SET_NULL; ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "create foreign key with set null option"); break; case T_NO_ACTION: action = ACTION_NO_ACTION; break; case T_SET_DEFAULT: ret = OB_ERR_CANNOT_ADD_FOREIGN; SQL_RESV_LOG(WARN, "Cannot add foreign key constraint, because the key word of action is ACTION_SET_DEFAULT", K(ret), K(node->int32_values_[1])); break; default: ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid reference option", K(ret), K(option_node->int32_values_[1])); break; } } if (OB_SUCC(ret)) { switch (option_node->int32_values_[0]) { case T_UPDATE: if (ACTION_INVALID != update_action) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "mutli update option", K(ret)); } else { update_action = action; } break; case T_DELETE: if (ACTION_INVALID != delete_action) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "mutli delete option", K(ret)); } else { delete_action = action; } break; default: ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid reference option", K(ret), K(option_node->int32_values_[0])); break; } } } } if (OB_SUCC(ret)) { if (ACTION_INVALID == update_action) { update_action = ACTION_RESTRICT; } if (ACTION_INVALID == delete_action) { delete_action = ACTION_RESTRICT; } } return ret; } // for oracle mode int ObDDLResolver::resolve_foreign_key_option(const ParseNode* option_node, share::schema::ObReferenceAction& update_action, share::schema::ObReferenceAction& delete_action) { int ret = OB_SUCCESS; if (OB_ISNULL(option_node)) { // do nothing. } else if (T_REFERENCE_OPTION != option_node->type_) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(option_node->type_)); } else { ObReferenceAction action = ACTION_INVALID; switch (option_node->int32_values_[1]) { case T_CASCADE: action = ACTION_CASCADE; break; case T_SET_NULL: // action = ACTION_SET_NULL; ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "create foreign key with set null option"); break; default: ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid reference option", K(ret), K(option_node->int32_values_[1])); break; } if (OB_SUCC(ret)) { switch (option_node->int32_values_[0]) { case T_DELETE: delete_action = action; break; default: ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid reference option", K(ret), K(option_node->int32_values_[0])); break; } } } // default value is ACTION_RESTRICT if (OB_SUCC(ret)) { if (ACTION_INVALID == update_action) { update_action = ACTION_RESTRICT; } if (ACTION_INVALID == delete_action) { delete_action = ACTION_RESTRICT; } } return ret; } int ObDDLResolver::resolve_foreign_key_name(const ParseNode* constraint_node, ObString& foreign_key_name) { int ret = OB_SUCCESS; foreign_key_name.reset(); if (OB_NOT_NULL(constraint_node)) { if (!is_oracle_mode()) { // mysql mode const ParseNode* constraint_name = NULL; if (T_CHECK_CONSTRAINT != constraint_node->type_ || 1 != constraint_node->num_child_ || OB_ISNULL(constraint_node->children_)) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(constraint_node->type_), K(constraint_node->num_child_), KP(constraint_node->children_)); } else if (OB_NOT_NULL(constraint_name = constraint_node->children_[0])) { foreign_key_name.assign_ptr(constraint_name->str_value_, static_cast(constraint_name->str_len_)); // check if fk name duplicated in create_table ObForeignKeyNameHashWrapper fk_key(foreign_key_name); if (OB_HASH_EXIST == (ret = current_foreign_key_name_set_.exist_refactored(fk_key))) { SQL_RESV_LOG(WARN, "duplicate fk name", K(ret), K(foreign_key_name)); ret = OB_ERR_CANNOT_ADD_FOREIGN; } else { ret = OB_SUCCESS; if (OB_FAIL(current_foreign_key_name_set_.set_refactored(fk_key))) { SQL_RESV_LOG(WARN, "set foreign key name to hash set failed", K(ret), K(foreign_key_name)); } } } else if (OB_FAIL(create_fk_cons_name_automatically(foreign_key_name))) { SQL_RESV_LOG(WARN, "create cons name automatically failed", K(ret)); } } else { // oracle mode foreign_key_name.assign_ptr(constraint_node->str_value_, static_cast(constraint_node->str_len_)); ObForeignKeyNameHashWrapper fk_key(foreign_key_name); if (OB_HASH_EXIST == (ret = current_foreign_key_name_set_.exist_refactored(fk_key))) { SQL_RESV_LOG(WARN, "duplicate fk name", K(ret), K(foreign_key_name)); ret = OB_ERR_CANNOT_ADD_FOREIGN; } else { ret = OB_SUCCESS; if (OB_FAIL(current_foreign_key_name_set_.set_refactored(fk_key))) { SQL_RESV_LOG(WARN, "set foreign key name to hash set failed", K(ret), K(foreign_key_name)); } } } } else if (OB_FAIL(create_fk_cons_name_automatically(foreign_key_name))) { SQL_RESV_LOG(WARN, "create cons name automatically failed", K(ret)); } return ret; } int ObDDLResolver::resolve_foreign_key_state(const ParseNode* fk_state_node, obrpc::ObCreateForeignKeyArg& arg) { int ret = OB_SUCCESS; if (OB_ISNULL(fk_state_node)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "cst_check_state_node is null ptr", K(ret)); } else if (T_CONSTRAINT_STATE != fk_state_node->type_) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "fk_state_node->type_ must be T_CONSTRAINT_STATE", K(ret), K(fk_state_node->type_)); } else if (fk_state_node->num_child_ != 4) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "the num_child of cst_check_state_node is wrong.", K(ret), K(fk_state_node->num_child_)); } else if (OB_NOT_NULL(fk_state_node->children_[1])) { // https://docs.oracle.com/cd/E11882_01/server.112/e41084/clauses002.htm#SQLRF52180 ret = OB_ERR_PARSER_SYNTAX; SQL_RESV_LOG(WARN, "foreign key can't assign state of using index", K(ret)); } else { if (OB_NOT_NULL(fk_state_node->children_[0])) { arg.rely_flag_ = (T_RELY_CONSTRAINT == fk_state_node->children_[0]->type_ ? true : false); } if (OB_NOT_NULL(fk_state_node->children_[2])) { arg.enable_flag_ = (T_ENABLE_CONSTRAINT == fk_state_node->children_[2]->type_ ? true : false); arg.validate_flag_ = (T_ENABLE_CONSTRAINT == fk_state_node->children_[2]->type_ ? true : false); } if (OB_NOT_NULL(fk_state_node->children_[3])) { arg.validate_flag_ = (T_VALIDATE_CONSTRAINT == fk_state_node->children_[3]->type_ ? true : false); } } return ret; } int ObDDLResolver::check_foreign_key_reference( obrpc::ObCreateForeignKeyArg& arg, bool is_alter_table, const ObColumnSchemaV2* column) { int ret = OB_SUCCESS; if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "session_info_ is null.", K(ret)); } else { ObCreateTableStmt* create_table_stmt = NULL; const ObTableSchema* child_table_schema = NULL; const ObTableSchema* parent_table_schema = NULL; ObString& database_name = arg.parent_database_; ObString& parent_table_name = arg.parent_table_; if (!is_alter_table) { create_table_stmt = static_cast(stmt_); if (OB_ISNULL(create_table_stmt)) { ret = OB_NOT_INIT; SQL_RESV_LOG(WARN, "stmt_ is null.", K(ret)); } else { child_table_schema = &create_table_stmt->get_create_table_arg().schema_; } } else { // is alter table ObAlterTableStmt* alter_table_stmt = static_cast(stmt_); if (OB_FAIL(schema_checker_->get_table_schema(session_info_->get_effective_tenant_id(), alter_table_stmt->get_org_database_name(), alter_table_stmt->get_org_table_name(), false, child_table_schema))) { LOG_WARN("table is not exist", K(database_name), K(parent_table_name), K(ret)); } else if (OB_ISNULL(child_table_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("parent table schema is null", K(ret)); } } if (OB_SUCC(ret)) { if (0 == parent_table_name.case_compare(table_name_) && 0 == database_name.case_compare(database_name_)) { parent_table_schema = child_table_schema; ObSEArray& parent_columns = arg.parent_columns_; ObSEArray& child_columns = arg.child_columns_; bool is_conflicted = false; for (int64_t i = 0; OB_SUCC(ret) && !is_conflicted && i < parent_columns.count(); ++i) { for (int64_t j = 0; OB_SUCC(ret) && !is_conflicted && j < child_columns.count(); ++j) { if (0 == parent_columns.at(i).compare(child_columns.at(j))) { is_conflicted = true; ret = OB_ERR_CANNOT_ADD_FOREIGN; LOG_WARN("cannot support that parent column is in child column list", K(ret)); } } } } else if (OB_FAIL(schema_checker_->get_table_schema(session_info_->get_effective_tenant_id(), database_name, parent_table_name, false, parent_table_schema))) { LOG_WARN("table is not exist", K(database_name), K(parent_table_name), K(ret)); } else if (OB_ISNULL(parent_table_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("parent table schema is null", K(ret)); } } if (OB_SUCC(ret)) { if (!child_table_schema->is_user_table() || !parent_table_schema->is_user_table()) { ret = OB_ERR_CANNOT_ADD_FOREIGN; LOG_WARN("foreign key cannot be based on non-user table", K(ret), K(child_table_schema->is_user_table()), K(parent_table_schema->is_user_table())); } else { ObSEArray& child_columns = arg.child_columns_; ObSEArray& parent_columns = arg.parent_columns_; if (OB_FAIL(ObResolverUtils::check_foreign_key_columns_type( *child_table_schema, *parent_table_schema, child_columns, parent_columns, column))) { LOG_WARN("Failed to check_foreign_key_columns_type", K(ret)); } else { bool is_matched = false; ObSArray index_arg_list; if (!is_alter_table) { if (parent_table_schema->get_table_id() == child_table_schema->get_table_id()) { index_arg_list.assign(create_table_stmt->get_index_arg_list()); } } if (OB_FAIL(ObResolverUtils::foreign_key_column_match_uk_pk_column( *parent_table_schema, *schema_checker_, parent_columns, index_arg_list, arg, is_matched))) { LOG_WARN("Failed to check reference columns in parent table"); } else if (!is_matched) { if (share::is_mysql_mode()) { ret = OB_ERR_CANNOT_ADD_FOREIGN; LOG_WARN("reference columns aren't reference to pk or uk in parent table", K(ret)); } else { // oracle mode ret = OB_ERR_NO_MATCHING_UK_PK_FOR_COL_LIST; LOG_WARN("reference columns aren't reference to pk or uk in parent table", K(ret)); } } else { } // do-nothing } } } } return ret; } int ObDDLResolver::resolve_match_options(const ParseNode* match_options_node) { int ret = OB_SUCCESS; if (OB_NOT_NULL(match_options_node)) { LOG_WARN("the function of match options on foreign key is not supported now."); if (T_FOREIGN_KEY_MATCH != match_options_node->type_) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid argument", K(ret), K(match_options_node->type_)); } else { switch (match_options_node->int32_values_[0]) { case T_SIMPLE: break; case T_FULL: break; case T_PARTIAL: break; default: ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid reference option", K(ret), K(match_options_node->int32_values_[0])); break; } } } else { } return ret; } int ObDDLResolver::create_fk_cons_name_automatically(ObString& foreign_key_name) { int ret = OB_SUCCESS; char temp_str_buf[number::ObNumber::MAX_PRINTABLE_SIZE]; ObString cons_name_str; bool is_exist = false; ObString tmp_table_name; if (table_name_.length() > OB_ORACLE_CONS_OR_IDX_CUTTED_NAME_LEN) { if (OB_FAIL(ob_sub_str(*allocator_, table_name_, 0, OB_ORACLE_CONS_OR_IDX_CUTTED_NAME_LEN - 1, tmp_table_name))) { SQL_RESV_LOG(WARN, "failed to cut table to 60 byte", K(ret), K(table_name_)); } } else { tmp_table_name = table_name_; } if (OB_SUCC(ret)) { // use timestamp to ensure fk name unique if (snprintf(temp_str_buf, sizeof(temp_str_buf), "%.*s_OBFK_%ld", tmp_table_name.length(), tmp_table_name.ptr(), ObTimeUtility::current_time()) < 0) { ret = OB_SIZE_OVERFLOW; SQL_RESV_LOG(WARN, "failed to generate buffer for temp_str_buf", K(ret)); } else if (OB_FAIL(ob_write_string(*allocator_, ObString::make_string(temp_str_buf), cons_name_str))) { SQL_RESV_LOG(WARN, "Can not malloc space for constraint name", K(ret)); } else { int hash_ret = OB_HASH_NOT_EXIST; ObForeignKeyNameHashWrapper fk_key(foreign_key_name); foreign_key_name.assign_ptr(cons_name_str.ptr(), cons_name_str.length()); // re-generate if fk name duplicated if (OB_HASH_EXIST == (hash_ret = current_foreign_key_name_set_.exist_refactored(fk_key))) { is_exist = true; } if (true == is_exist) { if (OB_FAIL(create_fk_cons_name_automatically(foreign_key_name))) { SQL_RESV_LOG(WARN, "create cons name automatically failed", K(ret)); } } else { if (OB_FAIL(current_foreign_key_name_set_.set_refactored(fk_key))) { SQL_RESV_LOG(WARN, "set foreign key name to hash set failed", K(ret), K(foreign_key_name)); } } } } return ret; } int ObDDLResolver::create_name_for_empty_partition( const bool is_subpartition, ObIArray& partitions, ObIArray& subpartitions) { int ret = OB_SUCCESS; if (is_subpartition) { if (OB_FAIL(create_name_for_empty_partition(subpartitions))) { LOG_WARN("failed to create name for empty subpartitions", K(ret)); } } else if (OB_FAIL(create_name_for_empty_partition(partitions))) { LOG_WARN("failed to create name for empty partitions", K(ret)); } return ret; } int ObDDLResolver::store_part_key(const ObTableSchema& table_schema, obrpc::ObCreateIndexArg& index_arg) { int ret = OB_SUCCESS; ObSEArray part_key_ids; ObSEArray index_rowkey_ids; const ObColumnSchemaV2* column = NULL; const bool check_column_exists = false; const bool is_hidden = true; if (GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_2250) { ret = OB_NOT_SUPPORTED; LOG_WARN("Create global index on no pk partitioned table not supported in old version", K(ret)); } else if (OB_UNLIKELY(!table_schema.is_partitioned_table())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected partition level", K(ret), K(table_schema.get_part_level())); } else if (OB_FAIL(table_schema.get_partition_key_info().get_column_ids(part_key_ids))) { LOG_WARN("failed to get column ids", K(ret)); } else if (PARTITION_LEVEL_TWO == table_schema.get_part_level() && OB_FAIL(table_schema.get_subpartition_key_info().get_column_ids(part_key_ids))) { LOG_WARN("failed to get column ids", K(ret)); } for (int64_t i = 0; OB_SUCC(ret) && i < index_arg.index_columns_.count(); ++i) { const ObColumnSortItem& column_item = index_arg.index_columns_.at(i); if (OB_FAIL(index_rowkey_ids.push_back(column_item.column_id_))) { LOG_WARN("failed to push back column id", K(ret)); } } for (int64_t i = 0; OB_SUCC(ret) && i < part_key_ids.count(); ++i) { uint64_t column_id = part_key_ids.at(i); if (ObOptimizerUtil::find_item(index_rowkey_ids, column_id)) { // part key already in index rowkey, do nothing } else if (OB_ISNULL(column = table_schema.get_column_schema(column_id))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } else if (OB_FAIL(add_storing_column(column->get_column_name_str(), check_column_exists, is_hidden))) { LOG_WARN("failed to add storing column", K(ret)); } } LOG_TRACE("store part key", K(hidden_store_column_names_)); return ret; } bool ObDDLResolver::is_column_exists( ObIArray& sort_column_array, ObColumnNameWrapper& column_key, bool check_prefix_len) { int bret = false; for (int64_t i = 0; !bret && i < sort_column_array.count(); ++i) { if (check_prefix_len) { if (sort_column_array.at(i).all_equal(column_key)) { bret = true; } } else if (sort_column_array.at(i).name_equal(column_key)) { bret = true; } } return bret; } int ObDDLResolver::get_enable_split_partition(const int64_t tenant_id, bool& enable_split_partition) { int ret = OB_SUCCESS; enable_split_partition = false; if (OB_INVALID_TENANT_ID == tenant_id) { ret = OB_INVALID_ARGUMENT; LOG_WARN("tenant id is invalid", K(ret), K(tenant_id)); } return ret; } int ObDDLResolver::resolve_partition_name( ParseNode* partition_name_node, ObString& partition_name, ObBasePartition& partition) { int ret = OB_SUCCESS; if (OB_ISNULL(partition_name_node) || OB_ISNULL(partition_name_node->children_[NAMENODE])) { if (is_oracle_mode()) { partition.set_is_empty_partition_name(true); } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition expr list node is null", K(ret)); } } else { ParseNode* name_node = partition_name_node->children_[NAMENODE]; partition_name.assign_ptr(name_node->str_value_, static_cast(name_node->str_len_)); if (partition_name.length() > OB_MAX_PARTITION_NAME_LENGTH) { ret = OB_ERR_TOO_LONG_IDENT; } else if (OB_FAIL(partition.set_part_name(partition_name))) { LOG_WARN("failed to set part name", K(ret)); } } return ret; } int ObDDLResolver::resolve_partition_part_id(ParseNode* part_id_node, const ObDDLStmt* stmt, const int64_t max_used_part_id, const int64_t partition_num, const int64_t partition_element_idx, int64_t& part_id, bool& is_spec_part_id) { int ret = OB_SUCCESS; is_spec_part_id = false; if (OB_ISNULL(part_id_node)) { part_id = max_used_part_id >= 0 ? max_used_part_id - partition_num + 1 + partition_element_idx : partition_element_idx; } else { part_id = static_cast(part_id_node->children_[0]->value_); is_spec_part_id = true; bool is_valid = false; if (OB_FAIL(check_partid_valid(stmt, part_id, max_used_part_id, is_valid))) { LOG_WARN("failed to check partid valid", K(ret)); } else if (!is_valid) { ret = OB_ERR_UNEXPECTED; LOG_WARN("part id not valid", K(ret), K(part_id)); } } if (OB_SUCC(ret) && part_id < 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid part_id", K(ret), K(part_id)); } return ret; } // resolve hash/key partition basic infos, include: // 1. partition function type // 2. partition function expr name // 3. partition keys (set in this function) int ObDDLResolver::resolve_hash_or_key_partition_basic_infos(ParseNode* node, bool is_subpartition, ObTableSchema& table_schema, ObPartitionFuncType& part_func_type, ObString& func_expr_name, ObSqlString& part_str) { int ret = OB_SUCCESS; ParseNode* partition_fun_node = NULL; part_func_type = PARTITION_FUNC_TYPE_HASH; const share::schema::ObTablegroupSchema* tablegroup_schema = NULL; if (OB_ISNULL(node) || OB_ISNULL(node->children_) || OB_ISNULL(partition_fun_node = node->children_[HASH_FUN_EXPR_NODE]) || OB_ISNULL(schema_checker_) || OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(node), K(partition_fun_node), K(schema_checker_), K(session_info_)); } else if (GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_3000 && !table_schema.get_tablegroup_name().empty() && OB_FAIL(schema_checker_->get_tablegroup_schema( session_info_->get_effective_tenant_id(), table_schema.get_tablegroup_name(), tablegroup_schema))) { LOG_WARN("fail to get tablegroup schema", K(ret), K(table_schema.get_tablegroup_name())); } else { if (GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_3000) { part_func_type = T_HASH_PARTITION == node->type_ ? share::schema::PARTITION_FUNC_TYPE_HASH : share::schema::PARTITION_FUNC_TYPE_KEY_V2; } else { part_func_type = T_HASH_PARTITION == node->type_ ? share::schema::PARTITION_FUNC_TYPE_HASH_V2 : share::schema::PARTITION_FUNC_TYPE_KEY_V3; } // compatible with old version if (tablegroup_schema != NULL) { if (tablegroup_schema->get_part_level() >= table_schema.get_part_level()) { const share::schema::ObPartitionOption& tablegroup_part = !is_subpartition ? tablegroup_schema->get_part_option() : tablegroup_schema->get_sub_part_option(); if (part_func_type == share::schema::PARTITION_FUNC_TYPE_HASH_V2 && tablegroup_part.get_part_func_type() == share::schema::PARTITION_FUNC_TYPE_HASH) { part_func_type = share::schema::PARTITION_FUNC_TYPE_HASH; } else if (part_func_type == share::schema::PARTITION_FUNC_TYPE_KEY_V3 && tablegroup_part.get_part_func_type() == share::schema::PARTITION_FUNC_TYPE_KEY_V2) { part_func_type = share::schema::PARTITION_FUNC_TYPE_KEY_V2; } else { /*do nothing */ } } } } if (OB_SUCC(ret)) { if (NULL == partition_fun_node->children_[1]) { // partition by key() if (GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_3000) { part_func_type = share::schema::PARTITION_FUNC_TYPE_KEY_IMPLICIT; } else { part_func_type = share::schema::PARTITION_FUNC_TYPE_KEY_IMPLICIT_V2; } if (OB_FAIL(build_partition_key_info( table_schema, is_subpartition, part_func_type == share::schema::PARTITION_FUNC_TYPE_KEY_IMPLICIT_V2))) { LOG_WARN("failed to build partition key info", K(ret), K(table_schema), K(is_subpartition)); } } else { ObSEArray dummy_part_func_exprs; ObSEArray partition_keys; if (OB_FAIL(resolve_part_func( params_, partition_fun_node, part_func_type, table_schema, dummy_part_func_exprs, partition_keys))) { LOG_WARN("failed to resolve part func", K(ret)); } else if (OB_FAIL(set_partition_keys(table_schema, partition_keys, is_subpartition))) { LOG_WARN("failed to set partition keys", K(ret), K(table_schema), K(is_subpartition)); } } } if (OB_SUCC(ret)) { func_expr_name.assign_ptr(node->str_value_, static_cast(node->str_len_)); if (!share::is_oracle_mode()) { // TODO(:maybe not valid here, if expr include table name or databae name) ObCharset::casedn(CS_TYPE_UTF8MB4_GENERAL_CI, func_expr_name); } // TODO now, just for compat inner_table process. if (is_inner_table(table_id_)) { if (OB_FAIL(get_part_str_with_type(part_func_type, func_expr_name, part_str))) { SQL_RESV_LOG(WARN, "Failed to get part str with type", K(ret)); } else if (FALSE_IT(func_expr_name = part_str.string())) { } else if (PARTITION_FUNC_TYPE_KEY_V2 == part_func_type || PARTITION_FUNC_TYPE_KEY_V3 == part_func_type) { part_func_type = PARTITION_FUNC_TYPE_KEY; } } } return ret; } // resolve range partition basic infos, include: // 1. partition function type // 2. partition function expr name // 3. partition function exprs // 4. partition keys (set in this function) int ObDDLResolver::resolve_range_partition_basic_infos(ParseNode* node, bool is_subpartition, ObTableSchema& table_schema, ObPartitionFuncType& part_func_type, ObString& func_expr_name, ObIArray& part_func_exprs) { int ret = OB_SUCCESS; ParseNode* partition_fun_node = NULL; part_func_type = PARTITION_FUNC_TYPE_RANGE; ObSEArray partition_keys; if (OB_ISNULL(node) || OB_ISNULL(partition_fun_node = node->children_[RANGE_FUN_EXPR_NODE])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(node), K(partition_fun_node)); } else if (T_RANGE_COLUMNS_PARTITION == node->type_) { part_func_type = PARTITION_FUNC_TYPE_RANGE_COLUMNS; } if (OB_SUCC(ret)) { func_expr_name.assign_ptr(node->str_value_, static_cast(node->str_len_)); if (OB_FAIL(resolve_part_func( params_, partition_fun_node, part_func_type, table_schema, part_func_exprs, partition_keys))) { LOG_WARN("resolve part func failed", K(ret)); } else if (OB_FAIL(set_partition_keys(table_schema, partition_keys, is_subpartition))) { LOG_WARN("Failed to set partition keys", K(ret), K(table_schema), K(is_subpartition)); } } return ret; } // resolve list partition basic infos, include: // 1. partition function type // 2. partition function expr name // 3. partition function exprs // 4. partition keys (set in this function) int ObDDLResolver::resolve_list_partition_basic_infos(ParseNode* node, bool is_subpartition, ObTableSchema& table_schema, ObPartitionFuncType& part_func_type, ObString& func_expr_name, ObIArray& part_func_exprs) { int ret = OB_SUCCESS; ParseNode* partition_fun_node = NULL; part_func_type = PARTITION_FUNC_TYPE_LIST; ObSEArray partition_keys; if (OB_ISNULL(node) || OB_ISNULL(partition_fun_node = node->children_[LIST_FUN_EXPR_NODE])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(node), K(partition_fun_node)); } else if (T_LIST_COLUMNS_PARTITION == node->type_) { part_func_type = PARTITION_FUNC_TYPE_LIST_COLUMNS; } if (OB_SUCC(ret)) { func_expr_name.assign_ptr(node->str_value_, static_cast(node->str_len_)); if (OB_FAIL(resolve_part_func( params_, partition_fun_node, part_func_type, table_schema, part_func_exprs, partition_keys))) { LOG_WARN("resolve part func failed", K(ret)); } else if (OB_FAIL(set_partition_keys(table_schema, partition_keys, is_subpartition))) { LOG_WARN("Failed to set partition keys", K(ret), K(table_schema), K(is_subpartition)); } } return ret; } int ObDDLResolver::resolve_partition_node(ObPartitionedStmt* stmt, ParseNode* part_node, ObTableSchema& table_schema) { int ret = OB_SUCCESS; if (is_hash_type_partition(part_node->type_)) { ret = resolve_partition_hash_or_key(stmt, part_node, false, table_schema); } else if (is_range_type_partition(part_node->type_)) { ret = resolve_partition_range(stmt, part_node, false, table_schema); } else if (is_list_type_partition(part_node->type_)) { ret = resolve_partition_list(stmt, part_node, false, table_schema); } else { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "node type is invalid.", K(ret), K(part_node->type_)); } if (OB_SUCC(ret) && !common::is_virtual_table(table_id_)) { if (table_schema.get_all_part_num() > (lib::is_oracle_mode() ? common::OB_MAX_PARTITION_NUM_ORACLE : common::OB_MAX_PARTITION_NUM_MYSQL)) { ret = common::OB_TOO_MANY_PARTITIONS_ERROR; } } if (OB_SUCC(ret)) { if (OB_FAIL(check_and_set_partition_names(stmt, table_schema))) { LOG_WARN("failed to check and set partition names", K(ret)); } } return ret; } int ObDDLResolver::resolve_subpartition_option( ObPartitionedStmt* stmt, ParseNode* subpart_node, ObTableSchema& table_schema) { int ret = OB_SUCCESS; if (is_hash_type_partition(subpart_node->type_)) { if (OB_FAIL(resolve_partition_hash_or_key(stmt, subpart_node, true, table_schema))) { SQL_RESV_LOG(WARN, "failed to resolve partition hash or key", K(ret)); } } else if (is_range_type_partition(subpart_node->type_)) { if (OB_FAIL(resolve_partition_range(stmt, subpart_node, true, table_schema))) { SQL_RESV_LOG(WARN, "failed to resolve partition range", K(ret)); } } else if (is_list_type_partition(subpart_node->type_)) { if (OB_FAIL(resolve_partition_list(stmt, subpart_node, true, table_schema))) { SQL_RESV_LOG(WARN, "failed to resolve partition list", K(ret)); } } else { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "get unexpected subpartition type", K(ret), K(subpart_node->type_)); } return ret; } int ObDDLResolver::resolve_individual_subpartition(ObPartitionedStmt* stmt, ParseNode* part_node, ParseNode* partition_list_node, ParseNode* subpart_node, share::schema::ObTableSchema& table_schema, bool& force_template) { int ret = OB_SUCCESS; share::schema::ObPartitionFuncType partition_func_type = share::schema::PARTITION_FUNC_TYPE_HASH; ObString func_expr_name; common::ObSEArray part_func_exprs; table_schema.set_part_level(share::schema::PARTITION_LEVEL_TWO); force_template = false; ObSqlString part_str; if (OB_ISNULL(stmt) || OB_ISNULL(part_node) || OB_ISNULL(subpart_node)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "get unexpected null", K(ret), K(stmt), K(part_node), K(subpart_node)); } else if (is_range_type_partition(subpart_node->type_)) { // range subpartition if (OB_FAIL(resolve_range_partition_basic_infos( subpart_node, true, table_schema, partition_func_type, func_expr_name, part_func_exprs))) { SQL_RESV_LOG(WARN, "failed to resolve range partition basic infos", K(ret)); } else if (OB_FAIL(stmt->get_subpart_fun_exprs().assign(part_func_exprs))) { SQL_RESV_LOG(WARN, "failed to assign range fun exprs", K(ret)); } } else if (is_list_type_partition(subpart_node->type_)) { // list subpartition if (OB_FAIL(resolve_list_partition_basic_infos( subpart_node, true, table_schema, partition_func_type, func_expr_name, part_func_exprs))) { SQL_RESV_LOG(WARN, "failed to resolve list partition basic infos", K(ret)); } else if (OB_FAIL(stmt->get_subpart_fun_exprs().assign(part_func_exprs))) { SQL_RESV_LOG(WARN, "failed to assign range fun exprs", K(ret)); } } else if (is_hash_type_partition(subpart_node->type_)) { /** * create table t1 (c1 int, c2 int) partition by range (c1) * subpartition by hash (c2) subpartitions 3 * ( * partition p0 values less than (100), * partition p1 values less than (200) * ); * create table t2 (c1 int, c2 int) partition by range (c1) * subpartition by hash (c2) subpartitions 3 * ( * partition p0 values less than (100) * ( * subpartition p0_h1, * subpartition p0_h2 * ), * partition p1 values less than (200) * ); */ if (NULL != partition_list_node) { bool has_def_subpart = false; for (int64_t i = 0; OB_SUCC(ret) && !has_def_subpart && i < partition_list_node->num_child_; ++i) { if (OB_ISNULL(partition_list_node->children_[i])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } else if (NULL != partition_list_node->children_[i]->children_[ELEMENT_SUBPARTITION_NODE]) { has_def_subpart = true; } } if (OB_SUCC(ret) && !has_def_subpart) { force_template = true; } } else { // auto set templated secondary partitions force_template = true; } if (OB_SUCC(ret) && !force_template) { if (OB_FAIL(resolve_hash_or_key_partition_basic_infos( subpart_node, true, table_schema, partition_func_type, func_expr_name, part_str))) { SQL_RESV_LOG(WARN, "failed to resolve hash or key parititon basic infos", K(ret)); } else if (NULL != subpart_node->children_[HASH_PARTITION_NUM_NODE]) { hash_subpart_num_ = subpart_node->children_[HASH_PARTITION_NUM_NODE]->value_; if (hash_subpart_num_ <= 0) { ret = common::OB_NO_PARTS_ERROR; LOG_USER_ERROR(OB_NO_PARTS_ERROR); } } else { hash_subpart_num_ = 1; } } } if (OB_SUCC(ret) && !force_template) { table_schema.get_sub_part_option().set_part_func_type(partition_func_type); if (OB_FAIL(table_schema.get_sub_part_option().set_part_expr(func_expr_name))) { SQL_RESV_LOG(WARN, "set partition express string failed", K(ret)); } } return ret; } int ObDDLResolver::resolve_subpartition_elements( ObPartitionedStmt* stmt, ParseNode* node, ObTableSchema& table_schema, ObPartition* partition, bool in_tablegroup) { int ret = OB_SUCCESS; ObPartitionFuncType subpart_type = table_schema.get_sub_part_option().get_part_func_type(); int64_t max_used_subpart_id = -1; if (OB_ISNULL(partition)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } else if (FALSE_IT(max_used_subpart_id = partition->get_max_used_sub_part_id())) { } else if (OB_ISNULL(node)) { if (!is_hash_like_part(subpart_type)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } else if (hash_subpart_num_ < 1) { ret = OB_INVALID_ARGUMENT; LOG_WARN("default subpart num not specified", K(ret), K(hash_subpart_num_)); } else if (OB_FAIL( generate_default_hash_subpart(hash_subpart_num_, max_used_subpart_id, table_schema, partition))) { LOG_WARN("failed to generate default hash subpart", K(ret)); } } else if ((is_hash_like_part(subpart_type) && node->type_ != T_HASH_SUBPARTITION_LIST) || (is_range_part(subpart_type) && node->type_ != T_RANGE_SUBPARTITION_LIST) || (is_list_part(subpart_type) && node->type_ != T_LIST_SUBPARTITION_LIST)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("subpartition define is not match declare", K(ret), K(subpart_type), K(node->type_)); } else if (T_HASH_SUBPARTITION_LIST == node->type_) { if (OB_FAIL(resolve_hash_subpartition_elements(stmt, node, table_schema, partition, max_used_subpart_id))) { LOG_WARN("failed to resolve hash subpartition elements", K(ret)); } } else if (T_RANGE_SUBPARTITION_LIST == node->type_) { ObDDLStmt::array_t range_value_exprs; if (OB_FAIL(resolve_range_subpartition_elements(stmt, node, table_schema, partition, subpart_type, stmt->get_subpart_fun_exprs(), range_value_exprs, max_used_subpart_id, in_tablegroup))) { LOG_WARN("failed to resolve hash subpartition elements", K(ret)); } else if (OB_FAIL(stmt->get_individual_subpart_values_exprs().push_back(range_value_exprs))) { LOG_WARN("failed to push back range value exprs"); } } else if (T_LIST_SUBPARTITION_LIST == node->type_) { ObDDLStmt::array_t list_value_exprs; if (OB_FAIL(resolve_list_subpartition_elements(stmt, node, table_schema, partition, subpart_type, stmt->get_subpart_fun_exprs(), list_value_exprs, max_used_subpart_id, in_tablegroup))) { LOG_WARN("failed to resolve hash subpartition elements", K(ret)); } else if (OB_FAIL(stmt->get_individual_subpart_values_exprs().push_back(list_value_exprs))) { LOG_WARN("failed to push back range value exprs"); } } if (OB_SUCC(ret)) { if (OB_FAIL(check_max_used_subpart_id_valid(table_schema, *partition, max_used_subpart_id))) { LOG_WARN("faield to check max used subpart id", K(ret)); } else { partition->set_max_used_sub_part_id(max_used_subpart_id); } } return ret; } int ObDDLResolver::resolve_partition_hash_or_key( ObPartitionedStmt* stmt, ParseNode* node, const bool is_subpartition, ObTableSchema& table_schema) { int ret = common::OB_SUCCESS; ObString partition_expr; ObPartitionFuncType partition_func_type = PARTITION_FUNC_TYPE_HASH; int64_t partition_num = 0; ObPartitionOption* partition_option = NULL; if (OB_ISNULL(node) || OB_ISNULL(node->children_) || !is_hash_type_partition(node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected node", K(ret), K(node)); } else if (is_subpartition && NULL != node->children_[HASH_SUBPARTITIOPPN_NODE]) { ret = OB_ERR_UNEXPECTED; LOG_WARN("subpartition cannot has another subpartition", K(ret)); } else if (is_subpartition) { partition_option = &(table_schema.get_sub_part_option()); table_schema.set_part_level(share::schema::PARTITION_LEVEL_TWO); } else { partition_option = &(table_schema.get_part_option()); table_schema.set_part_level(share::schema::PARTITION_LEVEL_ONE); } if (OB_SUCC(ret)) { if (NULL != node->children_[HASH_SUBPARTITIOPPN_NODE]) { bool force_template = false; if (NULL != node->children_[HASH_SUBPARTITIOPPN_NODE]->children_[HASH_TEMPLATE_MARK]) { table_schema.set_is_sub_part_template(true); } else if (OB_FAIL(resolve_individual_subpartition(stmt, node, node->children_[HASH_PARTITION_LIST_NODE], node->children_[HASH_SUBPARTITIOPPN_NODE], table_schema, force_template))) { SQL_RESV_LOG(WARN, "failed to resolve individual subpartition", K(ret)); } else if (force_template) { table_schema.set_is_sub_part_template(true); } else { table_schema.set_is_sub_part_template(false); } } } // 1. resolve partition type, partition keys, partition expr if (OB_SUCC(ret)) { ObSqlString part_str; if (OB_FAIL(resolve_hash_or_key_partition_basic_infos( node, is_subpartition, table_schema, partition_func_type, partition_expr, part_str))) { SQL_RESV_LOG(WARN, "failed to resolve hash or key parititon basic infos", K(ret)); } else { partition_option->set_part_func_type(partition_func_type); if (OB_FAIL(partition_option->set_part_expr(partition_expr))) { SQL_RESV_LOG(WARN, "set partition express string failed", K(ret)); } } } // 2. process part defination if (OB_SUCC(ret)) { if (NULL != node->children_[HASH_PARTITION_NUM_NODE]) { partition_num = node->children_[HASH_PARTITION_NUM_NODE]->value_; } else if (NULL == node->children_[HASH_PARTITION_LIST_NODE]) { partition_num = 1; } else { partition_num = 1; } if (NULL != node->children_[HASH_PARTITION_NUM_NODE] && NULL != node->children_[HASH_PARTITION_LIST_NODE]) { if (is_oracle_mode()) { ret = OB_ERR_SPECIFIY_PARTITION_DESCRIPTION; } else if (partition_num != node->children_[HASH_PARTITION_LIST_NODE]->num_child_) { ret = OB_ERR_PARSE_PARTITION_RANGE; } } if (OB_FAIL(ret)) { } else if (partition_num <= 0) { ret = common::OB_NO_PARTS_ERROR; LOG_USER_ERROR(OB_NO_PARTS_ERROR); } else if (!common::is_virtual_table(table_id_) && partition_num > (lib::is_oracle_mode() ? common::OB_MAX_PARTITION_NUM_ORACLE : common::OB_MAX_PARTITION_NUM_MYSQL)) { ret = common::OB_TOO_MANY_PARTITIONS_ERROR; } else if (is_subpartition) { if (NULL != node->children_[HASH_PARTITION_LIST_NODE]) { if (OB_FAIL(resolve_hash_subpartition_elements( stmt, node->children_[HASH_PARTITION_LIST_NODE], table_schema, NULL /* dummy partition*/))) { SQL_RESV_LOG(WARN, "failed to resolve hash subpartition elements", K(ret)); } } else { if (OB_FAIL(generate_default_hash_subpart(partition_num, -1, // max_used_supart_id table_schema, NULL))) { // dummy partition LOG_WARN("failed to generate default hash part", K(ret)); } } } else { if (NULL != node->children_[HASH_PARTITION_LIST_NODE]) { if (OB_FAIL(resolve_hash_partition_elements( stmt, node->children_[HASH_PARTITION_LIST_NODE], table_schema, max_used_part_id_))) { LOG_WARN("failed to resolve hash partition elements", K(ret)); } } else { if (OB_FAIL(generate_default_hash_part(partition_num, max_used_part_id_, table_schema))) { LOG_WARN("failed to generate default hash part", K(ret)); } if (!table_schema.is_sub_part_template()) { if (table_schema.is_hash_like_subpart()) { // partition by hash(c1) subpartition by hash(c2) subpartitions 3 partitions 3 for (int64_t i = 0; OB_SUCC(ret) && i < table_schema.get_first_part_num(); ++i) { if (OB_FAIL(resolve_subpartition_elements(stmt, NULL, // dummy node table_schema, table_schema.get_part_array()[i], false))) { LOG_WARN("failed to resolve subpartition elements", K(ret)); } } } else { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid partition define", K(ret)); } } } } } if (OB_SUCC(ret)) { if (NULL != node->children_[HASH_SUBPARTITIOPPN_NODE] && table_schema.is_sub_part_template()) { if (OB_FAIL(resolve_subpartition_option(stmt, node->children_[HASH_SUBPARTITIOPPN_NODE], table_schema))) { SQL_RESV_LOG(WARN, "failed to resolve subpartition", K(ret)); } } } return ret; } int ObDDLResolver::resolve_partition_range( ObPartitionedStmt* stmt, ParseNode* node, const bool is_subpartition, ObTableSchema& table_schema) { int ret = OB_SUCCESS; ObString func_expr_name; int64_t partition_num = 0; share::schema::ObPartitionFuncType part_func_type = share::schema::PARTITION_FUNC_TYPE_RANGE; common::ObSEArray part_func_exprs; common::ObSEArray range_values_exprs; share::schema::ObPartitionOption* partition_option = NULL; if (OB_ISNULL(stmt) || OB_ISNULL(node) || OB_ISNULL(node->children_) || OB_ISNULL(node->children_[RANGE_ELEMENTS_NODE])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "get unexpected null", K(ret), K(stmt), K(node)); } else if (!is_range_type_partition(node->type_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "get unexpected partition type", K(ret), K(node->type_)); } else if (is_subpartition) { partition_option = &(table_schema.get_sub_part_option()); table_schema.set_part_level(share::schema::PARTITION_LEVEL_TWO); } else { partition_option = &(table_schema.get_part_option()); table_schema.set_part_level(share::schema::PARTITION_LEVEL_ONE); } if (OB_SUCC(ret)) { if (NULL != node->children_[RANGE_SUBPARTITIOPPN_NODE]) { bool force_template = false; if (NULL != node->children_[RANGE_SUBPARTITIOPPN_NODE]->children_[RANGE_TEMPLATE_MARK]) { table_schema.set_is_sub_part_template(true); } else if (OB_FAIL(resolve_individual_subpartition(stmt, node, node->children_[RANGE_ELEMENTS_NODE], node->children_[RANGE_SUBPARTITIOPPN_NODE], table_schema, force_template))) { SQL_RESV_LOG(WARN, "failed to resolve individual subpartition", K(ret)); } else if (force_template) { table_schema.set_is_sub_part_template(true); } else { table_schema.set_is_sub_part_template(false); } } } // 1. resolve partition type, partition keys, partition expr if (OB_SUCC(ret)) { if (OB_FAIL(resolve_range_partition_basic_infos( node, is_subpartition, table_schema, part_func_type, func_expr_name, part_func_exprs))) { SQL_RESV_LOG(WARN, "failed to resolve range partition basic infos", K(ret)); } else if (OB_FAIL(partition_option->set_part_expr(func_expr_name))) { SQL_RESV_LOG(WARN, "set partition express string failed", K(ret)); } else { partition_option->set_part_func_type(part_func_type); } } // 2. resolve range partition define if (OB_SUCC(ret)) { if (NULL != node->children_[RANGE_PARTITION_NUM_NODE]) { partition_num = node->children_[RANGE_PARTITION_NUM_NODE]->value_; if (partition_num != node->children_[RANGE_ELEMENTS_NODE]->num_child_) { ret = OB_ERR_PARSE_PARTITION_RANGE; } } else { partition_num = node->children_[RANGE_ELEMENTS_NODE]->num_child_; } partition_option->set_part_num(partition_num); if (OB_SUCC(ret)) { if (OB_FAIL(check_partition_name_duplicate(node->children_[RANGE_ELEMENTS_NODE], lib::is_oracle_mode()))) { SQL_RESV_LOG(WARN, "duplicate partition name", K(ret)); } else if (is_subpartition) { if (OB_FAIL(resolve_range_subpartition_elements(stmt, node->children_[RANGE_ELEMENTS_NODE], table_schema, NULL, // dummy partition part_func_type, part_func_exprs, range_values_exprs, -1 /* max_used_subpart_id */))) { SQL_RESV_LOG(WARN, "resolve reange partition elements fail", K(ret)); } } else { if (OB_FAIL(resolve_range_partition_elements(stmt, node->children_[RANGE_ELEMENTS_NODE], table_schema, part_func_type, part_func_exprs, range_values_exprs, max_used_part_id_))) { SQL_RESV_LOG(WARN, "resolve reange partition elements fail", K(ret)); } } } } if (OB_SUCC(ret)) { if (NULL != node->children_[RANGE_SUBPARTITIOPPN_NODE] && table_schema.is_sub_part_template()) { if (OB_FAIL(resolve_subpartition_option(stmt, node->children_[RANGE_SUBPARTITIOPPN_NODE], table_schema))) { SQL_RESV_LOG(WARN, "failed to resolve subpartition", K(ret)); } } } if (OB_SUCC(ret)) { if (is_subpartition) { if (OB_FAIL(stmt->get_subpart_fun_exprs().assign(part_func_exprs))) { SQL_RESV_LOG(WARN, "failed to assign range fun exprs", K(ret)); } else if (OB_FAIL(stmt->get_template_subpart_values_exprs().assign(range_values_exprs))) { SQL_RESV_LOG(WARN, "failed to assign range values exprs", K(ret)); } } else { if (OB_FAIL(stmt->get_part_fun_exprs().assign(part_func_exprs))) { SQL_RESV_LOG(WARN, "failed to assign range fun exprs", K(ret)); } else if (OB_FAIL(stmt->get_part_values_exprs().assign(range_values_exprs))) { SQL_RESV_LOG(WARN, "failed to assign range values exprs", K(ret)); } } SQL_RESV_LOG(DEBUG, "succ to resolve_partition_range", KPC(stmt), K(part_func_exprs), K(range_values_exprs)); } return ret; } int ObDDLResolver::resolve_partition_list( ObPartitionedStmt* stmt, ParseNode* node, const bool is_subpartition, ObTableSchema& table_schema) { int ret = OB_SUCCESS; ObString func_expr_name; ObPartitionOption* partition_option = NULL; int64_t partition_num = 0; ObPartitionFuncType part_func_type = PARTITION_FUNC_TYPE_LIST; common::ObSEArray part_func_exprs; ObDDLStmt::array_t list_values_exprs; if (OB_ISNULL(stmt) || OB_ISNULL(node) || OB_ISNULL(node->children_) || OB_ISNULL(node->children_[LIST_ELEMENTS_NODE])) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "get unexpected null", K(ret), K(stmt), K(node)); } else if (!is_list_type_partition(node->type_)) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "get unexpected partition type", K(ret), K(node->type_)); } else if (is_subpartition) { partition_option = &(table_schema.get_sub_part_option()); table_schema.set_part_level(share::schema::PARTITION_LEVEL_TWO); } else { partition_option = &(table_schema.get_part_option()); table_schema.set_part_level(share::schema::PARTITION_LEVEL_ONE); } if (OB_SUCC(ret)) { if (NULL != node->children_[LIST_SUBPARTITIOPPN_NODE]) { bool force_template = false; if (NULL != node->children_[LIST_SUBPARTITIOPPN_NODE]->children_[LIST_TEMPLATE_MARK]) { table_schema.set_is_sub_part_template(true); } else if (OB_FAIL(resolve_individual_subpartition(stmt, node, node->children_[LIST_ELEMENTS_NODE], node->children_[LIST_SUBPARTITIOPPN_NODE], table_schema, force_template))) { SQL_RESV_LOG(WARN, "failed to resolve individual subpartition", K(ret)); } else if (force_template) { table_schema.set_is_sub_part_template(true); } else { table_schema.set_is_sub_part_template(false); } } } // 1. resolve partition type, partition keys, partition expr if (OB_SUCC(ret)) { if (OB_FAIL(resolve_list_partition_basic_infos( node, is_subpartition, table_schema, part_func_type, func_expr_name, part_func_exprs))) { SQL_RESV_LOG(WARN, "failed to resolve range partition basic infos", K(ret)); } else if (OB_FAIL(partition_option->set_part_expr(func_expr_name))) { SQL_RESV_LOG(WARN, "set partition express string failed", K(ret)); } else { partition_option->set_part_func_type(part_func_type); } } if (OB_SUCC(ret)) { if (!OB_ISNULL(node->children_[LIST_PARTITION_NUM_NODE])) { partition_num = node->children_[LIST_PARTITION_NUM_NODE]->value_; if (partition_num != node->children_[LIST_ELEMENTS_NODE]->num_child_) { ret = common::OB_ERR_PARSE_PARTITION_LIST; } } else { partition_num = node->children_[LIST_ELEMENTS_NODE]->num_child_; } partition_option->set_part_num(partition_num); if (OB_SUCC(ret)) { if (OB_FAIL(check_partition_name_duplicate(node->children_[LIST_ELEMENTS_NODE], lib::is_oracle_mode()))) { SQL_RESV_LOG(WARN, "duplicate partition name", K(ret)); } else if (is_subpartition) { if (OB_FAIL(resolve_list_subpartition_elements(stmt, node->children_[LIST_ELEMENTS_NODE], table_schema, NULL, // dummy partition part_func_type, part_func_exprs, list_values_exprs, -1))) { SQL_RESV_LOG(WARN, "resolve reange partition elements fail", K(ret)); } } else { if (OB_FAIL(resolve_list_partition_elements(stmt, node->children_[LIST_ELEMENTS_NODE], table_schema, part_func_type, part_func_exprs, list_values_exprs, max_used_part_id_))) { SQL_RESV_LOG(WARN, "resolve reange partition elements fail", K(ret)); } } } } if (OB_SUCC(ret)) { if (NULL != node->children_[LIST_SUBPARTITIOPPN_NODE] && table_schema.is_sub_part_template()) { if (OB_FAIL(resolve_subpartition_option(stmt, node->children_[LIST_SUBPARTITIOPPN_NODE], table_schema))) { SQL_RESV_LOG(WARN, "failed to resolve subpartition", K(ret)); } } } if (OB_SUCC(ret)) { if (is_subpartition) { if (OB_FAIL(stmt->get_subpart_fun_exprs().assign(part_func_exprs))) { SQL_RESV_LOG(WARN, "failed to assign range fun exprs", K(ret)); } else if (OB_FAIL(stmt->get_template_subpart_values_exprs().assign(list_values_exprs))) { SQL_RESV_LOG(WARN, "failed to assign range values exprs", K(ret)); } } else { if (OB_FAIL(stmt->get_part_fun_exprs().assign(part_func_exprs))) { SQL_RESV_LOG(WARN, "failed to assign range fun exprs", K(ret)); } else if (OB_FAIL(stmt->get_part_values_exprs().assign(list_values_exprs))) { SQL_RESV_LOG(WARN, "failed to assign range values exprs", K(ret)); } } SQL_RESV_LOG(DEBUG, "succ to resolve_partition_list", KPC(stmt), K(part_func_exprs), K(list_values_exprs)); } return ret; } int ObDDLResolver::resolve_hash_partition_elements( ObPartitionedStmt* stmt, ParseNode* node, ObTableSchema& table_schema, int64_t max_used_part_id) { int ret = OB_SUCCESS; ParseNode* element_node = NULL; if (OB_ISNULL(node) || OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(node), K(stmt)); } else if (max_used_part_id >= 0 && max_used_part_id < node->num_child_ - 1) { ret = OB_INVALID_ARGUMENT; LOG_WARN("max_used_part_id is invalid", K(ret), K(max_used_part_id), K(node->num_child_)); } else { int64_t partition_num = node->num_child_; ObPartition partition; bool init_specified = false; // ignore alter_table with part_id for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; ++i) { partition.reset(); ObString partition_name; int64_t part_id = OB_INVALID_ID; bool current_spec = false; // 1. check partition name if (OB_ISNULL(element_node = node->children_[i])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(element_node)); } else if (OB_FAIL( resolve_partition_name(element_node->children_[PARTITION_NAME_NODE], partition_name, partition))) { LOG_WARN("failed to resolve partition name", K(ret)); } else if (OB_FAIL(resolve_partition_part_id(element_node->children_[PART_ID_NODE], stmt, max_used_part_id, partition_num, i, part_id, current_spec))) { LOG_WARN("failed to resolve partition part id", K(ret)); } else { // all partition should both specified part id or not if (0 == i) { init_specified = current_spec; } else if (current_spec != init_specified) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Should speicify part id for all parts", K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "partition id which should include either none or all partition ids"); } } // add hash partition elements to table schema if (OB_SUCC(ret)) { partition.set_part_id(part_id); partition.set_part_idx(i); if (OB_FAIL(table_schema.check_part_id(partition))) { LOG_WARN("failed to check part id", K(ret)); } else if (OB_FAIL(table_schema.add_partition(partition))) { LOG_WARN("failed to add partition", K(ret)); } else if (table_schema.is_sub_part_template() && OB_NOT_NULL(element_node->children_[ELEMENT_SUBPARTITION_NODE])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("individual subpartition with sub part template", K(ret)); } else if (!table_schema.is_sub_part_template()) { // resolve non template ObPartition* cur_partition = table_schema.get_part_array()[i]; if (OB_ISNULL(cur_partition)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } else if (OB_FAIL(resolve_subpartition_elements(stmt, element_node->children_[ELEMENT_SUBPARTITION_NODE], table_schema, cur_partition, false))) { LOG_WARN("failed to resolve subpartition elements", K(ret)); } } } } if (OB_SUCC(ret)) { table_schema.get_part_option().set_part_num(partition_num); } } return ret; } int ObDDLResolver::resolve_hash_subpartition_elements(ObPartitionedStmt* stmt, ParseNode* node, ObTableSchema& table_schema, ObPartition* partition, int64_t max_used_subpart_id) { int ret = OB_SUCCESS; ParseNode* element_node = NULL; const bool is_template = table_schema.is_sub_part_template(); if (OB_ISNULL(node) || OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(node), K(stmt)); } else if (!is_template && OB_ISNULL(partition)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition is null while not sub part template", K(ret)); } else if (max_used_subpart_id >= 0 && max_used_subpart_id < node->num_child_ - 1) { ret = OB_INVALID_ARGUMENT; LOG_WARN("max_used_subpart_id is invalid", K(ret), K(max_used_subpart_id), K(node->num_child_)); } else { const int64_t part_id = is_template ? ObSubPartition::TEMPLATE_PART_ID : partition->get_part_id(); int64_t partition_num = node->num_child_; ObSubPartition subpartition; bool init_specified = false; for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; ++i) { subpartition.reset(); ObString partition_name; int64_t subpart_id = OB_INVALID_ID; bool current_spec = false; // 1. check partition name if (OB_ISNULL(element_node = node->children_[i])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } else if (OB_FAIL(resolve_partition_name( element_node->children_[PARTITION_NAME_NODE], partition_name, subpartition))) { LOG_WARN("failed to resolve partition name", K(ret)); } else if (OB_FAIL(resolve_partition_part_id(element_node->children_[PART_ID_NODE], stmt, max_used_subpart_id, partition_num, i, subpart_id, current_spec))) { LOG_WARN("failed to resolve partition part id", K(ret)); } else { // all partition should both specified part id or not if (0 == i) { init_specified = current_spec; } else if (init_specified != current_spec) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Should speicify part id for all parts", K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "partition id which should include either none or all partition ids"); } } // add hash subpartition elements to table schema or partition if (OB_SUCC(ret)) { subpartition.set_part_id(part_id); subpartition.set_sub_part_id(subpart_id); subpartition.set_sub_part_idx(i); if (is_template) { if (OB_FAIL(table_schema.add_def_subpartition(subpartition))) { LOG_WARN("failed to add partition", K(ret)); } } else if (OB_FAIL(partition->add_partition(subpartition))) { LOG_WARN("failed to add partition", K(ret)); } } } if (OB_SUCC(ret)) { if (is_template) { table_schema.get_sub_part_option().set_part_num(partition_num); } else { partition->set_sub_part_num(partition_num); } } } return ret; } int ObDDLResolver::resolve_range_partition_elements(ObPartitionedStmt* stmt, ParseNode* node, ObTableSchema& table_schema, const ObPartitionFuncType part_type, const ObIArray& part_func_exprs, ObIArray& range_value_exprs, int64_t max_used_part_id, const bool& in_tablegroup) { int ret = OB_SUCCESS; ParseNode* element_node = NULL; ParseNode* expr_list_node = NULL; if (OB_ISNULL(node) || OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null or stmt is null", K(ret), K(node), K(stmt)); } else if (max_used_part_id >= 0 && max_used_part_id < node->num_child_ - 1) { ret = OB_INVALID_ARGUMENT; LOG_WARN("max_used_part_id is invalid", K(ret), K(max_used_part_id), K(node->num_child_)); } else { int64_t partition_num = node->num_child_; ObPartition partition; bool init_specified = false; // ignore alter_table with part_id for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; ++i) { partition.reset(); ObString partition_name; int64_t part_id = OB_INVALID_ID; bool current_spec = false; if (OB_ISNULL(element_node = node->children_[i]) || OB_ISNULL(expr_list_node = element_node->children_[PARTITION_ELEMENT_NODE]) || OB_UNLIKELY(T_EXPR_LIST != expr_list_node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected node", K(ret), K(element_node), K(expr_list_node)); } else if (part_func_exprs.count() != expr_list_node->num_child_) { ret = OB_ERR_PARTITION_COLUMN_LIST_ERROR; LOG_WARN("Inconsistency in usage of column lists for partitioning near", K(ret)); } else if (OB_FAIL( resolve_partition_name(element_node->children_[PARTITION_NAME_NODE], partition_name, partition))) { LOG_WARN("failed to resolve partition name", K(ret)); } else if (OB_FAIL(resolve_range_partition_value_node( *expr_list_node, partition_name, part_type, part_func_exprs, range_value_exprs, in_tablegroup))) { LOG_WARN("failed to resolve range partition value node", K(ret)); } else if (OB_FAIL(resolve_partition_part_id(element_node->children_[PART_ID_NODE], stmt, max_used_part_id, partition_num, i, part_id, current_spec))) { LOG_WARN("failed to resolve partition part id", K(ret)); } else { if (0 == i) { init_specified = current_spec; } else if (current_spec != init_specified) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Should speicify part id for all parts", K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "partition id which should include either none or all partition ids"); } } // add range partition elements to table schema if (OB_SUCC(ret)) { partition.set_part_id(part_id); if (OB_FAIL(table_schema.check_part_id(partition))) { LOG_WARN("failed to check part id", K(ret)); } else if (OB_FAIL(table_schema.add_partition(partition))) { LOG_WARN("failed to add partition", K(ret)); } else if (table_schema.is_sub_part_template() && OB_NOT_NULL(element_node->children_[ELEMENT_SUBPARTITION_NODE])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("individual subpartition with sub part template", K(ret)); } else if (!table_schema.is_sub_part_template()) { // resolve non template ObPartition* cur_partition = table_schema.get_part_array()[i]; if (OB_ISNULL(cur_partition)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } else if (OB_FAIL(resolve_subpartition_elements(stmt, element_node->children_[ELEMENT_SUBPARTITION_NODE], table_schema, cur_partition, false))) { LOG_WARN("failed to resolve subpartition elements", K(ret)); } } } } if (OB_SUCC(ret)) { table_schema.get_part_option().set_part_num(partition_num); } } return ret; } int ObDDLResolver::resolve_range_subpartition_elements(ObPartitionedStmt* stmt, ParseNode* node, ObTableSchema& table_schema, ObPartition* partition, const ObPartitionFuncType part_type, const ObIArray& part_func_exprs, ObIArray& range_value_exprs, int64_t max_used_subpart_id, const bool& in_tablegroup) { int ret = OB_SUCCESS; ParseNode* element_node = NULL; ParseNode* expr_list_node = NULL; const bool is_template = table_schema.is_sub_part_template(); if (OB_ISNULL(node) || OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null or stmt is null", K(ret), K(node), K(stmt)); } else if (!is_template && OB_ISNULL(partition)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition is null while not sub part template", K(ret)); } else if (max_used_subpart_id >= 0 && max_used_subpart_id < node->num_child_ - 1) { ret = OB_INVALID_ARGUMENT; LOG_WARN("max_used_subpart_id is invalid", K(ret), K(max_used_subpart_id), K(node->num_child_)); } else { int64_t partition_num = node->num_child_; ObSubPartition subpartition; bool init_specified = false; const int64_t part_id = is_template ? ObSubPartition::TEMPLATE_PART_ID : partition->get_part_id(); // ignore alter_table with part_id for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; ++i) { subpartition.reset(); ObString partition_name; int64_t subpart_id = OB_INVALID_ID; bool current_spec = false; if (OB_ISNULL(element_node = node->children_[i]) || OB_ISNULL(expr_list_node = element_node->children_[PARTITION_ELEMENT_NODE]) || OB_UNLIKELY(T_EXPR_LIST != expr_list_node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected node", K(ret), K(element_node), K(expr_list_node)); } else if (part_func_exprs.count() != expr_list_node->num_child_) { ret = OB_ERR_PARTITION_COLUMN_LIST_ERROR; LOG_WARN("Inconsistency in usage of column lists for partitioning near", K(ret)); } else if (OB_FAIL(resolve_partition_name( element_node->children_[PARTITION_NAME_NODE], partition_name, subpartition))) { LOG_WARN("failed to resolve partition name", K(ret)); } else if (OB_FAIL(resolve_range_partition_value_node( *expr_list_node, partition_name, part_type, part_func_exprs, range_value_exprs, in_tablegroup))) { LOG_WARN("failed to resolve range partition value node", K(ret)); } else if (OB_FAIL(resolve_partition_part_id(element_node->children_[PART_ID_NODE], stmt, max_used_subpart_id, partition_num, i, subpart_id, current_spec))) { LOG_WARN("failed to resolve partition part id", K(ret)); } else { if (0 == i) { init_specified = current_spec; } else if (current_spec != init_specified) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Should speicify part id for all parts", K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "partition id which should include either none or all partition ids"); } } // add range partition elements to table schema if (OB_SUCC(ret)) { subpartition.set_part_id(part_id); subpartition.set_sub_part_id(subpart_id); if (is_template) { if (OB_FAIL(table_schema.add_def_subpartition(subpartition))) { LOG_WARN("failed to add partition", K(ret)); } } else if (OB_FAIL(partition->add_partition(subpartition))) { LOG_WARN("failed to add partition", K(ret)); } } } if (OB_SUCC(ret)) { if (is_template) { table_schema.get_sub_part_option().set_part_num(partition_num); } else { partition->set_sub_part_num(partition_num); } } } return ret; } int ObDDLResolver::resolve_list_partition_elements(ObPartitionedStmt* stmt, ParseNode* node, ObTableSchema& table_schema, const ObPartitionFuncType part_type, const ObIArray& part_func_exprs, ObDDLStmt::array_t& list_value_exprs, int64_t max_used_part_id, const bool& in_tablegroup) { int ret = OB_SUCCESS; ParseNode* element_node = NULL; ParseNode* expr_list_node = NULL; if (OB_ISNULL(node) || OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(node), K(stmt)); } else if (max_used_part_id >= 0 && max_used_part_id < node->num_child_ - 1) { ret = OB_INVALID_ARGUMENT; LOG_WARN("max_used_part_id is invalid", K(ret), K(max_used_part_id), K(node->num_child_)); } else { int64_t partition_num = node->num_child_; ObPartition partition; bool init_specified = false; for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; ++i) { partition.reset(); ObString partition_name; int64_t part_id = OB_INVALID_PARTITION_ID; bool current_spec = false; if (OB_ISNULL(element_node = node->children_[i]) || OB_ISNULL(expr_list_node = element_node->children_[PARTITION_ELEMENT_NODE])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpect node", K(ret), K(element_node), K(expr_list_node)); } else if (T_EXPR_LIST != expr_list_node->type_ && T_DEFAULT != expr_list_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected node type", K(ret), K(expr_list_node->type_)); } else if (OB_FAIL( resolve_partition_name(element_node->children_[PARTITION_NAME_NODE], partition_name, partition))) { LOG_WARN("failed to resolve partition name", K(ret)); } else if (OB_FAIL(resolve_list_partition_value_node( *expr_list_node, partition_name, part_type, part_func_exprs, list_value_exprs, in_tablegroup))) { LOG_WARN("failed to resolve list partiton value node", K(ret)); } else if (OB_FAIL(resolve_partition_part_id(element_node->children_[PART_ID_NODE], stmt, max_used_part_id, partition_num, i, part_id, current_spec))) { LOG_WARN("failed to resolve partition part id", K(ret)); } else { if (0 == i) { init_specified = current_spec; } else if (current_spec != init_specified) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Should speicify part id for all parts", K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "partition id which should include either none or all partition ids"); } } // add list partition elements to table schema if (OB_SUCC(ret)) { partition.set_part_id(part_id); if (OB_FAIL(table_schema.check_part_id(partition))) { LOG_WARN("failed to check part id", K(ret)); } else if (OB_FAIL(table_schema.add_partition(partition))) { LOG_WARN("failed to add partition", K(ret)); } else if (table_schema.is_sub_part_template() && OB_NOT_NULL(element_node->children_[ELEMENT_SUBPARTITION_NODE])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("individual subpartition with sub part template", K(ret)); } else if (!table_schema.is_sub_part_template()) { // resolve non template ObPartition* cur_partition = table_schema.get_part_array()[i]; if (OB_ISNULL(cur_partition)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } else if (OB_FAIL(resolve_subpartition_elements(stmt, element_node->children_[ELEMENT_SUBPARTITION_NODE], table_schema, cur_partition, false))) { LOG_WARN("failed to resolve subpartition elements", K(ret)); } } } } if (OB_SUCC(ret)) { table_schema.get_part_option().set_part_num(partition_num); } } return ret; } int ObDDLResolver::resolve_list_subpartition_elements(ObPartitionedStmt* stmt, ParseNode* node, ObTableSchema& table_schema, ObPartition* partition, const ObPartitionFuncType part_type, const ObIArray& part_func_exprs, ObDDLStmt::array_t& list_value_exprs, int64_t max_used_subpart_id, const bool& in_tablegroup) { int ret = OB_SUCCESS; ParseNode* element_node = NULL; ParseNode* expr_list_node = NULL; const bool is_template = table_schema.is_sub_part_template(); if (OB_ISNULL(node) || OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null or stmt is null", K(ret), K(node), K(stmt_)); } else if (max_used_subpart_id >= 0 && max_used_subpart_id < node->num_child_ - 1) { ret = OB_INVALID_ARGUMENT; LOG_WARN("max_used_subpart_id is invalid", K(ret), K(max_used_subpart_id), K(node->num_child_)); } else { int64_t partition_num = node->num_child_; ObSubPartition subpartition; const int64_t part_id = is_template ? ObSubPartition::TEMPLATE_PART_ID : partition->get_part_id(); bool init_specified = false; for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; i++) { subpartition.reset(); ObString partition_name; int64_t subpart_id = OB_INVALID_ID; bool current_spec = false; if (OB_ISNULL(element_node = node->children_[i]) || OB_ISNULL(expr_list_node = element_node->children_[PARTITION_ELEMENT_NODE])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpect node", K(ret), K(element_node), K(expr_list_node)); } else if (T_EXPR_LIST != expr_list_node->type_ && T_DEFAULT != expr_list_node->type_) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected node type", K(ret), K(expr_list_node->type_)); } else if (OB_FAIL(resolve_partition_name( element_node->children_[PARTITION_NAME_NODE], partition_name, subpartition))) { LOG_WARN("failed to resolve partition name", K(ret)); } else if (OB_FAIL(resolve_list_partition_value_node( *expr_list_node, partition_name, part_type, part_func_exprs, list_value_exprs, in_tablegroup))) { LOG_WARN("failed to resolve list partiton value node", K(ret)); } else if (OB_FAIL(resolve_partition_part_id(element_node->children_[PART_ID_NODE], stmt, max_used_subpart_id, partition_num, i, subpart_id, current_spec))) { LOG_WARN("failed to resolve partition part id", K(ret)); } else { if (0 == i) { init_specified = current_spec; } else if (current_spec != init_specified) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Should speicify part id for all parts", K(ret)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "partition id which should include either none or all partition ids"); } } // add list partition elements to table schema if (OB_SUCC(ret)) { subpartition.set_part_id(part_id); subpartition.set_sub_part_id(subpart_id); if (is_template) { if (OB_FAIL(table_schema.add_def_subpartition(subpartition))) { LOG_WARN("failed to add partition", K(ret)); } } else if (OB_FAIL(partition->add_partition(subpartition))) { LOG_WARN("failed to add partition", K(ret)); } } } if (OB_SUCC(ret)) { if (is_template) { table_schema.get_sub_part_option().set_part_num(partition_num); } else { partition->set_sub_part_num(partition_num); } } } return ret; } int ObDDLResolver::resolve_range_partition_value_node(ParseNode& expr_list_node, const ObString& partition_name, const ObPartitionFuncType part_type, const ObIArray& part_func_exprs, ObIArray& range_value_exprs, const bool& in_tablegroup) { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < expr_list_node.num_child_; ++i) { if (OB_ISNULL(expr_list_node.children_[i])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get null node", K(ret)); } else if (T_NULL == expr_list_node.children_[i]->type_) { ret = OB_EER_NULL_IN_VALUES_LESS_THAN; LOG_WARN("null value is not allowed in less than", K(ret)); } else if (T_MAXVALUE == expr_list_node.children_[i]->type_) { ObRawExpr* maxvalue_expr = NULL; ObConstRawExpr* c_expr = NULL; c_expr = (ObConstRawExpr*)allocator_->alloc(sizeof(ObConstRawExpr)); if (OB_ISNULL(c_expr)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory", K(ret)); } else { c_expr = new (c_expr) ObConstRawExpr(); maxvalue_expr = c_expr; maxvalue_expr->set_data_type(common::ObMaxType); if (OB_FAIL(range_value_exprs.push_back(maxvalue_expr))) { LOG_WARN("array push back fail", K(ret)); } } } else if (T_EXPR_LIST != expr_list_node.children_[i]->type_) { ObRawExpr* part_value_expr = NULL; ObRawExpr* part_func_expr = NULL; if (OB_FAIL(part_func_exprs.at(i, part_func_expr))) { LOG_WARN("get part expr failed", K(i), "size", part_func_exprs.count(), K(ret)); } else if (OB_ISNULL(part_func_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("part_func_expr is invalid", K(ret)); } else if (OB_FAIL(ObResolverUtils::resolve_partition_range_value_expr(params_, *(expr_list_node.children_[i]), partition_name, part_type, *part_func_expr, part_value_expr, in_tablegroup))) { LOG_WARN("resolve partition expr failed", K(ret)); } else if (OB_FAIL(range_value_exprs.push_back(part_value_expr))) { LOG_WARN("array push back fail", K(ret)); } } else { ret = OB_ERR_PARSER_SYNTAX; LOG_WARN("syntax error, expect single expr while expr list got", K(ret)); } } return ret; } int ObDDLResolver::resolve_list_partition_value_node(ParseNode& expr_list_node, const ObString& partition_name, const ObPartitionFuncType part_type, const ObIArray& part_func_exprs, ObDDLStmt::array_t& list_value_exprs, const bool& in_tablegroup) { int ret = OB_SUCCESS; ObOpRawExpr* row_expr = NULL; if (OB_ISNULL(params_.expr_factory_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } else if (OB_FAIL(params_.expr_factory_->create_raw_expr(T_OP_ROW, row_expr))) { LOG_WARN("failed to create raw expr", K(ret)); } else if (OB_ISNULL(row_expr)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allcoate memory", K(ret)); } else if (T_DEFAULT == expr_list_node.type_) { ObRawExpr* maxvalue_expr = NULL; ObConstRawExpr* c_expr = NULL; c_expr = (ObConstRawExpr*)allocator_->alloc(sizeof(ObConstRawExpr)); if (OB_ISNULL(c_expr)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allcoate memory", K(ret)); } else { c_expr = new (c_expr) ObConstRawExpr(); maxvalue_expr = c_expr; maxvalue_expr->set_data_type(common::ObMaxType); if (OB_FAIL(row_expr->add_param_expr(maxvalue_expr))) { LOG_WARN("failed add param expr", K(ret)); } } } else { ObSEArray part_value_exprs; bool is_all_expr_list = false; if (expr_list_node.num_child_ > 0) { is_all_expr_list = (expr_list_node.children_[0]->type_ == T_EXPR_LIST); } for (int64_t i = 0; OB_SUCC(ret) && i < expr_list_node.num_child_; ++i) { part_value_exprs.reset(); if ((is_all_expr_list && expr_list_node.children_[i]->type_ != T_EXPR_LIST) || (!is_all_expr_list && expr_list_node.children_[i]->type_ == T_EXPR_LIST)) { ret = OB_ERR_PARTITION_COLUMN_LIST_ERROR; LOG_WARN("Inconsistency in usage of column lists for partitioning near", K(ret)); } else if (OB_ISNULL(expr_list_node.children_[i])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("node is null", K(ret)); } else if (OB_FAIL(ObResolverUtils::resolve_partition_list_value_expr(params_, *(expr_list_node.children_[i]), partition_name, part_type, part_func_exprs, part_value_exprs, in_tablegroup))) { LOG_WARN("resolve partition expr failed", K(ret)); } for (int64_t j = 0; OB_SUCC(ret) && j < part_value_exprs.count(); ++j) { if (OB_FAIL(row_expr->add_param_expr(part_value_exprs.at(j)))) { LOG_WARN("failed add param expr", K(ret)); } } } if (OB_SUCC(ret)) { if (part_func_exprs.count() > 1 && !is_all_expr_list) { if (row_expr->get_param_count() != part_func_exprs.count()) { ret = OB_ERR_PARTITION_COLUMN_LIST_ERROR; LOG_WARN("Inconsistency in usage of column lists for partitioning near", K(ret)); } } } } if (OB_SUCC(ret)) { if (OB_FAIL(list_value_exprs.push_back(row_expr))) { LOG_WARN("failed to push back expr", K(ret)); } } return ret; } int ObDDLResolver::generate_default_hash_part( const int64_t partition_num, const int64_t max_used_part_id, ObTableSchema& table_schema) { int ret = OB_SUCCESS; table_schema.get_part_option().set_part_num(partition_num); char name_buf[common::OB_MAX_PARTITION_NAME_LENGTH]; for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; ++i) { ObPartition partition; partition.set_part_id(max_used_part_id >= 0 ? max_used_part_id - partition_num + 1 + i : i); partition.set_part_idx(i); ObString part_name; MEMSET(name_buf, 0, common::OB_MAX_PARTITION_NAME_LENGTH); if (OB_FAIL(table_schema.gen_hash_part_name(partition.get_part_idx(), ObHashNameType::FIRST_PART, is_oracle_mode(), name_buf, common::OB_MAX_PARTITION_NAME_LENGTH, NULL))) { LOG_WARN("failed to gen hash part name", K(ret)); } else if (FALSE_IT(part_name = ObString(strlen(name_buf), name_buf))) { } else if (OB_FAIL(partition.set_part_name(part_name))) { LOG_WARN("fail to set part name", K(ret)); } else if (OB_FAIL(table_schema.check_part_name(partition))) { LOG_WARN("fail to check part name", K(ret)); } else if (OB_FAIL(table_schema.add_partition(partition))) { LOG_WARN("fail to add partition", K(ret)); } } return ret; } int ObDDLResolver::generate_default_hash_subpart( const int64_t partition_num, const int64_t max_used_subpart_id, ObTableSchema& table_schema, ObPartition* partition) { int ret = OB_SUCCESS; char name_buf[common::OB_MAX_PARTITION_NAME_LENGTH]; const bool is_template = table_schema.is_sub_part_template(); if (!is_template && OB_ISNULL(partition)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table is not subpart template by partition is null", K(ret)); } else if (is_template) { table_schema.get_sub_part_option().set_part_num(partition_num); } else { partition->set_sub_part_num(partition_num); } if (OB_SUCC(ret)) { const int64_t part_id = is_template ? ObSubPartition::TEMPLATE_PART_ID : partition->get_part_id(); for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; ++i) { ObSubPartition subpartition; subpartition.set_part_id(part_id); subpartition.set_sub_part_id(max_used_subpart_id >= 0 ? max_used_subpart_id - partition_num + 1 + i : i); subpartition.set_sub_part_idx(i); ObString subpart_name; MEMSET(name_buf, 0, common::OB_MAX_PARTITION_NAME_LENGTH); if (is_template && OB_FAIL(table_schema.gen_hash_part_name(subpartition.get_sub_part_idx(), ObHashNameType::TEMPLATE_SUB_PART, is_oracle_mode(), name_buf, common::OB_MAX_PARTITION_NAME_LENGTH, NULL))) { LOG_WARN("faield to gen hash part name", K(ret)); } else if (!is_template && OB_FAIL(table_schema.gen_hash_part_name(subpartition.get_sub_part_idx(), ObHashNameType::INDIVIDUAL_SUB_PART, is_oracle_mode(), name_buf, common::OB_MAX_PARTITION_NAME_LENGTH, NULL, partition))) { LOG_WARN("faield to gen hash part name", K(ret)); } else if (FALSE_IT(subpart_name = ObString(strlen(name_buf), name_buf))) { } else if (OB_FAIL(subpartition.set_part_name(subpart_name))) { LOG_WARN("fail to set part name", K(ret)); } else if (is_template) { if (OB_FAIL(table_schema.add_def_subpartition(subpartition))) { LOG_WARN("fail to add partition", K(ret)); } } else if (OB_FAIL(partition->add_partition(subpartition))) { LOG_WARN("failed to add partition", K(ret)); } } } return ret; } int ObDDLResolver::check_and_set_partition_names(ObPartitionedStmt* stmt, ObTableSchema& table_schema) { int ret = OB_SUCCESS; if (OB_FAIL(check_and_set_partition_names(stmt, table_schema, false))) { LOG_WARN("failed to check and set partition names", K(ret)); } else if (PARTITION_LEVEL_TWO == table_schema.get_part_level()) { if (table_schema.is_sub_part_template()) { if (OB_FAIL(check_and_set_partition_names(stmt, table_schema, true))) { LOG_WARN("failed to check and set partition names", K(ret)); } } else if (OB_FAIL(check_and_set_individual_subpartition_names(stmt, table_schema))) { LOG_WARN("failed to check and set individual subpartition names", K(ret)); } } return ret; } int ObDDLResolver::check_and_set_partition_names(ObPartitionedStmt* stmt, ObTableSchema& table_schema, bool is_subpart) { int ret = OB_SUCCESS; hash::ObPlacementHashSet* partition_name_set = nullptr; void* buf = nullptr; int64_t partition_num = is_subpart ? table_schema.get_def_sub_part_num() : table_schema.get_first_part_num(); ObBasePartition* partition = NULL; ObPartition** partition_array = table_schema.get_part_array(); ObSubPartition** subpartition_array = table_schema.get_def_subpart_array(); ObSEArray empty_part_idx; if (is_subpart && OB_ISNULL(subpartition_array)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get null subpartition array", K(ret)); } else if (!is_subpart && OB_ISNULL(partition_array)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get null partition array", K(ret)); } else if (OB_ISNULL(buf = allocator_->alloc(sizeof( hash::ObPlacementHashSet)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to allocate memory", KR(ret)); } else { partition_name_set = new (buf) hash::ObPlacementHashSet(); if (OB_ISNULL(partition_name_set)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition name hash set is null", KR(ret)); } } for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; ++i) { if (is_subpart) { partition = subpartition_array[i]; } else { partition = partition_array[i]; } if (OB_ISNULL(partition)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } else if (partition->is_empty_partition_name()) { if (OB_FAIL(empty_part_idx.push_back(i))) { LOG_WARN("failed to push back part idx", K(ret)); } } else { const ObString& partition_name = partition->get_part_name(); ObPartitionNameHashWrapper partition_name_key(partition_name); if (OB_HASH_EXIST == partition_name_set->exist_refactored(partition_name_key)) { ret = OB_ERR_SAME_NAME_PARTITION; LOG_USER_ERROR(OB_ERR_SAME_NAME_PARTITION, partition_name.length(), partition_name.ptr()); } else if (OB_FAIL(partition_name_set->set_refactored(partition_name_key))) { LOG_WARN("add partition name to map failed", K(ret), K(ret)); } } } if (OB_SUCC(ret) && !empty_part_idx.empty() && (stmt::T_CREATE_TABLE == stmt->get_stmt_type() || stmt::T_CREATE_TABLEGROUP == stmt->get_stmt_type() || stmt::T_CREATE_INDEX == stmt->get_stmt_type())) { int64_t max_part_id = OB_MAX_PARTITION_NUM_MYSQL; ObString part_name_str; for (int64_t i = 0; OB_SUCC(ret) && i < empty_part_idx.count(); ++i) { const int64_t part_idx = empty_part_idx.at(i); if (is_subpart) { partition = subpartition_array[part_idx]; } else { partition = partition_array[part_idx]; } bool is_valid = false; while (OB_SUCC(ret) && !is_valid) { char part_name[OB_MAX_PARTITION_NAME_LENGTH]; int64_t pos = 0; if (OB_FAIL(databuff_printf(part_name, OB_MAX_PARTITION_NAME_LENGTH, pos, "P%ld", max_part_id))) { LOG_WARN("failed to print databuff", K(ret), K(max_part_id)); } else { part_name_str.assign(part_name, static_cast(pos)); ObPartitionNameHashWrapper partition_name_key(part_name_str); if (OB_HASH_EXIST == partition_name_set->exist_refactored(partition_name_key)) { // do nothing } else if (OB_FAIL(partition_name_set->set_refactored(partition_name_key))) { LOG_WARN("add partition name to map failed", K(ret), K(ret)); } else if (OB_FAIL(partition->set_part_name(part_name_str))) { LOG_WARN("failed to set part name", K(ret)); } else { partition->set_is_empty_partition_name(false); is_valid = true; } } ++max_part_id; } } } return ret; } int ObDDLResolver::check_and_set_individual_subpartition_names(ObPartitionedStmt* stmt, ObTableSchema& table_schema) { int ret = OB_SUCCESS; hash::ObPlacementHashSet* partition_name_set = nullptr; void* buf = nullptr; int64_t partition_num = table_schema.get_first_part_num(); ObPartition** partition_array = NULL; ObPartition* partition = NULL; ObSubPartition** subpartition_array = NULL; ObSubPartition* subpartition = NULL; ObSEArray empty_part_idx; ObSEArray empty_subpart_idx; if (OB_UNLIKELY(table_schema.is_sub_part_template())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected subpartition", K(ret)); } else if (OB_ISNULL(partition_array = table_schema.get_part_array())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } else if (OB_ISNULL(buf = allocator_->alloc(sizeof( hash::ObPlacementHashSet)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to allocate memory", KR(ret)); } else { partition_name_set = new (buf) hash::ObPlacementHashSet(); if (OB_ISNULL(partition_name_set)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("partition name hash set is null", KR(ret)); } } for (int64_t i = 0; OB_SUCC(ret) && i < partition_num; ++i) { if (OB_ISNULL(partition = partition_array[i]) || OB_ISNULL(subpartition_array = partition->get_subpart_array())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(partition), K(subpartition_array)); } for (int64_t j = 0; OB_SUCC(ret) && j < partition->get_sub_part_num(); ++j) { if (OB_ISNULL(subpartition = subpartition_array[j])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } else if (subpartition->is_empty_partition_name()) { if (OB_FAIL(empty_part_idx.push_back(i))) { LOG_WARN("failed to push back part idx", K(ret)); } else if (OB_FAIL(empty_subpart_idx.push_back(j))) { LOG_WARN("failed to push back subpart idx", K(ret)); } } else { const ObString& partition_name = subpartition->get_part_name(); ObPartitionNameHashWrapper partition_name_key(partition_name); if (OB_HASH_EXIST == partition_name_set->exist_refactored(partition_name_key)) { ret = OB_ERR_SAME_NAME_SUBPARTITION; LOG_USER_ERROR(OB_ERR_SAME_NAME_SUBPARTITION, partition_name.length(), partition_name.ptr()); } else if (OB_FAIL(partition_name_set->set_refactored(partition_name_key))) { LOG_WARN("add partition name to map failed", K(ret), K(ret)); } } } } if (!empty_part_idx.empty() && (stmt::T_CREATE_TABLE == stmt->get_stmt_type() || stmt::T_CREATE_TABLEGROUP == stmt->get_stmt_type() || stmt::T_CREATE_INDEX == stmt->get_stmt_type())) { int64_t max_part_id = OB_MAX_PARTITION_NUM_MYSQL; ObString part_name_str; for (int64_t i = 0; OB_SUCC(ret) && i < empty_part_idx.count(); ++i) { int64_t part_idx = empty_part_idx.at(i); int64_t subpart_idx = empty_subpart_idx.at(i); subpartition = partition_array[part_idx]->get_subpart_array()[subpart_idx]; bool is_valid = false; while (OB_SUCC(ret) && !is_valid) { char part_name[OB_MAX_PARTITION_NAME_LENGTH]; int64_t pos = 0; if (OB_FAIL(databuff_printf(part_name, OB_MAX_PARTITION_NAME_LENGTH, pos, "P%ld", max_part_id))) { LOG_WARN("failed to print databuff", K(ret), K(max_part_id)); } else { part_name_str.assign(part_name, static_cast(pos)); ObPartitionNameHashWrapper partition_name_key(part_name_str); if (OB_HASH_EXIST == partition_name_set->exist_refactored(partition_name_key)) { // do nothing } else if (OB_FAIL(partition_name_set->set_refactored(partition_name_key))) { LOG_WARN("add partition name to map failed", K(ret), K(ret)); } else if (OB_FAIL(subpartition->set_part_name(part_name_str))) { LOG_WARN("failed to set part name", K(ret)); } else { subpartition->set_is_empty_partition_name(false); is_valid = true; } } ++max_part_id; } } } return ret; } int ObDDLResolver::check_individual_subpartition_define(ObPartitionedStmt* stmt, ObTableSchema& table_schema) { int ret = OB_SUCCESS; int64_t partition_num = table_schema.get_first_part_num(); ObPartition** partition_array = NULL; ObPartition* partition = NULL; bool need_check_value = table_schema.is_range_subpart() || table_schema.is_list_subpart(); if (OB_ISNULL(stmt) || OB_ISNULL(partition_array = table_schema.get_part_array())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(stmt), K(partition_array)); } else if (OB_UNLIKELY(table_schema.is_sub_part_template())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected subpartition", K(ret), K(table_schema.is_sub_part_template())); } else if (need_check_value && partition_num != stmt->get_individual_subpart_values_exprs().count()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected subpartition value exprs", K(ret), K(partition_num), K(stmt->get_individual_subpart_values_exprs())); } else if (partition_num <= 1) { // do nothing } else if (OB_ISNULL(partition = partition_array[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(partition)); } else { const int64_t first_subpart_number = partition->get_sub_part_num(); const ObIArray* first_subpart_value_exprs = NULL; if (need_check_value) { first_subpart_value_exprs = &(stmt->get_individual_subpart_values_exprs().at(0)); } for (int64_t i = 1; OB_SUCC(ret) && i < partition_num; ++i) { if (OB_ISNULL(partition = partition_array[i])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(partition)); } else if (first_subpart_number != partition->get_sub_part_num()) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "individual subpartition with different define"); } else if (need_check_value) { const ObIArray& cur_value_exprs = stmt->get_individual_subpart_values_exprs().at(i); const ObRawExpr* l_expr = NULL; const ObRawExpr* r_expr = NULL; for (int64_t j = 0; OB_SUCC(ret) && j < first_subpart_value_exprs->count(); ++j) { if (OB_ISNULL(l_expr = first_subpart_value_exprs->at(j)) || OB_ISNULL(r_expr = cur_value_exprs.at(j))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(l_expr), K(r_expr)); } else if (!l_expr->same_as(*r_expr)) { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "individual subpartition with different define"); } } } } } return ret; } int ObDDLResolver::check_max_used_subpart_id_valid( const share::schema::ObTableSchema& table_schema, const ObPartition& partition, int64_t& max_used_subpart_id) { int ret = OB_SUCCESS; int64_t current_max_subpart_id = -1; const int64_t subpart_num = partition.get_sub_part_num(); if (table_schema.is_range_subpart() || table_schema.is_list_subpart()) { ObSubPartition** subpart_array = partition.get_subpart_array(); const int64_t subpart_idx = subpart_num - 1; if (subpart_idx < 0) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Invalid part idx", K(ret)); } else if (OB_ISNULL(subpart_array)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("Empty partition", K(ret)); } else if (OB_ISNULL(subpart_array[subpart_idx])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("NULL ptr", K(ret)); } else if (subpart_array[subpart_idx]->get_sub_part_id() < 0) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Invalid part id", K(ret), K(subpart_idx), K(subpart_array[subpart_idx]->get_sub_part_id())); } else { current_max_subpart_id = subpart_array[subpart_idx]->get_sub_part_id(); } } else { current_max_subpart_id = subpart_num - 1; } if (OB_SUCC(ret)) { if (max_used_subpart_id < 0) { max_used_subpart_id = current_max_subpart_id; } else if (PARTITION_LEVEL_ZERO == table_schema.get_part_level() || PARTITION_LEVEL_ONE == table_schema.get_part_level()) { ret = OB_NOT_SUPPORTED; SQL_RESV_LOG(WARN, "non subpart table with max_used_sub_part_id not support", K(ret), K(current_max_subpart_id)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "non subpart table with max_used_sub_part_id"); } else if (max_used_subpart_id < current_max_subpart_id) { ret = OB_INVALID_ARGUMENT; SQL_RESV_LOG(WARN, "invalid max_used_subpart_id", K(ret), K(max_used_subpart_id), K(current_max_subpart_id)); LOG_USER_ERROR(OB_INVALID_ARGUMENT, "max_used_subpart_id"); } else { // use max_used_part_id_ } } return ret; } } // namespace sql } // namespace oceanbase