Skip to content
Permalink
Browse files

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
  • Loading branch information...
kevgs committed Jun 17, 2019
1 parent 854c219 commit a82e42fd133949b560790c9b74a4072f899baee4
@@ -2449,12 +2449,12 @@ void Field_null::sql_type(String &res) const
}


uint Field_null::is_equal(Create_field *new_field)
bool Field_null::is_equal(const Column_definition &new_field) const
{
DBUG_ASSERT(!compression_method());
return new_field->type_handler() == type_handler() &&
new_field->charset == field_charset &&
new_field->length == max_display_length();
return new_field.type_handler() == type_handler() &&
new_field.charset == field_charset &&
new_field.length == max_display_length();
}


@@ -3492,15 +3492,15 @@ bool Field_new_decimal::compatible_field_size(uint field_metadata,
}


uint Field_new_decimal::is_equal(Create_field *new_field)
bool Field_new_decimal::is_equal(const Column_definition &new_field) const
{
return ((new_field->type_handler() == type_handler()) &&
((new_field->flags & UNSIGNED_FLAG) ==
return ((new_field.type_handler() == type_handler()) &&
((new_field.flags & UNSIGNED_FLAG) ==
(uint) (flags & UNSIGNED_FLAG)) &&
((new_field->flags & AUTO_INCREMENT_FLAG) <=
((new_field.flags & AUTO_INCREMENT_FLAG) <=
(uint) (flags & AUTO_INCREMENT_FLAG)) &&
(new_field->length == max_display_length()) &&
(new_field->decimals == dec));
(new_field.length == max_display_length()) &&
(new_field.decimals == dec));
}


@@ -5585,10 +5585,10 @@ bool Field_timestampf::val_native(Native *to)


/*************************************************************/
uint Field_temporal::is_equal(Create_field *new_field)
bool Field_temporal::is_equal(const Column_definition &new_field) const
{
return new_field->type_handler() == type_handler() &&
new_field->length == max_display_length();
return new_field.type_handler() == type_handler() &&
new_field.length == max_display_length();
}


@@ -7073,40 +7073,13 @@ int Field_str::store(double nr)
return store(buff, (uint)length, &my_charset_numeric);
}

uint Field_longstr::
is_equal_for_different_charsets(const Column_definition &to) const
{
Charset field_cs(field_charset);
if (!field_cs.encoding_allows_reinterpret_as(to.charset))
return IS_EQUAL_NO;

if (!field_cs.eq_collation_specific_names(to.charset))
return IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET_BUT_COLLATE;

return IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET;
}

uint Field_string::is_equal(Create_field *new_field)
bool Field_string::is_equal(const Column_definition &new_field) const
{
DBUG_ASSERT(!compression_method());
if (new_field->type_handler() != type_handler())
return IS_EQUAL_NO;
if (new_field->char_length < char_length())
return IS_EQUAL_NO;

if (new_field->charset != field_charset)
{
if (new_field->length != max_display_length() &&
table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION)
return IS_EQUAL_NO;

return is_equal_for_different_charsets(*new_field);
}

if (new_field->length != max_display_length())
return IS_EQUAL_NO;

return IS_EQUAL_YES;
return new_field.type_handler() == type_handler() &&
new_field.char_length == char_length() &&
new_field.charset == field_charset &&
new_field.length == max_display_length();
}


@@ -7940,48 +7913,13 @@ Field *Field_varstring::new_key_field(MEM_ROOT *root, TABLE *new_table,
return res;
}

/*
This check is InnoDB specific. ROW_FORMAT=REDUNDANT always allows such
enlargement. But other row formats can do this only for particular current
and new lengths. This is because InnoDB stores VARCHAR length in one or two
bytes.
*/
static bool supports_such_enlargement(const Field *field,
const Create_field *new_field)
bool Field_varstring::is_equal(const Column_definition &new_field) const
{
return field->field_length <= 127 || new_field->length <= 255 ||
field->field_length > 255 ||
(field->table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION);
}

uint Field_varstring::is_equal(Create_field *new_field)
{
if (new_field->length < field_length)
return IS_EQUAL_NO;
if (new_field->char_length < char_length())
return IS_EQUAL_NO;
if (!new_field->compression_method() != !compression_method())
return IS_EQUAL_NO;
if (new_field->type_handler() != type_handler())
return IS_EQUAL_NO;

if (new_field->charset != field_charset)
{
if (!supports_such_enlargement(this, new_field))
return IS_EQUAL_NO;

return is_equal_for_different_charsets(*new_field);
}

if (new_field->length != field_length)
{
if (!supports_such_enlargement(this, new_field))
return IS_EQUAL_NO;

return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer length
}

return IS_EQUAL_YES;
return new_field.type_handler() == type_handler() &&
new_field.length == field_length &&
new_field.char_length == char_length() &&
!new_field.compression_method() == !compression_method() &&
new_field.charset == field_charset;
}


@@ -8745,21 +8683,12 @@ uint Field_blob::max_packed_col_length(uint max_length)
again an already compressed field just because compression method changes.
*/

uint Field_blob::is_equal(Create_field *new_field)
bool Field_blob::is_equal(const Column_definition &new_field) const
{
if (new_field->type_handler() != type_handler())
return IS_EQUAL_NO;

if (!new_field->compression_method() != !compression_method())
return IS_EQUAL_NO;

if (new_field->pack_length != pack_length())
return IS_EQUAL_NO;

if (field_charset != new_field->charset)
return is_equal_for_different_charsets(*new_field);

return IS_EQUAL_YES;
return new_field.type_handler() == type_handler() &&
!new_field.compression_method() == !compression_method() &&
new_field.pack_length == pack_length() &&
new_field.charset == field_charset;
}


@@ -9068,16 +8997,16 @@ Field::geometry_type Field_geom::geometry_type_merge(geometry_type a,
}


uint Field_geom::is_equal(Create_field *new_field)
bool Field_geom::is_equal(const Column_definition &new_field) const
{
return new_field->type_handler() == type_handler() &&
return new_field.type_handler() == type_handler() &&
/*
- Allow ALTER..INPLACE to supertype (GEOMETRY),
e.g. POINT to GEOMETRY or POLYGON to GEOMETRY.
- Allow ALTER..INPLACE to the same geometry type: POINT -> POINT
*/
(new_field->geom_type == geom_type ||
new_field->geom_type == GEOM_GEOMETRY);
(new_field.geom_type == geom_type ||
new_field.geom_type == GEOM_GEOMETRY);
}


@@ -9507,36 +9436,36 @@ bool Field_enum::eq_def(const Field *field) const
alteration purposes. Fields are equal if they retain the same
pack length and if new members are added to the end of the list.
@return IS_EQUAL_YES if fields are compatible.
IS_EQUAL_NO otherwise.
@return true if fields are compatible.
false otherwise.
*/

uint Field_enum::is_equal(Create_field *new_field)
bool Field_enum::is_equal(const Column_definition &new_field) const
{
TYPELIB *values= new_field->interval;
TYPELIB *values= new_field.interval;

/*
The fields are compatible if they have the same flags,
type, charset and have the same underlying length.
*/
if (new_field->type_handler() != type_handler() ||
new_field->charset != field_charset ||
new_field->pack_length != pack_length())
return IS_EQUAL_NO;
if (new_field.type_handler() != type_handler() ||
new_field.charset != field_charset ||
new_field.pack_length != pack_length())
return false;

/*
Changing the definition of an ENUM or SET column by adding a new
enumeration or set members to the end of the list of valid member
values only alters table metadata and not table data.
*/
if (typelib->count > values->count)
return IS_EQUAL_NO;
return false;

/* Check whether there are modification before the end. */
if (! compare_type_names(field_charset, typelib, new_field->interval))
return IS_EQUAL_NO;
if (! compare_type_names(field_charset, typelib, new_field.interval))
return false;

return IS_EQUAL_YES;
return true;
}


@@ -9582,17 +9511,17 @@ bool Field_num::eq_def(const Field *field) const
and retain the same pack length.
*/

uint Field_num::is_equal(Create_field *new_field)
bool Field_num::is_equal(const Column_definition &new_field) const
{
if (((new_field->flags & UNSIGNED_FLAG) != (flags & UNSIGNED_FLAG)) ||
((new_field->flags & AUTO_INCREMENT_FLAG) > (flags & AUTO_INCREMENT_FLAG)))
return IS_EQUAL_NO;
if (((new_field.flags & UNSIGNED_FLAG) != (flags & UNSIGNED_FLAG)) ||
((new_field.flags & AUTO_INCREMENT_FLAG) > (flags & AUTO_INCREMENT_FLAG)))
return false;

const Type_handler *th= type_handler(), *new_th = new_field->type_handler();
const Type_handler *th= type_handler(), *new_th = new_field.type_handler();

if (th == new_th && new_field->pack_length == pack_length())
return IS_EQUAL_YES;
/* FIXME: Test and consider returning IS_EQUAL_YES for the following:
if (th == new_th && new_field.pack_length == pack_length())
return true;
/* FIXME: Test and consider returning true for the following:
TINYINT UNSIGNED to BIT(8)
SMALLINT UNSIGNED to BIT(16)
MEDIUMINT UNSIGNED to BIT(24)
@@ -9607,10 +9536,10 @@ uint Field_num::is_equal(Create_field *new_field)
Note: InnoDB stores integers in big-endian format, and BIT appears
to use big-endian format. For storage engines that use little-endian
format for integers, we can only return IS_EQUAL_YES for the TINYINT
format for integers, we can only return true for the TINYINT
conversion. */

return IS_EQUAL_NO;
return false;
}


@@ -9757,10 +9686,10 @@ Field *Field_bit::new_key_field(MEM_ROOT *root, TABLE *new_table,
}


uint Field_bit::is_equal(Create_field *new_field)
bool Field_bit::is_equal(const Column_definition &new_field) const
{
return new_field->type_handler() == type_handler() &&
new_field->length == max_display_length();
return new_field.type_handler() == type_handler() &&
new_field.length == max_display_length();
}


0 comments on commit a82e42f

Please sign in to comment.
You can’t perform that action at this time.