From 1facbc67f8b0ca15f8bf342879163c0991323a25 Mon Sep 17 00:00:00 2001 From: shadowao Date: Mon, 8 Apr 2024 05:44:53 +0000 Subject: [PATCH] [CP] fix lob max row data length check bug that causes table creation failure --- deps/oblib/src/common/ob_accuracy.cpp | 2 +- deps/oblib/src/lib/ob_define.h | 2 +- .../resolver/ddl/ob_create_table_resolver.cpp | 46 +++++++++++++++++-- .../resolver/ddl/ob_create_table_resolver.h | 1 + 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/deps/oblib/src/common/ob_accuracy.cpp b/deps/oblib/src/common/ob_accuracy.cpp index 2557e28a5..4bef95e9c 100644 --- a/deps/oblib/src/common/ob_accuracy.cpp +++ b/deps/oblib/src/common/ob_accuracy.cpp @@ -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 } diff --git a/deps/oblib/src/lib/ob_define.h b/deps/oblib/src/lib/ob_define.h index 128f1801f..1954ec494 100644 --- a/deps/oblib/src/lib/ob_define.h +++ b/deps/oblib/src/lib/ob_define.h @@ -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) diff --git a/src/sql/resolver/ddl/ob_create_table_resolver.cpp b/src/sql/resolver/ddl/ob_create_table_resolver.cpp index e7826a3bc..c7389beda 100644 --- a/src/sql/resolver/ddl/ob_create_table_resolver.cpp +++ b/src/sql/resolver/ddl/ob_create_table_resolver.cpp @@ -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(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(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 diff --git a/src/sql/resolver/ddl/ob_create_table_resolver.h b/src/sql/resolver/ddl/ob_create_table_resolver.h index 8bc87564b..3eae6e1df 100644 --- a/src/sql/resolver/ddl/ob_create_table_resolver.h +++ b/src/sql/resolver/ddl/ob_create_table_resolver.h @@ -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