fix hung when convert to character for partition.

This commit is contained in:
obdev 2022-11-23 13:05:40 +00:00 committed by wangzelin.wzl
parent 3e788f5391
commit 8129d41b24
5 changed files with 178 additions and 20 deletions

View File

@ -3374,19 +3374,6 @@ int ObDDLService::check_alter_table_index(const obrpc::ObAlterTableArg &alter_ta
return ret;
}
int ObDDLService::check_can_convert_to_character(const share::schema::ObColumnSchemaV2 &column_schema, bool &can_convert)
{
int ret = OB_SUCCESS;
can_convert = false;
if (OB_UNLIKELY(!column_schema.is_valid())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(column_schema));
} else {
can_convert = (column_schema.is_string_type() || column_schema.is_enum_or_set()) && CS_TYPE_BINARY != column_schema.get_collation_type();
}
return ret;
}
int ObDDLService::check_convert_to_character(obrpc::ObAlterTableArg &alter_table_arg,
const ObTableSchema &orig_table_schema,
ObDDLType &ddl_type)
@ -3421,9 +3408,7 @@ int ObDDLService::check_convert_to_character(obrpc::ObAlterTableArg &alter_table
if (OB_ISNULL(col)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("col is NULL", K(ret));
} else if (OB_FAIL(check_can_convert_to_character(*col, can_convert))) {
LOG_WARN("check can convert to character", K(ret));
} else if (can_convert) {
} else if (ObDDLUtil::check_can_convert_character(col->get_meta_type())) {
if (orig_table_schema.is_column_in_foreign_key(col->get_column_id())) {
ret = OB_NOT_SUPPORTED;
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Alter column charset or collation with foreign key");
@ -3577,6 +3562,93 @@ int ObDDLService::alter_table_partition_by(
return ret;
}
// convert character set for ObBasePartition, inluding high_bound_val and list_row_values.
int ObDDLService::convert_to_character_for_partition(
const ObCollationType &to_collation,
ObTableSchema &new_table_schema)
{
int ret = OB_SUCCESS;
const ObPartitionLevel part_level = new_table_schema.get_part_level();
const ObPartitionFuncType part_func_type = new_table_schema.get_part_option().get_part_func_type();
const ObPartitionFuncType subpart_func_type = new_table_schema.get_sub_part_option().get_sub_part_func_type();
if (PARTITION_LEVEL_MAX <= part_level) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arg", K(ret), K(part_level), K(new_table_schema));
} else if (PARTITION_LEVEL_ZERO == part_level) {
// non-partitioned, do nothing.
} else {
const int64_t part_num = new_table_schema.get_partition_num();
ObPartition **part_array = new_table_schema.get_part_array();
if (OB_ISNULL(part_array)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null first part array", K(ret), K(part_level), K(part_num), K(part_func_type));
}
// for the first-level part.
for (int64_t i = 0; OB_SUCC(ret) && i < part_num; i++) {
ObPartition *partition = part_array[i];
if (OB_ISNULL(partition)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected err", K(ret));
} else if (PARTITION_FUNC_TYPE_RANGE_COLUMNS == part_func_type
&& OB_FAIL(partition->convert_character_for_range_columns_part(to_collation))) {
LOG_WARN("convert charset failed", K(ret), K(to_collation));
} else if (PARTITION_FUNC_TYPE_LIST_COLUMNS == part_func_type
&& OB_FAIL(partition->convert_character_for_list_columns_part(to_collation))) {
LOG_WARN("convert charset failed", K(ret), K(to_collation));
} else if (PARTITION_LEVEL_TWO == part_level) {
// for the second-level part.
const int64_t subpart_num = partition->get_subpartition_num();
ObSubPartition **subpart_array = partition->get_subpart_array();
if (OB_ISNULL(subpart_array)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("part array is null", K(ret));
} else if (subpart_num < 1) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("sub_part_num less than 1", K(ret));
} else {
for (int64_t j = 0; OB_SUCC(ret) && j < subpart_num; j++) {
ObSubPartition *subpart = subpart_array[j];
if (OB_ISNULL(subpart)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected err", K(ret));
} else if (PARTITION_FUNC_TYPE_RANGE_COLUMNS == subpart_func_type
&& OB_FAIL(subpart->convert_character_for_range_columns_part(to_collation))) {
LOG_WARN("convert charset failed", K(ret), K(to_collation));
} else if (PARTITION_FUNC_TYPE_LIST_COLUMNS == subpart_func_type
&& OB_FAIL(subpart->convert_character_for_list_columns_part(to_collation))) {
LOG_WARN("convert charset failed", K(ret), K(to_collation));
}
}
}
}
}
}
// for def subpartition array.
if (OB_SUCC(ret) && new_table_schema.has_sub_part_template_def()) {
ObSubPartition **def_subpart_array = new_table_schema.get_def_subpart_array();
const int64_t def_subpart_num = new_table_schema.get_def_sub_part_num();
if (OB_ISNULL(def_subpart_array)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected err, def subpart arr is null", K(ret), K(new_table_schema));
} else {
ObSubPartition *subpart_info = nullptr;
for (int64_t i = 0; OB_SUCC(ret) && i < def_subpart_num; i++) {
if (OB_ISNULL(subpart_info = def_subpart_array[i])) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("sub part is nullptr", K(ret));
} else if (PARTITION_FUNC_TYPE_RANGE_COLUMNS == subpart_func_type
&& OB_FAIL(subpart_info->convert_character_for_range_columns_part(to_collation))) {
LOG_WARN("convert charset failed", K(ret), K(to_collation));
} else if (PARTITION_FUNC_TYPE_LIST_COLUMNS == subpart_func_type
&& OB_FAIL(subpart_info->convert_character_for_list_columns_part(to_collation))) {
LOG_WARN("convert charset failed", K(ret), K(to_collation));
}
}
}
}
return ret;
}
int ObDDLService::convert_to_character(
obrpc::ObAlterTableArg &alter_table_arg,
const ObTableSchema &orig_table_schema,
@ -3599,15 +3671,16 @@ int ObDDLService::convert_to_character(
ObTableSchema::const_column_iterator tmp_end = orig_table_schema.column_end();
if (OB_FAIL(orig_table_schema.check_if_oracle_compat_mode(is_oracle_mode))) {
LOG_WARN("failed to get oracle mode", K(ret));
} else if (is_oracle_mode) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected compat mode", K(ret), K(orig_table_schema));
} else {
for (; OB_SUCC(ret) && tmp_begin != tmp_end; tmp_begin++) {
ObColumnSchemaV2 *orig_col = (*tmp_begin);
if (OB_ISNULL(orig_col)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("col is NULL", K(ret));
} else if (OB_FAIL(check_can_convert_to_character(*orig_col, can_convert))) {
LOG_WARN("check can convert to character", K(ret));
} else if (can_convert) {
} else if (ObDDLUtil::check_can_convert_character(orig_col->get_meta_type())) {
ObColumnSchemaV2 *col = new_table_schema.get_column_schema(orig_col->get_column_name());
if (OB_ISNULL(col)) {
ret = OB_ERR_UNEXPECTED;
@ -3625,6 +3698,13 @@ int ObDDLService::convert_to_character(
}
}
}
// convert character set for partition.
if (OB_SUCC(ret)) {
if (OB_FAIL(convert_to_character_for_partition(collation_type, new_table_schema))) {
LOG_WARN("convert collation type for partition failed", K(ret));
}
}
OZ (create_user_hidden_table(orig_table_schema,
new_table_schema,
&alter_table_arg.sequence_ddl_arg_,

View File

@ -1322,6 +1322,8 @@ private:
const int64_t frozen_version,
ObDDLOperator &ddl_operator,
common::ObMySQLTransaction &trans);
int convert_to_character_for_partition(const ObCollationType &to_collation,
share::schema::ObTableSchema &new_table_schema);
int convert_to_character(obrpc::ObAlterTableArg &alter_table_arg,
const share::schema::ObTableSchema &orgin_table_schema,
share::schema::ObTableSchema &new_table_schema,
@ -2147,7 +2149,6 @@ private:
const int64_t part_id,
const share::schema::ObPartition *&part);
int check_table_pk(const share::schema::ObTableSchema &orig_table_schema);
int check_can_convert_to_character(const share::schema::ObColumnSchemaV2 &col_schema, bool &can_convert);
int clean_global_context(const ObContextSchema &context_schema);
int get_hard_code_system_table_schema_(

View File

@ -276,6 +276,12 @@ public:
}
static bool need_remote_write(const int ret_code);
static int check_can_convert_character(const ObObjMeta &obj_meta)
{
return (obj_meta.is_string_type() || obj_meta.is_enum_or_set())
&& CS_TYPE_BINARY != obj_meta.get_collation_type();
}
private:
static int generate_column_name_str(
const common::ObIArray<ObColumnNameInfo> &column_names,

View File

@ -22,6 +22,7 @@
#include "lib/string/ob_sql_string.h"
#include "lib/number/ob_number_v2.h"
#include "common/ob_zone_type.h"
#include "share/ob_ddl_common.h"
#include "share/schema/ob_table_schema.h"
#include "share/ob_primary_zone_util.h"
#include "sql/ob_sql_utils.h"
@ -5401,6 +5402,72 @@ int ObBasePartition::set_high_bound_val_with_hex_str(
return ret;
}
int ObBasePartition::convert_character_for_range_columns_part(
const ObCollationType &to_collation)
{
int ret = OB_SUCCESS;
ObIAllocator *allocator = get_allocator();
if (OB_ISNULL(allocator)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null allocator", K(ret));
} else if (low_bound_val_.get_obj_cnt() > 0) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("defensive code, unexpected error", K(ret), K(low_bound_val_));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < high_bound_val_.get_obj_cnt(); i++) {
ObObj &obj = high_bound_val_.get_obj_ptr()[i];
const ObObjMeta &obj_meta = obj.get_meta();
if (obj_meta.is_lob()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected err, lob column can not be part key", K(ret), K(obj_meta));
} else if (ObDDLUtil::check_can_convert_character(obj_meta)) {
ObString dst_string;
if (OB_FAIL(ObCharset::charset_convert(*allocator, obj.get_string(), obj.get_collation_type(),
to_collation, dst_string))) {
LOG_WARN("charset convert failed", K(ret), K(obj), K(to_collation));
} else {
obj.set_string(obj.get_type(), dst_string);
obj.set_collation_type(to_collation);
}
}
}
}
return ret;
}
int ObBasePartition::convert_character_for_list_columns_part(
const ObCollationType &to_collation)
{
int ret = OB_SUCCESS;
ObIAllocator *allocator = get_allocator();
if (OB_ISNULL(allocator)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null allocator", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < list_row_values_.count(); i++) {
common::ObNewRow &row = list_row_values_.at(i);
for (int64_t j = 0; OB_SUCC(ret) && j < row.get_count(); j++) {
ObObj &obj = row.get_cell(j);
const ObObjMeta &obj_meta = obj.get_meta();
if (obj_meta.is_lob()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected err, lob column can not be part key", K(ret), K(obj_meta));
} else if (ObDDLUtil::check_can_convert_character(obj_meta)) {
ObString dst_string;
if (OB_FAIL(ObCharset::charset_convert(*allocator, obj.get_string(), obj.get_collation_type(),
to_collation, dst_string))) {
LOG_WARN("charset convert failed", K(ret), K(obj), K(to_collation));
} else {
obj.set_string(obj.get_type(), dst_string);
obj.set_collation_type(to_collation);
}
}
}
}
}
return ret;
}
OB_DEF_SERIALIZE(ObBasePartition)
{
int ret = OB_SUCCESS;

View File

@ -1939,6 +1939,10 @@ public:
PartitionType get_partition_type() const { return partition_type_; }
virtual bool is_normal_partition() const = 0;
virtual bool is_hidden_partition() const { return share::schema::is_hidden_partition(partition_type_); }
// convert character set.
int convert_character_for_range_columns_part(const ObCollationType &to_collation);
int convert_character_for_list_columns_part(const ObCollationType &to_collation);
VIRTUAL_TO_STRING_KV(K_(tenant_id), K_(table_id), K_(part_id), K_(name), K_(low_bound_val),
K_(high_bound_val), K_(list_row_values), K_(part_idx),
K_(is_empty_partition_name), K_(tablet_id));