[CP] fix lob max row data length check bug that causes table creation failure

This commit is contained in:
shadowao 2024-04-08 05:44:53 +00:00 committed by ob-robot
parent b5792241c1
commit 1facbc67f8
4 changed files with 46 additions and 5 deletions

View File

@ -340,7 +340,7 @@ const ObAccuracy ObAccuracy::MAX_ACCURACY2[ORACLE_MODE + 1][ObMaxType] = {
ObAccuracy(), // urowid
ObAccuracy(OB_MAX_LONGTEXT_LENGTH), // lob, todo
ObAccuracy(OB_MAX_LONGTEXT_LENGTH), // json
ObAccuracy(), // geometry
ObAccuracy(OB_MAX_LONGTEXT_LENGTH), // geometry
ObAccuracy(), // user defined type in sql
ObAccuracy(OB_MAX_DECIMAL_PRECISION, OB_MAX_DECIMAL_SCALE), // decimal int
}

View File

@ -1789,7 +1789,7 @@ const int16_t MAX_SIGNED_INTEGER_PRECISION = 18;
// TODO@hanhui lob handle length will be much shorter in 2.0
const int64_t OB_MAX_LOB_INLINE_LENGTH = OB_MAX_VARCHAR_LENGTH;
const int64_t OB_MAX_LOB_HANDLE_LENGTH = 2 * 1024L;
const int64_t OB_MAX_LOB_HANDLE_LENGTH = 512L;
const int64_t OB_MAX_TINYTEXT_LENGTH = 256; // mysql (1LL << 8)
const int64_t OB_MAX_TEXT_LENGTH = 64 * 1024L; // mysql (1LL << 16)
const int64_t OB_MAX_MEDIUMTEXT_LENGTH = 16 * 1024 * 1024L; // mysql (1LL << 24)

View File

@ -674,6 +674,8 @@ int ObCreateTableResolver::resolve(const ParseNode &parse_tree)
SQL_RESV_LOG(WARN, "resolve table options failed", K(ret));
} else if (OB_FAIL(set_table_option_to_schema(table_schema))) {
SQL_RESV_LOG(WARN, "set table option to schema failed", K(ret));
} else if (OB_FAIL(check_max_row_data_length(table_schema))) {
SQL_RESV_LOG(WARN, "check max row data length failed", K(ret));
} else {
table_schema.set_collation_type(collation_type_);
table_schema.set_charset_type(charset_type_);
@ -1282,14 +1284,14 @@ int ObCreateTableResolver::resolve_table_elements(const ParseNode *node,
schema_checker_,
NULL == element->children_[1]))) {
SQL_RESV_LOG(WARN, "failed to cast default value!", K(ret));
} else if (column.is_string_type()) {
} else if (column.is_string_type() || is_lob_storage(column.get_data_type())) {
int64_t length = 0;
if (OB_FAIL(column.get_byte_length(length, is_oracle_mode, false))) {
SQL_RESV_LOG(WARN, "fail to get byte length of column", KR(ret), K(is_oracle_mode));
} else if (ob_is_string_tc(column.get_data_type()) && length > OB_MAX_VARCHAR_LENGTH) {
ret = OB_ERR_TOO_LONG_COLUMN_LENGTH;
LOG_USER_ERROR(OB_ERR_TOO_LONG_COLUMN_LENGTH, column.get_column_name(), static_cast<int32_t>(OB_MAX_VARCHAR_LENGTH));
} else if (ob_is_text_tc(column.get_data_type())) {
} else if (is_lob_storage(column.get_data_type())) {
ObLength max_length = 0;
max_length = ObAccuracy::MAX_ACCURACY2[is_oracle_mode][column.get_data_type()].get_length();
if (length > max_length) {
@ -1297,7 +1299,9 @@ int ObCreateTableResolver::resolve_table_elements(const ParseNode *node,
LOG_USER_ERROR(OB_ERR_TOO_LONG_COLUMN_LENGTH, column.get_column_name(),
ObAccuracy::MAX_ACCURACY2[is_oracle_mode][column.get_data_type()].get_length());
} else {
length = min(length, table_schema.get_lob_inrow_threshold());
// table lob inrow theshold has not been parsed, so use handle length check
// will recheck after parsing table lob inrow theshold
length = min(length, OB_MAX_LOB_HANDLE_LENGTH);
}
}
if (OB_SUCC(ret) && (row_data_length += length) > OB_MAX_USER_ROW_LENGTH) {
@ -3134,5 +3138,41 @@ int ObCreateTableResolver::add_inner_index_for_heap_gtt() {
return ret;
}
int ObCreateTableResolver::check_max_row_data_length(const ObTableSchema &table_schema)
{
int ret = OB_SUCCESS;
int64_t row_data_length = 0;
bool is_oracle_mode = lib::is_oracle_mode();
for (int64_t i = 0; OB_SUCC(ret) && i < table_schema.get_column_count(); ++i) {
int64_t length = 0;
const ObColumnSchemaV2 *column = table_schema.get_column_schema_by_idx(i);
if (OB_ISNULL(column)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("column is null", K(ret), K(table_schema));
} else if (! column->is_string_type() && ! is_lob_storage(column->get_data_type()) ) { // skip non string or lob storage type
} else if (OB_FAIL(column->get_byte_length(length, is_oracle_mode, false))) {
SQL_RESV_LOG(WARN, "fail to get byte length of column", KR(ret), K(is_oracle_mode));
} else if (ob_is_string_tc(column->get_data_type()) && length > OB_MAX_VARCHAR_LENGTH) {
ret = OB_ERR_TOO_LONG_COLUMN_LENGTH;
LOG_USER_ERROR(OB_ERR_TOO_LONG_COLUMN_LENGTH, column->get_column_name(), static_cast<int32_t>(OB_MAX_VARCHAR_LENGTH));
} else if (is_lob_storage(column->get_data_type())) {
ObLength max_length = 0;
max_length = ObAccuracy::MAX_ACCURACY2[is_oracle_mode][column->get_data_type()].get_length();
if (length > max_length) {
ret = OB_ERR_TOO_LONG_COLUMN_LENGTH;
LOG_USER_ERROR(OB_ERR_TOO_LONG_COLUMN_LENGTH, column->get_column_name(),
ObAccuracy::MAX_ACCURACY2[is_oracle_mode][column->get_data_type()].get_length());
} else {
length = min(length, max(table_schema.get_lob_inrow_threshold(), OB_MAX_LOB_HANDLE_LENGTH));
}
}
if (OB_SUCC(ret) && (row_data_length += length) > OB_MAX_USER_ROW_LENGTH) {
ret = OB_ERR_TOO_BIG_ROWSIZE;
SQL_RESV_LOG(WARN, "too big rowsize", KR(ret), K(is_oracle_mode), K(i), K(row_data_length), K(length));
}
}
return ret;
}
}//end namespace sql
}//end namespace oceanbase

View File

@ -136,6 +136,7 @@ private:
bool can_add_column_group(const ObTableSchema &table_schema);
int add_inner_index_for_heap_gtt();
int check_max_row_data_length(const ObTableSchema &table_schema);
private:
// data members