diff --git a/src/share/schema/ob_table_schema.cpp b/src/share/schema/ob_table_schema.cpp index 47ab632b587325411f8de6145222fabf347ab20c..149c5c76d47f44fe338820e46609e74b670430a7 100644 --- a/src/share/schema/ob_table_schema.cpp +++ b/src/share/schema/ob_table_schema.cpp @@ -3597,6 +3597,17 @@ int ObTableSchema::check_column_can_be_altered(const ObColumnSchemaV2* src_schem "dst", dst_schema->get_data_type(), K(ret)); + } else if ((src_schema->get_meta_type().is_varying_len_char_type() + || src_schema->get_meta_type().is_text()) + && dst_schema->get_meta_type().is_fixed_len_char_type()) { + ret = OB_NOT_SUPPORTED; + LOG_USER_ERROR(OB_NOT_SUPPORTED, "Change to fixed length char type"); + LOG_WARN("can't not change to fixed length char type", + "src", + src_schema->get_data_type(), + "dst", + dst_schema->get_data_type(), + K(ret)); } else { tmp_column = get_column_schema(dst_schema->get_column_name()); if ((NULL != tmp_column) && (tmp_column != src_schema)) { diff --git a/src/sql/engine/table/ob_table_scan_with_checksum.cpp b/src/sql/engine/table/ob_table_scan_with_checksum.cpp index e1a80fd9dadff10df997c45e33e2a1e48402392e..5e948295d30215477835a8495afd1bbf573dfd13 100644 --- a/src/sql/engine/table/ob_table_scan_with_checksum.cpp +++ b/src/sql/engine/table/ob_table_scan_with_checksum.cpp @@ -123,7 +123,24 @@ int ObTableScanWithChecksum::ObTableScanWithChecksumCtx::allocate_checksum_memor return ret; } -int ObTableScanWithChecksum::ObTableScanWithChecksumCtx::add_row_checksum(const common::ObNewRow* row) +int ObTableScanWithChecksum::ObTableScanWithChecksumCtx::calc_checksum(const ObObj &obj, int64_t &checksum) const +{ + int ret = OB_SUCCESS; + if (obj.is_fixed_len_char_type()) { + ObObj trunc_obj; + const char *ptr = obj.get_string_ptr(); + int32_t len = obj.get_string_len(); + int32_t trunc_len_byte = static_cast(ObCharset::strlen_byte_no_sp(obj.get_collation_type(), ptr, len)); + trunc_obj.copy_meta_type(obj.get_meta()); + trunc_obj.set_string(obj.get_type(), ObString(trunc_len_byte, ptr)); + checksum = trunc_obj.checksum_v2(0); + } else { + checksum = obj.checksum_v2(0); + } + return ret; +} + +int ObTableScanWithChecksum::ObTableScanWithChecksumCtx::add_row_checksum(const common::ObNewRow *row) { int ret = OB_SUCCESS; if (OB_ISNULL(row)) { @@ -139,7 +156,12 @@ int ObTableScanWithChecksum::ObTableScanWithChecksumCtx::add_row_checksum(const row->count_); } else { for (int64_t i = 0; OB_SUCC(ret) && i < row->count_; ++i) { - checksum_[i] += row->cells_[i].checksum_v2(0); + int64_t checksum = 0; + if (OB_FAIL(calc_checksum(row->cells_[i], checksum))) { + LOG_WARN("failed to calculate checksum", K(ret)); + } else { + checksum_[i] += checksum; + } } } return ret; diff --git a/src/sql/engine/table/ob_table_scan_with_checksum.h b/src/sql/engine/table/ob_table_scan_with_checksum.h index 0527c7c1d44d0455cc9b1aae91f29e591e9c552d..597ffc7de734031d1ef9d905ddafc80684fb0109 100644 --- a/src/sql/engine/table/ob_table_scan_with_checksum.h +++ b/src/sql/engine/table/ob_table_scan_with_checksum.h @@ -58,7 +58,8 @@ protected: virtual void destroy(); int get_output_col_ids(const share::schema::ObTableParam& table_param); int allocate_checksum_memory(); - int add_row_checksum(const common::ObNewRow* row); + int calc_checksum(const ObObj &obj, int64_t &checksum) const; + int add_row_checksum(const common::ObNewRow *row); int report_checksum(const int64_t execution_id); public: diff --git a/src/storage/ob_partition_storage.cpp b/src/storage/ob_partition_storage.cpp index ba0e8135e559e9b1cc5dc3a3aceec89075459cc6..ae28886b1bebb670cd6770e93a26bf5e84a3385f 100644 --- a/src/storage/ob_partition_storage.cpp +++ b/src/storage/ob_partition_storage.cpp @@ -907,7 +907,7 @@ int ObPartitionStorage::malloc_rows_reshape_if_need(ObIAllocator& work_allocator for (int64_t i = 0; OB_SUCC(ret) && i < col_descs.count(); ++i) { const share::schema::ObColDesc& col_desc = col_descs.at(i); - if (col_desc.col_type_.is_char() || col_desc.col_type_.is_binary()) { + if (col_desc.col_type_.is_fixed_len_char_type() || col_desc.col_type_.is_binary()) { char_binary_exists = true; if (col_desc.col_type_.is_binary()) { char_only = false; @@ -6001,7 +6001,15 @@ int ObPartitionStorage::local_sort_index_by_range( } ObTableSchemaParam schema_param(allocator); ObRelativeTable relative_table; - ObSQLMode ob_sql_mode = common::ob_compatibility_mode_to_sql_mode(static_cast(sql_mode)); + ObSQLMode sql_mode_for_ddl_reshape = SMO_TRADITIONAL; + // Hack to prevent row reshaping from converting empty string to null. + // + // Supposing we have a row of type varchar with some spaces and an index on this column, + // and then we convert this column to char. In this case, the DDL routine will first rebuild + // the data table and then rebuilding the index table. The row may be reshaped as follows. + // + // - without hack: ' '(varchar) => ''(char) => null(char) + // - with hack: ' '(varchar) => ''(char) => ''(char) ObFixedArray column_ids(allocator, org_col_ids.count()); RowReshape *row_reshape_ins = nullptr; for (int64_t i = 0; OB_SUCC(ret) && i < org_col_ids.count(); i++) { @@ -6017,7 +6025,7 @@ int ObPartitionStorage::local_sort_index_by_range( ret = OB_ERR_UNEXPECTED; LOG_WARN("failed to set schema param", K(ret)); } else if (OB_FAIL(malloc_rows_reshape_if_need( - allocator, org_col_ids, 1, relative_table, ob_sql_mode, row_reshape_ins))) { + allocator, org_col_ids, 1, relative_table, sql_mode_for_ddl_reshape, row_reshape_ins))) { STORAGE_LOG(WARN, "failed to malloc for row reshape", K(ret)); } else { // do nothing @@ -6142,8 +6150,12 @@ int ObPartitionStorage::local_sort_index_by_range( } } } - } else if (OB_FAIL(reshape_table_rows( - &tmp_row.row_val_, row_reshape_ins, org_col_ids.count(), &new_row, 1, ob_sql_mode))) { + } else if (OB_FAIL(reshape_table_rows(&tmp_row.row_val_, + row_reshape_ins, + org_col_ids.count(), + &new_row, + 1, + sql_mode_for_ddl_reshape))) { STORAGE_LOG(WARN, "failed to reshape rows", K(ret)); } else { tmp_row = new_row; @@ -7337,8 +7349,38 @@ int ObPartitionStorage::append_local_sort_data(const share::ObBuildIndexAppendLo STORAGE_LOG(WARN, "Fail to open macro block writer, ", K(ret)); } else { ObStoreRow row; - ObNewRow* row_val = NULL; + ObNewRow *row_val = NULL; + ObArenaAllocator allocator(lib::ObLabel("PartStorageTmp")); + ObColDescArray col_descs; + ObTableSchemaParam schema_param(allocator); + ObRelativeTable relative_table; + ObSQLMode sql_mode_for_ddl_reshape = SMO_TRADITIONAL; // see local_sort_index_by_range + ObFixedArray column_ids(allocator, data_desc.row_column_count_); + RowReshape *row_reshape_ins = nullptr; row.flag_ = ObActionFlag::OP_ROW_EXIST; + for (int64_t i = 0; OB_SUCC(ret) && i < data_desc.row_column_count_; i++) { + ObColDesc col_desc; + col_desc.col_id_ = data_desc.column_ids_[i]; + col_desc.col_order_ = data_desc.column_orders_[i]; + col_desc.col_type_ = data_desc.column_types_[i]; + if (OB_FAIL(col_descs.push_back(col_desc))) { + LOG_WARN("failed to push back col desc", K(ret)); + } else if (OB_FAIL(column_ids.push_back(col_desc.col_id_))) { + LOG_WARN("failed to push back column id", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(schema_param.convert(index_schema, column_ids))) { + LOG_WARN("failed to convert schema param", K(ret)); + } else if (OB_UNLIKELY(false == relative_table.set_schema_param(&schema_param))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to set schema param", K(ret)); + } else if (OB_FAIL(malloc_rows_reshape_if_need( + allocator, col_descs, 1, relative_table, sql_mode_for_ddl_reshape, row_reshape_ins))) { + STORAGE_LOG(WARN, "failed to malloc for row reshape", K(ret)); + } else { + // do nothing + } while (OB_SUCC(ret)) { if (OB_FAIL(THIS_WORKER.check_status())) { STORAGE_LOG(WARN, "failed to check status", K(ret)); @@ -7350,8 +7392,10 @@ int ObPartitionStorage::append_local_sort_data(const share::ObBuildIndexAppendLo break; } } else { - row.row_val_.assign(row_val->cells_, row_val->count_); - if (OB_FAIL(writer.append_row(row))) { + if (OB_FAIL(reshape_table_rows( + row_val, row_reshape_ins, col_descs.count(), &row, 1, sql_mode_for_ddl_reshape))) { + STORAGE_LOG(WARN, "failed to reshape rows", K(ret)); + } else if (OB_FAIL(writer.append_row(row))) { if (OB_ERR_PRIMARY_KEY_DUPLICATE == ret && index_schema->is_unique_index()) { LOG_USER_ERROR( OB_ERR_PRIMARY_KEY_DUPLICATE, "", static_cast(sizeof("UNIQUE IDX") - 1), "UNIQUE IDX"); @@ -7363,7 +7407,7 @@ int ObPartitionStorage::append_local_sort_data(const share::ObBuildIndexAppendLo } } } - + free_row_reshape(allocator, row_reshape_ins, 1); if (OB_SUCC(ret)) { if (OB_FAIL(writer.close())) { STORAGE_LOG(WARN, "fail to close writer", K(ret));