MDEV-19710 Split the server side code in rpl_utility.cc into virtual methods in Type_handler
This commit is contained in:
parent
9d6d37b5d0
commit
b685109596
@ -101,7 +101,9 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
|
||||
../sql/multi_range_read.cc
|
||||
../sql/opt_index_cond_pushdown.cc
|
||||
../sql/opt_subselect.cc
|
||||
../sql/create_options.cc ../sql/rpl_utility.cc
|
||||
../sql/create_options.cc
|
||||
../sql/rpl_utility.cc
|
||||
../sql/rpl_utility_server.cc
|
||||
../sql/rpl_reporting.cc
|
||||
../sql/sql_expression_cache.cc
|
||||
../sql/my_apc.cc ../sql/my_apc.h
|
||||
|
@ -510,7 +510,7 @@ INSERT INTO t11 () VALUES(1,@b1,'Testing is fun','Kyle',DEFAULT),
|
||||
|
||||
connection slave;
|
||||
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
|
||||
Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)''
|
||||
Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'blob' to type 'varchar(254)''
|
||||
|
||||
*** Drop t11 ***
|
||||
connection master;
|
||||
|
@ -510,7 +510,7 @@ INSERT INTO t11 () VALUES(1,@b1,'Testing is fun','Kyle',DEFAULT),
|
||||
|
||||
connection slave;
|
||||
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
|
||||
Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)''
|
||||
Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'blob' to type 'varchar(254)''
|
||||
|
||||
*** Drop t11 ***
|
||||
connection master;
|
||||
|
@ -102,7 +102,7 @@ INSERT INTO t3 () VALUES(@b1,2,'Kyle, TEX'),(@b1,1,'JOE AUSTIN'),(@b1,4,'QA TEST
|
||||
********************************************
|
||||
connection slave;
|
||||
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
|
||||
Last_SQL_Error = 'Column 0 of table 'test.t3' cannot be converted from type 'tinyblob' to type 'int(11)''
|
||||
Last_SQL_Error = 'Column 0 of table 'test.t3' cannot be converted from type 'blob' to type 'int(11)''
|
||||
*** Drop t3 ***
|
||||
connection master;
|
||||
DROP TABLE t3;
|
||||
|
@ -102,7 +102,7 @@ INSERT INTO t3 () VALUES(@b1,2,'Kyle, TEX'),(@b1,1,'JOE AUSTIN'),(@b1,4,'QA TEST
|
||||
********************************************
|
||||
connection slave;
|
||||
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
|
||||
Last_SQL_Error = 'Column 0 of table 'test.t3' cannot be converted from type 'tinyblob' to type 'int(11)''
|
||||
Last_SQL_Error = 'Column 0 of table 'test.t3' cannot be converted from type 'blob' to type 'int(11)''
|
||||
*** Drop t3 ***
|
||||
connection master;
|
||||
DROP TABLE t3;
|
||||
|
@ -334,7 +334,7 @@ INSERT INTO t1 VALUES ('This is a test.');
|
||||
connection slave;
|
||||
START SLAVE;
|
||||
include/wait_for_slave_sql_error.inc [errno=1677]
|
||||
Last_SQL_Error = 'Column 0 of table 'test.t1' cannot be converted from type 'tinyblob' to type 'tinyblob''
|
||||
Last_SQL_Error = 'Column 0 of table 'test.t1' cannot be converted from type 'longblob' to type 'tinyblob''
|
||||
SELECT COUNT(*) FROM t1;
|
||||
COUNT(*)
|
||||
0
|
||||
|
@ -111,7 +111,8 @@ SET (SQL_SOURCE
|
||||
rpl_tblmap.cc sql_binlog.cc event_scheduler.cc event_data_objects.cc
|
||||
event_queue.cc event_db_repository.cc
|
||||
sql_tablespace.cc events.cc ../sql-common/my_user.c
|
||||
partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc
|
||||
partition_info.cc rpl_utility.cc rpl_utility_server.cc
|
||||
rpl_injector.cc sql_locale.cc
|
||||
rpl_rli.cc rpl_mi.cc sql_servers.cc sql_audit.cc
|
||||
sql_connect.cc scheduler.cc sql_partition_admin.cc
|
||||
sql_profile.cc event_parse_data.cc sql_alter.cc
|
||||
|
110
sql/field.h
110
sql/field.h
@ -60,6 +60,46 @@ enum enum_check_fields
|
||||
CHECK_FIELD_ERROR_FOR_NULL,
|
||||
};
|
||||
|
||||
|
||||
enum enum_conv_type
|
||||
{
|
||||
CONV_TYPE_PRECISE,
|
||||
CONV_TYPE_VARIANT,
|
||||
CONV_TYPE_SUBSET_TO_SUPERSET,
|
||||
CONV_TYPE_SUPERSET_TO_SUBSET,
|
||||
CONV_TYPE_IMPOSSIBLE
|
||||
};
|
||||
|
||||
|
||||
class Conv_param
|
||||
{
|
||||
uint16 m_table_def_flags;
|
||||
public:
|
||||
Conv_param(uint16 table_def_flags)
|
||||
:m_table_def_flags(table_def_flags)
|
||||
{ }
|
||||
uint16 table_def_flags() const { return m_table_def_flags; }
|
||||
};
|
||||
|
||||
|
||||
class Conv_source: public Type_handler_hybrid_field_type
|
||||
{
|
||||
enum_field_types m_type;
|
||||
uint16 m_metadata;
|
||||
CHARSET_INFO *m_cs;
|
||||
public:
|
||||
Conv_source(const Type_handler *h, uint16 metadata, CHARSET_INFO *cs)
|
||||
:Type_handler_hybrid_field_type(h),
|
||||
m_metadata(metadata),
|
||||
m_cs(cs)
|
||||
{
|
||||
DBUG_ASSERT(cs);
|
||||
}
|
||||
uint16 metadata() const { return m_metadata; }
|
||||
uint mbmaxlen() const { return m_cs->mbmaxlen; }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Common declarations for Field and Item
|
||||
*/
|
||||
@ -1085,6 +1125,17 @@ public:
|
||||
*/
|
||||
return type();
|
||||
}
|
||||
/*
|
||||
Conversion type for from the source to the current field.
|
||||
*/
|
||||
virtual enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m)
|
||||
const= 0;
|
||||
enum_conv_type rpl_conv_type_from_same_data_type(uint16 metadata,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m)
|
||||
const;
|
||||
inline int cmp(const uchar *str) { return cmp(ptr,str); }
|
||||
virtual int cmp_max(const uchar *a, const uchar *b, uint max_len)
|
||||
{ return cmp(a, b); }
|
||||
@ -1940,7 +1991,9 @@ public:
|
||||
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
|
||||
field_name_arg, collation)
|
||||
{}
|
||||
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
int store_decimal(const my_decimal *d);
|
||||
uint32 max_data_length() const;
|
||||
|
||||
@ -1981,6 +2034,9 @@ public:
|
||||
{
|
||||
return do_field_real;
|
||||
}
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
Information_schema_numeric_attributes
|
||||
information_schema_numeric_attributes() const
|
||||
{
|
||||
@ -2090,6 +2146,9 @@ public:
|
||||
return Field_num::memcpy_field_possible(from) &&
|
||||
field_length == from->field_length;
|
||||
}
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
int reset(void);
|
||||
bool store_value(const my_decimal *decimal_value);
|
||||
bool store_value(const my_decimal *decimal_value, int *native_error);
|
||||
@ -2162,6 +2221,9 @@ public:
|
||||
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
|
||||
unireg_check_arg, field_name_arg, 0, zero_arg, unsigned_arg)
|
||||
{}
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
int store_decimal(const my_decimal *);
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
bool val_bool() { return val_int() != 0; }
|
||||
@ -2627,6 +2689,9 @@ public:
|
||||
unireg_check_arg, field_name_arg, collation)
|
||||
{}
|
||||
const Type_handler *type_handler() const { return &type_handler_null; }
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
Information_schema_character_attributes
|
||||
information_schema_character_attributes() const
|
||||
{
|
||||
@ -2815,6 +2880,9 @@ public:
|
||||
TABLE_SHARE *share);
|
||||
const Type_handler *type_handler() const { return &type_handler_timestamp; }
|
||||
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
Copy_func *get_copy_func(const Field *from) const;
|
||||
int store(const char *to,size_t length,CHARSET_INFO *charset);
|
||||
int store(double nr);
|
||||
@ -2967,6 +3035,9 @@ public:
|
||||
{}
|
||||
const Type_handler *type_handler() const { return &type_handler_timestamp2; }
|
||||
enum_field_types binlog_type() const { return MYSQL_TYPE_TIMESTAMP2; }
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
uint32 pack_length() const
|
||||
{
|
||||
return my_timestamp_binary_length(dec);
|
||||
@ -3006,6 +3077,9 @@ public:
|
||||
{
|
||||
return field_length == 2 ? &type_handler_year2 : &type_handler_year;
|
||||
}
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
Copy_func *get_copy_func(const Field *from) const
|
||||
{
|
||||
if (eq_def(from))
|
||||
@ -3088,6 +3162,9 @@ public:
|
||||
unireg_check_arg, field_name_arg) {}
|
||||
const Type_handler *type_handler() const { return &type_handler_date; }
|
||||
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; }
|
||||
bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||
{ return Field_date::get_TIME(ltime, ptr, fuzzydate); }
|
||||
@ -3125,6 +3202,9 @@ public:
|
||||
{}
|
||||
const Type_handler *type_handler() const { return &type_handler_newdate; }
|
||||
enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; }
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
|
||||
double val_real(void);
|
||||
longlong val_int(void);
|
||||
@ -3168,6 +3248,9 @@ public:
|
||||
const Item_equal *item_equal);
|
||||
const Type_handler *type_handler() const { return &type_handler_time; }
|
||||
enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; }
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
Copy_func *get_copy_func(const Field *from) const
|
||||
{
|
||||
return from->cmp_type() == REAL_RESULT ? do_field_string : // MDEV-9344
|
||||
@ -3280,6 +3363,9 @@ public:
|
||||
}
|
||||
const Type_handler *type_handler() const { return &type_handler_time2; }
|
||||
enum_field_types binlog_type() const { return MYSQL_TYPE_TIME2; }
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
uint32 pack_length() const
|
||||
{
|
||||
return my_time_binary_length(dec);
|
||||
@ -3325,6 +3411,9 @@ public:
|
||||
}
|
||||
const Type_handler *type_handler() const { return &type_handler_datetime; }
|
||||
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; }
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
int store(const char *to, size_t length, CHARSET_INFO *charset);
|
||||
int store(double nr);
|
||||
int store(longlong nr, bool unsigned_val);
|
||||
@ -3447,6 +3536,9 @@ public:
|
||||
{}
|
||||
const Type_handler *type_handler() const { return &type_handler_datetime2; }
|
||||
enum_field_types binlog_type() const { return MYSQL_TYPE_DATETIME2; }
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
uint32 pack_length() const
|
||||
{
|
||||
return my_datetime_binary_length(dec);
|
||||
@ -4130,6 +4222,9 @@ public:
|
||||
:Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
|
||||
field_name_arg, share, blob_pack_length, &my_charset_bin)
|
||||
{ geom_type= geom_type_arg; srid= field_srid; }
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; }
|
||||
const Type_handler *type_handler() const
|
||||
{
|
||||
@ -4212,6 +4307,9 @@ public:
|
||||
Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
|
||||
const Type_handler *type_handler() const { return &type_handler_enum; }
|
||||
enum ha_base_keytype key_type() const;
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
Copy_func *get_copy_func(const Field *from) const
|
||||
{
|
||||
if (eq_def(from))
|
||||
@ -4365,6 +4463,9 @@ public:
|
||||
uint32 key_length() const { return (uint32) (field_length + 7) / 8; }
|
||||
uint32 max_data_length() const { return (field_length + 7) / 8; }
|
||||
uint32 max_display_length() const { return field_length; }
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
Information_schema_numeric_attributes
|
||||
information_schema_numeric_attributes() const
|
||||
{
|
||||
@ -4531,6 +4632,13 @@ public:
|
||||
m_table(NULL)
|
||||
{}
|
||||
~Field_row();
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const
|
||||
{
|
||||
DBUG_ASSERT(0);
|
||||
return CONV_TYPE_IMPOSSIBLE;
|
||||
}
|
||||
Virtual_tmp_table **virtual_tmp_table_addr() { return &m_table; }
|
||||
bool sp_prepare_and_store_item(THD *thd, Item **value);
|
||||
};
|
||||
|
@ -19,185 +19,7 @@
|
||||
#include "rpl_utility.h"
|
||||
#include "log_event.h"
|
||||
|
||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||
#include "rpl_rli.h"
|
||||
#include "sql_select.h"
|
||||
|
||||
/**
|
||||
Calculate display length for MySQL56 temporal data types from their metadata.
|
||||
It contains fractional precision in the low 16-bit word.
|
||||
*/
|
||||
static uint32
|
||||
max_display_length_for_temporal2_field(uint32 int_display_length,
|
||||
unsigned int metadata)
|
||||
{
|
||||
metadata&= 0x00ff;
|
||||
return int_display_length + metadata + (metadata ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Compute the maximum display length of a field.
|
||||
|
||||
@param sql_type Type of the field
|
||||
@param metadata The metadata from the master for the field.
|
||||
@return Maximum length of the field in bytes.
|
||||
|
||||
The precise values calculated by field->max_display_length() and
|
||||
calculated by max_display_length_for_field() can differ (by +1 or -1)
|
||||
for integer data types (TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT).
|
||||
This slight difference is not important here, because we call
|
||||
this function only for two *different* integer data types.
|
||||
*/
|
||||
static uint32
|
||||
max_display_length_for_field(enum_field_types sql_type, unsigned int metadata)
|
||||
{
|
||||
DBUG_PRINT("debug", ("sql_type: %d, metadata: 0x%x", sql_type, metadata));
|
||||
DBUG_ASSERT(metadata >> 16 == 0);
|
||||
|
||||
switch (sql_type) {
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
return metadata >> 8;
|
||||
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
return 12;
|
||||
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
return 22;
|
||||
|
||||
case MYSQL_TYPE_SET:
|
||||
case MYSQL_TYPE_ENUM:
|
||||
return metadata & 0x00ff;
|
||||
|
||||
case MYSQL_TYPE_STRING:
|
||||
{
|
||||
uchar type= metadata >> 8;
|
||||
if (type == MYSQL_TYPE_SET || type == MYSQL_TYPE_ENUM)
|
||||
return metadata & 0xff;
|
||||
else
|
||||
/* This is taken from Field_string::unpack. */
|
||||
return (((metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0x00ff);
|
||||
}
|
||||
|
||||
case MYSQL_TYPE_YEAR:
|
||||
case MYSQL_TYPE_TINY:
|
||||
return 4;
|
||||
|
||||
case MYSQL_TYPE_SHORT:
|
||||
return 6;
|
||||
|
||||
case MYSQL_TYPE_INT24:
|
||||
return 9;
|
||||
|
||||
case MYSQL_TYPE_LONG:
|
||||
return 11;
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
return 20;
|
||||
|
||||
#endif
|
||||
case MYSQL_TYPE_NULL:
|
||||
return 0;
|
||||
|
||||
case MYSQL_TYPE_NEWDATE:
|
||||
return 3;
|
||||
|
||||
case MYSQL_TYPE_DATE:
|
||||
return 3;
|
||||
|
||||
case MYSQL_TYPE_TIME:
|
||||
return MIN_TIME_WIDTH;
|
||||
|
||||
case MYSQL_TYPE_TIME2:
|
||||
return max_display_length_for_temporal2_field(MIN_TIME_WIDTH, metadata);
|
||||
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
return MAX_DATETIME_WIDTH;
|
||||
|
||||
case MYSQL_TYPE_TIMESTAMP2:
|
||||
return max_display_length_for_temporal2_field(MAX_DATETIME_WIDTH, metadata);
|
||||
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
return MAX_DATETIME_WIDTH;
|
||||
|
||||
case MYSQL_TYPE_DATETIME2:
|
||||
return max_display_length_for_temporal2_field(MAX_DATETIME_WIDTH, metadata);
|
||||
|
||||
case MYSQL_TYPE_BIT:
|
||||
/*
|
||||
Decode the size of the bit field from the master.
|
||||
*/
|
||||
DBUG_ASSERT((metadata & 0xff) <= 7);
|
||||
return 8 * (metadata >> 8U) + (metadata & 0x00ff);
|
||||
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
return metadata;
|
||||
case MYSQL_TYPE_VARCHAR_COMPRESSED:
|
||||
return metadata - 1;
|
||||
|
||||
/*
|
||||
The actual length for these types does not really matter since
|
||||
they are used to calc_pack_length, which ignores the given
|
||||
length for these types.
|
||||
|
||||
Since we want this to be accurate for other uses, we return the
|
||||
maximum size in bytes of these BLOBs.
|
||||
*/
|
||||
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
return (uint32)my_set_bits(1 * 8);
|
||||
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
return (uint32)my_set_bits(3 * 8);
|
||||
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_BLOB_COMPRESSED:
|
||||
/*
|
||||
For the blob type, Field::real_type() lies and say that all
|
||||
blobs are of type MYSQL_TYPE_BLOB. In that case, we have to look
|
||||
at the length instead to decide what the max display size is.
|
||||
*/
|
||||
return (uint32)my_set_bits(metadata * 8);
|
||||
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_GEOMETRY:
|
||||
return (uint32)my_set_bits(4 * 8);
|
||||
|
||||
default:
|
||||
return ~(uint32) 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Compare the pack lengths of a source field (on the master) and a
|
||||
target field (on the slave).
|
||||
|
||||
@param field Target field.
|
||||
@param type Source field type.
|
||||
@param metadata Source field metadata.
|
||||
|
||||
@retval -1 The length of the source field is smaller than the target field.
|
||||
@retval 0 The length of the source and target fields are the same.
|
||||
@retval 1 The length of the source field is greater than the target field.
|
||||
*/
|
||||
int compare_lengths(Field *field, enum_field_types source_type, uint16 metadata)
|
||||
{
|
||||
DBUG_ENTER("compare_lengths");
|
||||
size_t const source_length=
|
||||
max_display_length_for_field(source_type, metadata);
|
||||
size_t const target_length= field->max_display_length();
|
||||
DBUG_PRINT("debug", ("source_length: %lu, source_type: %u,"
|
||||
" target_length: %lu, target_type: %u",
|
||||
(unsigned long) source_length, source_type,
|
||||
(unsigned long) target_length, field->real_type()));
|
||||
int result= source_length < target_length ? -1 : source_length > target_length;
|
||||
DBUG_PRINT("result", ("%d", result));
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
#endif //MYSQL_CLIENT
|
||||
/*********************************************************************
|
||||
* table_def member definitions *
|
||||
*********************************************************************/
|
||||
@ -349,739 +171,6 @@ uint32 table_def::calc_field_size(uint col, uchar *master_data) const
|
||||
return length;
|
||||
}
|
||||
|
||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||
/**
|
||||
*/
|
||||
void show_sql_type(enum_field_types type, uint16 metadata, String *str, CHARSET_INFO *field_cs)
|
||||
{
|
||||
DBUG_ENTER("show_sql_type");
|
||||
DBUG_PRINT("enter", ("type: %d, metadata: 0x%x", type, metadata));
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case MYSQL_TYPE_TINY:
|
||||
str->set_ascii(STRING_WITH_LEN("tinyint"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_SHORT:
|
||||
str->set_ascii(STRING_WITH_LEN("smallint"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_LONG:
|
||||
str->set_ascii(STRING_WITH_LEN("int"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
str->set_ascii(STRING_WITH_LEN("float"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
str->set_ascii(STRING_WITH_LEN("double"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_NULL:
|
||||
str->set_ascii(STRING_WITH_LEN("null"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
case MYSQL_TYPE_TIMESTAMP2:
|
||||
str->set_ascii(STRING_WITH_LEN("timestamp"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
str->set_ascii(STRING_WITH_LEN("bigint"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_INT24:
|
||||
str->set_ascii(STRING_WITH_LEN("mediumint"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_NEWDATE:
|
||||
case MYSQL_TYPE_DATE:
|
||||
str->set_ascii(STRING_WITH_LEN("date"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_TIME:
|
||||
case MYSQL_TYPE_TIME2:
|
||||
str->set_ascii(STRING_WITH_LEN("time"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
case MYSQL_TYPE_DATETIME2:
|
||||
str->set_ascii(STRING_WITH_LEN("datetime"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_YEAR:
|
||||
str->set_ascii(STRING_WITH_LEN("year"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
case MYSQL_TYPE_VARCHAR_COMPRESSED:
|
||||
{
|
||||
CHARSET_INFO *cs= str->charset();
|
||||
size_t length=
|
||||
cs->cset->snprintf(cs, (char*) str->ptr(), str->alloced_length(),
|
||||
"varchar(%u)%s", metadata,
|
||||
type == MYSQL_TYPE_VARCHAR_COMPRESSED ? " compressed"
|
||||
: "");
|
||||
str->length(length);
|
||||
}
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_BIT:
|
||||
{
|
||||
CHARSET_INFO *cs= str->charset();
|
||||
int bit_length= 8 * (metadata >> 8) + (metadata & 0xFF);
|
||||
size_t length=
|
||||
cs->cset->snprintf(cs, (char*) str->ptr(), str->alloced_length(),
|
||||
"bit(%d)", bit_length);
|
||||
str->length(length);
|
||||
}
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
{
|
||||
CHARSET_INFO *cs= str->charset();
|
||||
size_t length=
|
||||
cs->cset->snprintf(cs, (char*) str->ptr(), str->alloced_length(),
|
||||
"decimal(%d,?)/*old*/", metadata);
|
||||
str->length(length);
|
||||
}
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
{
|
||||
CHARSET_INFO *cs= str->charset();
|
||||
size_t length=
|
||||
cs->cset->snprintf(cs, (char*) str->ptr(), str->alloced_length(),
|
||||
"decimal(%d,%d)", metadata >> 8, metadata & 0xff);
|
||||
str->length(length);
|
||||
}
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_ENUM:
|
||||
str->set_ascii(STRING_WITH_LEN("enum"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_SET:
|
||||
str->set_ascii(STRING_WITH_LEN("set"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_BLOB_COMPRESSED:
|
||||
/*
|
||||
Field::real_type() lies regarding the actual type of a BLOB, so
|
||||
it is necessary to check the pack length to figure out what kind
|
||||
of blob it really is.
|
||||
*/
|
||||
switch (get_blob_type_from_length(metadata))
|
||||
{
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
str->set_ascii(STRING_WITH_LEN("tinyblob"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
str->set_ascii(STRING_WITH_LEN("mediumblob"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
str->set_ascii(STRING_WITH_LEN("longblob"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_BLOB:
|
||||
str->set_ascii(STRING_WITH_LEN("blob"));
|
||||
break;
|
||||
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == MYSQL_TYPE_BLOB_COMPRESSED)
|
||||
str->append(STRING_WITH_LEN(" compressed"));
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_STRING:
|
||||
{
|
||||
/*
|
||||
This is taken from Field_string::unpack.
|
||||
*/
|
||||
CHARSET_INFO *cs= str->charset();
|
||||
uint bytes= (((metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0x00ff);
|
||||
size_t length=
|
||||
cs->cset->snprintf(cs, (char*) str->ptr(), str->alloced_length(),
|
||||
"char(%d)", bytes / field_cs->mbmaxlen);
|
||||
str->length(length);
|
||||
}
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_GEOMETRY:
|
||||
str->set_ascii(STRING_WITH_LEN("geometry"));
|
||||
break;
|
||||
|
||||
default:
|
||||
str->set_ascii(STRING_WITH_LEN("<unknown type>"));
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check the order variable and print errors if the order is not
|
||||
acceptable according to the current settings.
|
||||
|
||||
@param order The computed order of the conversion needed.
|
||||
@param rli The relay log info data structure: for error reporting.
|
||||
*/
|
||||
bool is_conversion_ok(int order, Relay_log_info *rli)
|
||||
{
|
||||
DBUG_ENTER("is_conversion_ok");
|
||||
bool allow_non_lossy, allow_lossy;
|
||||
|
||||
allow_non_lossy = slave_type_conversions_options &
|
||||
(1ULL << SLAVE_TYPE_CONVERSIONS_ALL_NON_LOSSY);
|
||||
allow_lossy= slave_type_conversions_options &
|
||||
(1ULL << SLAVE_TYPE_CONVERSIONS_ALL_LOSSY);
|
||||
|
||||
DBUG_PRINT("enter", ("order: %d, flags:%s%s", order,
|
||||
allow_non_lossy ? " ALL_NON_LOSSY" : "",
|
||||
allow_lossy ? " ALL_LOSSY" : ""));
|
||||
if (order < 0 && !allow_non_lossy)
|
||||
{
|
||||
/* !!! Add error message saying that non-lossy conversions need to be allowed. */
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
if (order > 0 && !allow_lossy)
|
||||
{
|
||||
/* !!! Add error message saying that lossy conversions need to be allowed. */
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Can a type potentially be converted to another type?
|
||||
|
||||
This function check if the types are convertible and what
|
||||
conversion is required.
|
||||
|
||||
If conversion is not possible, and error is printed.
|
||||
|
||||
If conversion is possible:
|
||||
|
||||
- *order will be set to -1 if source type is smaller than target
|
||||
type and a non-lossy conversion can be required. This includes
|
||||
the case where the field types are different but types could
|
||||
actually be converted in either direction.
|
||||
|
||||
- *order will be set to 0 if no conversion is required.
|
||||
|
||||
- *order will be set to 1 if the source type is strictly larger
|
||||
than the target type and that conversion is potentially lossy.
|
||||
|
||||
@param[in] field Target field
|
||||
@param[in] type Source field type
|
||||
@param[in] metadata Source field metadata
|
||||
@param[in] rli Relay log info (for error reporting)
|
||||
@param[in] mflags Flags from the table map event
|
||||
@param[out] order Order between source field and target field
|
||||
|
||||
@return @c true if conversion is possible according to the current
|
||||
settings, @c false if conversion is not possible according to the
|
||||
current setting.
|
||||
*/
|
||||
static bool
|
||||
can_convert_field_to(Field *field,
|
||||
enum_field_types source_type, uint16 metadata,
|
||||
Relay_log_info *rli, uint16 mflags,
|
||||
int *order_var)
|
||||
{
|
||||
DBUG_ENTER("can_convert_field_to");
|
||||
bool same_type;
|
||||
#ifndef DBUG_OFF
|
||||
char field_type_buf[MAX_FIELD_WIDTH];
|
||||
String field_type(field_type_buf, sizeof(field_type_buf), &my_charset_latin1);
|
||||
field->sql_type(field_type);
|
||||
DBUG_PRINT("enter", ("field_type: %s, target_type: %d, source_type: %d, source_metadata: 0x%x",
|
||||
field_type.c_ptr_safe(), field->real_type(), source_type, metadata));
|
||||
#endif
|
||||
/**
|
||||
@todo
|
||||
Implement Field_varstring_cmopressed::real_type() and
|
||||
Field_blob_compressed::real_type() properly. All occurencies
|
||||
of Field::real_type() have to be inspected and adjusted if needed.
|
||||
|
||||
Until it is not ready we have to compare source_type against
|
||||
binlog_type() when replicating from or to compressed data types.
|
||||
|
||||
@sa Comment for Field::binlog_type()
|
||||
*/
|
||||
if (source_type == MYSQL_TYPE_VARCHAR_COMPRESSED ||
|
||||
source_type == MYSQL_TYPE_BLOB_COMPRESSED ||
|
||||
field->binlog_type() == MYSQL_TYPE_VARCHAR_COMPRESSED ||
|
||||
field->binlog_type() == MYSQL_TYPE_BLOB_COMPRESSED)
|
||||
same_type= field->binlog_type() == source_type;
|
||||
else
|
||||
same_type= field->real_type() == source_type;
|
||||
|
||||
/*
|
||||
If the real type is the same, we need to check the metadata to
|
||||
decide if conversions are allowed.
|
||||
*/
|
||||
if (same_type)
|
||||
{
|
||||
if (metadata == 0) // Metadata can only be zero if no metadata was provided
|
||||
{
|
||||
/*
|
||||
If there is no metadata, we either have an old event where no
|
||||
metadata were supplied, or a type that does not require any
|
||||
metadata. In either case, conversion can be done but no
|
||||
conversion table is necessary.
|
||||
*/
|
||||
DBUG_PRINT("debug", ("Base types are identical, but there is no metadata"));
|
||||
*order_var= 0;
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
DBUG_PRINT("debug", ("Base types are identical, doing field size comparison"));
|
||||
if (field->compatible_field_size(metadata, rli, mflags, order_var))
|
||||
DBUG_RETURN(is_conversion_ok(*order_var, rli));
|
||||
else
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
else if (
|
||||
/*
|
||||
Conversion from MariaDB TIMESTAMP(0), TIME(0), DATETIME(0)
|
||||
to the corresponding MySQL56 types is non-lossy.
|
||||
*/
|
||||
(metadata == 0 &&
|
||||
((field->real_type() == MYSQL_TYPE_TIMESTAMP2 &&
|
||||
source_type == MYSQL_TYPE_TIMESTAMP) ||
|
||||
(field->real_type() == MYSQL_TYPE_TIME2 &&
|
||||
source_type == MYSQL_TYPE_TIME) ||
|
||||
(field->real_type() == MYSQL_TYPE_DATETIME2 &&
|
||||
source_type == MYSQL_TYPE_DATETIME))) ||
|
||||
/*
|
||||
Conversion from MySQL56 TIMESTAMP(N), TIME(N), DATETIME(N)
|
||||
to the corresponding MariaDB or MySQL55 types is non-lossy.
|
||||
*/
|
||||
(metadata == field->decimals() &&
|
||||
((field->real_type() == MYSQL_TYPE_TIMESTAMP &&
|
||||
source_type == MYSQL_TYPE_TIMESTAMP2) ||
|
||||
(field->real_type() == MYSQL_TYPE_TIME &&
|
||||
source_type == MYSQL_TYPE_TIME2) ||
|
||||
(field->real_type() == MYSQL_TYPE_DATETIME &&
|
||||
source_type == MYSQL_TYPE_DATETIME2))))
|
||||
{
|
||||
/*
|
||||
TS-TODO: conversion from FSP1>FSP2.
|
||||
*/
|
||||
*order_var= -1;
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
else if (!slave_type_conversions_options)
|
||||
DBUG_RETURN(false);
|
||||
|
||||
/*
|
||||
Here, from and to will always be different. Since the types are
|
||||
different, we cannot use the compatible_field_size() function, but
|
||||
have to rely on hard-coded max-sizes for fields.
|
||||
*/
|
||||
|
||||
DBUG_PRINT("debug", ("Base types are different, checking conversion"));
|
||||
switch (source_type) // Source type (on master)
|
||||
{
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
switch (field->real_type())
|
||||
{
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
/*
|
||||
Then the other type is either FLOAT, DOUBLE, or old style
|
||||
DECIMAL, so we require lossy conversion.
|
||||
*/
|
||||
*order_var= 1;
|
||||
DBUG_RETURN(is_conversion_ok(*order_var, rli));
|
||||
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
{
|
||||
if (source_type == MYSQL_TYPE_NEWDECIMAL ||
|
||||
source_type == MYSQL_TYPE_DECIMAL)
|
||||
*order_var = 1; // Always require lossy conversions
|
||||
else
|
||||
*order_var= compare_lengths(field, source_type, metadata);
|
||||
DBUG_ASSERT(*order_var != 0);
|
||||
DBUG_RETURN(is_conversion_ok(*order_var, rli));
|
||||
}
|
||||
|
||||
default:
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
The length comparison check will do the correct job of comparing
|
||||
the field lengths (in bytes) of two integer types.
|
||||
*/
|
||||
case MYSQL_TYPE_TINY:
|
||||
case MYSQL_TYPE_SHORT:
|
||||
case MYSQL_TYPE_INT24:
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
switch (field->real_type())
|
||||
{
|
||||
case MYSQL_TYPE_TINY:
|
||||
case MYSQL_TYPE_SHORT:
|
||||
case MYSQL_TYPE_INT24:
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
/*
|
||||
max_display_length_for_field() is not fully precise for the integer
|
||||
data types. So its result cannot be compared to the result of
|
||||
field->max_dispay_length() when the table field and the binlog field
|
||||
are of the same type.
|
||||
This code should eventually be rewritten not to use
|
||||
compare_lengths(), to detect subtype/supetype relations
|
||||
just using the type codes.
|
||||
*/
|
||||
DBUG_ASSERT(source_type != field->real_type());
|
||||
*order_var= compare_lengths(field, source_type, metadata);
|
||||
DBUG_ASSERT(*order_var != 0);
|
||||
DBUG_RETURN(is_conversion_ok(*order_var, rli));
|
||||
|
||||
default:
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
Since source and target type is different, and it is not possible
|
||||
to convert bit types to anything else, this will return false.
|
||||
*/
|
||||
case MYSQL_TYPE_BIT:
|
||||
DBUG_RETURN(false);
|
||||
|
||||
/*
|
||||
If all conversions are disabled, it is not allowed to convert
|
||||
between these types. Since the TEXT vs. BINARY is distinguished by
|
||||
the charset, and the charset is not replicated, we cannot
|
||||
currently distinguish between , e.g., TEXT and BLOB.
|
||||
*/
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_BLOB_COMPRESSED:
|
||||
case MYSQL_TYPE_STRING:
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
case MYSQL_TYPE_VARCHAR_COMPRESSED:
|
||||
switch (field->real_type())
|
||||
{
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_BLOB_COMPRESSED:
|
||||
case MYSQL_TYPE_STRING:
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
case MYSQL_TYPE_VARCHAR_COMPRESSED:
|
||||
*order_var= compare_lengths(field, source_type, metadata);
|
||||
/*
|
||||
Here we know that the types are different, so if the order
|
||||
gives that they do not require any conversion, we still need
|
||||
to have non-lossy conversion enabled to allow conversion
|
||||
between different (string) types of the same length.
|
||||
*/
|
||||
if (*order_var == 0)
|
||||
*order_var= -1;
|
||||
DBUG_RETURN(is_conversion_ok(*order_var, rli));
|
||||
|
||||
default:
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_GEOMETRY:
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
case MYSQL_TYPE_DATE:
|
||||
case MYSQL_TYPE_TIME:
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
case MYSQL_TYPE_YEAR:
|
||||
case MYSQL_TYPE_NULL:
|
||||
case MYSQL_TYPE_ENUM:
|
||||
case MYSQL_TYPE_SET:
|
||||
case MYSQL_TYPE_TIMESTAMP2:
|
||||
case MYSQL_TYPE_TIME2:
|
||||
DBUG_RETURN(false);
|
||||
case MYSQL_TYPE_NEWDATE:
|
||||
{
|
||||
if (field->real_type() == MYSQL_TYPE_DATETIME2 ||
|
||||
field->real_type() == MYSQL_TYPE_DATETIME)
|
||||
{
|
||||
*order_var= -1;
|
||||
DBUG_RETURN(is_conversion_ok(*order_var, rli));
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//case MYSQL_TYPE_DATETIME: TODO: fix MDEV-17394 and uncomment.
|
||||
//
|
||||
//The "old" type does not specify the fraction part size which is required
|
||||
//for correct conversion.
|
||||
case MYSQL_TYPE_DATETIME2:
|
||||
{
|
||||
if (field->real_type() == MYSQL_TYPE_NEWDATE)
|
||||
{
|
||||
*order_var= 1;
|
||||
DBUG_RETURN(is_conversion_ok(*order_var, rli));
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
DBUG_RETURN(false); // To keep GCC happy
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Is the definition compatible with a table?
|
||||
|
||||
This function will compare the master table with an existing table
|
||||
on the slave and see if they are compatible with respect to the
|
||||
current settings of @c SLAVE_TYPE_CONVERSIONS.
|
||||
|
||||
If the tables are compatible and conversions are required, @c
|
||||
*tmp_table_var will be set to a virtual temporary table with field
|
||||
pointers for the fields that require conversions. This allow simple
|
||||
checking of whether a conversion are to be applied or not.
|
||||
|
||||
If tables are compatible, but no conversions are necessary, @c
|
||||
*tmp_table_var will be set to NULL.
|
||||
|
||||
@param rli_arg[in]
|
||||
Relay log info, for error reporting.
|
||||
|
||||
@param table[in]
|
||||
Table to compare with
|
||||
|
||||
@param tmp_table_var[out]
|
||||
Virtual temporary table for performing conversions, if necessary.
|
||||
|
||||
@retval true Master table is compatible with slave table.
|
||||
@retval false Master table is not compatible with slave table.
|
||||
*/
|
||||
bool
|
||||
table_def::compatible_with(THD *thd, rpl_group_info *rgi,
|
||||
TABLE *table, TABLE **conv_table_var)
|
||||
const
|
||||
{
|
||||
/*
|
||||
We only check the initial columns for the tables.
|
||||
*/
|
||||
uint const cols_to_check= MY_MIN(table->s->fields, size());
|
||||
Relay_log_info *rli= rgi->rli;
|
||||
TABLE *tmp_table= NULL;
|
||||
|
||||
for (uint col= 0 ; col < cols_to_check ; ++col)
|
||||
{
|
||||
Field *const field= table->field[col];
|
||||
int order;
|
||||
if (can_convert_field_to(field, type(col), field_metadata(col), rli, m_flags, &order))
|
||||
{
|
||||
DBUG_PRINT("debug", ("Checking column %d -"
|
||||
" field '%s' can be converted - order: %d",
|
||||
col, field->field_name.str, order));
|
||||
DBUG_ASSERT(order >= -1 && order <= 1);
|
||||
|
||||
/*
|
||||
If order is not 0, a conversion is required, so we need to set
|
||||
up the conversion table.
|
||||
*/
|
||||
if (order != 0 && tmp_table == NULL)
|
||||
{
|
||||
/*
|
||||
This will create the full table with all fields. This is
|
||||
necessary to ge the correct field lengths for the record.
|
||||
*/
|
||||
tmp_table= create_conversion_table(thd, rgi, table);
|
||||
if (tmp_table == NULL)
|
||||
return false;
|
||||
/*
|
||||
Clear all fields up to, but not including, this column.
|
||||
*/
|
||||
for (unsigned int i= 0; i < col; ++i)
|
||||
tmp_table->field[i]= NULL;
|
||||
}
|
||||
|
||||
if (order == 0 && tmp_table != NULL)
|
||||
tmp_table->field[col]= NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_PRINT("debug", ("Checking column %d -"
|
||||
" field '%s' can not be converted",
|
||||
col, field->field_name.str));
|
||||
DBUG_ASSERT(col < size() && col < table->s->fields);
|
||||
DBUG_ASSERT(table->s->db.str && table->s->table_name.str);
|
||||
DBUG_ASSERT(table->in_use);
|
||||
const char *db_name= table->s->db.str;
|
||||
const char *tbl_name= table->s->table_name.str;
|
||||
char source_buf[MAX_FIELD_WIDTH];
|
||||
char target_buf[MAX_FIELD_WIDTH];
|
||||
String source_type(source_buf, sizeof(source_buf), &my_charset_latin1);
|
||||
String target_type(target_buf, sizeof(target_buf), &my_charset_latin1);
|
||||
THD *thd= table->in_use;
|
||||
|
||||
show_sql_type(type(col), field_metadata(col), &source_type, field->charset());
|
||||
field->sql_type(target_type);
|
||||
rli->report(ERROR_LEVEL, ER_SLAVE_CONVERSION_FAILED, rgi->gtid_info(),
|
||||
ER_THD(thd, ER_SLAVE_CONVERSION_FAILED),
|
||||
col, db_name, tbl_name,
|
||||
source_type.c_ptr_safe(), target_type.c_ptr_safe());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
if (tmp_table)
|
||||
{
|
||||
for (unsigned int col= 0; col < tmp_table->s->fields; ++col)
|
||||
if (tmp_table->field[col])
|
||||
{
|
||||
char source_buf[MAX_FIELD_WIDTH];
|
||||
char target_buf[MAX_FIELD_WIDTH];
|
||||
String source_type(source_buf, sizeof(source_buf), &my_charset_latin1);
|
||||
String target_type(target_buf, sizeof(target_buf), &my_charset_latin1);
|
||||
tmp_table->field[col]->sql_type(source_type);
|
||||
table->field[col]->sql_type(target_type);
|
||||
DBUG_PRINT("debug", ("Field %s - conversion required."
|
||||
" Source type: '%s', Target type: '%s'",
|
||||
tmp_table->field[col]->field_name.str,
|
||||
source_type.c_ptr_safe(), target_type.c_ptr_safe()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
*conv_table_var= tmp_table;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
A wrapper to Virtual_tmp_table, to get access to its constructor,
|
||||
which is protected for safety purposes (against illegal use on stack).
|
||||
*/
|
||||
class Virtual_conversion_table: public Virtual_tmp_table
|
||||
{
|
||||
public:
|
||||
Virtual_conversion_table(THD *thd) :Virtual_tmp_table(thd) { }
|
||||
/**
|
||||
Add a new field into the virtual table.
|
||||
@param sql_type - The real_type of the field.
|
||||
@param metadata - The RBR binary log metadata for this field.
|
||||
@param target_field - The field from the target table, to get extra
|
||||
attributes from (e.g. typelib in case of ENUM).
|
||||
*/
|
||||
bool add(enum_field_types sql_type,
|
||||
uint16 metadata, const Field *target_field)
|
||||
{
|
||||
const Type_handler *handler= Type_handler::get_handler_by_real_type(sql_type);
|
||||
if (!handler)
|
||||
{
|
||||
sql_print_error("In RBR mode, Slave received unknown field type field %d "
|
||||
" for column Name: %s.%s.%s.",
|
||||
(int) sql_type,
|
||||
target_field->table->s->db.str,
|
||||
target_field->table->s->table_name.str,
|
||||
target_field->field_name.str);
|
||||
return true;
|
||||
}
|
||||
Field *tmp= handler->make_conversion_table_field(this, metadata,
|
||||
target_field);
|
||||
if (!tmp)
|
||||
return true;
|
||||
Virtual_tmp_table::add(tmp);
|
||||
DBUG_PRINT("debug", ("sql_type: %d, target_field: '%s', max_length: %d, decimals: %d,"
|
||||
" maybe_null: %d, unsigned_flag: %d, pack_length: %u",
|
||||
sql_type, target_field->field_name.str,
|
||||
tmp->field_length, tmp->decimals(), TRUE,
|
||||
tmp->flags, tmp->pack_length()));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Create a conversion table.
|
||||
|
||||
If the function is unable to create the conversion table, an error
|
||||
will be printed and NULL will be returned.
|
||||
|
||||
@return Pointer to conversion table, or NULL if unable to create
|
||||
conversion table.
|
||||
*/
|
||||
|
||||
TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi,
|
||||
TABLE *target_table) const
|
||||
{
|
||||
DBUG_ENTER("table_def::create_conversion_table");
|
||||
|
||||
Virtual_conversion_table *conv_table;
|
||||
Relay_log_info *rli= rgi->rli;
|
||||
/*
|
||||
At slave, columns may differ. So we should create
|
||||
MY_MIN(columns@master, columns@slave) columns in the
|
||||
conversion table.
|
||||
*/
|
||||
uint const cols_to_create= MY_MIN(target_table->s->fields, size());
|
||||
if (!(conv_table= new(thd) Virtual_conversion_table(thd)) ||
|
||||
conv_table->init(cols_to_create))
|
||||
goto err;
|
||||
for (uint col= 0 ; col < cols_to_create; ++col)
|
||||
{
|
||||
if (conv_table->add(type(col), field_metadata(col),
|
||||
target_table->field[col]))
|
||||
{
|
||||
DBUG_PRINT("debug", ("binlog_type: %d, metadata: %04X, target_field: '%s'"
|
||||
" make_conversion_table_field() failed",
|
||||
binlog_type(col), field_metadata(col),
|
||||
target_table->field[col]->field_name.str));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (conv_table->open())
|
||||
goto err; // Could not allocate record buffer?
|
||||
|
||||
DBUG_RETURN(conv_table);
|
||||
|
||||
err:
|
||||
if (conv_table)
|
||||
delete conv_table;
|
||||
rli->report(ERROR_LEVEL, ER_SLAVE_CANT_CREATE_CONVERSION, rgi->gtid_info(),
|
||||
ER_THD(thd, ER_SLAVE_CANT_CREATE_CONVERSION),
|
||||
target_table->s->db.str,
|
||||
target_table->s->table_name.str);
|
||||
DBUG_RETURN(NULL);
|
||||
}
|
||||
#endif /* MYSQL_CLIENT */
|
||||
|
||||
table_def::table_def(unsigned char *types, ulong size,
|
||||
uchar *field_metadata, int metadata_size,
|
||||
@ -1245,67 +334,3 @@ bool event_checksum_test(uchar *event_buf, ulong event_len, enum enum_binlog_che
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
|
||||
|
||||
Deferred_log_events::Deferred_log_events(Relay_log_info *rli) : last_added(NULL)
|
||||
{
|
||||
my_init_dynamic_array(&array, sizeof(Log_event *), 32, 16, MYF(0));
|
||||
}
|
||||
|
||||
Deferred_log_events::~Deferred_log_events()
|
||||
{
|
||||
delete_dynamic(&array);
|
||||
}
|
||||
|
||||
int Deferred_log_events::add(Log_event *ev)
|
||||
{
|
||||
last_added= ev;
|
||||
insert_dynamic(&array, (uchar*) &ev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Deferred_log_events::is_empty()
|
||||
{
|
||||
return array.elements == 0;
|
||||
}
|
||||
|
||||
bool Deferred_log_events::execute(rpl_group_info *rgi)
|
||||
{
|
||||
bool res= false;
|
||||
DBUG_ENTER("Deferred_log_events::execute");
|
||||
DBUG_ASSERT(rgi->deferred_events_collecting);
|
||||
|
||||
rgi->deferred_events_collecting= false;
|
||||
for (uint i= 0; !res && i < array.elements; i++)
|
||||
{
|
||||
Log_event *ev= (* (Log_event **)
|
||||
dynamic_array_ptr(&array, i));
|
||||
res= ev->apply_event(rgi);
|
||||
}
|
||||
rgi->deferred_events_collecting= true;
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
void Deferred_log_events::rewind()
|
||||
{
|
||||
/*
|
||||
Reset preceding Query log event events which execution was
|
||||
deferred because of slave side filtering.
|
||||
*/
|
||||
if (!is_empty())
|
||||
{
|
||||
for (uint i= 0; i < array.elements; i++)
|
||||
{
|
||||
Log_event *ev= *(Log_event **) dynamic_array_ptr(&array, i);
|
||||
delete ev;
|
||||
}
|
||||
last_added= NULL;
|
||||
if (array.elements > array.max_element)
|
||||
freeze_size(&array);
|
||||
reset_dynamic(&array);
|
||||
}
|
||||
last_added= NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -118,7 +118,9 @@ public:
|
||||
|
||||
return source_type;
|
||||
}
|
||||
|
||||
#ifdef MYSQL_SERVER
|
||||
const Type_handler *field_type_handler(uint index) const;
|
||||
#endif
|
||||
|
||||
/*
|
||||
This function allows callers to get the extra field data from the
|
||||
|
1191
sql/rpl_utility_server.cc
Normal file
1191
sql/rpl_utility_server.cc
Normal file
File diff suppressed because it is too large
Load Diff
@ -60,13 +60,13 @@ Type_handler_string type_handler_string;
|
||||
Type_handler_var_string type_handler_var_string;
|
||||
Type_handler_varchar type_handler_varchar;
|
||||
Type_handler_hex_hybrid type_handler_hex_hybrid;
|
||||
static Type_handler_varchar_compressed type_handler_varchar_compressed;
|
||||
Type_handler_varchar_compressed type_handler_varchar_compressed;
|
||||
|
||||
Type_handler_tiny_blob type_handler_tiny_blob;
|
||||
Type_handler_medium_blob type_handler_medium_blob;
|
||||
Type_handler_long_blob type_handler_long_blob;
|
||||
Type_handler_blob type_handler_blob;
|
||||
static Type_handler_blob_compressed type_handler_blob_compressed;
|
||||
Type_handler_blob_compressed type_handler_blob_compressed;
|
||||
|
||||
Type_handler_interval_DDhhmmssff type_handler_interval_DDhhmmssff;
|
||||
|
||||
@ -1908,13 +1908,7 @@ Type_handler::get_handler_by_real_type(enum_field_types type)
|
||||
case MYSQL_TYPE_LONG_BLOB: return &type_handler_long_blob;
|
||||
case MYSQL_TYPE_BLOB: return &type_handler_blob;
|
||||
case MYSQL_TYPE_BLOB_COMPRESSED: return &type_handler_blob_compressed;
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
/*
|
||||
VAR_STRING is actually a field_type(), not a real_type(),
|
||||
but it's used around the code in real_type() context.
|
||||
We should clean up the code and add DBUG_ASSERT(0) here.
|
||||
*/
|
||||
return &type_handler_string;
|
||||
case MYSQL_TYPE_VAR_STRING: return &type_handler_var_string;
|
||||
case MYSQL_TYPE_STRING: return &type_handler_string;
|
||||
case MYSQL_TYPE_ENUM: return &type_handler_enum;
|
||||
case MYSQL_TYPE_SET: return &type_handler_set;
|
||||
@ -1933,8 +1927,7 @@ Type_handler::get_handler_by_real_type(enum_field_types type)
|
||||
case MYSQL_TYPE_DATETIME2: return &type_handler_datetime2;
|
||||
case MYSQL_TYPE_NEWDATE: return &type_handler_newdate;
|
||||
};
|
||||
DBUG_ASSERT(0);
|
||||
return &type_handler_string;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -84,6 +84,7 @@ struct TABLE;
|
||||
struct SORT_FIELD_ATTR;
|
||||
class Vers_history_point;
|
||||
class Virtual_column_info;
|
||||
class Conv_source;
|
||||
struct ST_FIELD_INFO;
|
||||
|
||||
#define my_charset_numeric my_charset_latin1
|
||||
@ -3393,6 +3394,8 @@ public:
|
||||
virtual Field *make_conversion_table_field(TABLE *TABLE,
|
||||
uint metadata,
|
||||
const Field *target) const= 0;
|
||||
virtual void show_binlog_type(const Conv_source &src, String *str) const;
|
||||
virtual uint32 max_display_length_for_field(const Conv_source &src) const= 0;
|
||||
/*
|
||||
Performs the final data type validation for a UNION element,
|
||||
after the regular "aggregation for result" was done.
|
||||
@ -3891,6 +3894,11 @@ public:
|
||||
DBUG_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const
|
||||
{
|
||||
DBUG_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
uint32 calc_pack_length(uint32 length) const
|
||||
{
|
||||
DBUG_ASSERT(0);
|
||||
@ -4825,6 +4833,8 @@ public:
|
||||
return unsigned_fl ? &m_limits_uint8 : &m_limits_sint8;
|
||||
}
|
||||
uint32 calc_pack_length(uint32 length) const { return 1; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const
|
||||
{ return 4; }
|
||||
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
|
||||
{
|
||||
return Item_send_tiny(item, protocol, buf);
|
||||
@ -4877,6 +4887,8 @@ public:
|
||||
{
|
||||
return unsigned_fl ? &m_limits_uint16 : &m_limits_sint16;
|
||||
}
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const
|
||||
{ return 6; }
|
||||
uint32 calc_pack_length(uint32 length) const { return 2; }
|
||||
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
|
||||
const Field *target) const;
|
||||
@ -4922,6 +4934,8 @@ public:
|
||||
{
|
||||
return unsigned_fl ? &m_limits_uint32 : &m_limits_sint32;
|
||||
}
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const
|
||||
{ return 11; }
|
||||
uint32 calc_pack_length(uint32 length) const { return 4; }
|
||||
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
|
||||
{
|
||||
@ -4982,6 +4996,8 @@ public:
|
||||
{
|
||||
return unsigned_fl ? &m_limits_uint64 : &m_limits_sint64;
|
||||
}
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const
|
||||
{ return 20; }
|
||||
uint32 calc_pack_length(uint32 length) const { return 8; }
|
||||
Item *create_typecast_item(THD *thd, Item *item,
|
||||
const Type_cast_attributes &attr) const;
|
||||
@ -5050,6 +5066,8 @@ public:
|
||||
{
|
||||
return unsigned_fl ? &m_limits_uint24 : &m_limits_sint24;
|
||||
}
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const
|
||||
{ return 9; }
|
||||
uint32 calc_pack_length(uint32 length) const { return 3; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
@ -5084,6 +5102,8 @@ public:
|
||||
return PROTOCOL_SEND_SHORT;
|
||||
}
|
||||
uint32 max_display_length(const Item *item) const;
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const
|
||||
{ return 4; }
|
||||
uint32 calc_pack_length(uint32 length) const { return 1; }
|
||||
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
|
||||
{
|
||||
@ -5133,6 +5153,7 @@ public:
|
||||
return PROTOCOL_SEND_STRING;
|
||||
}
|
||||
uint32 max_display_length(const Item *item) const;
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
uint32 calc_pack_length(uint32 length) const { return length / 8; }
|
||||
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
|
||||
{
|
||||
@ -5142,6 +5163,7 @@ public:
|
||||
{
|
||||
return print_item_value_csstr(thd, item, str);
|
||||
}
|
||||
void show_binlog_type(const Conv_source &src, String *str) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
bool Column_definition_fix_attributes(Column_definition *c) const;
|
||||
@ -5186,6 +5208,8 @@ public:
|
||||
}
|
||||
bool type_can_have_auto_increment_attribute() const { return true; }
|
||||
uint32 max_display_length(const Item *item) const { return 25; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const
|
||||
{ return 12; }
|
||||
uint32 calc_pack_length(uint32 length) const { return sizeof(float); }
|
||||
Item *create_typecast_item(THD *thd, Item *item,
|
||||
const Type_cast_attributes &attr) const;
|
||||
@ -5239,6 +5263,8 @@ public:
|
||||
}
|
||||
bool type_can_have_auto_increment_attribute() const { return true; }
|
||||
uint32 max_display_length(const Item *item) const { return 53; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const
|
||||
{ return 22; }
|
||||
uint32 calc_pack_length(uint32 length) const { return sizeof(double); }
|
||||
Item *create_typecast_item(THD *thd, Item *item,
|
||||
const Type_cast_attributes &attr) const;
|
||||
@ -5375,6 +5401,8 @@ public:
|
||||
static uint hires_bytes(uint dec) { return m_hires_bytes[dec]; }
|
||||
virtual ~Type_handler_time() {}
|
||||
const Name version() const { return m_version_mariadb53; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const
|
||||
{ return MIN_TIME_WIDTH; }
|
||||
uint32 calc_pack_length(uint32 length) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
@ -5402,6 +5430,7 @@ public:
|
||||
virtual ~Type_handler_time2() {}
|
||||
const Name version() const { return m_version_mysql56; }
|
||||
enum_field_types real_field_type() const { return MYSQL_TYPE_TIME2; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
uint32 calc_pack_length(uint32 length) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
@ -5456,6 +5485,8 @@ public:
|
||||
const Name &default_value() const;
|
||||
const Type_handler *type_handler_for_comparison() const;
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const
|
||||
{ return 3; }
|
||||
enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) const
|
||||
{
|
||||
return DYN_COL_DATE;
|
||||
@ -5624,6 +5655,8 @@ public:
|
||||
static uint hires_bytes(uint dec) { return m_hires_bytes[dec]; }
|
||||
virtual ~Type_handler_datetime() {}
|
||||
const Name version() const { return m_version_mariadb53; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const
|
||||
{ return MAX_DATETIME_WIDTH; }
|
||||
uint32 calc_pack_length(uint32 length) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
@ -5651,6 +5684,7 @@ public:
|
||||
virtual ~Type_handler_datetime2() {}
|
||||
const Name version() const { return m_version_mysql56; }
|
||||
enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
uint32 calc_pack_length(uint32 length) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
@ -5759,6 +5793,8 @@ public:
|
||||
static uint sec_part_bytes(uint dec) { return m_sec_part_bytes[dec]; }
|
||||
virtual ~Type_handler_timestamp() {}
|
||||
const Name version() const { return m_version_mariadb53; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const
|
||||
{ return MAX_DATETIME_WIDTH; }
|
||||
uint32 calc_pack_length(uint32 length) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
@ -5786,6 +5822,7 @@ public:
|
||||
virtual ~Type_handler_timestamp2() {}
|
||||
const Name version() const { return m_version_mysql56; }
|
||||
enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
uint32 calc_pack_length(uint32 length) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
@ -5816,9 +5853,11 @@ public:
|
||||
virtual ~Type_handler_olddecimal() {}
|
||||
const Name name() const { return m_name_decimal; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
uint32 calc_pack_length(uint32 length) const { return length; }
|
||||
const Type_handler *type_handler_for_tmp_table(const Item *item) const;
|
||||
const Type_handler *type_handler_for_union(const Item *item) const;
|
||||
void show_binlog_type(const Conv_source &src, String *str) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
bool Column_definition_fix_attributes(Column_definition *c) const;
|
||||
@ -5847,7 +5886,9 @@ public:
|
||||
virtual ~Type_handler_newdecimal() {}
|
||||
const Name name() const { return m_name_decimal; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
uint32 calc_pack_length(uint32 length) const;
|
||||
void show_binlog_type(const Conv_source &src, String *str) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
bool Column_definition_fix_attributes(Column_definition *c) const;
|
||||
@ -5893,6 +5934,7 @@ public:
|
||||
const Type_handler *type_handler_for_tmp_table(const Item *item) const;
|
||||
const Type_handler *type_handler_for_union(const Item *) const;
|
||||
uint32 max_display_length(const Item *item) const { return 0; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const { return 0;}
|
||||
uint32 calc_pack_length(uint32 length) const { return 0; }
|
||||
bool Item_const_eq(const Item_const *a, const Item_const *b,
|
||||
bool binary_cmp) const;
|
||||
@ -5947,11 +5989,13 @@ public:
|
||||
const Name name() const { return m_name_char; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
|
||||
bool is_param_long_data_type() const { return true; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
uint32 calc_pack_length(uint32 length) const { return length; }
|
||||
const Type_handler *type_handler_for_tmp_table(const Item *item) const
|
||||
{
|
||||
return varstring_type_handler(item);
|
||||
}
|
||||
void show_binlog_type(const Conv_source &src, String *str) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
bool Column_definition_fix_attributes(Column_definition *c) const;
|
||||
@ -5993,6 +6037,8 @@ public:
|
||||
{
|
||||
return varstring_type_handler(item);
|
||||
}
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
void show_binlog_type(const Conv_source &src, String *str) const;
|
||||
void Column_definition_implicit_upgrade(Column_definition *c) const;
|
||||
bool Column_definition_fix_attributes(Column_definition *c) const;
|
||||
bool Column_definition_prepare_stage2(Column_definition *c,
|
||||
@ -6017,6 +6063,7 @@ public:
|
||||
{
|
||||
return MYSQL_TYPE_VAR_STRING; // Keep things compatible for old clients
|
||||
}
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
uint32 calc_pack_length(uint32 length) const
|
||||
{
|
||||
return (length + (length < 256 ? 1: 2));
|
||||
@ -6030,6 +6077,7 @@ public:
|
||||
return varstring_type_handler(item);
|
||||
}
|
||||
bool is_param_long_data_type() const { return true; }
|
||||
void show_binlog_type(const Conv_source &src, String *str) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
bool Column_definition_fix_attributes(Column_definition *c) const;
|
||||
@ -6065,6 +6113,12 @@ public:
|
||||
class Type_handler_varchar_compressed: public Type_handler_varchar
|
||||
{
|
||||
public:
|
||||
enum_field_types real_field_type() const
|
||||
{
|
||||
return MYSQL_TYPE_VARCHAR_COMPRESSED;
|
||||
}
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
void show_binlog_type(const Conv_source &src, String *str) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) const
|
||||
@ -6132,6 +6186,7 @@ public:
|
||||
uint length_bytes() const { return 1; }
|
||||
const Name name() const { return m_name_tinyblob; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_TINY_BLOB; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
uint32 calc_pack_length(uint32 length) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
@ -6149,6 +6204,7 @@ public:
|
||||
uint length_bytes() const { return 3; }
|
||||
const Name name() const { return m_name_mediumblob; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_MEDIUM_BLOB; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
uint32 calc_pack_length(uint32 length) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
@ -6166,6 +6222,7 @@ public:
|
||||
uint length_bytes() const { return 4; }
|
||||
const Name name() const { return m_name_longblob; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
uint32 calc_pack_length(uint32 length) const;
|
||||
Item *create_typecast_item(THD *thd, Item *item,
|
||||
const Type_cast_attributes &attr) const;
|
||||
@ -6185,6 +6242,7 @@ public:
|
||||
uint length_bytes() const { return 2; }
|
||||
const Name name() const { return m_name_blob; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
uint32 calc_pack_length(uint32 length) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
@ -6197,6 +6255,12 @@ public:
|
||||
class Type_handler_blob_compressed: public Type_handler_blob
|
||||
{
|
||||
public:
|
||||
enum_field_types real_field_type() const
|
||||
{
|
||||
return MYSQL_TYPE_BLOB_COMPRESSED;
|
||||
}
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
void show_binlog_type(const Conv_source &src, String *str) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) const
|
||||
@ -6216,6 +6280,7 @@ public:
|
||||
const Name name() const { return m_name_geometry; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
|
||||
bool is_param_long_data_type() const { return true; }
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
uint32 calc_pack_length(uint32 length) const;
|
||||
const Type_handler *type_handler_for_comparison() const;
|
||||
bool type_can_have_key_part() const
|
||||
@ -6313,6 +6378,7 @@ public:
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
|
||||
const Type_handler *type_handler_for_item_field() const;
|
||||
const Type_handler *cast_to_int_type_handler() const;
|
||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||
bool Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const char *name,
|
||||
Type_handler_hybrid_field_type *,
|
||||
@ -6508,12 +6574,16 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_set type_handler_set;
|
||||
extern MYSQL_PLUGIN_IMPORT Type_handler_string type_handler_string;
|
||||
extern MYSQL_PLUGIN_IMPORT Type_handler_var_string type_handler_var_string;
|
||||
extern MYSQL_PLUGIN_IMPORT Type_handler_varchar type_handler_varchar;
|
||||
extern MYSQL_PLUGIN_IMPORT Type_handler_varchar_compressed
|
||||
type_handler_varchar_compressed;
|
||||
extern MYSQL_PLUGIN_IMPORT Type_handler_hex_hybrid type_handler_hex_hybrid;
|
||||
|
||||
extern MYSQL_PLUGIN_IMPORT Type_handler_tiny_blob type_handler_tiny_blob;
|
||||
extern MYSQL_PLUGIN_IMPORT Type_handler_medium_blob type_handler_medium_blob;
|
||||
extern MYSQL_PLUGIN_IMPORT Type_handler_long_blob type_handler_long_blob;
|
||||
extern MYSQL_PLUGIN_IMPORT Type_handler_blob type_handler_blob;
|
||||
extern MYSQL_PLUGIN_IMPORT Type_handler_blob_compressed
|
||||
type_handler_blob_compressed;
|
||||
|
||||
extern MYSQL_PLUGIN_IMPORT Type_handler_bool type_handler_bool;
|
||||
extern MYSQL_PLUGIN_IMPORT Type_handler_tiny type_handler_tiny;
|
||||
|
@ -510,7 +510,7 @@ INSERT INTO t11 () VALUES(1,@b1,'Testing is fun','Kyle',DEFAULT),
|
||||
|
||||
connection slave;
|
||||
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
|
||||
Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)''
|
||||
Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'blob' to type 'varchar(254)''
|
||||
|
||||
*** Drop t11 ***
|
||||
connection master;
|
||||
|
@ -102,7 +102,7 @@ INSERT INTO t3 () VALUES(@b1,2,'Kyle, TEX'),(@b1,1,'JOE AUSTIN'),(@b1,4,'QA TEST
|
||||
********************************************
|
||||
connection slave;
|
||||
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
|
||||
Last_SQL_Error = 'Column 0 of table 'test.t3' cannot be converted from type 'tinyblob' to type 'int(11)''
|
||||
Last_SQL_Error = 'Column 0 of table 'test.t3' cannot be converted from type 'blob' to type 'int(11)''
|
||||
*** Drop t3 ***
|
||||
connection master;
|
||||
DROP TABLE t3;
|
||||
|
Loading…
x
Reference in New Issue
Block a user