diff options
Diffstat (limited to 'sql/rpl_utility.cc')
-rw-r--r-- | sql/rpl_utility.cc | 89 |
1 files changed, 41 insertions, 48 deletions
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index 27a7a0478b6..ff2cd74c3a7 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -15,6 +15,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <my_global.h> +#include <my_bit.h> #include "rpl_utility.h" #include "log_event.h" @@ -23,30 +24,6 @@ #include "sql_select.h" /** - Function to compare two size_t integers for their relative - order. Used below. - */ -int compare(size_t a, size_t b) -{ - if (a < b) - return -1; - if (b < a) - return 1; - return 0; -} - - -/** - Max value for an unsigned integer of 'bits' bits. - - The somewhat contorted expression is to avoid overflow. - */ -uint32 uint_max(int bits) { - return (((1UL << (bits - 1)) - 1) << 1) | 1; -} - - -/** Calculate display length for MySQL56 temporal data types from their metadata. It contains fractional precision in the low 16-bit word. */ @@ -121,20 +98,22 @@ max_display_length_for_field(enum_field_types sql_type, unsigned int metadata) return 3; case MYSQL_TYPE_DATE: - case MYSQL_TYPE_TIME: 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 4; + return MAX_DATETIME_WIDTH; case MYSQL_TYPE_TIMESTAMP2: return max_display_length_for_temporal2_field(MAX_DATETIME_WIDTH, metadata); case MYSQL_TYPE_DATETIME: - return 8; + return MAX_DATETIME_WIDTH; case MYSQL_TYPE_DATETIME2: return max_display_length_for_temporal2_field(MAX_DATETIME_WIDTH, metadata); @@ -160,10 +139,10 @@ max_display_length_for_field(enum_field_types sql_type, unsigned int metadata) */ case MYSQL_TYPE_TINY_BLOB: - return uint_max(1 * 8); + return my_set_bits(1 * 8); case MYSQL_TYPE_MEDIUM_BLOB: - return uint_max(3 * 8); + return my_set_bits(3 * 8); case MYSQL_TYPE_BLOB: /* @@ -171,11 +150,11 @@ max_display_length_for_field(enum_field_types sql_type, unsigned int metadata) 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 uint_max(metadata * 8); + return my_set_bits(metadata * 8); case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_GEOMETRY: - return uint_max(4 * 8); + return my_set_bits(4 * 8); default: return ~(uint32) 0; @@ -205,7 +184,7 @@ int compare_lengths(Field *field, enum_field_types source_type, uint16 metadata) " target_length: %lu, target_type: %u", (unsigned long) source_length, source_type, (unsigned long) target_length, field->real_type())); - int result= compare(source_length, target_length); + int result= source_length < target_length ? -1 : source_length > target_length; DBUG_PRINT("result", ("%d", result)); DBUG_RETURN(result); } @@ -879,16 +858,19 @@ table_def::compatible_with(THD *thd, rpl_group_info *rgi, col, field->field_name)); 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(ER_SLAVE_CONVERSION_FAILED), + ER_THD(thd, ER_SLAVE_CONVERSION_FAILED), col, db_name, tbl_name, source_type.c_ptr_safe(), target_type.c_ptr_safe()); return false; @@ -947,8 +929,9 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi, { Create_field *field_def= (Create_field*) alloc_root(thd->mem_root, sizeof(Create_field)); + Field *target_field= target_table->field[col]; bool unsigned_flag= 0; - if (field_list.push_back(field_def)) + if (field_list.push_back(field_def, thd->mem_root)) DBUG_RETURN(NULL); uint decimals= 0; @@ -961,7 +944,7 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi, int precision; case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: - interval= static_cast<Field_enum*>(target_table->field[col])->typelib; + interval= static_cast<Field_enum*>(target_field)->typelib; pack_length= field_metadata(col) & 0x00ff; break; @@ -985,7 +968,7 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi, " column Name: %s.%s.%s.", target_table->s->db.str, target_table->s->table_name.str, - target_table->field[col]->field_name); + target_field->field_name); goto err; case MYSQL_TYPE_TINY_BLOB: @@ -1006,7 +989,18 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi, assume we have same sign on master and slave. This is true when not using conversions so it should be true also when using conversions. */ - unsigned_flag= ((Field_num*) target_table->field[col])->unsigned_flag; + unsigned_flag= static_cast<Field_num*>(target_field)->unsigned_flag; + break; + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATETIME: + /* + As we don't know the precision of the temporal field on the master, + assume it's the same on master and slave. This is true when not + using conversions so it should be true also when using conversions. + */ + if (target_field->decimals()) + max_length+= target_field->decimals() + 1; break; default: break; @@ -1014,7 +1008,7 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi, DBUG_PRINT("debug", ("sql_type: %d, target_field: '%s', max_length: %d, decimals: %d," " maybe_null: %d, unsigned_flag: %d, pack_length: %u", - binlog_type(col), target_table->field[col]->field_name, + binlog_type(col), target_field->field_name, max_length, decimals, TRUE, unsigned_flag, pack_length)); field_def->init_for_tmp_table(type(col), @@ -1023,7 +1017,7 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi, TRUE, // maybe_null unsigned_flag, pack_length); - field_def->charset= target_table->field[col]->charset(); + field_def->charset= target_field->charset(); field_def->interval= interval; } @@ -1031,10 +1025,12 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi, err: if (conv_table == NULL) + { rli->report(ERROR_LEVEL, ER_SLAVE_CANT_CREATE_CONVERSION, rgi->gtid_info(), - ER(ER_SLAVE_CANT_CREATE_CONVERSION), + ER_THD(thd, ER_SLAVE_CANT_CREATE_CONVERSION), target_table->s->db.str, target_table->s->table_name.str); + } DBUG_RETURN(conv_table); } #endif /* MYSQL_CLIENT */ @@ -1153,7 +1149,7 @@ table_def::~table_def() @return TRUE if test fails FALSE as success */ -bool event_checksum_test(uchar *event_buf, ulong event_len, uint8 alg) +bool event_checksum_test(uchar *event_buf, ulong event_len, enum enum_binlog_checksum_alg alg) { bool res= FALSE; uint16 flags= 0; // to store in FD's buffer flags orig value @@ -1187,19 +1183,17 @@ bool event_checksum_test(uchar *event_buf, ulong event_len, uint8 alg) compile_time_assert(BINLOG_CHECKSUM_ALG_ENUM_END <= 0x80); } incoming= uint4korr(event_buf + event_len - BINLOG_CHECKSUM_LEN); - computed= 0; - /* checksum the event content but the checksum part itself */ - computed= my_checksum(computed, (const uchar*) event_buf, - event_len - BINLOG_CHECKSUM_LEN); + /* checksum the event content without the checksum part itself */ + computed= my_checksum(0, event_buf, event_len - BINLOG_CHECKSUM_LEN); if (flags != 0) { /* restoring the orig value of flags of FD */ DBUG_ASSERT(event_buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT); event_buf[FLAGS_OFFSET]= (uchar) flags; } - res= !(computed == incoming); + res= DBUG_EVALUATE_IF("simulate_checksum_test_failure", TRUE, computed != incoming); } - return DBUG_EVALUATE_IF("simulate_checksum_test_failure", TRUE, res); + return res; } #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) @@ -1265,4 +1259,3 @@ void Deferred_log_events::rewind() } #endif - |