diff options
Diffstat (limited to 'storage/innobase/handler/ha_innodb.cc')
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 146 |
1 files changed, 141 insertions, 5 deletions
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 88ea6f5e642..107fcac762a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -54,6 +54,7 @@ this program; if not, write to the Free Software Foundation, Inc., #include <my_bitmap.h> #include <mysql/service_thd_alloc.h> #include <mysql/service_thd_wait.h> +#include "field.h" // MYSQL_PLUGIN_IMPORT extern my_bool lower_case_file_system; // MYSQL_PLUGIN_IMPORT extern char mysql_unpacked_real_data_home[]; @@ -6141,11 +6142,6 @@ no_such_table: DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); } - if (!ib_table->not_redundant()) { - m_int_table_flags |= HA_EXTENDED_TYPES_CONVERSION; - cached_table_flags |= HA_EXTENDED_TYPES_CONVERSION; - } - size_t n_fields = omits_virtual_cols(*table_share) ? table_share->stored_fields : table_share->fields; size_t n_cols = dict_table_get_n_user_cols(ib_table) @@ -20875,6 +20871,146 @@ bool ha_innobase::rowid_filter_push(Rowid_filter* pk_filter) DBUG_RETURN(false); } +static bool +is_part_of_a_primary_key(const Field* field) +{ + const TABLE_SHARE* s = field->table->s; + + return s->primary_key != MAX_KEY + && field->part_of_key.is_set(s->primary_key); +} + +bool +ha_innobase::can_convert_string(const Field_string* field, + const Column_definition& new_type) const +{ + DBUG_ASSERT(!field->compression_method()); + if (new_type.type_handler() != field->type_handler()) { + return false; + } + + if (new_type.char_length < field->char_length()) { + return false; + } + + if (new_type.charset != field->charset()) { + if (new_type.length != field->max_display_length() + && !m_prebuilt->table->not_redundant()) { + return IS_EQUAL_NO; + } + + Charset field_cs(field->charset()); + if (!field_cs.encoding_allows_reinterpret_as( + new_type.charset)) { + return false; + } + + if (!field_cs.eq_collation_specific_names(new_type.charset)) { + return !is_part_of_a_primary_key(field); + } + + return true; + } + + if (new_type.length != field->max_display_length()) { + return false; + } + + return true; +} + +static bool +supports_enlarging(const dict_table_t* table, const Field_varstring* field, + const Column_definition& new_type) +{ + return field->field_length <= 127 || new_type.length <= 255 + || field->field_length > 255 || !table->not_redundant(); +} + +bool +ha_innobase::can_convert_varstring(const Field_varstring* field, + const Column_definition& new_type) const +{ + if (new_type.length < field->field_length) { + return false; + } + + if (new_type.char_length < field->char_length()) { + return false; + } + + if (!new_type.compression_method() != !field->compression_method()) { + return false; + } + + if (new_type.type_handler() != field->type_handler()) { + return false; + } + + if (new_type.charset != field->charset()) { + if (!supports_enlarging(m_prebuilt->table, field, new_type)) { + return false; + } + + Charset field_cs(field->charset()); + if (!field_cs.encoding_allows_reinterpret_as( + new_type.charset)) { + return false; + } + + if (!field_cs.eq_collation_specific_names(new_type.charset)) { + return !is_part_of_a_primary_key(field); + } + + return true; + } + + if (new_type.length != field->field_length) { + if (!supports_enlarging(m_prebuilt->table, field, new_type)) { + return false; + } + + return true; + } + + return true; +} + +bool +ha_innobase::can_convert_blob(const Field_blob* field, + const Column_definition& new_type) const +{ + if (new_type.type_handler() != field->type_handler()) { + return false; + } + + if (!new_type.compression_method() != !field->compression_method()) { + return false; + } + + if (new_type.pack_length != field->pack_length()) { + return false; + } + + if (new_type.charset != field->charset()) { + Charset field_cs(field->charset()); + if (!field_cs.encoding_allows_reinterpret_as( + new_type.charset)) { + return false; + } + + if (!field_cs.eq_collation_specific_names(new_type.charset)) { + bool is_part_of_a_key + = !field->part_of_key.is_clear_all(); + return !is_part_of_a_key; + } + + return true; + } + + return true; +} + /******************************************************************//** Use this when the args are passed to the format string from errmsg-utf8.txt directly as is. |