mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
NFC: refactor Field::is_equal() and related stuff
Make Field::is_equal() const and return bool as it's a naturally fitting
type for it. Also it's agrument was narrowed to Column_definition.
InnoDB can change type of some columns by itself. InnoDB-specific code used to
reside in Field_xxx:is_equal() methods. Now engine-specific stuff was
moved to a virtual methods of handler::can_convert{string,varstring,blob,geom}.
These methods are called by Field::can_be_converted_by_engine() which is a
double dispatch pattern.
Some InnoDB-specific code still resides in compare_keys_but_name(). It should
be moved from here someday to handler::compare_key_parts(...) or similar.
IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET
IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET_BUT_COLLATE: both was removed
IS_EQUAL_NO, IS_EQUAL_YES are not needed now and should be removed
along with deprecated handler::check_if_incompatible_data().
HA_EXTENDED_TYPES_CONVERSION: was removed as such logic is not needed now by
server code.
ALTER_COLUMN_EQUAL_PACK_LENGTH: was renamed to a more generic
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE
This commit is contained in:
143
sql/sql_table.cc
143
sql/sql_table.cc
@@ -6560,27 +6560,28 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key,
|
||||
if the user key part length is different.
|
||||
*/
|
||||
const Field *old_field= table->field[key_part->fieldnr - 1];
|
||||
auto old_field_len= old_field->pack_length();
|
||||
|
||||
if (old_field->type() == MYSQL_TYPE_VARCHAR)
|
||||
bool is_equal= key_part->field->is_equal(*new_field);
|
||||
/* TODO: below is an InnoDB specific code which should be moved to InnoDB */
|
||||
if (!is_equal)
|
||||
{
|
||||
old_field_len= (old_field->pack_length() -
|
||||
((Field_varstring *) old_field)->length_bytes);
|
||||
if (!key_part->field->can_be_converted_by_engine(*new_field))
|
||||
return Compare_keys::NotEqual;
|
||||
|
||||
if (!Charset(old_field->charset())
|
||||
.eq_collation_specific_names(new_field->charset))
|
||||
return Compare_keys::NotEqual;
|
||||
}
|
||||
|
||||
uint is_equal= key_part->field->is_equal(new_field);
|
||||
if (key_part->length == old_field_len &&
|
||||
key_part->length < new_part->length &&
|
||||
(is_equal == IS_EQUAL_PACK_LENGTH ||
|
||||
is_equal == IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET))
|
||||
if (key_part->length != new_part->length)
|
||||
{
|
||||
if (key_part->length != old_field->field_length ||
|
||||
key_part->length >= new_part->length || is_equal)
|
||||
{
|
||||
return Compare_keys::NotEqual;
|
||||
}
|
||||
result= Compare_keys::EqualButKeyPartLength;
|
||||
}
|
||||
else if (key_part->length != new_part->length)
|
||||
return Compare_keys::NotEqual;
|
||||
|
||||
if (is_equal == IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET_BUT_COLLATE)
|
||||
return Compare_keys::NotEqual;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -6602,40 +6603,6 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key,
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Change Field::is_equal() result depending on field being a part of some index.
|
||||
*/
|
||||
static uint process_is_equal_result_for_key_parts(uint is_equal,
|
||||
const Field *old_field,
|
||||
const Create_field *new_field)
|
||||
{
|
||||
if (is_equal == IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET)
|
||||
return IS_EQUAL_PACK_LENGTH;
|
||||
|
||||
if (is_equal == IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET_BUT_COLLATE)
|
||||
{
|
||||
bool part_of_a_key= !new_field->field->part_of_key.is_clear_all();
|
||||
|
||||
if (part_of_a_key)
|
||||
{
|
||||
const TABLE_SHARE *s= new_field->field->table->s;
|
||||
|
||||
bool part_of_a_primary_key=
|
||||
s->primary_key != MAX_KEY &&
|
||||
new_field->field->part_of_key.is_set(s->primary_key);
|
||||
|
||||
if (part_of_a_primary_key)
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
return IS_EQUAL_PACK_LENGTH;
|
||||
}
|
||||
|
||||
return IS_EQUAL_PACK_LENGTH;
|
||||
}
|
||||
|
||||
return is_equal;
|
||||
}
|
||||
|
||||
/**
|
||||
Compare original and new versions of a table and fill Alter_inplace_info
|
||||
describing differences between those versions.
|
||||
@@ -6770,61 +6737,50 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar,
|
||||
/* Field is not dropped. Evaluate changes bitmap for it. */
|
||||
|
||||
/*
|
||||
Check if type of column has changed to some incompatible type.
|
||||
Check if type of column has changed.
|
||||
*/
|
||||
uint is_equal= field->is_equal(new_field);
|
||||
switch (process_is_equal_result_for_key_parts(is_equal, field, new_field))
|
||||
bool is_equal= field->is_equal(*new_field);
|
||||
if (!is_equal)
|
||||
{
|
||||
case IS_EQUAL_NO:
|
||||
/* New column type is incompatible with old one. */
|
||||
if (field->stored_in_db())
|
||||
ha_alter_info->handler_flags|= ALTER_STORED_COLUMN_TYPE;
|
||||
else
|
||||
ha_alter_info->handler_flags|= ALTER_VIRTUAL_COLUMN_TYPE;
|
||||
if (table->s->tmp_table == NO_TMP_TABLE)
|
||||
if (field->can_be_converted_by_engine(*new_field))
|
||||
{
|
||||
delete_statistics_for_column(thd, table, field);
|
||||
KEY *key_info= table->key_info;
|
||||
for (uint i=0; i < table->s->keys; i++, key_info++)
|
||||
/*
|
||||
New column type differs from the old one, but storage engine can
|
||||
change it by itself.
|
||||
(for example, VARCHAR(300) is changed to VARCHAR(400)).
|
||||
*/
|
||||
ha_alter_info->handler_flags|= ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* New column type is incompatible with old one. */
|
||||
ha_alter_info->handler_flags|= field->stored_in_db()
|
||||
? ALTER_STORED_COLUMN_TYPE
|
||||
: ALTER_VIRTUAL_COLUMN_TYPE;
|
||||
|
||||
if (table->s->tmp_table == NO_TMP_TABLE)
|
||||
{
|
||||
if (field->part_of_key.is_set(i))
|
||||
delete_statistics_for_column(thd, table, field);
|
||||
KEY *key_info= table->key_info;
|
||||
for (uint i= 0; i < table->s->keys; i++, key_info++)
|
||||
{
|
||||
if (!field->part_of_key.is_set(i))
|
||||
continue;
|
||||
|
||||
uint key_parts= table->actual_n_key_parts(key_info);
|
||||
for (uint j= 0; j < key_parts; j++)
|
||||
{
|
||||
if (key_info->key_part[j].fieldnr-1 == field->field_index)
|
||||
if (key_info->key_part[j].fieldnr - 1 == field->field_index)
|
||||
{
|
||||
delete_statistics_for_index(thd, table, key_info,
|
||||
j >= key_info->user_defined_key_parts);
|
||||
delete_statistics_for_index(
|
||||
thd, table, key_info,
|
||||
j >= key_info->user_defined_key_parts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IS_EQUAL_YES:
|
||||
/*
|
||||
New column is the same as the old one or the fully compatible with
|
||||
it (for example, ENUM('a','b') was changed to ENUM('a','b','c')).
|
||||
Such a change if any can ALWAYS be carried out by simply updating
|
||||
data-dictionary without even informing storage engine.
|
||||
No flag is set in this case.
|
||||
*/
|
||||
break;
|
||||
case IS_EQUAL_PACK_LENGTH:
|
||||
/*
|
||||
New column type differs from the old one, but has compatible packed
|
||||
data representation. Depending on storage engine, such a change can
|
||||
be carried out by simply updating data dictionary without changing
|
||||
actual data (for example, VARCHAR(300) is changed to VARCHAR(400)).
|
||||
*/
|
||||
ha_alter_info->handler_flags|= ALTER_COLUMN_EQUAL_PACK_LENGTH;
|
||||
break;
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
/* Safety. */
|
||||
ha_alter_info->handler_flags|= ALTER_STORED_COLUMN_TYPE;
|
||||
}
|
||||
|
||||
if (field->vcol_info || new_field->vcol_info)
|
||||
@@ -6835,7 +6791,7 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar,
|
||||
ALTER_VIRTUAL_COLUMN_TYPE);
|
||||
if (field->vcol_info && new_field->vcol_info)
|
||||
{
|
||||
bool value_changes= is_equal == IS_EQUAL_NO;
|
||||
bool value_changes= !is_equal;
|
||||
alter_table_operations alter_expr;
|
||||
if (field->stored_in_db())
|
||||
alter_expr= ALTER_STORED_GCOL_EXPR;
|
||||
@@ -6929,7 +6885,6 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar,
|
||||
ha_alter_info->create_info->fields_option_struct[f_ptr - table->field]=
|
||||
new_field->option_struct;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -7294,7 +7249,7 @@ bool mysql_compare_tables(TABLE *table,
|
||||
DBUG_RETURN(false);
|
||||
|
||||
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
|
||||
uint field_changes= field->is_equal(tmp_new_field);
|
||||
uint field_changes= field->is_equal(*tmp_new_field);
|
||||
if (field_changes != IS_EQUAL_YES)
|
||||
DBUG_RETURN(false);
|
||||
|
||||
@@ -8797,7 +8752,7 @@ fk_check_column_changes(THD *thd, Alter_info *alter_info,
|
||||
return FK_COLUMN_RENAMED;
|
||||
}
|
||||
|
||||
if ((old_field->is_equal(new_field) == IS_EQUAL_NO) ||
|
||||
if ((old_field->is_equal(*new_field) == IS_EQUAL_NO) ||
|
||||
((new_field->flags & NOT_NULL_FLAG) &&
|
||||
!(old_field->flags & NOT_NULL_FLAG)))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user