1
0
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:
Alexander Barkov
2019-04-19 15:18:38 +04:00
parent 9aa80fcf46
commit c59d6395a6
8 changed files with 925 additions and 847 deletions

View File

@ -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)
{