diff --git a/src/rootserver/ob_ddl_operator.cpp b/src/rootserver/ob_ddl_operator.cpp index 1b66383967..3fc5f8b257 100644 --- a/src/rootserver/ob_ddl_operator.cpp +++ b/src/rootserver/ob_ddl_operator.cpp @@ -2348,7 +2348,8 @@ int ObDDLOperator::alter_table_column(const ObTableSchema& origin_table_schema, new_table_schema.get_charset_type(), new_table_schema.get_collation_type()))) { RS_LOG(WARN, "failed to fill column charset info"); - } else if (OB_FAIL(ObDDLResolver::check_text_column_length_and_promote(*alter_column_schema))) { + } else if (OB_FAIL(ObDDLResolver::check_text_column_length_and_promote(*alter_column_schema, + origin_table_schema.get_table_id()))) { RS_LOG(WARN, "failed to check text or blob column length"); } } else if (ObEnumSetTC == col_tc) { @@ -2568,7 +2569,8 @@ int ObDDLOperator::alter_table_column(const ObTableSchema& origin_table_schema, new_table_schema.get_charset_type(), new_table_schema.get_collation_type()))) { RS_LOG(WARN, "failed to fill column charset info"); - } else if (OB_FAIL(ObDDLResolver::check_text_column_length_and_promote(*alter_column_schema))) { + } else if (OB_FAIL(ObDDLResolver::check_text_column_length_and_promote(*alter_column_schema, + origin_table_schema.get_table_id()))) { RS_LOG(WARN, "failed to check text or blob column length"); } } @@ -2775,7 +2777,8 @@ int ObDDLOperator::alter_table_column(const ObTableSchema& origin_table_schema, new_table_schema.get_charset_type(), new_table_schema.get_collation_type()))) { RS_LOG(WARN, "failed to fill column charset info"); - } else if (OB_FAIL(ObDDLResolver::check_text_column_length_and_promote(*alter_column_schema))) { + } else if (OB_FAIL(ObDDLResolver::check_text_column_length_and_promote(*alter_column_schema, + origin_table_schema.get_table_id()))) { RS_LOG(WARN, "failed to check text or blob column length"); } } diff --git a/src/sql/resolver/ddl/ob_create_table_resolver.cpp b/src/sql/resolver/ddl/ob_create_table_resolver.cpp index e68f4028dc..5384b48818 100644 --- a/src/sql/resolver/ddl/ob_create_table_resolver.cpp +++ b/src/sql/resolver/ddl/ob_create_table_resolver.cpp @@ -554,6 +554,11 @@ int ObCreateTableResolver::resolve(const ParseNode& parse_tree) // do nothing } + // 1、 resolve table_id first for check whether is inner_table + if (OB_SUCC(ret) && OB_FAIL(resolve_table_id_pre(create_table_node->children_[4]))) { + SQL_RESV_LOG(WARN, "resolve_table_id_pre failed", K(ret)); + } + // consider index can be defined before column, so column should be // resolved firstly;avoid to rescan table_element_list_node, use a // array named index_node_position_list to record the position of indexes @@ -1576,7 +1581,7 @@ int ObCreateTableResolver::resolve_table_elements_from_select(const ParseNode& p } else if (is_oracle_mode() && create_table_column_count > 0) { if (column.is_string_type()) { if (column.get_meta_type().is_lob()) { - if (OB_FAIL(check_text_column_length_and_promote(column))) { + if (OB_FAIL(check_text_column_length_and_promote(column, table_id_))) { LOG_WARN("fail to check text or blob column length", K(ret), K(column)); } } else if (OB_FAIL(check_string_column_length(column, share::is_oracle_mode()))) { @@ -1619,7 +1624,7 @@ int ObCreateTableResolver::resolve_table_elements_from_select(const ParseNode& p } else { if (column.is_string_type()) { if (column.get_meta_type().is_lob()) { - if (OB_FAIL(check_text_column_length_and_promote(column))) { + if (OB_FAIL(check_text_column_length_and_promote(column, table_id_))) { LOG_WARN("fail to check text or blob column length", K(ret), K(column)); } } else if (OB_FAIL(check_string_column_length(column, share::is_oracle_mode()))) { diff --git a/src/sql/resolver/ddl/ob_ddl_resolver.cpp b/src/sql/resolver/ddl/ob_ddl_resolver.cpp index b75bb6ddc6..4bf3f84238 100644 --- a/src/sql/resolver/ddl/ob_ddl_resolver.cpp +++ b/src/sql/resolver/ddl/ob_ddl_resolver.cpp @@ -513,6 +513,38 @@ int ObDDLResolver::set_database_name(const ObString& database_name) 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; @@ -1875,7 +1907,7 @@ int ObDDLResolver::resolve_column_definition(ObColumnSchemaV2& column, ParseNode 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))) { + 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()))) { @@ -2913,8 +2945,12 @@ int ObDDLResolver::check_urowid_column_length(const share::schema::ObColumnSchem return ret; } -int ObDDLResolver::check_text_length( - ObCharsetType cs_type, ObCollationType co_type, const char* name, ObObjType& type, int32_t& length) +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; @@ -2961,17 +2997,50 @@ int ObDDLResolver::check_text_length( 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) +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_FAIL(check_text_length( - column.get_charset_type(), column.get_collation_type(), column.get_column_name(), type, 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); diff --git a/src/sql/resolver/ddl/ob_ddl_resolver.h b/src/sql/resolver/ddl/ob_ddl_resolver.h index a6e408f473..f4c54b9a04 100644 --- a/src/sql/resolver/ddl/ob_ddl_resolver.h +++ b/src/sql/resolver/ddl/ob_ddl_resolver.h @@ -142,8 +142,14 @@ public: static const int64_t DEFAULT_TABLE_DOP = 1; explicit ObDDLResolver(ObResolverParams& params); virtual ~ObDDLResolver(); - static int check_text_length( - ObCharsetType cs_type, ObCollationType co_type, const char* name, ObObjType& type, int32_t& length); + static int check_text_length(ObCharsetType cs_type, + ObCollationType co_type, + const char* name, + ObObjType& type, + int32_t& length, + bool need_rewrite_length); + + static int rewrite_text_length_mysql(ObObjType &type, int32_t &length); static int check_uniq_allow( share::schema::ObTableSchema& table_schema, obrpc::ObCreateIndexArg& index_arg, bool& allow); static int get_primary_key_default_value(common::ObObjType type, common::ObObj& default_value); @@ -181,7 +187,7 @@ public: static int cast_enum_or_set_default_value( const share::schema::ObColumnSchemaV2& column, common::ObObjCastParams& params, common::ObObj& def_val); int check_partition_name_duplicate(ParseNode* node, bool is_oracle_modle = false); - static int check_text_column_length_and_promote(share::schema::ObColumnSchemaV2& column); + static int check_text_column_length_and_promote(share::schema::ObColumnSchemaV2& column, int64_t table_id); static int get_enable_split_partition(const int64_t tenant_id, bool& enable_split_partition); typedef common::hash::ObPlacementHashSet IndexNameSet; @@ -250,6 +256,7 @@ protected: int set_table_name(const common::ObString& table_name); int set_database_name(const common::ObString& database_name); int set_encryption_name(const common::ObString& encryption); + int resolve_table_id_pre(ParseNode *node); int resolve_table_options(ParseNode* node, bool is_index_option); int resolve_table_option(const ParseNode* node, const bool is_index_option); int resolve_column_definition_ref(