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());
|
||||
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,22 +9436,22 @@ 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
|
||||
@ -9530,13 +9459,13 @@ uint Field_enum::is_equal(Create_field *new_field)
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
58
sql/field.h
58
sql/field.h
@ -1503,13 +1503,16 @@ public:
|
||||
/* maximum possible display length */
|
||||
virtual uint32 max_display_length() const= 0;
|
||||
/**
|
||||
Whether a field being created is compatible with a existing one.
|
||||
|
||||
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).
|
||||
Whether a field being created has the samle type.
|
||||
Used by the ALTER TABLE
|
||||
*/
|
||||
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 */
|
||||
longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag,
|
||||
int *err);
|
||||
@ -1809,7 +1812,7 @@ public:
|
||||
!((flags & UNSIGNED_FLAG) && !(from->flags & UNSIGNED_FLAG)) &&
|
||||
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(); }
|
||||
uint32 pack_length_from_metadata(uint field_metadata) {
|
||||
uint32 length= pack_length();
|
||||
@ -1874,7 +1877,7 @@ public:
|
||||
bool val_bool() { return val_real() != 0e0; }
|
||||
virtual bool str_needs_quotes() { return TRUE; }
|
||||
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)
|
||||
{
|
||||
return pos_in_interval_val_str(min, max, length_size());
|
||||
@ -1928,8 +1931,6 @@ protected:
|
||||
CHARSET_INFO *cs, size_t nchars);
|
||||
String *uncompress(String *val_buffer, String *val_ptr,
|
||||
const uchar *from, uint from_length);
|
||||
uint is_equal_for_different_charsets(const Column_definition &to) const;
|
||||
|
||||
public:
|
||||
Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
|
||||
uchar null_bit_arg, utype unireg_check_arg,
|
||||
@ -2142,7 +2143,7 @@ public:
|
||||
uint row_pack_length() const { return pack_length(); }
|
||||
bool compatible_field_size(uint field_metadata, Relay_log_info *rli,
|
||||
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);
|
||||
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; }
|
||||
String *val_str(String *value,String *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;}
|
||||
void sort_string(uchar *buff, uint length) {}
|
||||
uint32 pack_length() const { return 0; }
|
||||
@ -2729,7 +2730,7 @@ public:
|
||||
CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; }
|
||||
bool binary() const { return true; }
|
||||
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
|
||||
{
|
||||
return (Field::eq_def(field) && decimals() == field->decimals());
|
||||
@ -3570,7 +3571,11 @@ public:
|
||||
int cmp(const uchar *,const uchar *);
|
||||
void sort_string(uchar *buff,uint length);
|
||||
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,
|
||||
uint max_length);
|
||||
virtual const uchar *unpack(uchar* to, const uchar *from,
|
||||
@ -3698,9 +3703,13 @@ public:
|
||||
Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
|
||||
uchar *new_ptr, uint32 length,
|
||||
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);
|
||||
uint length_size() { return length_bytes; }
|
||||
uint length_size() const { return length_bytes; }
|
||||
void print_key_value(String *out, uint32 length);
|
||||
private:
|
||||
int save_field_metadata(uchar *first_byte);
|
||||
@ -4039,7 +4048,11 @@ public:
|
||||
uint32 max_display_length() const;
|
||||
uint32 char_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);
|
||||
|
||||
friend void TABLE::remember_blob_values(String *blob_storage);
|
||||
@ -4154,7 +4167,12 @@ public:
|
||||
geom_type == static_cast<const Field_geom*>(from)->geom_type) &&
|
||||
!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(double nr);
|
||||
int store(longlong nr, bool unsigned_val);
|
||||
@ -4298,7 +4316,7 @@ public:
|
||||
bool is_eq_func) const;
|
||||
private:
|
||||
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_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)
|
||||
{
|
||||
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);
|
||||
|
||||
alter_table_operations inplace_offline_operations=
|
||||
ALTER_COLUMN_EQUAL_PACK_LENGTH |
|
||||
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE |
|
||||
ALTER_COLUMN_NAME |
|
||||
ALTER_RENAME_COLUMN |
|
||||
ALTER_CHANGE_COLUMN_DEFAULT |
|
||||
@ -4629,7 +4629,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
|
||||
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
|
||||
|
||||
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;
|
||||
if (table->file->check_if_incompatible_data(create_info, table_changes)
|
||||
== COMPATIBLE_DATA_YES)
|
||||
|
@ -49,6 +49,11 @@ class Alter_info;
|
||||
class Virtual_column_info;
|
||||
class sequence_definition;
|
||||
class Rowid_filter;
|
||||
class Field_string;
|
||||
class Field_varstring;
|
||||
class Field_blob;
|
||||
class Field_geom;
|
||||
class Column_definition;
|
||||
|
||||
// the following is for checking tables
|
||||
|
||||
@ -321,10 +326,6 @@ enum enum_alter_inplace_result {
|
||||
/* Safe for online backup */
|
||||
#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 */
|
||||
#define HA_CAN_HASH_KEYS (1ULL << 58)
|
||||
#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_STORED_COLUMN_TYPE (1ULL << 48)
|
||||
|
||||
/**
|
||||
Change column datatype in such way that new type has compatible
|
||||
packed representation with old type, so it is theoretically
|
||||
possible to perform change by only updating data dictionary
|
||||
without changing table rows.
|
||||
*/
|
||||
#define ALTER_COLUMN_EQUAL_PACK_LENGTH (1ULL << 49)
|
||||
|
||||
// Engine can handle type change by itself in ALGORITHM=INPLACE
|
||||
#define ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE (1ULL << 49)
|
||||
|
||||
// Reorder column
|
||||
#define ALTER_STORED_COLUMN_ORDER (1ULL << 50)
|
||||
@ -4815,6 +4812,32 @@ public:
|
||||
|
||||
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:
|
||||
Handler_share *get_ha_share_ptr();
|
||||
void set_ha_share_ptr(Handler_share *arg_ha_share);
|
||||
|
@ -354,14 +354,6 @@
|
||||
data dictionary without changing table rows
|
||||
*/
|
||||
#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
|
||||
{
|
||||
|
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)))
|
||||
{
|
||||
|
@ -8367,6 +8367,5 @@ Charset::eq_collation_specific_names(CHARSET_INFO *cs) const
|
||||
{
|
||||
LEX_CSTRING name0= collation_specific_name();
|
||||
LEX_CSTRING name1= Charset(cs).collation_specific_name();
|
||||
/* Empty collations are not equal */
|
||||
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_table_operations inplace_offline_operations=
|
||||
ALTER_COLUMN_EQUAL_PACK_LENGTH |
|
||||
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE |
|
||||
ALTER_COLUMN_NAME |
|
||||
ALTER_COLUMN_DEFAULT |
|
||||
ALTER_CHANGE_CREATE_OPTION |
|
||||
@ -7117,7 +7117,7 @@ ha_connect::check_if_supported_inplace_alter(TABLE *altered_table,
|
||||
|
||||
#if 0
|
||||
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;
|
||||
|
||||
if (table->file->check_if_incompatible_data(create_info, table_changes)
|
||||
|
@ -74,6 +74,8 @@ Warnings:
|
||||
Warning 1105 Truncated author content
|
||||
# increase author size
|
||||
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;
|
||||
category title lang author year price
|
||||
COOKING Everyday Italian en Giada De Laurentiis 2005 30.00
|
||||
|
@ -72,6 +72,8 @@ Warnings:
|
||||
Warning 1105 Truncated author content
|
||||
# increase author size
|
||||
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;
|
||||
category title lang author year price
|
||||
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 <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.
|
||||
|
@ -437,6 +437,13 @@ public:
|
||||
@retval false if pushed (always) */
|
||||
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:
|
||||
/**
|
||||
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_ADD_VIRTUAL_COLUMN
|
||||
| INNOBASE_FOREIGN_OPERATIONS
|
||||
| ALTER_COLUMN_EQUAL_PACK_LENGTH
|
||||
| ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE
|
||||
| ALTER_COLUMN_UNVERSIONED
|
||||
| ALTER_RENAME_INDEX
|
||||
| ALTER_DROP_VIRTUAL_COLUMN;
|
||||
@ -8332,7 +8332,7 @@ ok_exit:
|
||||
rebuild_templ
|
||||
= ctx->need_rebuild()
|
||||
|| ((ha_alter_info->handler_flags
|
||||
& ALTER_COLUMN_EQUAL_PACK_LENGTH)
|
||||
& ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE)
|
||||
&& alter_templ_needs_rebuild(
|
||||
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");
|
||||
|
||||
if (!(ha_alter_info->handler_flags
|
||||
& (ALTER_COLUMN_EQUAL_PACK_LENGTH
|
||||
& (ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE
|
||||
| ALTER_COLUMN_NAME))) {
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
@ -9242,7 +9242,7 @@ innobase_rename_or_enlarge_columns_cache(
|
||||
dict_table_t* user_table)
|
||||
{
|
||||
if (!(ha_alter_info->handler_flags
|
||||
& (ALTER_COLUMN_EQUAL_PACK_LENGTH
|
||||
& (ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE
|
||||
| ALTER_COLUMN_NAME))) {
|
||||
return;
|
||||
}
|
||||
|
@ -916,6 +916,9 @@ public:
|
||||
Item* idx_cond_push(uint keyno, class Item* 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
|
||||
public:
|
||||
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;
|
||||
}
|
||||
} else if ((ctx->handler_flags &
|
||||
ALTER_COLUMN_EQUAL_PACK_LENGTH) &&
|
||||
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE) &&
|
||||
only_flags(
|
||||
ctx->handler_flags,
|
||||
ALTER_COLUMN_EQUAL_PACK_LENGTH |
|
||||
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE |
|
||||
ALTER_COLUMN_DEFAULT) &&
|
||||
table->s->fields == altered_table->s->fields &&
|
||||
find_changed_fields(
|
||||
@ -1180,6 +1180,18 @@ static bool change_varchar_length_is_supported(Field* old_field,
|
||||
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 false
|
||||
static bool change_length_is_supported(TABLE* table,
|
||||
|
Loading…
x
Reference in New Issue
Block a user