mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
A joint patch for MDEV-19284 and MDEV-19285 (INSTANT ALTER)
This patch fixes: - MDEV-19284 INSTANT ALTER with ucs2-to-utf16 conversion produces bad data - MDEV-19285 INSTANT ALTER from ascii_general_ci to latin1_general_ci produces corrupt data These regressions were introduced in 10.4.3 by: - MDEV-15564 Avoid table rebuild in ALTER TABLE on collation or charset changes Changes: 1. Cleanup: Adding a helper method Field_longstr::csinfo_change_allows_instant_alter(), to remove some duplicate code in field.cc. 2. Cleanup: removing Type_handler::Charsets_are_compatible() and static function charsets_are_compatible() and introducing new methods in the recently added class Charset instead: - encoding_allows_reinterpret_as() - encoding_and_order_allow_reinterpret_as() 3. Bug fix: Removing the code that allowed instant conversion for ascii-to->8bit and ucs2-to->utf16. This actually fixes MDEV-19284 and MDEV-19285. 4. Bug fix: Adding a helper method Charset::collation_specific_name(). The old corresponding code in Type_handler::Charsets_are_compatible() was not safe against (badly named) user-defined collations whose character set name can be longer than collation name.
This commit is contained in:
25
sql/field.cc
25
sql/field.cc
@ -7092,6 +7092,17 @@ int Field_str::store(double nr)
|
||||
}
|
||||
|
||||
|
||||
bool Field_longstr::
|
||||
csinfo_change_allows_instant_alter(const Create_field *to) const
|
||||
{
|
||||
Charset cs(field_charset);
|
||||
const bool part_of_a_key= !to->field->part_of_key.is_clear_all();
|
||||
return part_of_a_key ?
|
||||
cs.encoding_and_order_allow_reinterpret_as(to->charset) :
|
||||
cs.encoding_allows_reinterpret_as(to->charset);
|
||||
}
|
||||
|
||||
|
||||
uint Field_string::is_equal(Create_field *new_field)
|
||||
{
|
||||
DBUG_ASSERT(!compression_method());
|
||||
@ -7102,9 +7113,7 @@ uint Field_string::is_equal(Create_field *new_field)
|
||||
if (new_field->char_length < char_length())
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
const bool part_of_a_key= !new_field->field->part_of_key.is_clear_all();
|
||||
if (!Type_handler::Charsets_are_compatible(field_charset, new_field->charset,
|
||||
part_of_a_key))
|
||||
if (!csinfo_change_allows_instant_alter(new_field))
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
if (new_field->length == max_display_length())
|
||||
@ -7954,9 +7963,7 @@ uint Field_varstring::is_equal(Create_field *new_field)
|
||||
if (!new_field->compression_method() != !compression_method())
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
bool part_of_a_key= !new_field->field->part_of_key.is_clear_all();
|
||||
if (!Type_handler::Charsets_are_compatible(field_charset, new_field->charset,
|
||||
part_of_a_key))
|
||||
if (!csinfo_change_allows_instant_alter(new_field))
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
const Type_handler *new_type_handler= new_field->type_handler();
|
||||
@ -8751,12 +8758,8 @@ uint Field_blob::is_equal(Create_field *new_field)
|
||||
return IS_EQUAL_NO;
|
||||
}
|
||||
|
||||
bool part_of_a_key= !new_field->field->part_of_key.is_clear_all();
|
||||
if (!Type_handler::Charsets_are_compatible(field_charset, new_field->charset,
|
||||
part_of_a_key))
|
||||
{
|
||||
if (!csinfo_change_allows_instant_alter(new_field))
|
||||
return IS_EQUAL_NO;
|
||||
}
|
||||
|
||||
if (field_charset != new_field->charset)
|
||||
{
|
||||
|
Reference in New Issue
Block a user