diff options
Diffstat (limited to 'sql')
44 files changed, 1052 insertions, 618 deletions
diff --git a/sql/field.cc b/sql/field.cc index 7ae8916de71..37262f8c38c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1360,6 +1360,27 @@ bool Field::send_binary(Protocol *protocol) } +/** + Check to see if field size is compatible with destination. + + This method is used in row-based replication to verify that the slave's + field size is less than or equal to the master's field size. The + encoded field metadata (from the master or source) is decoded and compared + to the size of this field (the slave or destination). + + @param field_metadata Encoded size in field metadata + + @retval 0 if this field's size is < the source field's size + @retval 1 if this field's size is >= the source field's size +*/ +int Field::compatible_field_size(uint field_metadata) +{ + uint const source_size= pack_length_from_metadata(field_metadata); + uint const destination_size= row_pack_length(); + return (source_size <= destination_size); +} + + int Field::store(const char *to, uint length, CHARSET_INFO *cs, enum_check_fields check_level) { @@ -2690,6 +2711,76 @@ void Field_new_decimal::sql_type(String &str) const } +/** + Save the field metadata for new decimal fields. + + Saves the precision in the first byte and decimals() in the second + byte of the field metadata array at index of *metadata_ptr and + *(metadata_ptr + 1). + + @param metadata_ptr First byte of field metadata + + @returns number of bytes written to metadata_ptr +*/ +int Field_new_decimal::do_save_field_metadata(uchar *metadata_ptr) +{ + *metadata_ptr= precision; + *(metadata_ptr + 1)= decimals(); + return 2; +} + + +/** + Returns the number of bytes field uses in row-based replication + row packed size. + + This method is used in row-based replication to determine the number + of bytes that the field consumes in the row record format. This is + used to skip fields in the master that do not exist on the slave. + + @param field_metadata Encoded size in field metadata + + @returns The size of the field based on the field metadata. +*/ +uint Field_new_decimal::pack_length_from_metadata(uint field_metadata) +{ + uint const source_precision= (field_metadata >> 8U) & 0x00ff; + uint const source_decimal= field_metadata & 0x00ff; + uint const source_size= my_decimal_get_binary_size(source_precision, + source_decimal); + return (source_size); +} + + +/** + Check to see if field size is compatible with destination. + + This method is used in row-based replication to verify that the slave's + field size is less than or equal to the master's field size. The + encoded field metadata (from the master or source) is decoded and compared + to the size of this field (the slave or destination). + + @param field_metadata Encoded size in field metadata + + @retval 0 if this field's size is < the source field's size + @retval 1 if this field's size is >= the source field's size +*/ +int Field_new_decimal::compatible_field_size(uint field_metadata) +{ + int compatible= 0; + uint const source_precision= (field_metadata >> 8U) & 0x00ff; + uint const source_decimal= field_metadata & 0x00ff; + uint const source_size= my_decimal_get_binary_size(source_precision, + source_decimal); + uint const destination_size= row_pack_length(); + compatible= (source_size <= destination_size); + if (compatible) + compatible= (source_precision <= precision) && + (source_decimal <= decimals()); + return (compatible); +} + + uint Field_new_decimal::is_equal(Create_field *new_field) { return ((new_field->sql_type == real_type()) && @@ -2724,7 +2815,9 @@ const uchar *Field_new_decimal::unpack(uchar* to, uint from_pack_len= my_decimal_get_binary_size(from_precision, from_decimal); uint len= (param_data && (from_pack_len < length)) ? from_pack_len : length; - if (from_pack_len && (from_pack_len < length)) + if ((from_pack_len && (from_pack_len < length)) || + (from_precision < precision) || + (from_decimal < decimals())) { /* If the master's data is smaller than the slave, we need to convert @@ -4087,6 +4180,22 @@ bool Field_float::send_binary(Protocol *protocol) } +/** + Save the field metadata for float fields. + + Saves the pack length in the first byte. + + @param metadata_ptr First byte of field metadata + + @returns number of bytes written to metadata_ptr +*/ +int Field_float::do_save_field_metadata(uchar *metadata_ptr) +{ + *metadata_ptr= pack_length(); + return 1; +} + + void Field_float::sql_type(String &res) const { if (dec == NOT_FIXED_DEC) @@ -4404,6 +4513,23 @@ void Field_double::sort_string(uchar *to,uint length __attribute__((unused))) } +/** + Save the field metadata for double fields. + + Saves the pack length in the first byte of the field metadata array + at index of *metadata_ptr. + + @param metadata_ptr First byte of field metadata + + @returns number of bytes written to metadata_ptr +*/ +int Field_double::do_save_field_metadata(uchar *metadata_ptr) +{ + *metadata_ptr= pack_length(); + return 1; +} + + void Field_double::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); @@ -4655,6 +4781,7 @@ longlong Field_timestamp::val_int(void) MYSQL_TIME time_tmp; THD *thd= table ? table->in_use : current_thd; + thd->time_zone_used= 1; #ifdef WORDS_BIGENDIAN if (table && table->s->db_low_byte_first) temp=uint4korr(ptr); @@ -4666,7 +4793,6 @@ longlong Field_timestamp::val_int(void) return(0); /* purecov: inspected */ thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, (my_time_t)temp); - thd->time_zone_used= 1; return time_tmp.year * LL(10000000000) + time_tmp.month * LL(100000000) + time_tmp.day * 1000000L + time_tmp.hour * 10000L + @@ -4686,6 +4812,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr) to= (char*) val_buffer->ptr(); val_buffer->length(field_length); + thd->time_zone_used= 1; #ifdef WORDS_BIGENDIAN if (table && table->s->db_low_byte_first) temp=uint4korr(ptr); @@ -4701,7 +4828,6 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr) val_buffer->set_charset(&my_charset_bin); // Safety thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,(my_time_t)temp); - thd->time_zone_used= 1; temp= time_tmp.year % 100; if (temp < YY_PART_YEAR - 1) @@ -4751,6 +4877,7 @@ bool Field_timestamp::get_date(MYSQL_TIME *ltime, uint fuzzydate) { long temp; THD *thd= table ? table->in_use : current_thd; + thd->time_zone_used= 1; #ifdef WORDS_BIGENDIAN if (table && table->s->db_low_byte_first) temp=uint4korr(ptr); @@ -4766,7 +4893,6 @@ bool Field_timestamp::get_date(MYSQL_TIME *ltime, uint fuzzydate) else { thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)temp); - thd->time_zone_used= 1; } return 0; } @@ -6421,6 +6547,25 @@ const uchar *Field_string::unpack(uchar *to, const uchar *from) } +/** + Save the field metadata for string fields. + + Saves the real type in the first byte and the field length in the + second byte of the field metadata array at index of *metadata_ptr and + *(metadata_ptr + 1). + + @param metadata_ptr First byte of field metadata + + @returns number of bytes written to metadata_ptr +*/ +int Field_string::do_save_field_metadata(uchar *metadata_ptr) +{ + *metadata_ptr= real_type(); + *(metadata_ptr + 1)= field_length; + return 2; +} + + /* Compare two packed keys @@ -6573,6 +6718,24 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table, const uint Field_varstring::MAX_SIZE= UINT_MAX16; +/** + Save the field metadata for varstring fields. + + Saves the field length in the first byte. Note: may consume + 2 bytes. Caller must ensure second byte is contiguous with + first byte (e.g. array index 0,1). + + @param metadata_ptr First byte of field metadata + + @returns number of bytes written to metadata_ptr +*/ +int Field_varstring::do_save_field_metadata(uchar *metadata_ptr) +{ + char *ptr= (char *)metadata_ptr; + int2store(ptr, field_length); + return 2; +} + int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) { ASSERT_COLUMN_MARKED_FOR_WRITE; @@ -7539,6 +7702,23 @@ int Field_blob::key_cmp(const uchar *a,const uchar *b) } +/** + Save the field metadata for blob fields. + + Saves the pack length in the first byte of the field metadata array + at index of *metadata_ptr. + + @param metadata_ptr First byte of field metadata + + @returns number of bytes written to metadata_ptr +*/ +int Field_blob::do_save_field_metadata(uchar *metadata_ptr) +{ + *metadata_ptr= pack_length_no_ptr(); + return 1; +} + + uint32 Field_blob::sort_length() const { return (uint32) (current_thd->variables.max_sort_length + @@ -8127,6 +8307,25 @@ longlong Field_enum::val_int(void) } +/** + Save the field metadata for enum fields. + + Saves the real type in the first byte and the pack length in the + second byte of the field metadata array at index of *metadata_ptr and + *(metadata_ptr + 1). + + @param metadata_ptr First byte of field metadata + + @returns number of bytes written to metadata_ptr +*/ +int Field_enum::do_save_field_metadata(uchar *metadata_ptr) +{ + *metadata_ptr= real_type(); + *(metadata_ptr + 1)= pack_length(); + return 2; +} + + String *Field_enum::val_str(String *val_buffer __attribute__((unused)), String *val_ptr) { @@ -8663,6 +8862,77 @@ uint Field_bit::get_key_image(uchar *buff, uint length, imagetype type_arg) } +/** + Save the field metadata for bit fields. + + Saves the bit length in the first byte and bytes in record in the + second byte of the field metadata array at index of *metadata_ptr and + *(metadata_ptr + 1). + + @param metadata_ptr First byte of field metadata + + @returns number of bytes written to metadata_ptr +*/ +int Field_bit::do_save_field_metadata(uchar *metadata_ptr) +{ + *metadata_ptr= bit_len; + *(metadata_ptr + 1)= bytes_in_rec; + return 2; +} + + +/** + Returns the number of bytes field uses in row-based replication + row packed size. + + This method is used in row-based replication to determine the number + of bytes that the field consumes in the row record format. This is + used to skip fields in the master that do not exist on the slave. + + @param field_metadata Encoded size in field metadata + + @returns The size of the field based on the field metadata. +*/ +uint Field_bit::pack_length_from_metadata(uint field_metadata) +{ + uint const from_len= (field_metadata >> 8U) & 0x00ff; + uint const from_bit_len= field_metadata & 0x00ff; + uint const source_size= from_len + ((from_bit_len > 0) ? 1 : 0); + return (source_size); +} + + +/** + Check to see if field size is compatible with destination. + + This method is used in row-based replication to verify that the slave's + field size is less than or equal to the master's field size. The + encoded field metadata (from the master or source) is decoded and compared + to the size of this field (the slave or destination). + + @param field_metadata Encoded size in field metadata + + @retval 0 if this field's size is < the source field's size + @retval 1 if this field's size is >= the source field's size +*/ +int Field_bit::compatible_field_size(uint field_metadata) +{ + int compatible= 0; + uint const source_size= pack_length_from_metadata(field_metadata); + uint const destination_size= row_pack_length(); + uint const from_bit_len= field_metadata & 0x00ff; + uint const from_len= (field_metadata >> 8U) & 0x00ff; + if ((bit_len == 0) || (from_bit_len == 0)) + compatible= (source_size <= destination_size); + else if (from_bit_len > bit_len) + compatible= (from_len < bytes_in_rec); + else + compatible= ((from_bit_len <= bit_len) && (from_len <= bytes_in_rec)); + return (compatible); +} + + + void Field_bit::sql_type(String &res) const { CHARSET_INFO *cs= res.charset(); diff --git a/sql/field.h b/sql/field.h index 4ef4898cdb5..8aad6783291 100644 --- a/sql/field.h +++ b/sql/field.h @@ -151,6 +151,24 @@ public: table, which is located on disk). */ virtual uint32 pack_length_in_rec() const { return pack_length(); } + virtual int compatible_field_size(uint field_metadata); + virtual uint pack_length_from_metadata(uint field_metadata) + { return field_metadata; } + /* + This method is used to return the size of the data in a row-based + replication row record. The default implementation of returning 0 is + designed to allow fields that do not use metadata to return TRUE (1) + from compatible_field_size() which uses this function in the comparison. + The default value for field metadata for fields that do not have + metadata is 0. Thus, 0 == 0 means the fields are compatible in size. + + Note: While most classes that override this method return pack_length(), + the classes Field_string, Field_varstring, and Field_blob return + field_length + 1, field_length, and pack_length_no_ptr() respectfully. + */ + virtual uint row_pack_length() { return 0; } + virtual int save_field_metadata(uchar *first_byte) + { return do_save_field_metadata(first_byte); } /* data_length() return the "real size" of the data in memory. @@ -275,9 +293,9 @@ public: if (null_ptr) null_ptr=ADD_TO_PTR(null_ptr,ptr_diff,uchar*); } - inline void get_image(uchar *buff,uint length, CHARSET_INFO *cs) + virtual void get_image(uchar *buff, uint length, CHARSET_INFO *cs) { memcpy(buff,ptr,length); } - inline void set_image(const uchar *buff,uint length, CHARSET_INFO *cs) + virtual void set_image(const uchar *buff,uint length, CHARSET_INFO *cs) { memcpy(ptr,buff,length); } @@ -463,6 +481,19 @@ private: overridden by subclasses. */ virtual size_t do_last_null_byte() const; + +/** + Retrieve the field metadata for fields. + + This default implementation returns 0 and saves 0 in the metadata_ptr + value. + + @param metadata_ptr First byte of field metadata + + @returns 0 no bytes written. +*/ + virtual int do_save_field_metadata(uchar *metadata_ptr) + { return 0; } }; @@ -589,6 +620,8 @@ public: /* New decimal/numeric field which use fixed point arithmetic */ class Field_new_decimal :public Field_num { +private: + int do_save_field_metadata(uchar *first_byte); public: /* The maximum number of decimal digits can be stored */ uint precision; @@ -628,6 +661,9 @@ public: uint32 max_display_length() { return field_length; } uint size_of() const { return sizeof(*this); } uint32 pack_length() const { return (uint32) bin_size; } + uint pack_length_from_metadata(uint field_metadata); + uint row_pack_length() { return pack_length(); } + int compatible_field_size(uint field_metadata); uint is_equal(Create_field *new_field); virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data); }; @@ -834,7 +870,10 @@ public: int cmp(const uchar *,const uchar *); void sort_string(uchar *buff,uint length); uint32 pack_length() const { return sizeof(float); } + uint row_pack_length() { return pack_length(); } void sql_type(String &str) const; +private: + int do_save_field_metadata(uchar *first_byte); }; @@ -871,7 +910,10 @@ public: int cmp(const uchar *,const uchar *); void sort_string(uchar *buff,uint length); uint32 pack_length() const { return sizeof(double); } + uint row_pack_length() { return pack_length(); } void sql_type(String &str) const; +private: + int do_save_field_metadata(uchar *first_byte); }; @@ -1179,6 +1221,9 @@ public: uchar *pack(uchar *to, const uchar *from, uint max_length=~(uint) 0); virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data); const uchar *unpack(uchar* to, const uchar *from); + uint pack_length_from_metadata(uint field_metadata) + { return (field_metadata & 0x00ff); } + uint row_pack_length() { return (field_length + 1); } int pack_cmp(const uchar *a,const uchar *b,uint key_length, my_bool insert_or_update); int pack_cmp(const uchar *b,uint key_length,my_bool insert_or_update); @@ -1190,6 +1235,8 @@ public: { return charset() == &my_charset_bin ? FALSE : TRUE; } Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type); virtual uint get_key_image(uchar *buff,uint length, imagetype type); +private: + int do_save_field_metadata(uchar *first_byte); }; @@ -1225,6 +1272,7 @@ public: enum_field_types type() const { return MYSQL_TYPE_VARCHAR; } enum ha_base_keytype key_type() const; + uint row_pack_length() { return field_length; } bool zero_pack() const { return 0; } int reset(void) { bzero(ptr,field_length+length_bytes); return 0; } uint32 pack_length() const { return (uint32) field_length+length_bytes; } @@ -1276,6 +1324,8 @@ public: uint new_null_bit); uint is_equal(Create_field *new_field); void hash(ulong *nr, ulong *nr2); +private: + int do_save_field_metadata(uchar *first_byte); }; @@ -1341,10 +1391,11 @@ public: This is used to determine the size of the actual data in the row buffer. - @retval The length of the raw data itself without the pointer. + @returns The length of the raw data itself without the pointer. */ uint32 pack_length_no_ptr() const { return (uint32) (packlength); } + uint row_pack_length() { return pack_length_no_ptr(); } uint32 sort_length() const; inline uint32 max_data_length() const { @@ -1371,7 +1422,7 @@ public: This is used to determine the size of the data plus the packed length portion in the row data. - @retval The length in the row plus the size of the data. + @returns The length in the row plus the size of the data. */ uint32 get_packed_size(const uchar *ptr_arg, bool low_byte_first) {return packlength + get_length(ptr_arg, low_byte_first);} @@ -1443,6 +1494,8 @@ public: uint is_equal(Create_field *new_field); inline bool in_read_set() { return bitmap_is_set(table->read_set, field_index); } inline bool in_write_set() { return bitmap_is_set(table->write_set, field_index); } +private: + int do_save_field_metadata(uchar *first_byte); }; @@ -1512,12 +1565,17 @@ public: void sql_type(String &str) const; uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return MYSQL_TYPE_ENUM; } + uint pack_length_from_metadata(uint field_metadata) + { return (field_metadata & 0x00ff); } + uint row_pack_length() { return pack_length(); } virtual bool zero_pack() const { return 0; } bool optimize_range(uint idx, uint part) { return 0; } bool eq_def(Field *field); bool has_charset(void) const { return TRUE; } /* enum and set are sorted as integers */ CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } +private: + int do_save_field_metadata(uchar *first_byte); }; @@ -1538,6 +1596,7 @@ public: int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr) { return Field_set::store((longlong) nr, FALSE); } int store(longlong nr, bool unsigned_val); + virtual bool zero_pack() const { return 1; } String *val_str(String*,String *); void sql_type(String &str) const; @@ -1586,7 +1645,10 @@ public: virtual bool str_needs_quotes() { return TRUE; } my_decimal *val_decimal(my_decimal *); int cmp(const uchar *a, const uchar *b) - { return cmp_binary(a, b); } + { + DBUG_ASSERT(ptr == a); + return Field_bit::key_cmp(b, bytes_in_rec+test(bit_len)); + } int cmp_binary_offset(uint row_offset) { return cmp_offset(row_offset); } int cmp_max(const uchar *a, const uchar *b, uint max_length); @@ -1594,6 +1656,10 @@ public: { return cmp_binary((uchar *) a, (uchar *) b); } int key_cmp(const uchar *str, uint length); int cmp_offset(uint row_offset); + void get_image(uchar *buff, uint length, CHARSET_INFO *cs) + { get_key_image(buff, length, itRAW); } + void set_image(const uchar *buff,uint length, CHARSET_INFO *cs) + { Field_bit::store((char *) buff, length, cs); } uint get_key_image(uchar *buff, uint length, imagetype type); void set_key_image(const uchar *buff, uint length) { Field_bit::store((char*) buff, length, &my_charset_bin); } @@ -1601,6 +1667,10 @@ public: { get_key_image(buff, length, itRAW); } uint32 pack_length() const { return (uint32) (field_length + 7) / 8; } uint32 pack_length_in_rec() const { return bytes_in_rec; } + uint pack_length_from_metadata(uint field_metadata); + uint row_pack_length() + { return (bytes_in_rec + ((bit_len > 0) ? 1 : 0)); } + int compatible_field_size(uint field_metadata); void sql_type(String &str) const; uchar *pack(uchar *to, const uchar *from, uint max_length=~(uint) 0); virtual const uchar *unpack(uchar *to, const uchar *from, uint param_data); @@ -1631,6 +1701,7 @@ public: private: virtual size_t do_last_null_byte() const; + int do_save_field_metadata(uchar *first_byte); }; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 3b68b3828d2..68295509e78 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -4287,7 +4287,7 @@ THR_LOCK_DATA **ha_ndbcluster::store_lock(THD *thd, */ #ifdef HAVE_NDB_BINLOG -extern MASTER_INFO *active_mi; +extern Master_info *active_mi; static int ndbcluster_update_apply_status(THD *thd, int do_update) { Thd_ndb *thd_ndb= get_thd_ndb(thd); diff --git a/sql/item_func.cc b/sql/item_func.cc index 83b27de29b7..f016aa6cd05 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2916,7 +2916,8 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, String *res= arguments[i]->val_str(&buffers[i]); if (arguments[i]->null_value) continue; - f_args.args[i]= (char*) res->ptr(); + f_args.args[i]= (char*) res->c_ptr(); + f_args.lengths[i]= res->length(); break; } case INT_RESULT: diff --git a/sql/lock.cc b/sql/lock.cc index f859f028504..d9e9dd31f81 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -857,6 +857,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, if ((table=table_ptr[i])->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE) continue; lock_type= table->reginfo.lock_type; + DBUG_ASSERT (lock_type != TL_WRITE_DEFAULT); if (lock_type >= TL_WRITE_ALLOW_WRITE) { *write_lock_used=table; diff --git a/sql/log.cc b/sql/log.cc index ed1a8bdb7f7..3686459fedf 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2734,7 +2734,7 @@ err: #ifdef HAVE_REPLICATION -int MYSQL_BIN_LOG::purge_first_log(struct st_relay_log_info* rli, bool included) +int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included) { int error; DBUG_ENTER("purge_first_log"); diff --git a/sql/log.h b/sql/log.h index c116c4a93f7..e597c986794 100644 --- a/sql/log.h +++ b/sql/log.h @@ -16,7 +16,7 @@ #ifndef LOG_H #define LOG_H -struct st_relay_log_info; +class Relay_log_info; class Format_description_log_event; @@ -121,7 +121,7 @@ extern TC_LOG_DUMMY tc_log_dummy; #define LOG_CLOSE_TO_BE_OPENED 2 #define LOG_CLOSE_STOP_EVENT 4 -struct st_relay_log_info; +class Relay_log_info; typedef struct st_log_info { @@ -362,7 +362,7 @@ public: bool need_mutex, bool need_update_threads, ulonglong *decrease_log_space); int purge_logs_before_date(time_t purge_time); - int purge_first_log(struct st_relay_log_info* rli, bool included); + int purge_first_log(Relay_log_info* rli, bool included); bool reset_logs(THD* thd); void close(uint exiting); diff --git a/sql/log_event.cc b/sql/log_event.cc index a65d759efa7..fecc35c95b9 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -146,7 +146,7 @@ static void pretty_print_str(IO_CACHE* cache, char* str, int len) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -static void clear_all_errors(THD *thd, RELAY_LOG_INFO *rli) +static void clear_all_errors(THD *thd, Relay_log_info *rli) { thd->query_error = 0; thd->clear_error(); @@ -536,7 +536,7 @@ Log_event::Log_event(const char* buf, #ifndef MYSQL_CLIENT #ifdef HAVE_REPLICATION -int Log_event::do_update_pos(RELAY_LOG_INFO *rli) +int Log_event::do_update_pos(Relay_log_info *rli) { /* rli is null when (as far as I (Guilhem) know) the caller is @@ -558,7 +558,7 @@ int Log_event::do_update_pos(RELAY_LOG_INFO *rli) Log_event::enum_skip_reason -Log_event::do_shall_skip(RELAY_LOG_INFO *rli) +Log_event::do_shall_skip(Relay_log_info *rli) { DBUG_PRINT("info", ("ev->server_id=%lu, ::server_id=%lu," " rli->replicate_same_server_id=%d," @@ -597,7 +597,7 @@ int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos) const char *event_type; if (p) log_name = p + 1; - + protocol->prepare_for_resend(); protocol->store(log_name, &my_charset_bin); protocol->store((ulonglong) pos); @@ -1920,13 +1920,13 @@ void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -int Query_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +int Query_log_event::do_apply_event(Relay_log_info const *rli) { return do_apply_event(rli, query, q_len); } -int Query_log_event::do_apply_event(RELAY_LOG_INFO const *rli, +int Query_log_event::do_apply_event(Relay_log_info const *rli, const char *query_arg, uint32 q_len_arg) { LEX_STRING new_db; @@ -1955,11 +1955,11 @@ int Query_log_event::do_apply_event(RELAY_LOG_INFO const *rli, END of the current log event (COMMIT). We save it in rli so that InnoDB can access it. */ - const_cast<RELAY_LOG_INFO*>(rli)->future_group_master_log_pos= log_pos; + const_cast<Relay_log_info*>(rli)->future_group_master_log_pos= log_pos; DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos)); - clear_all_errors(thd, const_cast<RELAY_LOG_INFO*>(rli)); - const_cast<RELAY_LOG_INFO*>(rli)->clear_tables_to_lock(); + clear_all_errors(thd, const_cast<Relay_log_info*>(rli)); + const_cast<Relay_log_info*>(rli)->clear_tables_to_lock(); /* Note: We do not need to execute reset_one_shot_variables() if this @@ -2085,7 +2085,7 @@ int Query_log_event::do_apply_event(RELAY_LOG_INFO const *rli, to check/fix it. */ if (mysql_test_parse_for_slave(thd, thd->query, thd->query_length)) - clear_all_errors(thd, const_cast<RELAY_LOG_INFO*>(rli)); /* Can ignore query */ + clear_all_errors(thd, const_cast<Relay_log_info*>(rli)); /* Can ignore query */ else { rli->report(ERROR_LEVEL, expected_error, @@ -2136,7 +2136,7 @@ Default database: '%s'. Query: '%s'", ignored_error_code(actual_error)) { DBUG_PRINT("info",("error ignored")); - clear_all_errors(thd, const_cast<RELAY_LOG_INFO*>(rli)); + clear_all_errors(thd, const_cast<Relay_log_info*>(rli)); thd->killed= THD::NOT_KILLED; } /* @@ -2207,7 +2207,7 @@ end: return thd->query_error; } -int Query_log_event::do_update_pos(RELAY_LOG_INFO *rli) +int Query_log_event::do_update_pos(Relay_log_info *rli) { /* Note that we will not increment group* positions if we are just @@ -2371,7 +2371,7 @@ bool Start_log_event_v3::write(IO_CACHE* file) */ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -int Start_log_event_v3::do_apply_event(RELAY_LOG_INFO const *rli) +int Start_log_event_v3::do_apply_event(Relay_log_info const *rli) { DBUG_ENTER("Start_log_event_v3::do_apply_event"); switch (binlog_version) @@ -2608,7 +2608,7 @@ bool Format_description_log_event::write(IO_CACHE* file) #endif #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -int Format_description_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +int Format_description_log_event::do_apply_event(Relay_log_info const *rli) { DBUG_ENTER("Format_description_log_event::do_apply_event"); @@ -2632,7 +2632,7 @@ int Format_description_log_event::do_apply_event(RELAY_LOG_INFO const *rli) "or ROLLBACK in relay log). A probable cause is that " "the master died while writing the transaction to " "its binary log, thus rolled back too."); - const_cast<RELAY_LOG_INFO*>(rli)->cleanup_context(thd, 1); + const_cast<Relay_log_info*>(rli)->cleanup_context(thd, 1); } #endif /* @@ -2656,7 +2656,7 @@ int Format_description_log_event::do_apply_event(RELAY_LOG_INFO const *rli) DBUG_RETURN(0); } -int Format_description_log_event::do_update_pos(RELAY_LOG_INFO *rli) +int Format_description_log_event::do_update_pos(Relay_log_info *rli) { /* save the information describing this binlog */ delete rli->relay_log.description_event_for_exec; @@ -2687,7 +2687,7 @@ int Format_description_log_event::do_update_pos(RELAY_LOG_INFO *rli) } Log_event::enum_skip_reason -Format_description_log_event::do_shall_skip(RELAY_LOG_INFO *rli) +Format_description_log_event::do_shall_skip(Relay_log_info *rli) { return Log_event::EVENT_SKIP_NOT; } @@ -3230,7 +3230,7 @@ void Load_log_event::set_fields(const char* affected_db, 1 Failure */ -int Load_log_event::do_apply_event(NET* net, RELAY_LOG_INFO const *rli, +int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli, bool use_rli_only_for_errors) { LEX_STRING new_db; @@ -3240,7 +3240,7 @@ int Load_log_event::do_apply_event(NET* net, RELAY_LOG_INFO const *rli, DBUG_ASSERT(thd->query == 0); thd->query_length= 0; // Should not be needed thd->query_error= 0; - clear_all_errors(thd, const_cast<RELAY_LOG_INFO*>(rli)); + clear_all_errors(thd, const_cast<Relay_log_info*>(rli)); /* see Query_log_event::do_apply_event() and BUG#13360 */ DBUG_ASSERT(!rli->m_table_map.count()); @@ -3257,7 +3257,7 @@ int Load_log_event::do_apply_event(NET* net, RELAY_LOG_INFO const *rli, Saved for InnoDB, see comment in Query_log_event::do_apply_event() */ - const_cast<RELAY_LOG_INFO*>(rli)->future_group_master_log_pos= log_pos; + const_cast<Relay_log_info*>(rli)->future_group_master_log_pos= log_pos; DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos)); } @@ -3621,7 +3621,7 @@ bool Rotate_log_event::write(IO_CACHE* file) */ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -int Rotate_log_event::do_update_pos(RELAY_LOG_INFO *rli) +int Rotate_log_event::do_update_pos(Relay_log_info *rli) { DBUG_ENTER("Rotate_log_event::do_update_pos"); #ifndef DBUG_OFF @@ -3691,7 +3691,7 @@ int Rotate_log_event::do_update_pos(RELAY_LOG_INFO *rli) Log_event::enum_skip_reason -Rotate_log_event::do_shall_skip(RELAY_LOG_INFO *rli) +Rotate_log_event::do_shall_skip(Relay_log_info *rli) { enum_skip_reason reason= Log_event::do_shall_skip(rli); @@ -3817,13 +3817,13 @@ void Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) */ #if defined(HAVE_REPLICATION)&& !defined(MYSQL_CLIENT) -int Intvar_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +int Intvar_log_event::do_apply_event(Relay_log_info const *rli) { /* We are now in a statement until the associated query log event has been processed. */ - const_cast<RELAY_LOG_INFO*>(rli)->set_flag(RELAY_LOG_INFO::IN_STMT); + const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT); switch (type) { case LAST_INSERT_ID_EVENT: @@ -3837,7 +3837,7 @@ int Intvar_log_event::do_apply_event(RELAY_LOG_INFO const *rli) return 0; } -int Intvar_log_event::do_update_pos(RELAY_LOG_INFO *rli) +int Intvar_log_event::do_update_pos(Relay_log_info *rli) { rli->inc_event_relay_log_pos(); return 0; @@ -3845,7 +3845,7 @@ int Intvar_log_event::do_update_pos(RELAY_LOG_INFO *rli) Log_event::enum_skip_reason -Intvar_log_event::do_shall_skip(RELAY_LOG_INFO *rli) +Intvar_log_event::do_shall_skip(Relay_log_info *rli) { /* It is a common error to set the slave skip counter to 1 instead of @@ -3923,20 +3923,20 @@ void Rand_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -int Rand_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +int Rand_log_event::do_apply_event(Relay_log_info const *rli) { /* We are now in a statement until the associated query log event has been processed. */ - const_cast<RELAY_LOG_INFO*>(rli)->set_flag(RELAY_LOG_INFO::IN_STMT); + const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT); thd->rand.seed1= (ulong) seed1; thd->rand.seed2= (ulong) seed2; return 0; } -int Rand_log_event::do_update_pos(RELAY_LOG_INFO *rli) +int Rand_log_event::do_update_pos(Relay_log_info *rli) { rli->inc_event_relay_log_pos(); return 0; @@ -3944,7 +3944,7 @@ int Rand_log_event::do_update_pos(RELAY_LOG_INFO *rli) Log_event::enum_skip_reason -Rand_log_event::do_shall_skip(RELAY_LOG_INFO *rli) +Rand_log_event::do_shall_skip(Relay_log_info *rli) { /* It is a common error to set the slave skip counter to 1 instead of @@ -4026,7 +4026,7 @@ void Xid_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -int Xid_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +int Xid_log_event::do_apply_event(Relay_log_info const *rli) { /* For a slave Xid_log_event is COMMIT */ general_log_print(thd, COM_QUERY, @@ -4323,7 +4323,7 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) */ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -int User_var_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +int User_var_log_event::do_apply_event(Relay_log_info const *rli) { Item *it= 0; CHARSET_INFO *charset; @@ -4339,7 +4339,7 @@ int User_var_log_event::do_apply_event(RELAY_LOG_INFO const *rli) We are now in a statement until the associated query log event has been processed. */ - const_cast<RELAY_LOG_INFO*>(rli)->set_flag(RELAY_LOG_INFO::IN_STMT); + const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT); if (is_null) { @@ -4394,14 +4394,14 @@ int User_var_log_event::do_apply_event(RELAY_LOG_INFO const *rli) return 0; } -int User_var_log_event::do_update_pos(RELAY_LOG_INFO *rli) +int User_var_log_event::do_update_pos(Relay_log_info *rli) { rli->inc_event_relay_log_pos(); return 0; } Log_event::enum_skip_reason -User_var_log_event::do_shall_skip(RELAY_LOG_INFO *rli) +User_var_log_event::do_shall_skip(Relay_log_info *rli) { /* It is a common error to set the slave skip counter to 1 instead @@ -4455,14 +4455,14 @@ void Slave_log_event::pack_info(Protocol *protocol) #ifndef MYSQL_CLIENT Slave_log_event::Slave_log_event(THD* thd_arg, - RELAY_LOG_INFO* rli) + Relay_log_info* rli) :Log_event(thd_arg, 0, 0) , mem_pool(0), master_host(0) { DBUG_ENTER("Slave_log_event"); if (!rli->inited) // QQ When can this happen ? DBUG_VOID_RETURN; - MASTER_INFO* mi = rli->mi; + Master_info* mi = rli->mi; // TODO: re-write this better without holding both locks at the same time pthread_mutex_lock(&mi->data_lock); pthread_mutex_lock(&rli->data_lock); @@ -4565,7 +4565,7 @@ Slave_log_event::Slave_log_event(const char* buf, uint event_len) #ifndef MYSQL_CLIENT -int Slave_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +int Slave_log_event::do_apply_event(Relay_log_info const *rli) { if (mysql_bin_log.is_open()) mysql_bin_log.write(this); @@ -4612,7 +4612,7 @@ void Stop_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) */ #ifndef MYSQL_CLIENT -int Stop_log_event::do_update_pos(RELAY_LOG_INFO *rli) +int Stop_log_event::do_update_pos(Relay_log_info *rli) { /* We do not want to update master_log pos because we get a rotate event @@ -4825,7 +4825,7 @@ void Create_file_log_event::pack_info(Protocol *protocol) */ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -int Create_file_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +int Create_file_log_event::do_apply_event(Relay_log_info const *rli) { char proc_info[17+FN_REFLEN+10], *fname_buf; char *ext; @@ -5001,7 +5001,7 @@ int Append_block_log_event::get_create_or_append() const Append_block_log_event::do_apply_event() */ -int Append_block_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +int Append_block_log_event::do_apply_event(Relay_log_info const *rli) { char proc_info[17+FN_REFLEN+10], *fname= proc_info+17; int fd; @@ -5133,7 +5133,7 @@ void Delete_file_log_event::pack_info(Protocol *protocol) */ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -int Delete_file_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +int Delete_file_log_event::do_apply_event(Relay_log_info const *rli) { char fname[FN_REFLEN+10]; char *ext= slave_load_file_stem(fname, file_id, server_id, ".data"); @@ -5229,7 +5229,7 @@ void Execute_load_log_event::pack_info(Protocol *protocol) Execute_load_log_event::do_apply_event() */ -int Execute_load_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +int Execute_load_log_event::do_apply_event(Relay_log_info const *rli) { char fname[FN_REFLEN+10]; char *ext; @@ -5268,7 +5268,7 @@ int Execute_load_log_event::do_apply_event(RELAY_LOG_INFO const *rli) calls mysql_load()). */ - const_cast<RELAY_LOG_INFO*>(rli)->future_group_master_log_pos= log_pos; + const_cast<Relay_log_info*>(rli)->future_group_master_log_pos= log_pos; if (lev->do_apply_event(0,rli,1)) { /* @@ -5478,7 +5478,7 @@ void Execute_load_query_log_event::pack_info(Protocol *protocol) int -Execute_load_query_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +Execute_load_query_log_event::do_apply_event(Relay_log_info const *rli) { char *p; char *buf; @@ -5867,9 +5867,9 @@ int Rows_log_event::do_add_row_data(uchar *row_data, size_t length) #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) -int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +int Rows_log_event::do_apply_event(Relay_log_info const *rli) { - DBUG_ENTER("Rows_log_event::do_apply_event(st_relay_log_info*)"); + DBUG_ENTER("Rows_log_event::do_apply_event(Relay_log_info*)"); int error= 0; uchar const *row_start= m_rows_buf; @@ -5887,7 +5887,7 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) */ DBUG_ASSERT(get_flags(STMT_END_F)); - const_cast<RELAY_LOG_INFO*>(rli)->clear_tables_to_lock(); + const_cast<Relay_log_info*>(rli)->clear_tables_to_lock(); close_thread_tables(thd); thd->clear_error(); DBUG_RETURN(0); @@ -5943,7 +5943,7 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) "Error in %s event: when locking tables", get_type_str()); } - const_cast<RELAY_LOG_INFO*>(rli)->clear_tables_to_lock(); + const_cast<Relay_log_info*>(rli)->clear_tables_to_lock(); DBUG_RETURN(error); } @@ -5980,7 +5980,7 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) "unexpected success or fatal error")); thd->query_error= 1; } - const_cast<RELAY_LOG_INFO*>(rli)->clear_tables_to_lock(); + const_cast<Relay_log_info*>(rli)->clear_tables_to_lock(); DBUG_RETURN(error); } } @@ -6002,7 +6002,7 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) mysql_unlock_tables(thd, thd->lock); thd->lock= 0; thd->query_error= 1; - const_cast<RELAY_LOG_INFO*>(rli)->clear_tables_to_lock(); + const_cast<Relay_log_info*>(rli)->clear_tables_to_lock(); DBUG_RETURN(ERR_BAD_TABLE_DEF); } } @@ -6024,14 +6024,14 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) */ for (TABLE_LIST *ptr= rli->tables_to_lock ; ptr ; ptr= ptr->next_global) { - const_cast<RELAY_LOG_INFO*>(rli)->m_table_map.set_table(ptr->table_id, ptr->table); + const_cast<Relay_log_info*>(rli)->m_table_map.set_table(ptr->table_id, ptr->table); } #ifdef HAVE_QUERY_CACHE query_cache.invalidate_locked_for_write(rli->tables_to_lock); #endif } - TABLE* table= const_cast<RELAY_LOG_INFO*>(rli)->m_table_map.get_table(m_table_id); + TABLE* table= const_cast<Relay_log_info*>(rli)->m_table_map.get_table(m_table_id); if (table) { @@ -6076,7 +6076,7 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) inside a statement and halting abruptly might cause problems when restarting. */ - const_cast<RELAY_LOG_INFO*>(rli)->set_flag(RELAY_LOG_INFO::IN_STMT); + const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT); error= do_before_row_operations(table); while (error == 0 && row_start < m_rows_end) @@ -6117,7 +6117,7 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) row_start= row_end; } DBUG_EXECUTE_IF("STOP_SLAVE_after_first_Rows_event", - const_cast<RELAY_LOG_INFO*>(rli)->abort_slave= 1;); + const_cast<Relay_log_info*>(rli)->abort_slave= 1;); error= do_after_row_operations(table, error); if (!cache_stmt) { @@ -6131,7 +6131,7 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) The table def is needed in unpack_row(). */ if (rli->tables_to_lock && get_flags(STMT_END_F)) - const_cast<RELAY_LOG_INFO*>(rli)->clear_tables_to_lock(); + const_cast<Relay_log_info*>(rli)->clear_tables_to_lock(); if (error) { /* error has occured during the transaction */ @@ -6154,7 +6154,7 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) rollback at the caller along with sbr. */ thd->reset_current_stmt_binlog_row_based(); - const_cast<RELAY_LOG_INFO*>(rli)->cleanup_context(thd, error); + const_cast<Relay_log_info*>(rli)->cleanup_context(thd, error); thd->query_error= 1; DBUG_RETURN(error); } @@ -6181,16 +6181,16 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) wait (reached end of last relay log and nothing gets appended there), we timeout after one minute, and notify DBA about the problem. When WL#2975 is implemented, just remove the member - st_relay_log_info::last_event_start_time and all its occurences. + Relay_log_info::last_event_start_time and all its occurences. */ - const_cast<RELAY_LOG_INFO*>(rli)->last_event_start_time= my_time(0); + const_cast<Relay_log_info*>(rli)->last_event_start_time= my_time(0); } DBUG_RETURN(0); } Log_event::enum_skip_reason -Rows_log_event::do_shall_skip(RELAY_LOG_INFO *rli) +Rows_log_event::do_shall_skip(Relay_log_info *rli) { /* If the slave skip counter is 1 and this event does not end a @@ -6204,7 +6204,7 @@ Rows_log_event::do_shall_skip(RELAY_LOG_INFO *rli) } int -Rows_log_event::do_update_pos(RELAY_LOG_INFO *rli) +Rows_log_event::do_update_pos(Relay_log_info *rli) { DBUG_ENTER("Rows_log_event::do_update_pos"); int error= 0; @@ -6384,63 +6384,18 @@ void Rows_log_event::print_helper(FILE *file, **************************************************************************/ /** - * Calculate field metadata size based on the real_type of the field. - * - * @returns int Size of field metadata. - */ -#if !defined(MYSQL_CLIENT) -const int Table_map_log_event::calc_field_metadata_size() -{ - DBUG_ENTER("Table_map_log_event::calc_field_metadata_size"); - int size= 0; - for (unsigned int i= 0 ; i < m_table->s->fields ; i++) - { - switch (m_table->s->field[i]->real_type()) { - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_DOUBLE: - case MYSQL_TYPE_FLOAT: - { - size++; // Store one byte here. - break; - } - case MYSQL_TYPE_BIT: - case MYSQL_TYPE_NEWDECIMAL: - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_SET: - { - size= size + 2; // Store short int here. - break; - } - default: - break; - } - } - m_field_metadata_size= size; - DBUG_PRINT("info", ("Table_map_log_event: %d bytes in field metadata.", - (int)m_field_metadata_size)); - DBUG_RETURN(m_field_metadata_size); -} -#endif /* !defined(MYSQL_CLIENT) */ - -/** @page How replication of field metadata works. When a table map is created, the master first calls - Table_map_log_event::get_field_metadata_size() which calculates how many + Table_map_log_event::save_field_metadata() which calculates how many values will be in the field metadata. Only those fields that require the - extra data are added (see table above). The master then loops through all - of the fields in the table calling the method - Table_map_log_event::get_field_metadata() which returns the values for the - field that will be saved in the metadata and replicated to the slave. Once - all fields have been processed, the table map is written to the binlog - adding the size of the field metadata and the field metadata to the end of - the body of the table map. - + extra data are added. The method also loops through all of the fields in + the table calling the method Field::save_field_metadata() which returns the + values for the field that will be saved in the metadata and replicated to + the slave. Once all fields have been processed, the table map is written to + the binlog adding the size of the field metadata and the field metadata to + the end of the body of the table map. + When a table map is read on the slave, the field metadata is read from the table map and passed to the table_def class constructor which saves the field metadata from the table map into an array based on the type of the @@ -6479,64 +6434,8 @@ int Table_map_log_event::save_field_metadata() DBUG_ENTER("Table_map_log_event::save_field_metadata"); int index= 0; for (unsigned int i= 0 ; i < m_table->s->fields ; i++) - { - switch (m_table->s->field[i]->real_type()) { - case MYSQL_TYPE_NEWDECIMAL: - { - m_field_metadata[index++]= - (uchar)((Field_new_decimal *)m_table->s->field[i])->precision; - m_field_metadata[index++]= - (uchar)((Field_new_decimal *)m_table->s->field[i])->decimals(); - break; - } - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - { - m_field_metadata[index++]= - (uchar)((Field_blob *)m_table->s->field[i])->pack_length_no_ptr(); - break; - } - case MYSQL_TYPE_DOUBLE: - case MYSQL_TYPE_FLOAT: - { - m_field_metadata[index++]= (uchar)m_table->s->field[i]->pack_length(); - break; - } - case MYSQL_TYPE_BIT: - { - m_field_metadata[index++]= - (uchar)((Field_bit *)m_table->s->field[i])->bit_len; - m_field_metadata[index++]= - (uchar)((Field_bit *)m_table->s->field[i])->bytes_in_rec; - break; - } - case MYSQL_TYPE_VARCHAR: - { - char *ptr= (char *)&m_field_metadata[index]; - int2store(ptr, m_table->s->field[i]->field_length); - index= index + 2; - break; - } - case MYSQL_TYPE_STRING: - { - m_field_metadata[index++]= (uchar)m_table->s->field[i]->real_type(); - m_field_metadata[index++]= m_table->s->field[i]->field_length; - break; - } - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_SET: - { - m_field_metadata[index++]= (uchar)m_table->s->field[i]->real_type(); - m_field_metadata[index++]= m_table->s->field[i]->pack_length(); - break; - } - default: - break; - } - } - DBUG_RETURN(0); + index+= m_table->s->field[i]->save_field_metadata(&m_field_metadata[index]); + DBUG_RETURN(index); } #endif /* !defined(MYSQL_CLIENT) */ @@ -6574,16 +6473,6 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, m_data_size+= m_dblen + 2; // Include length and terminating \0 m_data_size+= m_tbllen + 2; // Include length and terminating \0 m_data_size+= 1 + m_colcnt; // COLCNT and column types - m_field_metadata_size= calc_field_metadata_size(); - - /* - Now set the size of the data to the size of the field metadata array - plus one or two bytes for number of elements in the field metadata array. - */ - if (m_field_metadata_size > 255) - m_data_size+= m_field_metadata_size + 2; - else - m_data_size+= m_field_metadata_size + 1; /* If malloc fails, catched in is_valid() */ if ((m_memory= (uchar*) my_malloc(m_colcnt, MYF(MY_WME)))) @@ -6603,17 +6492,31 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, m_data_size+= num_null_bytes; m_meta_memory= (uchar *)my_multi_malloc(MYF(MY_WME), &m_null_bits, num_null_bytes, - &m_field_metadata, m_field_metadata_size, + &m_field_metadata, (m_colcnt * 2), NULL); + + bzero(m_field_metadata, (m_colcnt * 2)); + + /* + Create an array for the field metadata and store it. + */ + m_field_metadata_size= save_field_metadata(); + DBUG_ASSERT(m_field_metadata_size <= (m_colcnt * 2)); + + /* + Now set the size of the data to the size of the field metadata array + plus one or two bytes for number of elements in the field metadata array. + */ + if (m_field_metadata_size > 255) + m_data_size+= m_field_metadata_size + 2; + else + m_data_size+= m_field_metadata_size + 1; + bzero(m_null_bits, num_null_bytes); for (unsigned int i= 0 ; i < m_table->s->fields ; ++i) if (m_table->field[i]->maybe_null()) m_null_bits[(i / 8)]+= 1 << (i % 8); - /* - Create an array for the field metadata and store it. - */ - save_field_metadata(); } #endif /* !defined(MYSQL_CLIENT) */ @@ -6744,13 +6647,13 @@ Table_map_log_event::~Table_map_log_event() */ #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) -int Table_map_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +int Table_map_log_event::do_apply_event(Relay_log_info const *rli) { RPL_TABLE_LIST *table_list; char *db_mem, *tname_mem; size_t dummy_len; void *memory; - DBUG_ENTER("Table_map_log_event::do_apply_event(st_relay_log_info*)"); + DBUG_ENTER("Table_map_log_event::do_apply_event(Relay_log_info*)"); DBUG_ASSERT(rli->sql_thd == thd); /* Step the query id to mark what columns that are actually used. */ @@ -6856,7 +6759,7 @@ int Table_map_log_event::do_apply_event(RELAY_LOG_INFO const *rli) The memory allocated by the table_def structure (i.e., not the memory allocated *for* the table_def structure) is released - inside st_relay_log_info::clear_tables_to_lock() by calling the + inside Relay_log_info::clear_tables_to_lock() by calling the table_def destructor explicitly. */ new (&table_list->m_tabledef) table_def(m_coltype, m_colcnt, @@ -6868,8 +6771,8 @@ int Table_map_log_event::do_apply_event(RELAY_LOG_INFO const *rli) locked by linking the table into the list of tables to lock. */ table_list->next_global= table_list->next_local= rli->tables_to_lock; - const_cast<RELAY_LOG_INFO*>(rli)->tables_to_lock= table_list; - const_cast<RELAY_LOG_INFO*>(rli)->tables_to_lock_count++; + const_cast<Relay_log_info*>(rli)->tables_to_lock= table_list; + const_cast<Relay_log_info*>(rli)->tables_to_lock_count++; /* 'memory' is freed in clear_tables_to_lock */ } @@ -6881,7 +6784,7 @@ err: } Log_event::enum_skip_reason -Table_map_log_event::do_shall_skip(RELAY_LOG_INFO *rli) +Table_map_log_event::do_shall_skip(Relay_log_info *rli) { /* If the slave skip counter is 1, then we should not start executing @@ -6893,7 +6796,7 @@ Table_map_log_event::do_shall_skip(RELAY_LOG_INFO *rli) return Log_event::do_shall_skip(rli); } -int Table_map_log_event::do_update_pos(RELAY_LOG_INFO *rli) +int Table_map_log_event::do_update_pos(Relay_log_info *rli) { rli->inc_event_relay_log_pos(); return 0; @@ -7095,7 +6998,7 @@ int Write_rows_log_event::do_after_row_operations(TABLE *table, int error) return error? error : local_error; } -int Write_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO const *rli, +int Write_rows_log_event::do_prepare_row(THD *thd, Relay_log_info const *rli, TABLE *table, uchar const *const row_start, uchar const **const row_end) @@ -7825,7 +7728,7 @@ int Delete_rows_log_event::do_after_row_operations(TABLE *table, int error) return error; } -int Delete_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO const *rli, +int Delete_rows_log_event::do_prepare_row(THD *thd, Relay_log_info const *rli, TABLE *table, uchar const *const row_start, uchar const **const row_end) @@ -8001,7 +7904,7 @@ int Update_rows_log_event::do_after_row_operations(TABLE *table, int error) return error; } -int Update_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO const *rli, +int Update_rows_log_event::do_prepare_row(THD *thd, Relay_log_info const *rli, TABLE *table, uchar const *const row_start, uchar const **const row_end) @@ -8185,7 +8088,7 @@ Incident_log_event::print(FILE *file, #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) int -Incident_log_event::do_apply_event(RELAY_LOG_INFO const *rli) +Incident_log_event::do_apply_event(Relay_log_info const *rli) { DBUG_ENTER("Incident_log_event::do_apply_event"); rli->report(ERROR_LEVEL, ER_SLAVE_INCIDENT, diff --git a/sql/log_event.h b/sql/log_event.h index c93bfa32029..3785a0bea0f 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -529,9 +529,7 @@ class THD; #endif class Format_description_log_event; - -struct st_relay_log_info; -typedef st_relay_log_info RELAY_LOG_INFO; +class Relay_log_info; #ifdef MYSQL_CLIENT /* @@ -820,7 +818,7 @@ public: @see do_apply_event */ - int apply_event(RELAY_LOG_INFO const *rli) { + int apply_event(Relay_log_info const *rli) { return do_apply_event(rli); } @@ -833,7 +831,7 @@ public: @see do_update_pos */ - int update_pos(RELAY_LOG_INFO *rli) + int update_pos(Relay_log_info *rli) { return do_update_pos(rli); } @@ -844,7 +842,7 @@ public: @see do_shall_skip */ - enum_skip_reason shall_skip(RELAY_LOG_INFO *rli) + enum_skip_reason shall_skip(Relay_log_info *rli) { return do_shall_skip(rli); } @@ -866,7 +864,7 @@ protected: @retval 0 Event applied successfully @retval errno Error code if event application failed */ - virtual int do_apply_event(RELAY_LOG_INFO const *rli) + virtual int do_apply_event(Relay_log_info const *rli) { return 0; /* Default implementation does nothing */ } @@ -895,7 +893,7 @@ protected: 1). Observe that handler errors are returned by the do_apply_event() function, and not by this one. */ - virtual int do_update_pos(RELAY_LOG_INFO *rli); + virtual int do_update_pos(Relay_log_info *rli); /** @@ -927,7 +925,7 @@ protected: The event shall be skipped because the slave skip counter was non-zero. The caller shall decrease the counter by one. */ - virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli); + virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); #endif }; @@ -1068,10 +1066,10 @@ public: public: /* !!! Public in this patch to allow old usage */ #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); - virtual int do_update_pos(RELAY_LOG_INFO *rli); + virtual int do_apply_event(Relay_log_info const *rli); + virtual int do_update_pos(Relay_log_info *rli); - int do_apply_event(RELAY_LOG_INFO const *rli, + int do_apply_event(Relay_log_info const *rli, const char *query_arg, uint32 q_len_arg); #endif /* HAVE_REPLICATION */ @@ -1123,7 +1121,7 @@ public: uint16 master_port; #ifndef MYSQL_CLIENT - Slave_log_event(THD* thd_arg, RELAY_LOG_INFO* rli); + Slave_log_event(THD* thd_arg, Relay_log_info* rli); void pack_info(Protocol* protocol); #else void print(FILE* file, PRINT_EVENT_INFO* print_event_info); @@ -1140,7 +1138,7 @@ public: private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const* rli); + virtual int do_apply_event(Relay_log_info const* rli); #endif }; @@ -1245,12 +1243,12 @@ public: public: /* !!! Public in this patch to allow old usage */ #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const* rli) + virtual int do_apply_event(Relay_log_info const* rli) { return do_apply_event(thd->slave_net,rli,0); } - int do_apply_event(NET *net, RELAY_LOG_INFO const *rli, + int do_apply_event(NET *net, Relay_log_info const *rli, bool use_rli_only_for_errors); #endif }; @@ -1332,8 +1330,8 @@ public: protected: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); - virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO*) + virtual int do_apply_event(Relay_log_info const *rli); + virtual enum_skip_reason do_shall_skip(Relay_log_info*) { /* Events from ourself should be skipped, but they should not @@ -1397,9 +1395,9 @@ public: protected: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); - virtual int do_update_pos(RELAY_LOG_INFO *rli); - virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli); + virtual int do_apply_event(Relay_log_info const *rli); + virtual int do_update_pos(Relay_log_info *rli); + virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); #endif }; @@ -1441,9 +1439,9 @@ public: private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); - virtual int do_update_pos(RELAY_LOG_INFO *rli); - virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli); + virtual int do_apply_event(Relay_log_info const *rli); + virtual int do_update_pos(Relay_log_info *rli); + virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); #endif }; @@ -1487,9 +1485,9 @@ class Rand_log_event: public Log_event private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); - virtual int do_update_pos(RELAY_LOG_INFO *rli); - virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli); + virtual int do_apply_event(Relay_log_info const *rli); + virtual int do_update_pos(Relay_log_info *rli); + virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); #endif }; @@ -1530,7 +1528,7 @@ class Xid_log_event: public Log_event private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); + virtual int do_apply_event(Relay_log_info const *rli); #endif }; @@ -1575,9 +1573,9 @@ public: private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); - virtual int do_update_pos(RELAY_LOG_INFO *rli); - virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli); + virtual int do_apply_event(Relay_log_info const *rli); + virtual int do_update_pos(Relay_log_info *rli); + virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); #endif }; @@ -1606,8 +1604,8 @@ public: private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_update_pos(RELAY_LOG_INFO *rli); - virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli) + virtual int do_update_pos(Relay_log_info *rli); + virtual enum_skip_reason do_shall_skip(Relay_log_info *rli) { /* Events from ourself should be skipped, but they should not @@ -1666,8 +1664,8 @@ public: private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_update_pos(RELAY_LOG_INFO *rli); - virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli); + virtual int do_update_pos(Relay_log_info *rli); + virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); #endif }; @@ -1739,7 +1737,7 @@ public: private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); + virtual int do_apply_event(Relay_log_info const *rli); #endif }; @@ -1793,7 +1791,7 @@ public: private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); + virtual int do_apply_event(Relay_log_info const *rli); #endif }; @@ -1833,7 +1831,7 @@ public: private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); + virtual int do_apply_event(Relay_log_info const *rli); #endif }; @@ -1872,7 +1870,7 @@ public: private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); + virtual int do_apply_event(Relay_log_info const *rli); #endif }; @@ -1964,7 +1962,7 @@ public: private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); + virtual int do_apply_event(Relay_log_info const *rli); #endif }; @@ -2058,7 +2056,6 @@ public: virtual int get_data_size() { return m_data_size; } #ifndef MYSQL_CLIENT - virtual const int calc_field_metadata_size(); virtual int save_field_metadata(); virtual bool write_data_header(IO_CACHE *file); virtual bool write_data_body(IO_CACHE *file); @@ -2076,9 +2073,9 @@ public: private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); - virtual int do_update_pos(RELAY_LOG_INFO *rli); - virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli); + virtual int do_apply_event(Relay_log_info const *rli); + virtual int do_update_pos(Relay_log_info *rli); + virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); #endif #ifndef MYSQL_CLIENT @@ -2099,7 +2096,7 @@ private: uchar *m_field_metadata; // buffer for field metadata /* - The size of field metadata buffer set by calling calc_field_metadata_size() + The size of field metadata buffer set by calling save_field_metadata() */ ulong m_field_metadata_size; uchar *m_null_bits; @@ -2263,9 +2260,9 @@ protected: private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); - virtual int do_update_pos(RELAY_LOG_INFO *rli); - virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli); + virtual int do_apply_event(Relay_log_info const *rli); + virtual int do_update_pos(Relay_log_info *rli); + virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); /* Primitive to prepare for a sequence of row executions. @@ -2314,7 +2311,7 @@ private: RETURN VALUE Error code, if something went wrong, 0 otherwise. */ - virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, + virtual int do_prepare_row(THD*, Relay_log_info const*, TABLE*, uchar const *row_start, uchar const **row_end) = 0; @@ -2386,7 +2383,7 @@ private: virtual int do_before_row_operations(TABLE *table); virtual int do_after_row_operations(TABLE *table, int error); - virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, + virtual int do_prepare_row(THD*, Relay_log_info const*, TABLE*, uchar const *row_start, uchar const **row_end); virtual int do_exec_row(TABLE *table); #endif @@ -2466,7 +2463,7 @@ protected: virtual int do_before_row_operations(TABLE *table); virtual int do_after_row_operations(TABLE *table, int error); - virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, + virtual int do_prepare_row(THD*, Relay_log_info const*, TABLE*, uchar const *row_start, uchar const **row_end); virtual int do_exec_row(TABLE *table); #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ @@ -2537,7 +2534,7 @@ protected: virtual int do_before_row_operations(TABLE *table); virtual int do_after_row_operations(TABLE *table, int error); - virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, + virtual int do_prepare_row(THD*, Relay_log_info const*, TABLE*, uchar const *row_start, uchar const **row_end); virtual int do_exec_row(TABLE *table); #endif @@ -2615,7 +2612,7 @@ public: #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_apply_event(RELAY_LOG_INFO const *rli); + virtual int do_apply_event(Relay_log_info const *rli); #endif virtual bool write_data_header(IO_CACHE *file); diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index e6a9dd50c08..8663963b35e 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -6,7 +6,7 @@ #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) int Write_rows_log_event_old::do_prepare_row(THD *thd, - RELAY_LOG_INFO const *rli, + Relay_log_info const *rli, TABLE *table, uchar const *row_start, uchar const **row_end) @@ -15,7 +15,7 @@ Write_rows_log_event_old::do_prepare_row(THD *thd, DBUG_ASSERT(row_start && row_end); int error; - error= unpack_row_old(const_cast<RELAY_LOG_INFO*>(rli), + error= unpack_row_old(const_cast<Relay_log_info*>(rli), table, m_width, table->record[0], row_start, &m_cols, row_end, &m_master_reclength, table->write_set, PRE_GA_WRITE_ROWS_EVENT); @@ -26,7 +26,7 @@ Write_rows_log_event_old::do_prepare_row(THD *thd, int Delete_rows_log_event_old::do_prepare_row(THD *thd, - RELAY_LOG_INFO const *rli, + Relay_log_info const *rli, TABLE *table, uchar const *row_start, uchar const **row_end) @@ -39,7 +39,7 @@ Delete_rows_log_event_old::do_prepare_row(THD *thd, */ DBUG_ASSERT(table->s->fields >= m_width); - error= unpack_row_old(const_cast<RELAY_LOG_INFO*>(rli), + error= unpack_row_old(const_cast<Relay_log_info*>(rli), table, m_width, table->record[0], row_start, &m_cols, row_end, &m_master_reclength, table->read_set, PRE_GA_DELETE_ROWS_EVENT); @@ -59,7 +59,7 @@ Delete_rows_log_event_old::do_prepare_row(THD *thd, int Update_rows_log_event_old::do_prepare_row(THD *thd, - RELAY_LOG_INFO const *rli, + Relay_log_info const *rli, TABLE *table, uchar const *row_start, uchar const **row_end) @@ -73,13 +73,13 @@ int Update_rows_log_event_old::do_prepare_row(THD *thd, DBUG_ASSERT(table->s->fields >= m_width); /* record[0] is the before image for the update */ - error= unpack_row_old(const_cast<RELAY_LOG_INFO*>(rli), + error= unpack_row_old(const_cast<Relay_log_info*>(rli), table, m_width, table->record[0], row_start, &m_cols, row_end, &m_master_reclength, table->read_set, PRE_GA_UPDATE_ROWS_EVENT); row_start = *row_end; /* m_after_image is the after image for the update */ - error= unpack_row_old(const_cast<RELAY_LOG_INFO*>(rli), + error= unpack_row_old(const_cast<Relay_log_info*>(rli), table, m_width, m_after_image, row_start, &m_cols, row_end, &m_master_reclength, table->write_set, PRE_GA_UPDATE_ROWS_EVENT); diff --git a/sql/log_event_old.h b/sql/log_event_old.h index 7c2932360f5..b6e25b6bc73 100644 --- a/sql/log_event_old.h +++ b/sql/log_event_old.h @@ -49,7 +49,7 @@ private: virtual Log_event_type get_type_code() { return (Log_event_type)TYPE_CODE; } #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, + virtual int do_prepare_row(THD*, Relay_log_info const*, TABLE*, uchar const *row_start, uchar const **row_end); #endif }; @@ -83,7 +83,7 @@ private: virtual Log_event_type get_type_code() { return (Log_event_type)TYPE_CODE; } #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, + virtual int do_prepare_row(THD*, Relay_log_info const*, TABLE*, uchar const *row_start, uchar const **row_end); #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ }; @@ -117,7 +117,7 @@ private: virtual Log_event_type get_type_code() { return (Log_event_type)TYPE_CODE; } #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*, + virtual int do_prepare_row(THD*, Relay_log_info const*, TABLE*, uchar const *row_start, uchar const **row_end); #endif }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 34d92a13945..a607e77eecf 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1278,7 +1278,6 @@ bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *, List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows); int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags, bool is_locked); -void mysql_ha_mark_tables_for_reopen(THD *thd, TABLE *table); /* mysql_ha_flush mode_flags bits */ #define MYSQL_HA_CLOSE_FINAL 0x00 #define MYSQL_HA_REOPEN_ON_USAGE 0x01 diff --git a/sql/mysqld.cc b/sql/mysqld.cc index fe4f83dd79e..6c8fa7e7ac3 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5073,6 +5073,7 @@ enum options_mysqld OPT_PLUGIN_DIR, OPT_LOG_OUTPUT, OPT_PORT_OPEN_TIMEOUT, + OPT_KEEP_FILES_ON_CREATE, OPT_GENERAL_LOG, OPT_SLOW_LOG, OPT_THREAD_HANDLING, @@ -5950,6 +5951,11 @@ log and this option does nothing anymore.", (uchar**) &max_system_variables.join_buff_size, 0, GET_ULONG, REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0}, + {"keep_files_on_create", OPT_KEEP_FILES_ON_CREATE, + "Don't overwrite stale .MYD and .MYI even if no directory is specified.", + (uchar**) &global_system_variables.keep_files_on_create, + (uchar**) &max_system_variables.keep_files_on_create, + 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"key_buffer_size", OPT_KEY_BUFFER_SIZE, "The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.", (uchar**) &dflt_key_cache_var.param_buff_size, diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 8bab1ff1ca3..834d87532af 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -492,7 +492,7 @@ bool show_new_master(THD* thd) 0 success */ -int update_slave_list(MYSQL* mysql, MASTER_INFO* mi) +int update_slave_list(MYSQL* mysql, Master_info* mi) { MYSQL_RES* res=0; MYSQL_ROW row; @@ -679,7 +679,7 @@ bool show_slave_hosts(THD* thd) } -int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi) +int connect_to_master(THD *thd, MYSQL* mysql, Master_info* mi) { DBUG_ENTER("connect_to_master"); @@ -728,7 +728,7 @@ static inline void cleanup_mysql_results(MYSQL_RES* db_res, static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db, - MYSQL_RES *table_res, MASTER_INFO *mi) + MYSQL_RES *table_res, Master_info *mi) { MYSQL_ROW row; for (row = mysql_fetch_row(table_res); row; diff --git a/sql/repl_failsafe.h b/sql/repl_failsafe.h index 561db00d841..6ff78067aca 100644 --- a/sql/repl_failsafe.h +++ b/sql/repl_failsafe.h @@ -33,12 +33,12 @@ extern const char* rpl_role_type[], *rpl_status_type[]; pthread_handler_t handle_failsafe_rpl(void *arg); void change_rpl_status(RPL_STATUS from_status, RPL_STATUS to_status); int find_recovery_captain(THD* thd, MYSQL* mysql); -int update_slave_list(MYSQL* mysql, MASTER_INFO* mi); +int update_slave_list(MYSQL* mysql, Master_info* mi); extern HASH slave_list; bool load_master_data(THD* thd); -int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi); +int connect_to_master(THD *thd, MYSQL* mysql, Master_info* mi); bool show_new_master(THD* thd); bool show_slave_hosts(THD* thd); diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index f506a3c319d..1165164fd88 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -27,7 +27,7 @@ int init_intvar_from_file(int* var, IO_CACHE* f, int default_val); int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, const char *default_val); -MASTER_INFO::MASTER_INFO() +Master_info::Master_info() :Slave_reporting_capability("I/O"), ssl(0), fd(-1), io_thd(0), inited(0), abort_slave(0),slave_running(0), @@ -45,7 +45,7 @@ MASTER_INFO::MASTER_INFO() pthread_cond_init(&stop_cond, NULL); } -MASTER_INFO::~MASTER_INFO() +Master_info::~Master_info() { pthread_mutex_destroy(&run_lock); pthread_mutex_destroy(&data_lock); @@ -55,7 +55,7 @@ MASTER_INFO::~MASTER_INFO() } -void init_master_info_with_options(MASTER_INFO* mi) +void init_master_info_with_options(Master_info* mi) { DBUG_ENTER("init_master_info_with_options"); @@ -98,7 +98,7 @@ enum { LINES_IN_MASTER_INFO= LINE_FOR_MASTER_SSL_VERIFY_SERVER_CERT }; -int init_master_info(MASTER_INFO* mi, const char* master_info_fname, +int init_master_info(Master_info* mi, const char* master_info_fname, const char* slave_info_fname, bool abort_if_no_master_info_file, int thread_mask) @@ -338,7 +338,7 @@ err: 1 - flush master info failed 0 - all ok */ -int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache) +int flush_master_info(Master_info* mi, bool flush_relay_log_cache) { IO_CACHE* file = &mi->file; char lbuf[22]; @@ -392,7 +392,7 @@ int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache) } -void end_master_info(MASTER_INFO* mi) +void end_master_info(Master_info* mi) { DBUG_ENTER("end_master_info"); diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index 44ab0d1dc15..93fb0a98198 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -26,13 +26,13 @@ Replication IO Thread - MASTER_INFO contains: + Master_info contains: - information about how to connect to a master - current master log name - current master log offset - misc control variables - MASTER_INFO is initialized once from the master.info file if such + Master_info is initialized once from the master.info file if such exists. Otherwise, data members corresponding to master.info fields are initialized with defaults specified by master-* options. The initialization is done through init_master_info() call. @@ -55,11 +55,11 @@ *****************************************************************************/ -class MASTER_INFO : public Slave_reporting_capability +class Master_info : public Slave_reporting_capability { public: - MASTER_INFO(); - ~MASTER_INFO(); + Master_info(); + ~Master_info(); /* the variables below are needed because we can change masters on the fly */ char master_log_name[FN_REFLEN]; @@ -80,7 +80,7 @@ class MASTER_INFO : public Slave_reporting_capability THD *io_thd; MYSQL* mysql; uint32 file_id; /* for 3.23 load data infile */ - RELAY_LOG_INFO rli; + Relay_log_info rli; uint port; uint connect_retry; #ifndef DBUG_OFF @@ -102,13 +102,13 @@ class MASTER_INFO : public Slave_reporting_capability long clock_diff_with_master; }; -void init_master_info_with_options(MASTER_INFO* mi); -int init_master_info(MASTER_INFO* mi, const char* master_info_fname, +void init_master_info_with_options(Master_info* mi); +int init_master_info(Master_info* mi, const char* master_info_fname, const char* slave_info_fname, bool abort_if_no_master_info_file, int thread_mask); -void end_master_info(MASTER_INFO* mi); -int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache); +void end_master_info(Master_info* mi); +int flush_master_info(Master_info* mi, bool flush_relay_log_cache); #endif /* HAVE_REPLICATION */ #endif /* RPL_MI_H */ diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 1b6b3adb52b..17b759f8426 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -189,7 +189,7 @@ pack_row(TABLE *table, MY_BITMAP const* cols, */ #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) int -unpack_row(RELAY_LOG_INFO const *rli, +unpack_row(Relay_log_info const *rli, TABLE *table, uint const colcnt, uchar const *const row_data, MY_BITMAP const *cols, uchar const **const row_end, ulong *const master_reclength, @@ -218,7 +218,7 @@ unpack_row(RELAY_LOG_INFO const *rli, // The "current" null bits unsigned int null_bits= *null_ptr++; uint i= 0; - table_def *tabledef= ((RELAY_LOG_INFO*)rli)->get_tabledef(table); + table_def *tabledef= ((Relay_log_info*)rli)->get_tabledef(table); for (field_ptr= begin_ptr ; field_ptr < end_ptr && *field_ptr ; ++field_ptr) { Field *const f= *field_ptr; diff --git a/sql/rpl_record.h b/sql/rpl_record.h index 12c2f1fc713..b817dba0292 100644 --- a/sql/rpl_record.h +++ b/sql/rpl_record.h @@ -22,7 +22,7 @@ size_t pack_row(TABLE* table, MY_BITMAP const* cols, #endif #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) -int unpack_row(RELAY_LOG_INFO const *rli, +int unpack_row(Relay_log_info const *rli, TABLE *table, uint const colcnt, uchar const *const row_data, MY_BITMAP const *cols, uchar const **const row_end, ulong *const master_reclength, diff --git a/sql/rpl_record_old.cc b/sql/rpl_record_old.cc index 377aec49113..ab4e993ce41 100644 --- a/sql/rpl_record_old.cc +++ b/sql/rpl_record_old.cc @@ -70,7 +70,7 @@ pack_row_old(TABLE *table, MY_BITMAP const* cols, */ #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) int -unpack_row_old(RELAY_LOG_INFO *rli, +unpack_row_old(Relay_log_info *rli, TABLE *table, uint const colcnt, uchar *record, uchar const *row, MY_BITMAP const *cols, uchar const **row_end, ulong *master_reclength, diff --git a/sql/rpl_record_old.h b/sql/rpl_record_old.h index 6af61141d47..bdaedd56741 100644 --- a/sql/rpl_record_old.h +++ b/sql/rpl_record_old.h @@ -21,7 +21,7 @@ size_t pack_row_old(TABLE *table, MY_BITMAP const* cols, uchar *row_data, const uchar *record); #ifdef HAVE_REPLICATION -int unpack_row_old(RELAY_LOG_INFO *rli, +int unpack_row_old(Relay_log_info *rli, TABLE *table, uint const colcnt, uchar *record, uchar const *row, MY_BITMAP const *cols, uchar const **row_end, ulong *master_reclength, diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 41df3f63825..867d55a60a3 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -21,7 +21,7 @@ #include "sql_repl.h" // For check_binlog_magic #include "rpl_utility.h" -static int count_relay_log_space(RELAY_LOG_INFO* rli); +static int count_relay_log_space(Relay_log_info* rli); // Defined in slave.cc int init_intvar_from_file(int* var, IO_CACHE* f, int default_val); @@ -29,7 +29,7 @@ int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, const char *default_val); -st_relay_log_info::st_relay_log_info() +Relay_log_info::Relay_log_info() :Slave_reporting_capability("SQL"), no_storage(FALSE), replicate_same_server_id(::replicate_same_server_id), info_fd(-1), cur_log_fd(-1), save_temporary_tables(0), @@ -41,7 +41,7 @@ st_relay_log_info::st_relay_log_info() tables_to_lock(0), tables_to_lock_count(0), last_event_start_time(0), m_flags(0) { - DBUG_ENTER("st_relay_log_info::st_relay_log_info"); + DBUG_ENTER("Relay_log_info::Relay_log_info"); group_relay_log_name[0]= event_relay_log_name[0]= group_master_log_name[0]= 0; @@ -61,9 +61,9 @@ st_relay_log_info::st_relay_log_info() } -st_relay_log_info::~st_relay_log_info() +Relay_log_info::~Relay_log_info() { - DBUG_ENTER("st_relay_log_info::~st_relay_log_info"); + DBUG_ENTER("Relay_log_info::~Relay_log_info"); pthread_mutex_destroy(&run_lock); pthread_mutex_destroy(&data_lock); @@ -77,7 +77,7 @@ st_relay_log_info::~st_relay_log_info() } -int init_relay_log_info(RELAY_LOG_INFO* rli, +int init_relay_log_info(Relay_log_info* rli, const char* info_fname) { char fname[FN_REFLEN+128]; @@ -294,7 +294,7 @@ err: } -static inline int add_relay_log(RELAY_LOG_INFO* rli,LOG_INFO* linfo) +static inline int add_relay_log(Relay_log_info* rli,LOG_INFO* linfo) { MY_STAT s; DBUG_ENTER("add_relay_log"); @@ -313,7 +313,7 @@ static inline int add_relay_log(RELAY_LOG_INFO* rli,LOG_INFO* linfo) } -static int count_relay_log_space(RELAY_LOG_INFO* rli) +static int count_relay_log_space(Relay_log_info* rli) { LOG_INFO linfo; DBUG_ENTER("count_relay_log_space"); @@ -339,18 +339,18 @@ static int count_relay_log_space(RELAY_LOG_INFO* rli) /* - Reset UNTIL condition for RELAY_LOG_INFO + Reset UNTIL condition for Relay_log_info SYNOPSYS clear_until_condition() - rli - RELAY_LOG_INFO structure where UNTIL condition should be reset + rli - Relay_log_info structure where UNTIL condition should be reset */ -void st_relay_log_info::clear_until_condition() +void Relay_log_info::clear_until_condition() { DBUG_ENTER("clear_until_condition"); - until_condition= RELAY_LOG_INFO::UNTIL_NONE; + until_condition= Relay_log_info::UNTIL_NONE; until_log_name[0]= 0; until_log_pos= 0; DBUG_VOID_RETURN; @@ -389,7 +389,7 @@ void st_relay_log_info::clear_until_condition() 1 error. errmsg is set to point to the error message */ -int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log, +int init_relay_log_pos(Relay_log_info* rli,const char* log, ulonglong pos, bool need_data_lock, const char** errmsg, bool look_for_description_event) @@ -599,7 +599,7 @@ err: before reaching the desired log/position */ -int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, +int Relay_log_info::wait_for_pos(THD* thd, String* log_name, longlong log_pos, longlong timeout) { @@ -608,7 +608,7 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, int error=0; struct timespec abstime; // for timeout checking const char *msg; - DBUG_ENTER("st_relay_log_info::wait_for_pos"); + DBUG_ENTER("Relay_log_info::wait_for_pos"); if (!inited) DBUG_RETURN(-1); @@ -779,10 +779,10 @@ improper_arguments: %d timed_out: %d", } -void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, +void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, bool skip_lock) { - DBUG_ENTER("st_relay_log_info::inc_group_relay_log_pos"); + DBUG_ENTER("Relay_log_info::inc_group_relay_log_pos"); if (!skip_lock) pthread_mutex_lock(&data_lock); @@ -836,10 +836,10 @@ void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, } -void st_relay_log_info::close_temporary_tables() +void Relay_log_info::close_temporary_tables() { TABLE *table,*next; - DBUG_ENTER("st_relay_log_info::close_temporary_tables"); + DBUG_ENTER("Relay_log_info::close_temporary_tables"); for (table=save_temporary_tables ; table ; table=next) { @@ -863,7 +863,7 @@ void st_relay_log_info::close_temporary_tables() Assumes to have a run lock on rli and that no slave thread are running. */ -int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset, +int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, const char** errmsg) { int error=0; @@ -950,12 +950,12 @@ err: /* Check if condition stated in UNTIL clause of START SLAVE is reached. SYNOPSYS - st_relay_log_info::is_until_satisfied() + Relay_log_info::is_until_satisfied() DESCRIPTION Checks if UNTIL condition is reached. Uses caching result of last comparison of current log file name and target log file name. So cached value should be invalidated if current log file name changes - (see st_relay_log_info::notify_... functions). + (see Relay_log_info::notify_... functions). This caching is needed to avoid of expensive string comparisons and strtol() conversions needed for log names comparison. We don't need to @@ -975,11 +975,11 @@ err: false - condition not met */ -bool st_relay_log_info::is_until_satisfied() +bool Relay_log_info::is_until_satisfied() { const char *log_name; ulonglong log_pos; - DBUG_ENTER("st_relay_log_info::is_until_satisfied"); + DBUG_ENTER("Relay_log_info::is_until_satisfied"); DBUG_ASSERT(until_condition != UNTIL_NONE); @@ -1055,9 +1055,9 @@ bool st_relay_log_info::is_until_satisfied() } -void st_relay_log_info::cached_charset_invalidate() +void Relay_log_info::cached_charset_invalidate() { - DBUG_ENTER("st_relay_log_info::cached_charset_invalidate"); + DBUG_ENTER("Relay_log_info::cached_charset_invalidate"); /* Full of zeroes means uninitialized. */ bzero(cached_charset, sizeof(cached_charset)); @@ -1065,9 +1065,9 @@ void st_relay_log_info::cached_charset_invalidate() } -bool st_relay_log_info::cached_charset_compare(char *charset) const +bool Relay_log_info::cached_charset_compare(char *charset) const { - DBUG_ENTER("st_relay_log_info::cached_charset_compare"); + DBUG_ENTER("Relay_log_info::cached_charset_compare"); if (bcmp((uchar*) cached_charset, (uchar*) charset, sizeof(cached_charset))) @@ -1079,7 +1079,7 @@ bool st_relay_log_info::cached_charset_compare(char *charset) const } -void st_relay_log_info::stmt_done(my_off_t event_master_log_pos, +void Relay_log_info::stmt_done(my_off_t event_master_log_pos, time_t event_creation_time) { clear_flag(IN_STMT); @@ -1126,9 +1126,9 @@ void st_relay_log_info::stmt_done(my_off_t event_master_log_pos, } #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) -void st_relay_log_info::cleanup_context(THD *thd, bool error) +void Relay_log_info::cleanup_context(THD *thd, bool error) { - DBUG_ENTER("st_relay_log_info::cleanup_context"); + DBUG_ENTER("Relay_log_info::cleanup_context"); DBUG_ASSERT(sql_thd == thd); /* @@ -1156,7 +1156,7 @@ void st_relay_log_info::cleanup_context(THD *thd, bool error) DBUG_VOID_RETURN; } -void st_relay_log_info::clear_tables_to_lock() +void Relay_log_info::clear_tables_to_lock() { while (tables_to_lock) { diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index 7ae21897e3f..10ecf1a43d4 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -21,22 +21,22 @@ #include "rpl_utility.h" struct RPL_TABLE_LIST; - +class Master_info; /**************************************************************************** Replication SQL Thread - st_relay_log_info contains: + Relay_log_info contains: - the current relay log - the current relay log offset - master log name - master log sequence corresponding to the last update - misc information specific to the SQL thread - st_relay_log_info is initialized from the slave.info file if such exists. - Otherwise, data members are intialized with defaults. The initialization is - done with init_relay_log_info() call. + Relay_log_info is initialized from the slave.info file if such + exists. Otherwise, data members are intialized with defaults. The + initialization is done with init_relay_log_info() call. The format of slave.info file: @@ -49,8 +49,9 @@ struct RPL_TABLE_LIST; *****************************************************************************/ -typedef struct st_relay_log_info : public Slave_reporting_capability +class Relay_log_info : public Slave_reporting_capability { +public: /** Flags for the state of the replication. */ @@ -120,8 +121,8 @@ typedef struct st_relay_log_info : public Slave_reporting_capability */ pthread_cond_t start_cond, stop_cond, data_cond; - /* parent MASTER_INFO structure */ - class MASTER_INFO *mi; + /* parent Master_info structure */ + Master_info *mi; /* Needed to deal properly with cur_log getting closed and re-opened with @@ -255,8 +256,8 @@ typedef struct st_relay_log_info : public Slave_reporting_capability char ign_master_log_name_end[FN_REFLEN]; ulonglong ign_master_log_pos_end; - st_relay_log_info(); - ~st_relay_log_info(); + Relay_log_info(); + ~Relay_log_info(); /* Invalidate cached until_log_name and group_relay_log_name comparison @@ -391,11 +392,11 @@ typedef struct st_relay_log_info : public Slave_reporting_capability private: uint32 m_flags; -} RELAY_LOG_INFO; +}; // Defined in rpl_rli.cc -int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname); +int init_relay_log_info(Relay_log_info* rli, const char* info_fname); #endif /* RPL_RLI_H */ diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index 85ed6089f56..bc552650ac5 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -164,7 +164,7 @@ uint32 table_def::calc_field_size(uint col, uchar *master_data) */ int -table_def::compatible_with(RELAY_LOG_INFO const *rli_arg, TABLE *table) +table_def::compatible_with(Relay_log_info const *rli_arg, TABLE *table) const { /* @@ -172,7 +172,7 @@ table_def::compatible_with(RELAY_LOG_INFO const *rli_arg, TABLE *table) */ uint const cols_to_check= min(table->s->fields, size()); int error= 0; - RELAY_LOG_INFO const *rli= const_cast<RELAY_LOG_INFO*>(rli_arg); + Relay_log_info const *rli= const_cast<Relay_log_info*>(rli_arg); TABLE_SHARE const *const tsh= table->s; @@ -191,6 +191,25 @@ table_def::compatible_with(RELAY_LOG_INFO const *rli_arg, TABLE *table) rli->report(ERROR_LEVEL, ER_BINLOG_ROW_WRONG_TABLE_DEF, ER(ER_BINLOG_ROW_WRONG_TABLE_DEF), buf); } + /* + Check the slave's field size against that of the master. + */ + if (!error && + !table->field[col]->compatible_field_size(field_metadata(col))) + { + error= 1; + char buf[256]; + my_snprintf(buf, sizeof(buf), "Column %d size mismatch - " + "master has size %d, %s.%s on slave has size %d." + " Master's column size should be <= the slave's " + "column size.", col, + table->field[col]->pack_length_from_metadata( + m_field_metadata[col]), + tsh->db.str, tsh->table_name.str, + table->field[col]->row_pack_length()); + rli->report(ERROR_LEVEL, ER_BINLOG_ROW_WRONG_TABLE_DEF, + ER(ER_BINLOG_ROW_WRONG_TABLE_DEF), buf); + } } return error; diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h index d08f62363af..eac3d14dfc6 100644 --- a/sql/rpl_utility.h +++ b/sql/rpl_utility.h @@ -22,8 +22,7 @@ #include "mysql_priv.h" -struct st_relay_log_info; -typedef st_relay_log_info RELAY_LOG_INFO; +class Relay_log_info; /** @@ -61,7 +60,7 @@ public: */ table_def(field_type *types, ulong size, uchar *field_metadata, int metadata_size, uchar *null_bitmap) - : m_size(size), m_type(0), + : m_size(size), m_type(0), m_field_metadata_size(metadata_size), m_field_metadata(0), m_null_bits(0), m_memory(NULL) { m_memory= (uchar *)my_multi_malloc(MYF(MY_WME), @@ -194,7 +193,7 @@ public: uint16 field_metadata(uint index) const { DBUG_ASSERT(index < m_size); - if (m_field_metadata) + if (m_field_metadata_size) return m_field_metadata[index]; else return 0; @@ -237,12 +236,13 @@ public: @retval 1 if the table definition is not compatible with @c table @retval 0 if the table definition is compatible with @c table */ - int compatible_with(RELAY_LOG_INFO const *rli, TABLE *table) const; + int compatible_with(Relay_log_info const *rli, TABLE *table) const; private: ulong m_size; // Number of elements in the types array field_type *m_type; // Array of type descriptors uint16 *m_field_metadata; + uint m_field_metadata_size; uchar *m_null_bits; uchar *m_memory; }; diff --git a/sql/share/charsets/ascii.xml b/sql/share/charsets/ascii.xml index 068fb84eeae..f4fb79ac632 100644 --- a/sql/share/charsets/ascii.xml +++ b/sql/share/charsets/ascii.xml @@ -117,9 +117,9 @@ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F - 50 51 52 53 54 55 56 57 58 59 5A 5C 5D 5B 5E 5F - 45 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F - 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 59 7F + 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F + 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F + 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 966e841ccbf..8ecba1d4be0 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5654,6 +5654,8 @@ ER_NON_INSERTABLE_TABLE ger "Die Zieltabelle %-.100s von %s ist nicht einfügbar" ER_ADMIN_WRONG_MRG_TABLE eng "Table '%-.64s' is differently defined or of non-MyISAM type or doesn't exist" +ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT + eng "Too high level of nesting for select" ER_FOREIGN_SERVER_EXISTS eng "The foreign server, %s, you are trying to create already exists." ER_FOREIGN_SERVER_DOESNT_EXIST diff --git a/sql/slave.cc b/sql/slave.cc index 0854bc123f9..cb957b7b3b5 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -33,8 +33,8 @@ #include "rpl_tblmap.h" -int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len); -static Log_event* next_event(RELAY_LOG_INFO* rli); +int queue_event(Master_info* mi,const char* buf,ulong event_len); +static Log_event* next_event(Relay_log_info* rli); #define FLAGSTR(V,F) ((V)&(F)?#F" ":"") @@ -46,7 +46,7 @@ MY_BITMAP slave_error_mask; typedef bool (*CHECK_KILLED_FUNC)(THD*,void*); char* slave_load_tmpdir = 0; -MASTER_INFO *active_mi= 0; +Master_info *active_mi= 0; my_bool replicate_same_server_id; ulonglong relay_log_space_limit = 0; @@ -54,7 +54,7 @@ ulonglong relay_log_space_limit = 0; When slave thread exits, we need to remember the temporary tables so we can re-use them on slave start. - TODO: move the vars below under MASTER_INFO + TODO: move the vars below under Master_info */ int disconnect_slave_event_count = 0, abort_slave_event_count = 0; @@ -114,24 +114,24 @@ failed read" typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE; -static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev); -static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev); -static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli); -static inline bool io_slave_killed(THD* thd,MASTER_INFO* mi); -static inline bool sql_slave_killed(THD* thd,RELAY_LOG_INFO* rli); +static int process_io_rotate(Master_info* mi, Rotate_log_event* rev); +static int process_io_create_file(Master_info* mi, Create_file_log_event* cev); +static bool wait_for_relay_log_space(Relay_log_info* rli); +static inline bool io_slave_killed(THD* thd,Master_info* mi); +static inline bool sql_slave_killed(THD* thd,Relay_log_info* rli); static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type); -static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi); -static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi, +static int safe_connect(THD* thd, MYSQL* mysql, Master_info* mi); +static int safe_reconnect(THD* thd, MYSQL* mysql, Master_info* mi, bool suppress_warnings); -static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi, +static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi, bool reconnect, bool suppress_warnings); static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed, void* thread_killed_arg); static int request_table_dump(MYSQL* mysql, const char* db, const char* table); static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, const char* table_name, bool overwrite); -static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi); -static Log_event* next_event(RELAY_LOG_INFO* rli); +static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi); +static Log_event* next_event(Relay_log_info* rli); /* Find out which replications threads are running @@ -151,7 +151,7 @@ static Log_event* next_event(RELAY_LOG_INFO* rli); If inverse == 1, stopped threads */ -void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse) +void init_thread_mask(int* mask,Master_info* mi,bool inverse) { bool set_io = mi->slave_running, set_sql = mi->rli.slave_running; register int tmp_mask=0; @@ -172,7 +172,7 @@ void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse) lock_slave_threads() */ -void lock_slave_threads(MASTER_INFO* mi) +void lock_slave_threads(Master_info* mi) { DBUG_ENTER("lock_slave_threads"); @@ -187,7 +187,7 @@ void lock_slave_threads(MASTER_INFO* mi) unlock_slave_threads() */ -void unlock_slave_threads(MASTER_INFO* mi) +void unlock_slave_threads(Master_info* mi) { DBUG_ENTER("unlock_slave_threads"); @@ -214,7 +214,7 @@ int init_slave() TODO: re-write this to interate through the list of files for multi-master */ - active_mi= new MASTER_INFO; + active_mi= new Master_info; /* If master_host is not specified, try to read it from the master_info file. @@ -304,7 +304,7 @@ void init_slave_skip_errors(const char* arg) } -int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock) +int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock) { DBUG_ENTER("terminate_slave_threads"); @@ -393,7 +393,7 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock, pthread_cond_t *start_cond, volatile uint *slave_running, volatile ulong *slave_run_id, - MASTER_INFO* mi, + Master_info* mi, bool high_priority) { pthread_t th; @@ -463,7 +463,7 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock, */ int start_slave_threads(bool need_slave_mutex, bool wait_for_start, - MASTER_INFO* mi, const char* master_info_fname, + Master_info* mi, const char* master_info_fname, const char* slave_info_fname, int thread_mask) { pthread_mutex_t *lock_io=0,*lock_sql=0,*lock_cond_io=0,*lock_cond_sql=0; @@ -503,7 +503,7 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start, #ifdef NOT_USED_YET -static int end_slave_on_walk(MASTER_INFO* mi, uchar* /*unused*/) +static int end_slave_on_walk(Master_info* mi, uchar* /*unused*/) { DBUG_ENTER("end_slave_on_walk"); @@ -549,7 +549,7 @@ void end_slave() } -static bool io_slave_killed(THD* thd, MASTER_INFO* mi) +static bool io_slave_killed(THD* thd, Master_info* mi) { DBUG_ENTER("io_slave_killed"); @@ -559,7 +559,7 @@ static bool io_slave_killed(THD* thd, MASTER_INFO* mi) } -static bool sql_slave_killed(THD* thd, RELAY_LOG_INFO* rli) +static bool sql_slave_killed(THD* thd, Relay_log_info* rli) { DBUG_ENTER("sql_slave_killed"); @@ -699,7 +699,7 @@ int init_intvar_from_file(int* var, IO_CACHE* f, int default_val) 1 error */ -static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi) +static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi) { const char* errmsg= 0; DBUG_ENTER("get_master_version_and_clock"); @@ -1018,7 +1018,7 @@ err: int fetch_master_table(THD *thd, const char *db_name, const char *table_name, - MASTER_INFO *mi, MYSQL *mysql, bool overwrite) + Master_info *mi, MYSQL *mysql, bool overwrite) { int error= 1; const char *errmsg=0; @@ -1073,10 +1073,10 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name, } -static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli) +static bool wait_for_relay_log_space(Relay_log_info* rli) { bool slave_killed=0; - MASTER_INFO* mi = rli->mi; + Master_info* mi = rli->mi; const char *save_proc_info; THD* thd = mi->io_thd; DBUG_ENTER("wait_for_relay_log_space"); @@ -1108,9 +1108,9 @@ Waiting for the slave SQL thread to free enough relay log space"); ignored events' end position for the use of the slave SQL thread, by calling this function. Only that thread can call it (see assertion). */ -static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi) +static void write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi) { - RELAY_LOG_INFO *rli= &mi->rli; + Relay_log_info *rli= &mi->rli; pthread_mutex_t *log_lock= rli->relay_log.get_log_lock(); DBUG_ENTER("write_ignored_events_info_to_relay_log"); @@ -1151,7 +1151,7 @@ static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi) } -int register_slave_on_master(MYSQL* mysql, MASTER_INFO *mi, +int register_slave_on_master(MYSQL* mysql, Master_info *mi, bool *suppress_warnings) { uchar buf[1024], *pos= buf; @@ -1200,7 +1200,7 @@ int register_slave_on_master(MYSQL* mysql, MASTER_INFO *mi, } -bool show_master_info(THD* thd, MASTER_INFO* mi) +bool show_master_info(THD* thd, Master_info* mi) { // TODO: fix this for multi-master List<Item> field_list; @@ -1322,8 +1322,8 @@ bool show_master_info(THD* thd, MASTER_INFO* mi) protocol->store((ulonglong) mi->rli.log_space_total); protocol->store( - mi->rli.until_condition==RELAY_LOG_INFO::UNTIL_NONE ? "None": - ( mi->rli.until_condition==RELAY_LOG_INFO::UNTIL_MASTER_POS? "Master": + mi->rli.until_condition==Relay_log_info::UNTIL_NONE ? "None": + ( mi->rli.until_condition==Relay_log_info::UNTIL_MASTER_POS? "Master": "Relay"), &my_charset_bin); protocol->store(mi->rli.until_log_name, &my_charset_bin); protocol->store((ulonglong) mi->rli.until_log_pos); @@ -1419,7 +1419,7 @@ void set_slave_thread_options(THD* thd) DBUG_VOID_RETURN; } -void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO const *rli) +void set_slave_thread_default_charset(THD* thd, Relay_log_info const *rli) { DBUG_ENTER("set_slave_thread_default_charset"); @@ -1437,7 +1437,7 @@ void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO const *rli) the thread. That the cache has to be invalidated is a secondary effect. */ - const_cast<RELAY_LOG_INFO*>(rli)->cached_charset_invalidate(); + const_cast<Relay_log_info*>(rli)->cached_charset_invalidate(); DBUG_VOID_RETURN; } @@ -1515,7 +1515,7 @@ static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed, } -static int request_dump(MYSQL* mysql, MASTER_INFO* mi, +static int request_dump(MYSQL* mysql, Master_info* mi, bool *suppress_warnings) { uchar buf[FN_REFLEN + 10]; @@ -1599,7 +1599,7 @@ command"); number Length of packet */ -static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) +static ulong read_event(MYSQL* mysql, Master_info *mi, bool* suppress_warnings) { ulong len; DBUG_ENTER("read_event"); @@ -1647,7 +1647,7 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) } -int check_expected_error(THD* thd, RELAY_LOG_INFO const *rli, +int check_expected_error(THD* thd, Relay_log_info const *rli, int expected_error) { DBUG_ENTER("check_expected_error"); @@ -1709,7 +1709,7 @@ static int has_temporary_error(THD *thd) DBUG_RETURN(0); } -static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) +static int exec_relay_log_event(THD* thd, Relay_log_info* rli) { DBUG_ENTER("exec_relay_log_event"); @@ -1727,7 +1727,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) was an event ignored by the I/O thread just before (BUG#13861 to be fixed). */ - if (rli->until_condition!=RELAY_LOG_INFO::UNTIL_NONE && + if (rli->until_condition!=Relay_log_info::UNTIL_NONE && rli->is_until_satisfied()) { char buf[22]; @@ -1944,7 +1944,7 @@ on this slave.\ } -static bool check_io_slave_killed(THD *thd, MASTER_INFO *mi, const char *info) +static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info) { if (io_slave_killed(thd, mi)) { @@ -1982,7 +1982,7 @@ static bool check_io_slave_killed(THD *thd, MASTER_INFO *mi, const char *info) @retval 1 There was an error. */ -static int try_to_reconnect(THD *thd, MYSQL *mysql, MASTER_INFO *mi, +static int try_to_reconnect(THD *thd, MYSQL *mysql, Master_info *mi, uint *retry_count, bool suppress_warnings, const char *messages[SLAVE_RECON_MSG_MAX]) { @@ -2038,8 +2038,8 @@ pthread_handler_t handle_slave_io(void *arg) { THD *thd; // needs to be first for thread_stack MYSQL *mysql; - MASTER_INFO *mi = (MASTER_INFO*)arg; - RELAY_LOG_INFO *rli= &mi->rli; + Master_info *mi = (Master_info*)arg; + Relay_log_info *rli= &mi->rli; char llbuff[22]; uint retry_count; bool suppress_warnings; @@ -2312,7 +2312,7 @@ err: /* Forget the relay log's format */ delete mi->rli.relay_log.description_event_for_queue; mi->rli.relay_log.description_event_for_queue= 0; - // TODO: make rpl_status part of MASTER_INFO + // TODO: make rpl_status part of Master_info change_rpl_status(RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE); DBUG_ASSERT(thd->net.buff != 0); net_end(&thd->net); // destructor will not free it, because net.vio is 0 @@ -2344,7 +2344,7 @@ pthread_handler_t handle_slave_sql(void *arg) THD *thd; /* needs to be first for thread_stack */ char llbuff[22],llbuff1[22]; - RELAY_LOG_INFO* rli = &((MASTER_INFO*)arg)->rli; + Relay_log_info* rli = &((Master_info*)arg)->rli; const char *errmsg; // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff @@ -2613,7 +2613,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ process_io_create_file() */ -static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev) +static int process_io_create_file(Master_info* mi, Create_file_log_event* cev) { int error = 1; ulong num_bytes; @@ -2740,7 +2740,7 @@ err: */ -static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev) +static int process_io_rotate(Master_info *mi, Rotate_log_event *rev) { DBUG_ENTER("process_io_rotate"); safe_mutex_assert_owner(&mi->data_lock); @@ -2788,14 +2788,14 @@ static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev) Reads a 3.23 event and converts it to the slave's format. This code was copied from MySQL 4.0. */ -static int queue_binlog_ver_1_event(MASTER_INFO *mi, const char *buf, +static int queue_binlog_ver_1_event(Master_info *mi, const char *buf, ulong event_len) { const char *errmsg = 0; ulong inc_pos; bool ignore_event= 0; char *tmp_buf = 0; - RELAY_LOG_INFO *rli= &mi->rli; + Relay_log_info *rli= &mi->rli; DBUG_ENTER("queue_binlog_ver_1_event"); /* @@ -2906,13 +2906,13 @@ static int queue_binlog_ver_1_event(MASTER_INFO *mi, const char *buf, Reads a 4.0 event and converts it to the slave's format. This code was copied from queue_binlog_ver_1_event(), with some affordable simplifications. */ -static int queue_binlog_ver_3_event(MASTER_INFO *mi, const char *buf, +static int queue_binlog_ver_3_event(Master_info *mi, const char *buf, ulong event_len) { const char *errmsg = 0; ulong inc_pos; char *tmp_buf = 0; - RELAY_LOG_INFO *rli= &mi->rli; + Relay_log_info *rli= &mi->rli; DBUG_ENTER("queue_binlog_ver_3_event"); /* read_log_event() will adjust log_pos to be end_log_pos */ @@ -2970,7 +2970,7 @@ err: setup with 3.23 master or 4.0 master */ -static int queue_old_event(MASTER_INFO *mi, const char *buf, +static int queue_old_event(Master_info *mi, const char *buf, ulong event_len) { DBUG_ENTER("queue_old_event"); @@ -2998,11 +2998,11 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf, any >=5.0.0 format. */ -int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len) +int queue_event(Master_info* mi,const char* buf, ulong event_len) { int error= 0; ulong inc_pos; - RELAY_LOG_INFO *rli= &mi->rli; + Relay_log_info *rli= &mi->rli; pthread_mutex_t *log_lock= rli->relay_log.get_log_lock(); DBUG_ENTER("queue_event"); @@ -3154,7 +3154,7 @@ err: } -void end_relay_log_info(RELAY_LOG_INFO* rli) +void end_relay_log_info(Relay_log_info* rli) { DBUG_ENTER("end_relay_log_info"); @@ -3198,7 +3198,7 @@ void end_relay_log_info(RELAY_LOG_INFO* rli) # Error */ -static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi) +static int safe_connect(THD* thd, MYSQL* mysql, Master_info* mi) { DBUG_ENTER("safe_connect"); @@ -3215,7 +3215,7 @@ static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi) master_retry_count times */ -static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi, +static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi, bool reconnect, bool suppress_warnings) { int slave_was_killed; @@ -3321,7 +3321,7 @@ replication resumed in log '%s' at position %s", mi->user, master_retry_count times */ -static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi, +static int safe_reconnect(THD* thd, MYSQL* mysql, Master_info* mi, bool suppress_warnings) { DBUG_ENTER("safe_reconnect"); @@ -3358,7 +3358,7 @@ static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi, 1 write error */ -bool flush_relay_log_info(RELAY_LOG_INFO* rli) +bool flush_relay_log_info(Relay_log_info* rli) { bool error=0; DBUG_ENTER("flush_relay_log_info"); @@ -3392,7 +3392,7 @@ bool flush_relay_log_info(RELAY_LOG_INFO* rli) Called when we notice that the current "hot" log got rotated under our feet. */ -static IO_CACHE *reopen_relay_log(RELAY_LOG_INFO *rli, const char **errmsg) +static IO_CACHE *reopen_relay_log(Relay_log_info *rli, const char **errmsg) { DBUG_ENTER("reopen_relay_log"); DBUG_ASSERT(rli->cur_log != &rli->cache_buf); @@ -3413,7 +3413,7 @@ static IO_CACHE *reopen_relay_log(RELAY_LOG_INFO *rli, const char **errmsg) } -static Log_event* next_event(RELAY_LOG_INFO* rli) +static Log_event* next_event(Relay_log_info* rli) { Log_event* ev; IO_CACHE* cur_log = rli->cur_log; @@ -3605,10 +3605,10 @@ static Log_event* next_event(RELAY_LOG_INFO* rli) // prevent the I/O thread from blocking next times rli->ignore_log_space_limit= 1; /* - If the I/O thread is blocked, unblock it. - Ok to broadcast after unlock, because the mutex is only destroyed in - ~st_relay_log_info(), i.e. when rli is destroyed, and rli will not be - destroyed before we exit the present function. + If the I/O thread is blocked, unblock it. Ok to broadcast + after unlock, because the mutex is only destroyed in + ~Relay_log_info(), i.e. when rli is destroyed, and rli will + not be destroyed before we exit the present function. */ pthread_mutex_unlock(&rli->log_space_lock); pthread_cond_broadcast(&rli->log_space_cond); @@ -3765,10 +3765,10 @@ err: is void). */ -void rotate_relay_log(MASTER_INFO* mi) +void rotate_relay_log(Master_info* mi) { DBUG_ENTER("rotate_relay_log"); - RELAY_LOG_INFO* rli= &mi->rli; + Relay_log_info* rli= &mi->rli; /* We don't lock rli->run_lock. This would lead to deadlocks. */ pthread_mutex_lock(&mi->run_lock); @@ -3809,11 +3809,11 @@ end: /** Detects, based on master's version (as found in the relay log), if master has a certain bug. - @param rli RELAY_LOG_INFO which tells the master's version + @param rli Relay_log_info which tells the master's version @param bug_id Number of the bug as found in bugs.mysql.com @return TRUE if master has the bug, FALSE if it does not. */ -bool rpl_master_has_bug(RELAY_LOG_INFO *rli, uint bug_id) +bool rpl_master_has_bug(Relay_log_info *rli, uint bug_id) { struct st_version_range_for_one_bug { uint bug_id; diff --git a/sql/slave.h b/sql/slave.h index 791f95ef7ae..68b00f65ded 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -35,10 +35,9 @@ // Forward declarations -struct st_relay_log_info; -typedef st_relay_log_info RELAY_LOG_INFO; +class Relay_log_info; +class Master_info; -class MASTER_INFO; /***************************************************************************** @@ -49,11 +48,11 @@ class MASTER_INFO; I/O Thread - One of these threads is started for each master server. They maintain a connection to their master server, read log events from the master as they arrive, and queues them into - a single, shared relay log file. A MASTER_INFO + a single, shared relay log file. A Master_info represents each of these threads. SQL Thread - One of these threads is started and reads from the relay log - file, executing each event. A RELAY_LOG_INFO + file, executing each event. A Relay_log_info represents this thread. Buffering in the relay log file makes it unnecessary to reread events from @@ -76,18 +75,18 @@ class MASTER_INFO; mi->run_lock, keeps rli->run_lock, and tries to re-acquire mi->run_lock). Currently active_mi never moves (it's created at startup and deleted at - shutdown, and not changed: it always points to the same MASTER_INFO struct), + shutdown, and not changed: it always points to the same Master_info struct), because we don't have multimaster. So for the moment, mi does not move, and mi->rli does not either. - In MASTER_INFO: run_lock, data_lock + In Master_info: run_lock, data_lock run_lock protects all information about the run state: slave_running, and the existence of the I/O thread (to stop/start it, you need this mutex). data_lock protects some moving members of the struct: counters (log name, position) and relay log (MYSQL_BIN_LOG object). - In RELAY_LOG_INFO: run_lock, data_lock - see MASTER_INFO + In Relay_log_info: run_lock, data_lock + see Master_info Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you must acquire LOCK_active_mi first. @@ -108,12 +107,12 @@ extern my_bool opt_log_slave_updates; extern ulonglong relay_log_space_limit; /* - 3 possible values for MASTER_INFO::slave_running and - RELAY_LOG_INFO::slave_running. + 3 possible values for Master_info::slave_running and + Relay_log_info::slave_running. The values 0,1,2 are very important: to keep the diff small, I didn't substitute places where we use 0/1 with the newly defined symbols. So don't change these values. - The same way, code is assuming that in RELAY_LOG_INFO we use only values + The same way, code is assuming that in Relay_log_info we use only values 0/1. I started with using an enum, but enum_variable=1; is not legal so would have required many line changes. @@ -135,16 +134,16 @@ extern ulonglong relay_log_space_limit; int init_slave(); void init_slave_skip_errors(const char* arg); -bool flush_relay_log_info(RELAY_LOG_INFO* rli); +bool flush_relay_log_info(Relay_log_info* rli); int register_slave_on_master(MYSQL* mysql); -int terminate_slave_threads(MASTER_INFO* mi, int thread_mask, +int terminate_slave_threads(Master_info* mi, int thread_mask, bool skip_lock = 0); int terminate_slave_thread(THD* thd, pthread_mutex_t* term_mutex, pthread_mutex_t* cond_lock, pthread_cond_t* term_cond, volatile uint* slave_running); int start_slave_threads(bool need_slave_mutex, bool wait_for_start, - MASTER_INFO* mi, const char* master_info_fname, + Master_info* mi, const char* master_info_fname, const char* slave_info_fname, int thread_mask); /* cond_lock is usually same as start_lock. It is needed for the case when @@ -157,7 +156,7 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t* start_lock, pthread_cond_t* start_cond, volatile uint *slave_running, volatile ulong *slave_run_id, - MASTER_INFO* mi, + Master_info* mi, bool high_priority); /* If fd is -1, dump to NET */ @@ -166,37 +165,37 @@ int mysql_table_dump(THD* thd, const char* db, /* retrieve table from master and copy to slave*/ int fetch_master_table(THD* thd, const char* db_name, const char* table_name, - MASTER_INFO* mi, MYSQL* mysql, bool overwrite); + Master_info* mi, MYSQL* mysql, bool overwrite); -bool show_master_info(THD* thd, MASTER_INFO* mi); +bool show_master_info(THD* thd, Master_info* mi); bool show_binlog_info(THD* thd); -bool rpl_master_has_bug(RELAY_LOG_INFO *rli, uint bug_id); +bool rpl_master_has_bug(Relay_log_info *rli, uint bug_id); const char *print_slave_db_safe(const char *db); -int check_expected_error(THD* thd, RELAY_LOG_INFO const *rli, int error_code); +int check_expected_error(THD* thd, Relay_log_info const *rli, int error_code); void skip_load_data_infile(NET* net); void end_slave(); /* clean up */ -void clear_until_condition(RELAY_LOG_INFO* rli); -void clear_slave_error(RELAY_LOG_INFO* rli); -void end_relay_log_info(RELAY_LOG_INFO* rli); -void lock_slave_threads(MASTER_INFO* mi); -void unlock_slave_threads(MASTER_INFO* mi); -void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse); -int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos, +void clear_until_condition(Relay_log_info* rli); +void clear_slave_error(Relay_log_info* rli); +void end_relay_log_info(Relay_log_info* rli); +void lock_slave_threads(Master_info* mi); +void unlock_slave_threads(Master_info* mi); +void init_thread_mask(int* mask,Master_info* mi,bool inverse); +int init_relay_log_pos(Relay_log_info* rli,const char* log,ulonglong pos, bool need_data_lock, const char** errmsg, bool look_for_description_event); -int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset, +int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, const char** errmsg); void set_slave_thread_options(THD* thd); -void set_slave_thread_default_charset(THD *thd, RELAY_LOG_INFO const *rli); -void rotate_relay_log(MASTER_INFO* mi); +void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli); +void rotate_relay_log(Master_info* mi); pthread_handler_t handle_slave_io(void *arg); pthread_handler_t handle_slave_sql(void *arg); extern bool volatile abort_loop; -extern MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */ +extern Master_info main_mi, *active_mi; /* active_mi for multi-master */ extern LIST master_list; extern my_bool replicate_same_server_id; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e15bc1c3137..83bab51f870 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1221,13 +1221,6 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables)); - /* - End open index scans and table scans and remove references to the tables - from the handler tables hash. After this preparation it is safe to close - the tables. - */ - mysql_ha_mark_tables_for_reopen(thd, thd->open_tables); - found_old_table= 0; while (thd->open_tables) found_old_table|= close_thread_table(thd, &thd->open_tables); @@ -2255,7 +2248,6 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, HASH_SEARCH_STATE state; DBUG_ENTER("open_table"); - DBUG_ASSERT (table_list->lock_type != TL_WRITE_DEFAULT); /* find a unused table in the open table cache */ if (refresh) *refresh=0; @@ -3559,11 +3551,6 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) { safe_to_ignore_table= FALSE; - if (tables->lock_type == TL_WRITE_DEFAULT) - { - tables->lock_type= thd->update_lock_default; - DBUG_ASSERT (tables->lock_type >= TL_WRITE_ALLOW_WRITE); - } /* Ignore placeholders for derived tables. After derived tables processing, link to created temporary table will be put here. @@ -3708,7 +3695,8 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) } if (tables->lock_type != TL_UNLOCK && ! thd->locked_tables) - tables->table->reginfo.lock_type=tables->lock_type; + tables->table->reginfo.lock_type= tables->lock_type == TL_WRITE_DEFAULT ? + thd->update_lock_default : tables->lock_type; tables->table->grant= tables->grant; process_view_routines: diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index 87224b8eea0..a3a804db8f0 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -52,7 +52,7 @@ void mysql_client_binlog_statement(THD* thd) Allocation */ if (!thd->rli_fake) - thd->rli_fake= new RELAY_LOG_INFO; + thd->rli_fake= new Relay_log_info; const Format_description_log_event *desc= new Format_description_log_event(4); diff --git a/sql/sql_class.h b/sql/sql_class.h index ef4869fa244..55987ae8ad9 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -23,8 +23,7 @@ #include "log.h" #include "rpl_tblmap.h" -struct st_relay_log_info; -typedef st_relay_log_info RELAY_LOG_INFO; +class Relay_log_info; class Query_log_event; class Load_log_event; @@ -424,6 +423,8 @@ typedef struct system_status_var #define last_system_status_var com_stmt_close +void mark_transaction_to_rollback(THD *thd, bool all); + #ifdef MYSQL_SERVER void free_tmp_table(THD *thd, TABLE *entry); @@ -968,7 +969,7 @@ class THD :public Statement, { public: /* Used to execute base64 coded binlog events in MySQL server */ - RELAY_LOG_INFO* rli_fake; + Relay_log_info* rli_fake; /* Constant for THD::where initialization in the beginning of every query. @@ -2482,6 +2483,7 @@ public: /* Functions in sql_class.cc */ void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var); + void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, STATUS_VAR *dec_var); void mark_transaction_to_rollback(THD *thd, bool all); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index eaa0da06630..bd3a53c5f1e 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -772,48 +772,3 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags) DBUG_RETURN(0); } - - -/* - Mark tables for reopen. - - SYNOPSIS - mysql_ha_mark_tables_for_reopen() - thd Thread identifier. - table Table list to mark for reopen. - - DESCRIPTION - For each table found in the handler hash mark it as closed - (ready for reopen) and end all index/table scans. - - NOTE - The caller must lock LOCK_open. -*/ - -void mysql_ha_mark_tables_for_reopen(THD *thd, TABLE *table) -{ - DBUG_ENTER("mysql_ha_mark_tables_for_reopen"); - - safe_mutex_assert_owner(&LOCK_open); - for (; table; table= table->next) - { - /* - Some elements in open table list, for example placeholders used for - name-locking, can have alias set to 0. - */ - if (table->alias) - { - TABLE_LIST *hash_tables; - if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, - (uchar*) table->alias, - strlen(table->alias) + 1))) - { - /* Mark table as ready for reopen. */ - hash_tables->table= NULL; - /* End open index/table scans. */ - table->file->ha_index_or_rnd_end(); - } - } - } - DBUG_VOID_RETURN; -} diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3e6218c5aa8..2e4ce65f1c4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5256,6 +5256,11 @@ mysql_new_select(LEX *lex, bool move_down) select_lex->init_query(); select_lex->init_select(); lex->nest_level++; + if (lex->nest_level > (int) MAX_SELECT_NESTING) + { + my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT,MYF(0),MAX_SELECT_NESTING); + DBUG_RETURN(1); + } select_lex->nest_level= lex->nest_level; /* Don't evaluate this subquery during statement prepare even if diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 5d9d30b6020..a6e52c05219 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -762,7 +762,7 @@ err: DBUG_VOID_RETURN; } -int start_slave(THD* thd , MASTER_INFO* mi, bool net_report) +int start_slave(THD* thd , Master_info* mi, bool net_report) { int slave_errno= 0; int thread_mask; @@ -799,7 +799,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report) if (thd->lex->mi.pos) { - mi->rli.until_condition= RELAY_LOG_INFO::UNTIL_MASTER_POS; + mi->rli.until_condition= Relay_log_info::UNTIL_MASTER_POS; mi->rli.until_log_pos= thd->lex->mi.pos; /* We don't check thd->lex->mi.log_file_name for NULL here @@ -810,7 +810,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report) } else if (thd->lex->mi.relay_log_pos) { - mi->rli.until_condition= RELAY_LOG_INFO::UNTIL_RELAY_POS; + mi->rli.until_condition= Relay_log_info::UNTIL_RELAY_POS; mi->rli.until_log_pos= thd->lex->mi.relay_log_pos; strmake(mi->rli.until_log_name, thd->lex->mi.relay_log_name, sizeof(mi->rli.until_log_name)-1); @@ -818,7 +818,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report) else mi->rli.clear_until_condition(); - if (mi->rli.until_condition != RELAY_LOG_INFO::UNTIL_NONE) + if (mi->rli.until_condition != Relay_log_info::UNTIL_NONE) { /* Preparing members for effective until condition checking */ const char *p= fn_ext(mi->rli.until_log_name); @@ -840,7 +840,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report) /* mark the cached result of the UNTIL comparison as "undefined" */ mi->rli.until_log_names_cmp_result= - RELAY_LOG_INFO::UNTIL_LOG_NAMES_CMP_UNKNOWN; + Relay_log_info::UNTIL_LOG_NAMES_CMP_UNKNOWN; /* Issuing warning then started without --skip-slave-start */ if (!opt_skip_slave_start) @@ -887,7 +887,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report) } -int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report ) +int stop_slave(THD* thd, Master_info* mi, bool net_report ) { DBUG_ENTER("stop_slave"); @@ -953,7 +953,7 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report ) */ -int reset_slave(THD *thd, MASTER_INFO* mi) +int reset_slave(THD *thd, Master_info* mi) { MY_STAT stat_area; char fname[FN_REFLEN]; @@ -1067,7 +1067,7 @@ void kill_zombie_dump_threads(uint32 slave_server_id) } -bool change_master(THD* thd, MASTER_INFO* mi) +bool change_master(THD* thd, Master_info* mi) { int thread_mask; const char* errmsg= 0; diff --git a/sql/sql_repl.h b/sql/sql_repl.h index da50d47c60d..cf5201f17b1 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -42,20 +42,20 @@ extern my_bool opt_sporadic_binlog_dump_fail; pthread_mutex_unlock(&(thd)->LOCK_delete); \ } while(0) -int start_slave(THD* thd, MASTER_INFO* mi, bool net_report); -int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report); -bool change_master(THD* thd, MASTER_INFO* mi); +int start_slave(THD* thd, Master_info* mi, bool net_report); +int stop_slave(THD* thd, Master_info* mi, bool net_report); +bool change_master(THD* thd, Master_info* mi); bool mysql_show_binlog_events(THD* thd); int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1, const char* log_file_name2, ulonglong log_pos2); -int reset_slave(THD *thd, MASTER_INFO* mi); +int reset_slave(THD *thd, Master_info* mi); int reset_master(THD* thd); bool purge_master_logs(THD* thd, const char* to_log); bool purge_master_logs_before_date(THD* thd, time_t purge_time); bool log_in_use(const char* log_name); void adjust_linfo_offsets(my_off_t purge_offset); bool show_binlogs(THD* thd); -extern int init_master_info(MASTER_INFO* mi); +extern int init_master_info(Master_info* mi); void kill_zombie_dump_threads(uint32 slave_server_id); int check_binlog_magic(IO_CACHE* log, const char** errmsg); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 14e5beada8b..5de81898723 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6452,6 +6452,7 @@ void JOIN_TAB::cleanup() quick= 0; x_free(cache.buff); cache.buff= 0; + limit= 0; if (table) { if (table->key_read) @@ -12590,9 +12591,12 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, { int ref_key; uint ref_key_parts; + int order_direction; + uint used_key_parts; TABLE *table=tab->table; SQL_SELECT *select=tab->select; key_map usable_keys; + QUICK_SELECT_I *save_quick= 0; DBUG_ENTER("test_if_skip_sort_order"); LINT_INIT(ref_key_parts); @@ -12627,6 +12631,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, else if (select && select->quick) // Range found by opt_range { int quick_type= select->quick->get_type(); + save_quick= select->quick; /* assume results are not ordered when index merge is used TODO: sergeyp: Results of all index merge selects actually are ordered @@ -12646,8 +12651,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, /* We come here when there is a REF key. */ - int order_direction; - uint used_key_parts; if (!usable_keys.is_set(ref_key)) { /* @@ -12708,63 +12711,33 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, } /* Check if we get the rows in requested sorted order by using the key */ if (usable_keys.is_set(ref_key) && - (order_direction = test_if_order_by_key(order,table,ref_key, - &used_key_parts))) - { - if (order_direction == -1) // If ORDER BY ... DESC - { - if (select && select->quick) - { - /* - Don't reverse the sort order, if it's already done. - (In some cases test_if_order_by_key() can be called multiple times - */ - if (!select->quick->reverse_sorted()) - { - QUICK_SELECT_DESC *tmp; - int quick_type= select->quick->get_type(); - if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE || - quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT || - quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION || - quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX) - DBUG_RETURN(0); // Use filesort - - /* ORDER BY range_key DESC */ - tmp= new QUICK_SELECT_DESC((QUICK_RANGE_SELECT*)(select->quick), - used_key_parts); - if (!tmp || tmp->error) - { - delete tmp; - DBUG_RETURN(0); // Reverse sort not supported - } - select->quick=tmp; - } - DBUG_RETURN(1); - } - if (tab->ref.key_parts < used_key_parts) - { - /* - SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC - - Use a traversal function that starts by reading the last row - with key part (A) and then traverse the index backwards. - */ - tab->read_first_record= join_read_last_key; - tab->read_record.read_record= join_read_prev_same; - /* fall through */ - } - } - else if (select && select->quick) - select->quick->sorted= 1; - DBUG_RETURN(1); /* No need to sort */ - } + (order_direction= test_if_order_by_key(order,table,ref_key, + &used_key_parts))) + goto check_reverse_order; } - else { - /* check if we can use a key to resolve the group */ - /* Tables using JT_NEXT are handled here */ + /* + Check whether there is an index compatible with the given order + usage of which is cheaper than usage of the ref_key index (ref_key>=0) + or a table scan. + It may be the case if ORDER/GROUP BY is used with LIMIT. + */ uint nr; key_map keys; + uint best_key_parts; + int best_key_direction; + ha_rows best_records; + double read_time; + int best_key= -1; + bool is_best_covering= FALSE; + double fanout= 1; + JOIN *join= tab->join; + uint tablenr= tab - join->join_tab; + ha_rows table_records= table->file->stats.records; + bool group= join->group && order == join->group_list; + LINT_INIT(best_key_parts); + LINT_INIT(best_key_direction); + LINT_INIT(best_records); /* filesort() and join cache are usually faster than reading in @@ -12777,7 +12750,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, resolved with a key; This is because filesort() is usually faster than retrieving all rows through an index. */ - if (select_limit >= table->file->stats.records) + if (select_limit >= table_records) { keys= *table->file->keys_to_use_for_scanning(); keys.merge(table->covering_keys); @@ -12788,38 +12761,227 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, This is to allow users to use index in ORDER BY. */ if (table->force_index) - keys.merge(table->keys_in_use_for_query); + keys.merge(group ? table->keys_in_use_for_group_by : + table->keys_in_use_for_order_by); keys.intersect(usable_keys); } else keys= usable_keys; + read_time= join->best_positions[tablenr].read_time; + for (uint i= tablenr+1; i < join->tables; i++) + fanout*= join->best_positions[i].records_read; // fanout is always >= 1 + for (nr=0; nr < table->s->keys ; nr++) { - uint not_used; - if (keys.is_set(nr)) + int direction; + if (keys.is_set(nr) && + (direction= test_if_order_by_key(order, table, nr, &used_key_parts))) { - int flag; - if ((flag= test_if_order_by_key(order, table, nr, ¬_used))) + bool is_covering= table->covering_keys.is_set(nr) || + nr == table->s->primary_key && + table->file->primary_key_is_clustered(); + + /* + Don't use an index scan with ORDER BY without limit. + For GROUP BY without limit always use index scan + if there is a suitable index. + Why we hold to this asymmetry hardly can be explained + rationally. It's easy to demonstrate that using + temporary table + filesort could be cheaper for grouping + queries too. + */ + if (is_covering || + select_limit != HA_POS_ERROR || + ref_key < 0 && (group || table->force_index)) + { + double rec_per_key; + double index_scan_time; + KEY *keyinfo= tab->table->key_info+nr; + if (select_limit == HA_POS_ERROR) + select_limit= table_records; + if (group) + { + rec_per_key= keyinfo->rec_per_key[used_key_parts-1]; + set_if_bigger(rec_per_key, 1); + /* + With a grouping query each group containing on average + rec_per_key records produces only one row that will + be included into the result set. + */ + if (select_limit > table_records/rec_per_key) + select_limit= table_records; + else + select_limit= (ha_rows) (select_limit*rec_per_key); + } + /* + If tab=tk is not the last joined table tn then to get first + L records from the result set we can expect to retrieve + only L/fanout(tk,tn) where fanout(tk,tn) says how many + rows in the record set on average will match each row tk. + Usually our estimates for fanouts are too pessimistic. + So the estimate for L/fanout(tk,tn) will be too optimistic + and as result we'll choose an index scan when using ref/range + access + filesort will be cheaper. + */ + select_limit= (ha_rows) (select_limit < fanout ? + 1 : select_limit/fanout); + /* + We assume that each of the tested indexes is not correlated + with ref_key. Thus, to select first N records we have to scan + N/selectivity(ref_key) index entries. + selectivity(ref_key) = #scanned_records/#table_records = + table->quick_condition_rows/table_records. + In any case we can't select more than #table_records. + N/(table->quick_condition_rows/table_records) > table_records + <=> N > table->quick_condition_rows. + */ + if (select_limit > table->quick_condition_rows) + select_limit= table_records; + else + select_limit= (ha_rows) (select_limit * + (double) table_records / + table->quick_condition_rows); + rec_per_key= keyinfo->rec_per_key[keyinfo->key_parts-1]; + set_if_bigger(rec_per_key, 1); + /* + Here we take into account the fact that rows are + accessed in sequences rec_per_key records in each. + Rows in such a sequence are supposed to be ordered + by rowid/primary key. When reading the data + in a sequence we'll touch not more pages than the + table file contains. + TODO. Use the formula for a disk sweep sequential access + to calculate the cost of accessing data rows for one + index entry. + */ + index_scan_time= select_limit/rec_per_key * + min(rec_per_key, table->file->scan_time()); + if (is_covering || + ref_key < 0 && (group || table->force_index) || + index_scan_time < read_time) + { + ha_rows quick_records= table_records; + if (is_best_covering && !is_covering) + continue; + if (table->quick_keys.is_set(nr)) + quick_records= table->quick_rows[nr]; + if (best_key < 0 || + (select_limit <= min(quick_records,best_records) ? + keyinfo->key_parts < best_key_parts : + quick_records < best_records)) + { + best_key= nr; + best_key_parts= keyinfo->key_parts; + best_records= quick_records; + is_best_covering= is_covering; + best_key_direction= direction; + } + } + } + } + } + if (best_key >= 0) + { + bool quick_created= FALSE; + if (table->quick_keys.is_set(best_key) && best_key != ref_key) + { + key_map map; + map.clear_all(); // Force the creation of quick select + map.set_bit(best_key); // only best_key. + quick_created= + select->test_quick_select(join->thd, map, 0, + join->select_options & OPTION_FOUND_ROWS ? + HA_POS_ERROR : + join->unit->select_limit_cnt, + 0) > 0; + } + if (!no_changes) + { + if (!quick_created) { - if (!no_changes) - { - tab->index=nr; - tab->read_first_record= (flag > 0 ? join_read_first: - join_read_last); - tab->type=JT_NEXT; // Read with index_first(), index_next() - if (table->covering_keys.is_set(nr)) - { - table->key_read=1; - table->file->extra(HA_EXTRA_KEYREAD); - } - } - DBUG_RETURN(1); + tab->index= best_key; + tab->read_first_record= best_key_direction > 0 ? + join_read_first:join_read_last; + tab->type=JT_NEXT; // Read with index_first(), index_next() + if (table->covering_keys.is_set(best_key)) + { + table->key_read=1; + table->file->extra(HA_EXTRA_KEYREAD); + } + table->file->ha_index_or_rnd_end(); + if (join->select_options & SELECT_DESCRIBE) + { + tab->ref.key= -1; + tab->ref.key_parts= 0; + if (select && select->quick) + { + delete select->quick; + select->quick= 0; + } + if (select_limit < table_records) + tab->limit= select_limit; + } + } + } + used_key_parts= best_key_parts; + order_direction= best_key_direction; + } + else + DBUG_RETURN(0); + } + +check_reverse_order: + if (order_direction == -1) // If ORDER BY ... DESC + { + if (select && select->quick) + { + /* + Don't reverse the sort order, if it's already done. + (In some cases test_if_order_by_key() can be called multiple times + */ + if (!select->quick->reverse_sorted()) + { + QUICK_SELECT_DESC *tmp; + int quick_type= select->quick->get_type(); + if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE || + quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT || + quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION || + quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX) + { + tab->limit= 0; + select->quick= save_quick; + DBUG_RETURN(0); // Use filesort + } + + /* ORDER BY range_key DESC */ + tmp= new QUICK_SELECT_DESC((QUICK_RANGE_SELECT*)(select->quick), + used_key_parts); + if (!tmp || tmp->error) + { + delete tmp; + select->quick= save_quick; + tab->limit= 0; + DBUG_RETURN(0); // Reverse sort not supported } + select->quick=tmp; } } + else if (tab->ref.key >= 0 && tab->ref.key_parts < used_key_parts) + { + /* + SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC + + Use a traversal function that starts by reading the last row + with key part (A) and then traverse the index backwards. + */ + tab->read_first_record= join_read_last_key; + tab->read_record.read_record= join_read_prev_same; + } } - DBUG_RETURN(0); // Can't use index. + else if (select && select->quick) + select->quick->sorted= 1; + DBUG_RETURN(1); } @@ -15558,7 +15720,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, if (tab->select && tab->select->quick) examined_rows= tab->select->quick->records; else if (tab->type == JT_NEXT || tab->type == JT_ALL) - examined_rows= tab->table->file->records(); + examined_rows= tab->limit ? tab->limit : tab->table->file->records(); else examined_rows=(ha_rows)join->best_positions[i].records_read; diff --git a/sql/sql_select.h b/sql/sql_select.h index d1acad1c5d6..efa92432e2b 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -194,6 +194,12 @@ typedef struct st_join_table { enum join_type type; bool cached_eq_ref_table,eq_ref_table,not_used_in_distinct; bool sorted; + /* + If it's not 0 the number stored this field indicates that the index + scan has been chosen to access the table data and we expect to scan + this number of rows for the table. + */ + ha_rows limit; TABLE_REF ref; JOIN_CACHE cache; JOIN *join; diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 53b2499846c..6c7dea6bf22 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -253,8 +253,6 @@ bool String::needs_conversion(uint32 arg_length, (to_cs == &my_charset_bin) || (to_cs == from_cs) || my_charset_same(from_cs, to_cs) || - (my_charset_is_ascii_based(to_cs) && - my_charset_is_8bit_pure_ascii(from_cs)) || ((from_cs == &my_charset_bin) && (!(*offset=(arg_length % to_cs->mbminlen))))) return FALSE; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index eb81e7647eb..17544b8ccde 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -157,6 +157,7 @@ uint tablename_to_filename(const char *from, char *to, uint to_length) SYNOPSIS build_table_filename() buff Where to write result in my_charset_filename. + This may be the same as table_name. bufflen buff size db Database name in system_charset_info. table_name Table name in system_charset_info. @@ -186,10 +187,11 @@ uint tablename_to_filename(const char *from, char *to, uint to_length) uint build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, const char *ext, uint flags) { - uint length; char dbbuff[FN_REFLEN]; char tbbuff[FN_REFLEN]; DBUG_ENTER("build_table_filename"); + DBUG_PRINT("enter", ("db: '%s' table_name: '%s' ext: '%s' flags: %x", + db, table_name, ext, flags)); if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP strnmov(tbbuff, table_name, sizeof(tbbuff)); @@ -197,10 +199,18 @@ uint build_table_filename(char *buff, size_t bufflen, const char *db, VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff))); VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff))); - length= strxnmov(buff, bufflen, mysql_data_home, FN_ROOTDIR, dbbuff, - FN_ROOTDIR, tbbuff, ext, NullS) - buff; + + char *end = buff + bufflen; + /* Don't add FN_ROOTDIR if mysql_data_home already includes it */ + char *pos = strnmov(buff, mysql_data_home, bufflen); + int rootdir_len= strlen(FN_ROOTDIR); + if (pos - rootdir_len >= buff && + memcmp(pos - rootdir_len, FN_ROOTDIR, rootdir_len) != 0) + pos= strnmov(pos, FN_ROOTDIR, end - pos); + pos= strxnmov(pos, end - pos, dbbuff, FN_ROOTDIR, tbbuff, ext, NullS); + DBUG_PRINT("exit", ("buff: '%s'", buff)); - DBUG_RETURN(length); + DBUG_RETURN(pos - buff); } diff --git a/sql/time.cc b/sql/time.cc index c552d085f5e..a6619cf4cee 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -263,11 +263,11 @@ my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, my_bool *in_dst_time_ my_time_t timestamp; *in_dst_time_gap= 0; + thd->time_zone_used= 1; timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap); if (timestamp) { - thd->time_zone_used= 1; return timestamp; } diff --git a/sql/udf_example.c b/sql/udf_example.c index b603464568e..6c07a929b04 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1106,4 +1106,39 @@ char * is_const(UDF_INIT *initid, UDF_ARGS *args __attribute__((unused)), } +my_bool check_const_len_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + if (args->arg_count != 1) + { + strmov(message, "IS_CONST accepts only one argument"); + return 1; + } + if (args->args[0] == 0) + { + initid->ptr= (char*)"Not constant"; + } + else if(strlen(args->args[0]) == args->lengths[0]) + { + initid->ptr= (char*)"Correct length"; + } + else + { + initid->ptr= (char*)"Wrong length"; + } + initid->max_length = 100; + return 0; +} + +char * check_const_len(UDF_INIT *initid, UDF_ARGS *args __attribute__((unused)), + char *result, unsigned long *length, + char *is_null, char *error __attribute__((unused))) +{ + strmov(result, initid->ptr); + *length= strlen(result); + *is_null= 0; + return result; +} + + + #endif /* HAVE_DLOPEN */ diff --git a/sql/udf_example.def b/sql/udf_example.def index 7a87147d7b6..3d569941cc8 100644 --- a/sql/udf_example.def +++ b/sql/udf_example.def @@ -23,3 +23,5 @@ EXPORTS avgcost is_const is_const_init + check_const_len + check_const_len_init diff --git a/sql/unireg.h b/sql/unireg.h index 232ea5e70e7..b368eee6f0e 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -85,6 +85,8 @@ #define MAX_FIELDS 4096 /* Limit in the .frm file */ #define MAX_PARTITIONS 1024 +#define MAX_SELECT_NESTING (sizeof(nesting_map)*8-1) + #define MAX_SORT_MEMORY (2048*1024-MALLOC_OVERHEAD) #define MIN_SORT_MEMORY (32*1024-MALLOC_OVERHEAD) |