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:
parent
854c219a7f
commit
a82e42fd13
187
sql/field.cc
187
sql/field.cc
@ -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());
|
DBUG_ASSERT(!compression_method());
|
||||||
return new_field->type_handler() == type_handler() &&
|
return new_field.type_handler() == type_handler() &&
|
||||||
new_field->charset == field_charset &&
|
new_field.charset == field_charset &&
|
||||||
new_field->length == max_display_length();
|
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()) &&
|
return ((new_field.type_handler() == type_handler()) &&
|
||||||
((new_field->flags & UNSIGNED_FLAG) ==
|
((new_field.flags & UNSIGNED_FLAG) ==
|
||||||
(uint) (flags & UNSIGNED_FLAG)) &&
|
(uint) (flags & UNSIGNED_FLAG)) &&
|
||||||
((new_field->flags & AUTO_INCREMENT_FLAG) <=
|
((new_field.flags & AUTO_INCREMENT_FLAG) <=
|
||||||
(uint) (flags & AUTO_INCREMENT_FLAG)) &&
|
(uint) (flags & AUTO_INCREMENT_FLAG)) &&
|
||||||
(new_field->length == max_display_length()) &&
|
(new_field.length == max_display_length()) &&
|
||||||
(new_field->decimals == dec));
|
(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() &&
|
return new_field.type_handler() == type_handler() &&
|
||||||
new_field->length == max_display_length();
|
new_field.length == max_display_length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -7073,40 +7073,13 @@ int Field_str::store(double nr)
|
|||||||
return store(buff, (uint)length, &my_charset_numeric);
|
return store(buff, (uint)length, &my_charset_numeric);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint Field_longstr::
|
bool Field_string::is_equal(const Column_definition &new_field) const
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(!compression_method());
|
DBUG_ASSERT(!compression_method());
|
||||||
if (new_field->type_handler() != type_handler())
|
return new_field.type_handler() == type_handler() &&
|
||||||
return IS_EQUAL_NO;
|
new_field.char_length == char_length() &&
|
||||||
if (new_field->char_length < char_length())
|
new_field.charset == field_charset &&
|
||||||
return IS_EQUAL_NO;
|
new_field.length == max_display_length();
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -7940,48 +7913,13 @@ Field *Field_varstring::new_key_field(MEM_ROOT *root, TABLE *new_table,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
bool Field_varstring::is_equal(const Column_definition &new_field) const
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
return field->field_length <= 127 || new_field->length <= 255 ||
|
return new_field.type_handler() == type_handler() &&
|
||||||
field->field_length > 255 ||
|
new_field.length == field_length &&
|
||||||
(field->table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION);
|
new_field.char_length == char_length() &&
|
||||||
}
|
!new_field.compression_method() == !compression_method() &&
|
||||||
|
new_field.charset == field_charset;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -8745,21 +8683,12 @@ uint Field_blob::max_packed_col_length(uint max_length)
|
|||||||
again an already compressed field just because compression method changes.
|
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 new_field.type_handler() == type_handler() &&
|
||||||
return IS_EQUAL_NO;
|
!new_field.compression_method() == !compression_method() &&
|
||||||
|
new_field.pack_length == pack_length() &&
|
||||||
if (!new_field->compression_method() != !compression_method())
|
new_field.charset == field_charset;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -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),
|
- Allow ALTER..INPLACE to supertype (GEOMETRY),
|
||||||
e.g. POINT to GEOMETRY or POLYGON to GEOMETRY.
|
e.g. POINT to GEOMETRY or POLYGON to GEOMETRY.
|
||||||
- Allow ALTER..INPLACE to the same geometry type: POINT -> POINT
|
- Allow ALTER..INPLACE to the same geometry type: POINT -> POINT
|
||||||
*/
|
*/
|
||||||
(new_field->geom_type == geom_type ||
|
(new_field.geom_type == geom_type ||
|
||||||
new_field->geom_type == GEOM_GEOMETRY);
|
new_field.geom_type == GEOM_GEOMETRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -9507,22 +9436,22 @@ bool Field_enum::eq_def(const Field *field) const
|
|||||||
alteration purposes. Fields are equal if they retain the same
|
alteration purposes. Fields are equal if they retain the same
|
||||||
pack length and if new members are added to the end of the list.
|
pack length and if new members are added to the end of the list.
|
||||||
|
|
||||||
@return IS_EQUAL_YES if fields are compatible.
|
@return true if fields are compatible.
|
||||||
IS_EQUAL_NO otherwise.
|
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,
|
The fields are compatible if they have the same flags,
|
||||||
type, charset and have the same underlying length.
|
type, charset and have the same underlying length.
|
||||||
*/
|
*/
|
||||||
if (new_field->type_handler() != type_handler() ||
|
if (new_field.type_handler() != type_handler() ||
|
||||||
new_field->charset != field_charset ||
|
new_field.charset != field_charset ||
|
||||||
new_field->pack_length != pack_length())
|
new_field.pack_length != pack_length())
|
||||||
return IS_EQUAL_NO;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changing the definition of an ENUM or SET column by adding a new
|
Changing the definition of an ENUM or SET column by adding a new
|
||||||
@ -9530,13 +9459,13 @@ uint Field_enum::is_equal(Create_field *new_field)
|
|||||||
values only alters table metadata and not table data.
|
values only alters table metadata and not table data.
|
||||||
*/
|
*/
|
||||||
if (typelib->count > values->count)
|
if (typelib->count > values->count)
|
||||||
return IS_EQUAL_NO;
|
return false;
|
||||||
|
|
||||||
/* Check whether there are modification before the end. */
|
/* Check whether there are modification before the end. */
|
||||||
if (! compare_type_names(field_charset, typelib, new_field->interval))
|
if (! compare_type_names(field_charset, typelib, new_field.interval))
|
||||||
return IS_EQUAL_NO;
|
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.
|
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)) ||
|
if (((new_field.flags & UNSIGNED_FLAG) != (flags & UNSIGNED_FLAG)) ||
|
||||||
((new_field->flags & AUTO_INCREMENT_FLAG) > (flags & AUTO_INCREMENT_FLAG)))
|
((new_field.flags & AUTO_INCREMENT_FLAG) > (flags & AUTO_INCREMENT_FLAG)))
|
||||||
return IS_EQUAL_NO;
|
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())
|
if (th == new_th && new_field.pack_length == pack_length())
|
||||||
return IS_EQUAL_YES;
|
return true;
|
||||||
/* FIXME: Test and consider returning IS_EQUAL_YES for the following:
|
/* FIXME: Test and consider returning true for the following:
|
||||||
TINYINT UNSIGNED to BIT(8)
|
TINYINT UNSIGNED to BIT(8)
|
||||||
SMALLINT UNSIGNED to BIT(16)
|
SMALLINT UNSIGNED to BIT(16)
|
||||||
MEDIUMINT UNSIGNED to BIT(24)
|
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
|
Note: InnoDB stores integers in big-endian format, and BIT appears
|
||||||
to use big-endian format. For storage engines that use little-endian
|
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. */
|
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() &&
|
return new_field.type_handler() == type_handler() &&
|
||||||
new_field->length == max_display_length();
|
new_field.length == max_display_length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
58
sql/field.h
58
sql/field.h
@ -1503,13 +1503,16 @@ public:
|
|||||||
/* maximum possible display length */
|
/* maximum possible display length */
|
||||||
virtual uint32 max_display_length() const= 0;
|
virtual uint32 max_display_length() const= 0;
|
||||||
/**
|
/**
|
||||||
Whether a field being created is compatible with a existing one.
|
Whether a field being created has the samle type.
|
||||||
|
Used by the ALTER TABLE
|
||||||
Used by the ALTER TABLE code to evaluate whether the new definition
|
|
||||||
of a table is compatible with the old definition so that it can
|
|
||||||
determine if data needs to be copied over (table data change).
|
|
||||||
*/
|
*/
|
||||||
virtual uint is_equal(Create_field *new_field)= 0;
|
virtual bool is_equal(const Column_definition &new_field) const= 0;
|
||||||
|
// Used as double dispatch pattern: calls virtual method of handler
|
||||||
|
virtual bool
|
||||||
|
can_be_converted_by_engine(const Column_definition &new_type) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
/* convert decimal to longlong with overflow check */
|
/* convert decimal to longlong with overflow check */
|
||||||
longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag,
|
longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag,
|
||||||
int *err);
|
int *err);
|
||||||
@ -1809,7 +1812,7 @@ public:
|
|||||||
!((flags & UNSIGNED_FLAG) && !(from->flags & UNSIGNED_FLAG)) &&
|
!((flags & UNSIGNED_FLAG) && !(from->flags & UNSIGNED_FLAG)) &&
|
||||||
decimals() == from->decimals();
|
decimals() == from->decimals();
|
||||||
}
|
}
|
||||||
uint is_equal(Create_field *new_field);
|
bool is_equal(const Column_definition &new_field) const;
|
||||||
uint row_pack_length() const { return pack_length(); }
|
uint row_pack_length() const { return pack_length(); }
|
||||||
uint32 pack_length_from_metadata(uint field_metadata) {
|
uint32 pack_length_from_metadata(uint field_metadata) {
|
||||||
uint32 length= pack_length();
|
uint32 length= pack_length();
|
||||||
@ -1874,7 +1877,7 @@ public:
|
|||||||
bool val_bool() { return val_real() != 0e0; }
|
bool val_bool() { return val_real() != 0e0; }
|
||||||
virtual bool str_needs_quotes() { return TRUE; }
|
virtual bool str_needs_quotes() { return TRUE; }
|
||||||
bool eq_cmp_as_binary() { return MY_TEST(flags & BINARY_FLAG); }
|
bool eq_cmp_as_binary() { return MY_TEST(flags & BINARY_FLAG); }
|
||||||
virtual uint length_size() { return 0; }
|
virtual uint length_size() const { return 0; }
|
||||||
double pos_in_interval(Field *min, Field *max)
|
double pos_in_interval(Field *min, Field *max)
|
||||||
{
|
{
|
||||||
return pos_in_interval_val_str(min, max, length_size());
|
return pos_in_interval_val_str(min, max, length_size());
|
||||||
@ -1928,8 +1931,6 @@ protected:
|
|||||||
CHARSET_INFO *cs, size_t nchars);
|
CHARSET_INFO *cs, size_t nchars);
|
||||||
String *uncompress(String *val_buffer, String *val_ptr,
|
String *uncompress(String *val_buffer, String *val_ptr,
|
||||||
const uchar *from, uint from_length);
|
const uchar *from, uint from_length);
|
||||||
uint is_equal_for_different_charsets(const Column_definition &to) const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
|
Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
|
||||||
uchar null_bit_arg, utype unireg_check_arg,
|
uchar null_bit_arg, utype unireg_check_arg,
|
||||||
@ -2142,7 +2143,7 @@ public:
|
|||||||
uint row_pack_length() const { return pack_length(); }
|
uint row_pack_length() const { return pack_length(); }
|
||||||
bool compatible_field_size(uint field_metadata, Relay_log_info *rli,
|
bool compatible_field_size(uint field_metadata, Relay_log_info *rli,
|
||||||
uint16 mflags, int *order_var);
|
uint16 mflags, int *order_var);
|
||||||
uint is_equal(Create_field *new_field);
|
bool is_equal(const Column_definition &new_field) const;
|
||||||
virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data);
|
virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data);
|
||||||
Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item);
|
Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item);
|
||||||
};
|
};
|
||||||
@ -2646,7 +2647,7 @@ public:
|
|||||||
my_decimal *val_decimal(my_decimal *) { return 0; }
|
my_decimal *val_decimal(my_decimal *) { return 0; }
|
||||||
String *val_str(String *value,String *value2)
|
String *val_str(String *value,String *value2)
|
||||||
{ value2->length(0); return value2;}
|
{ value2->length(0); return value2;}
|
||||||
uint is_equal(Create_field *new_field);
|
bool is_equal(const Column_definition &new_field) const;
|
||||||
int cmp(const uchar *a, const uchar *b) { return 0;}
|
int cmp(const uchar *a, const uchar *b) { return 0;}
|
||||||
void sort_string(uchar *buff, uint length) {}
|
void sort_string(uchar *buff, uint length) {}
|
||||||
uint32 pack_length() const { return 0; }
|
uint32 pack_length() const { return 0; }
|
||||||
@ -2729,7 +2730,7 @@ public:
|
|||||||
CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; }
|
CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; }
|
||||||
bool binary() const { return true; }
|
bool binary() const { return true; }
|
||||||
bool val_bool() { return val_real() != 0e0; }
|
bool val_bool() { return val_real() != 0e0; }
|
||||||
uint is_equal(Create_field *new_field);
|
bool is_equal(const Column_definition &new_field) const;
|
||||||
bool eq_def(const Field *field) const
|
bool eq_def(const Field *field) const
|
||||||
{
|
{
|
||||||
return (Field::eq_def(field) && decimals() == field->decimals());
|
return (Field::eq_def(field) && decimals() == field->decimals());
|
||||||
@ -3570,7 +3571,11 @@ public:
|
|||||||
int cmp(const uchar *,const uchar *);
|
int cmp(const uchar *,const uchar *);
|
||||||
void sort_string(uchar *buff,uint length);
|
void sort_string(uchar *buff,uint length);
|
||||||
void sql_type(String &str) const;
|
void sql_type(String &str) const;
|
||||||
uint is_equal(Create_field *new_field);
|
bool is_equal(const Column_definition &new_field) const;
|
||||||
|
bool can_be_converted_by_engine(const Column_definition &new_type) const
|
||||||
|
{
|
||||||
|
return table->file->can_convert_string(this, new_type);
|
||||||
|
}
|
||||||
virtual uchar *pack(uchar *to, const uchar *from,
|
virtual uchar *pack(uchar *to, const uchar *from,
|
||||||
uint max_length);
|
uint max_length);
|
||||||
virtual const uchar *unpack(uchar* to, const uchar *from,
|
virtual const uchar *unpack(uchar* to, const uchar *from,
|
||||||
@ -3698,9 +3703,13 @@ public:
|
|||||||
Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
|
Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
|
||||||
uchar *new_ptr, uint32 length,
|
uchar *new_ptr, uint32 length,
|
||||||
uchar *new_null_ptr, uint new_null_bit);
|
uchar *new_null_ptr, uint new_null_bit);
|
||||||
uint is_equal(Create_field *new_field);
|
bool is_equal(const Column_definition &new_field) const;
|
||||||
|
bool can_be_converted_by_engine(const Column_definition &new_type) const
|
||||||
|
{
|
||||||
|
return table->file->can_convert_varstring(this, new_type);
|
||||||
|
}
|
||||||
void hash(ulong *nr, ulong *nr2);
|
void hash(ulong *nr, ulong *nr2);
|
||||||
uint length_size() { return length_bytes; }
|
uint length_size() const { return length_bytes; }
|
||||||
void print_key_value(String *out, uint32 length);
|
void print_key_value(String *out, uint32 length);
|
||||||
private:
|
private:
|
||||||
int save_field_metadata(uchar *first_byte);
|
int save_field_metadata(uchar *first_byte);
|
||||||
@ -4039,7 +4048,11 @@ public:
|
|||||||
uint32 max_display_length() const;
|
uint32 max_display_length() const;
|
||||||
uint32 char_length() const;
|
uint32 char_length() const;
|
||||||
uint32 character_octet_length() const;
|
uint32 character_octet_length() const;
|
||||||
uint is_equal(Create_field *new_field);
|
bool is_equal(const Column_definition &new_field) const;
|
||||||
|
bool can_be_converted_by_engine(const Column_definition &new_type) const
|
||||||
|
{
|
||||||
|
return table->file->can_convert_blob(this, new_type);
|
||||||
|
}
|
||||||
void print_key_value(String *out, uint32 length);
|
void print_key_value(String *out, uint32 length);
|
||||||
|
|
||||||
friend void TABLE::remember_blob_values(String *blob_storage);
|
friend void TABLE::remember_blob_values(String *blob_storage);
|
||||||
@ -4154,7 +4167,12 @@ public:
|
|||||||
geom_type == static_cast<const Field_geom*>(from)->geom_type) &&
|
geom_type == static_cast<const Field_geom*>(from)->geom_type) &&
|
||||||
!table->copy_blobs;
|
!table->copy_blobs;
|
||||||
}
|
}
|
||||||
uint is_equal(Create_field *new_field);
|
bool is_equal(const Column_definition &new_field) const;
|
||||||
|
bool can_be_converted_by_engine(const Column_definition &new_type) const
|
||||||
|
{
|
||||||
|
return table->file->can_convert_geom(this, new_type);
|
||||||
|
}
|
||||||
|
|
||||||
int store(const char *to, size_t length, CHARSET_INFO *charset);
|
int store(const char *to, size_t length, CHARSET_INFO *charset);
|
||||||
int store(double nr);
|
int store(double nr);
|
||||||
int store(longlong nr, bool unsigned_val);
|
int store(longlong nr, bool unsigned_val);
|
||||||
@ -4298,7 +4316,7 @@ public:
|
|||||||
bool is_eq_func) const;
|
bool is_eq_func) const;
|
||||||
private:
|
private:
|
||||||
int save_field_metadata(uchar *first_byte);
|
int save_field_metadata(uchar *first_byte);
|
||||||
uint is_equal(Create_field *new_field);
|
bool is_equal(const Column_definition &new_field) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -4477,7 +4495,7 @@ public:
|
|||||||
bit_ptr == ((Field_bit *)field)->bit_ptr &&
|
bit_ptr == ((Field_bit *)field)->bit_ptr &&
|
||||||
bit_ofs == ((Field_bit *)field)->bit_ofs);
|
bit_ofs == ((Field_bit *)field)->bit_ofs);
|
||||||
}
|
}
|
||||||
uint is_equal(Create_field *new_field);
|
bool is_equal(const Column_definition &new_field) const;
|
||||||
void move_field_offset(my_ptrdiff_t ptr_diff)
|
void move_field_offset(my_ptrdiff_t ptr_diff)
|
||||||
{
|
{
|
||||||
Field::move_field_offset(ptr_diff);
|
Field::move_field_offset(ptr_diff);
|
||||||
|
@ -4593,7 +4593,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
|
|||||||
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
|
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
|
||||||
|
|
||||||
alter_table_operations inplace_offline_operations=
|
alter_table_operations inplace_offline_operations=
|
||||||
ALTER_COLUMN_EQUAL_PACK_LENGTH |
|
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE |
|
||||||
ALTER_COLUMN_NAME |
|
ALTER_COLUMN_NAME |
|
||||||
ALTER_RENAME_COLUMN |
|
ALTER_RENAME_COLUMN |
|
||||||
ALTER_CHANGE_COLUMN_DEFAULT |
|
ALTER_CHANGE_COLUMN_DEFAULT |
|
||||||
@ -4629,7 +4629,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
|
|||||||
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
|
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
|
||||||
|
|
||||||
uint table_changes= (ha_alter_info->handler_flags &
|
uint table_changes= (ha_alter_info->handler_flags &
|
||||||
ALTER_COLUMN_EQUAL_PACK_LENGTH) ?
|
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE) ?
|
||||||
IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES;
|
IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES;
|
||||||
if (table->file->check_if_incompatible_data(create_info, table_changes)
|
if (table->file->check_if_incompatible_data(create_info, table_changes)
|
||||||
== COMPATIBLE_DATA_YES)
|
== COMPATIBLE_DATA_YES)
|
||||||
|
@ -49,6 +49,11 @@ class Alter_info;
|
|||||||
class Virtual_column_info;
|
class Virtual_column_info;
|
||||||
class sequence_definition;
|
class sequence_definition;
|
||||||
class Rowid_filter;
|
class Rowid_filter;
|
||||||
|
class Field_string;
|
||||||
|
class Field_varstring;
|
||||||
|
class Field_blob;
|
||||||
|
class Field_geom;
|
||||||
|
class Column_definition;
|
||||||
|
|
||||||
// the following is for checking tables
|
// the following is for checking tables
|
||||||
|
|
||||||
@ -321,10 +326,6 @@ enum enum_alter_inplace_result {
|
|||||||
/* Safe for online backup */
|
/* Safe for online backup */
|
||||||
#define HA_CAN_ONLINE_BACKUPS (1ULL << 56)
|
#define HA_CAN_ONLINE_BACKUPS (1ULL << 56)
|
||||||
|
|
||||||
/** whether every data field explicitly stores length
|
|
||||||
(holds for InnoDB ROW_FORMAT=REDUNDANT) */
|
|
||||||
#define HA_EXTENDED_TYPES_CONVERSION (1ULL << 57)
|
|
||||||
|
|
||||||
/* Support native hash index */
|
/* Support native hash index */
|
||||||
#define HA_CAN_HASH_KEYS (1ULL << 58)
|
#define HA_CAN_HASH_KEYS (1ULL << 58)
|
||||||
#define HA_LAST_TABLE_FLAG HA_CAN_HASH_KEYS
|
#define HA_LAST_TABLE_FLAG HA_CAN_HASH_KEYS
|
||||||
@ -706,13 +707,9 @@ typedef ulonglong alter_table_operations;
|
|||||||
#define ALTER_VIRTUAL_COLUMN_TYPE (1ULL << 47)
|
#define ALTER_VIRTUAL_COLUMN_TYPE (1ULL << 47)
|
||||||
#define ALTER_STORED_COLUMN_TYPE (1ULL << 48)
|
#define ALTER_STORED_COLUMN_TYPE (1ULL << 48)
|
||||||
|
|
||||||
/**
|
|
||||||
Change column datatype in such way that new type has compatible
|
// Engine can handle type change by itself in ALGORITHM=INPLACE
|
||||||
packed representation with old type, so it is theoretically
|
#define ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE (1ULL << 49)
|
||||||
possible to perform change by only updating data dictionary
|
|
||||||
without changing table rows.
|
|
||||||
*/
|
|
||||||
#define ALTER_COLUMN_EQUAL_PACK_LENGTH (1ULL << 49)
|
|
||||||
|
|
||||||
// Reorder column
|
// Reorder column
|
||||||
#define ALTER_STORED_COLUMN_ORDER (1ULL << 50)
|
#define ALTER_STORED_COLUMN_ORDER (1ULL << 50)
|
||||||
@ -4815,6 +4812,32 @@ public:
|
|||||||
|
|
||||||
virtual bool is_clustering_key(uint index) { return false; }
|
virtual bool is_clustering_key(uint index) { return false; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Some engines can perform column type conversion with ALGORITHM=INPLACE.
|
||||||
|
These functions check for such possibility.
|
||||||
|
Implementation could be based on Field_xxx::is_equal()
|
||||||
|
*/
|
||||||
|
virtual bool can_convert_string(const Field_string *field,
|
||||||
|
const Column_definition &new_type) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool can_convert_varstring(const Field_varstring *field,
|
||||||
|
const Column_definition &new_type) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool can_convert_blob(const Field_blob *field,
|
||||||
|
const Column_definition &new_type) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool can_convert_geom(const Field_geom *field,
|
||||||
|
const Column_definition &new_type) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Handler_share *get_ha_share_ptr();
|
Handler_share *get_ha_share_ptr();
|
||||||
void set_ha_share_ptr(Handler_share *arg_ha_share);
|
void set_ha_share_ptr(Handler_share *arg_ha_share);
|
||||||
|
@ -354,14 +354,6 @@
|
|||||||
data dictionary without changing table rows
|
data dictionary without changing table rows
|
||||||
*/
|
*/
|
||||||
#define IS_EQUAL_PACK_LENGTH 2
|
#define IS_EQUAL_PACK_LENGTH 2
|
||||||
/**
|
|
||||||
charsets are the same or compatible, collates are the same, the rest is equal
|
|
||||||
*/
|
|
||||||
#define IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET 3
|
|
||||||
/**
|
|
||||||
charsets are the same or compatible, collates are different, the rest is equal
|
|
||||||
*/
|
|
||||||
#define IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET_BUT_COLLATE 4
|
|
||||||
|
|
||||||
enum enum_parsing_place
|
enum enum_parsing_place
|
||||||
{
|
{
|
||||||
|
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.
|
if the user key part length is different.
|
||||||
*/
|
*/
|
||||||
const Field *old_field= table->field[key_part->fieldnr - 1];
|
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() -
|
if (!key_part->field->can_be_converted_by_engine(*new_field))
|
||||||
((Field_varstring *) old_field)->length_bytes);
|
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 != new_part->length)
|
||||||
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 != old_field->field_length ||
|
||||||
|
key_part->length >= new_part->length || is_equal)
|
||||||
|
{
|
||||||
|
return Compare_keys::NotEqual;
|
||||||
|
}
|
||||||
result= Compare_keys::EqualButKeyPartLength;
|
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;
|
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
|
Compare original and new versions of a table and fill Alter_inplace_info
|
||||||
describing differences between those versions.
|
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. */
|
/* 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);
|
bool is_equal= field->is_equal(*new_field);
|
||||||
switch (process_is_equal_result_for_key_parts(is_equal, field, new_field))
|
if (!is_equal)
|
||||||
{
|
{
|
||||||
case IS_EQUAL_NO:
|
if (field->can_be_converted_by_engine(*new_field))
|
||||||
/* 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)
|
|
||||||
{
|
{
|
||||||
delete_statistics_for_column(thd, table, field);
|
/*
|
||||||
KEY *key_info= table->key_info;
|
New column type differs from the old one, but storage engine can
|
||||||
for (uint i=0; i < table->s->keys; i++, key_info++)
|
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);
|
uint key_parts= table->actual_n_key_parts(key_info);
|
||||||
for (uint j= 0; j < key_parts; j++)
|
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,
|
delete_statistics_for_index(
|
||||||
j >= key_info->user_defined_key_parts);
|
thd, table, key_info,
|
||||||
|
j >= key_info->user_defined_key_parts);
|
||||||
break;
|
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)
|
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);
|
ALTER_VIRTUAL_COLUMN_TYPE);
|
||||||
if (field->vcol_info && new_field->vcol_info)
|
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;
|
alter_table_operations alter_expr;
|
||||||
if (field->stored_in_db())
|
if (field->stored_in_db())
|
||||||
alter_expr= ALTER_STORED_GCOL_EXPR;
|
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]=
|
ha_alter_info->create_info->fields_option_struct[f_ptr - table->field]=
|
||||||
new_field->option_struct;
|
new_field->option_struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -7294,7 +7249,7 @@ bool mysql_compare_tables(TABLE *table,
|
|||||||
DBUG_RETURN(false);
|
DBUG_RETURN(false);
|
||||||
|
|
||||||
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
|
/* 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)
|
if (field_changes != IS_EQUAL_YES)
|
||||||
DBUG_RETURN(false);
|
DBUG_RETURN(false);
|
||||||
|
|
||||||
@ -8797,7 +8752,7 @@ fk_check_column_changes(THD *thd, Alter_info *alter_info,
|
|||||||
return FK_COLUMN_RENAMED;
|
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) &&
|
((new_field->flags & NOT_NULL_FLAG) &&
|
||||||
!(old_field->flags & NOT_NULL_FLAG)))
|
!(old_field->flags & NOT_NULL_FLAG)))
|
||||||
{
|
{
|
||||||
|
@ -8367,6 +8367,5 @@ Charset::eq_collation_specific_names(CHARSET_INFO *cs) const
|
|||||||
{
|
{
|
||||||
LEX_CSTRING name0= collation_specific_name();
|
LEX_CSTRING name0= collation_specific_name();
|
||||||
LEX_CSTRING name1= Charset(cs).collation_specific_name();
|
LEX_CSTRING name1= Charset(cs).collation_specific_name();
|
||||||
/* Empty collations are not equal */
|
|
||||||
return name0.length && !cmp(&name0, &name1);
|
return name0.length && !cmp(&name0, &name1);
|
||||||
}
|
}
|
||||||
|
@ -7018,7 +7018,7 @@ ha_connect::check_if_supported_inplace_alter(TABLE *altered_table,
|
|||||||
ALTER_DROP_PK_INDEX;
|
ALTER_DROP_PK_INDEX;
|
||||||
|
|
||||||
alter_table_operations inplace_offline_operations=
|
alter_table_operations inplace_offline_operations=
|
||||||
ALTER_COLUMN_EQUAL_PACK_LENGTH |
|
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE |
|
||||||
ALTER_COLUMN_NAME |
|
ALTER_COLUMN_NAME |
|
||||||
ALTER_COLUMN_DEFAULT |
|
ALTER_COLUMN_DEFAULT |
|
||||||
ALTER_CHANGE_CREATE_OPTION |
|
ALTER_CHANGE_CREATE_OPTION |
|
||||||
@ -7117,7 +7117,7 @@ ha_connect::check_if_supported_inplace_alter(TABLE *altered_table,
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
uint table_changes= (ha_alter_info->handler_flags &
|
uint table_changes= (ha_alter_info->handler_flags &
|
||||||
ALTER_COLUMN_EQUAL_PACK_LENGTH) ?
|
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE) ?
|
||||||
IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES;
|
IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES;
|
||||||
|
|
||||||
if (table->file->check_if_incompatible_data(create_info, table_changes)
|
if (table->file->check_if_incompatible_data(create_info, table_changes)
|
||||||
|
@ -74,6 +74,8 @@ Warnings:
|
|||||||
Warning 1105 Truncated author content
|
Warning 1105 Truncated author content
|
||||||
# increase author size
|
# increase author size
|
||||||
ALTER TABLE bookstore MODIFY `author` VARCHAR(128) NOT NULL;
|
ALTER TABLE bookstore MODIFY `author` VARCHAR(128) NOT NULL;
|
||||||
|
Warnings:
|
||||||
|
Warning 1105 This is an outward table, table data were not modified.
|
||||||
SELECT * FROM bookstore;
|
SELECT * FROM bookstore;
|
||||||
category title lang author year price
|
category title lang author year price
|
||||||
COOKING Everyday Italian en Giada De Laurentiis 2005 30.00
|
COOKING Everyday Italian en Giada De Laurentiis 2005 30.00
|
||||||
|
@ -72,6 +72,8 @@ Warnings:
|
|||||||
Warning 1105 Truncated author content
|
Warning 1105 Truncated author content
|
||||||
# increase author size
|
# increase author size
|
||||||
ALTER TABLE bookstore MODIFY `author` VARCHAR(128) NOT NULL;
|
ALTER TABLE bookstore MODIFY `author` VARCHAR(128) NOT NULL;
|
||||||
|
Warnings:
|
||||||
|
Warning 1105 This is an outward table, table data were not modified.
|
||||||
SELECT * FROM bookstore;
|
SELECT * FROM bookstore;
|
||||||
category title lang author year price
|
category title lang author year price
|
||||||
COOKING Everyday Italian en Giada De Laurentiis 2005 30.00
|
COOKING Everyday Italian en Giada De Laurentiis 2005 30.00
|
||||||
|
@ -54,6 +54,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <my_bitmap.h>
|
#include <my_bitmap.h>
|
||||||
#include <mysql/service_thd_alloc.h>
|
#include <mysql/service_thd_alloc.h>
|
||||||
#include <mysql/service_thd_wait.h>
|
#include <mysql/service_thd_wait.h>
|
||||||
|
#include "field.h"
|
||||||
|
|
||||||
// MYSQL_PLUGIN_IMPORT extern my_bool lower_case_file_system;
|
// MYSQL_PLUGIN_IMPORT extern my_bool lower_case_file_system;
|
||||||
// MYSQL_PLUGIN_IMPORT extern char mysql_unpacked_real_data_home[];
|
// MYSQL_PLUGIN_IMPORT extern char mysql_unpacked_real_data_home[];
|
||||||
@ -6141,11 +6142,6 @@ no_such_table:
|
|||||||
DBUG_RETURN(HA_ERR_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)
|
size_t n_fields = omits_virtual_cols(*table_share)
|
||||||
? table_share->stored_fields : table_share->fields;
|
? table_share->stored_fields : table_share->fields;
|
||||||
size_t n_cols = dict_table_get_n_user_cols(ib_table)
|
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);
|
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
|
Use this when the args are passed to the format string from
|
||||||
errmsg-utf8.txt directly as is.
|
errmsg-utf8.txt directly as is.
|
||||||
|
@ -437,6 +437,13 @@ public:
|
|||||||
@retval false if pushed (always) */
|
@retval false if pushed (always) */
|
||||||
bool rowid_filter_push(Rowid_filter *rowid_filter);
|
bool rowid_filter_push(Rowid_filter *rowid_filter);
|
||||||
|
|
||||||
|
bool can_convert_string(const Field_string* field,
|
||||||
|
const Column_definition& new_field) const;
|
||||||
|
bool can_convert_varstring(const Field_varstring* field,
|
||||||
|
const Column_definition& new_field) const;
|
||||||
|
bool can_convert_blob(const Field_blob* field,
|
||||||
|
const Column_definition& new_field) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
MySQL calls this method at the end of each statement. This method
|
MySQL calls this method at the end of each statement. This method
|
||||||
|
@ -131,7 +131,7 @@ static const alter_table_operations INNOBASE_ALTER_INSTANT
|
|||||||
| ALTER_COLUMN_NAME
|
| ALTER_COLUMN_NAME
|
||||||
| ALTER_ADD_VIRTUAL_COLUMN
|
| ALTER_ADD_VIRTUAL_COLUMN
|
||||||
| INNOBASE_FOREIGN_OPERATIONS
|
| INNOBASE_FOREIGN_OPERATIONS
|
||||||
| ALTER_COLUMN_EQUAL_PACK_LENGTH
|
| ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE
|
||||||
| ALTER_COLUMN_UNVERSIONED
|
| ALTER_COLUMN_UNVERSIONED
|
||||||
| ALTER_RENAME_INDEX
|
| ALTER_RENAME_INDEX
|
||||||
| ALTER_DROP_VIRTUAL_COLUMN;
|
| ALTER_DROP_VIRTUAL_COLUMN;
|
||||||
@ -8332,7 +8332,7 @@ ok_exit:
|
|||||||
rebuild_templ
|
rebuild_templ
|
||||||
= ctx->need_rebuild()
|
= ctx->need_rebuild()
|
||||||
|| ((ha_alter_info->handler_flags
|
|| ((ha_alter_info->handler_flags
|
||||||
& ALTER_COLUMN_EQUAL_PACK_LENGTH)
|
& ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE)
|
||||||
&& alter_templ_needs_rebuild(
|
&& alter_templ_needs_rebuild(
|
||||||
altered_table, ha_alter_info, ctx->new_table));
|
altered_table, ha_alter_info, ctx->new_table));
|
||||||
|
|
||||||
@ -9194,7 +9194,7 @@ innobase_rename_or_enlarge_columns_try(
|
|||||||
DBUG_ENTER("innobase_rename_or_enlarge_columns_try");
|
DBUG_ENTER("innobase_rename_or_enlarge_columns_try");
|
||||||
|
|
||||||
if (!(ha_alter_info->handler_flags
|
if (!(ha_alter_info->handler_flags
|
||||||
& (ALTER_COLUMN_EQUAL_PACK_LENGTH
|
& (ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE
|
||||||
| ALTER_COLUMN_NAME))) {
|
| ALTER_COLUMN_NAME))) {
|
||||||
DBUG_RETURN(false);
|
DBUG_RETURN(false);
|
||||||
}
|
}
|
||||||
@ -9242,7 +9242,7 @@ innobase_rename_or_enlarge_columns_cache(
|
|||||||
dict_table_t* user_table)
|
dict_table_t* user_table)
|
||||||
{
|
{
|
||||||
if (!(ha_alter_info->handler_flags
|
if (!(ha_alter_info->handler_flags
|
||||||
& (ALTER_COLUMN_EQUAL_PACK_LENGTH
|
& (ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE
|
||||||
| ALTER_COLUMN_NAME))) {
|
| ALTER_COLUMN_NAME))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -916,6 +916,9 @@ public:
|
|||||||
Item* idx_cond_push(uint keyno, class Item* idx_cond);
|
Item* idx_cond_push(uint keyno, class Item* idx_cond);
|
||||||
void cancel_pushed_idx_cond();
|
void cancel_pushed_idx_cond();
|
||||||
|
|
||||||
|
bool can_convert_varstring(const Field_varstring* field,
|
||||||
|
const Column_definition&new_type) const;
|
||||||
|
|
||||||
#if defined(TOKU_INCLUDE_ALTER_56) && TOKU_INCLUDE_ALTER_56
|
#if defined(TOKU_INCLUDE_ALTER_56) && TOKU_INCLUDE_ALTER_56
|
||||||
public:
|
public:
|
||||||
enum_alter_inplace_result check_if_supported_inplace_alter(TABLE *altered_table, Alter_inplace_info *ha_alter_info);
|
enum_alter_inplace_result check_if_supported_inplace_alter(TABLE *altered_table, Alter_inplace_info *ha_alter_info);
|
||||||
|
@ -465,10 +465,10 @@ enum_alter_inplace_result ha_tokudb::check_if_supported_inplace_alter(
|
|||||||
result = HA_ALTER_INPLACE_EXCLUSIVE_LOCK;
|
result = HA_ALTER_INPLACE_EXCLUSIVE_LOCK;
|
||||||
}
|
}
|
||||||
} else if ((ctx->handler_flags &
|
} else if ((ctx->handler_flags &
|
||||||
ALTER_COLUMN_EQUAL_PACK_LENGTH) &&
|
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE) &&
|
||||||
only_flags(
|
only_flags(
|
||||||
ctx->handler_flags,
|
ctx->handler_flags,
|
||||||
ALTER_COLUMN_EQUAL_PACK_LENGTH |
|
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE |
|
||||||
ALTER_COLUMN_DEFAULT) &&
|
ALTER_COLUMN_DEFAULT) &&
|
||||||
table->s->fields == altered_table->s->fields &&
|
table->s->fields == altered_table->s->fields &&
|
||||||
find_changed_fields(
|
find_changed_fields(
|
||||||
@ -1180,6 +1180,18 @@ static bool change_varchar_length_is_supported(Field* old_field,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ha_tokudb::can_convert_varstring(const Field_varstring* field,
|
||||||
|
const Column_definition& new_type) const {
|
||||||
|
if (new_type.length < field->field_length ||
|
||||||
|
new_type.char_length < field->char_length() ||
|
||||||
|
!new_type.compression_method() != !field->compression_method() ||
|
||||||
|
new_type.type_handler() != field->type_handler()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Return true if all changed field lengths can be changed inplace, otherwise
|
// Return true if all changed field lengths can be changed inplace, otherwise
|
||||||
// return false
|
// return false
|
||||||
static bool change_length_is_supported(TABLE* table,
|
static bool change_length_is_supported(TABLE* table,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user