diff options
author | Igor Babaev <igor@askmonty.org> | 2012-03-17 01:26:58 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2012-03-17 01:26:58 -0700 |
commit | 5d954e7cd0f9f4106d848a7d7fc8fbce35668785 (patch) | |
tree | bd812fb49b473d759c5054fe89d12e4dc1e50a59 /sql | |
parent | d110e0377dda1bb9f5a5c36745d3a6feb8e8a1d4 (diff) | |
parent | 5338a28912589f1169b66b880a489ec5636bcd83 (diff) | |
download | mariadb-git-5d954e7cd0f9f4106d848a7d7fc8fbce35668785.tar.gz |
Merge 5.3->5.5
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 74 | ||||
-rw-r--r-- | sql/field.h | 104 | ||||
-rw-r--r-- | sql/filesort.cc | 7 | ||||
-rw-r--r-- | sql/item_subselect.cc | 3 | ||||
-rw-r--r-- | sql/log_event.h | 3 | ||||
-rw-r--r-- | sql/log_event_old.cc | 12 | ||||
-rw-r--r-- | sql/log_event_old.h | 3 | ||||
-rw-r--r-- | sql/opt_sum.cc | 10 | ||||
-rw-r--r-- | sql/records.cc | 6 | ||||
-rw-r--r-- | sql/rpl_record.cc | 18 | ||||
-rw-r--r-- | sql/rpl_record.h | 3 | ||||
-rw-r--r-- | sql/rpl_record_old.cc | 17 | ||||
-rw-r--r-- | sql/rpl_record_old.h | 3 | ||||
-rw-r--r-- | sql/signal_handler.cc | 2 | ||||
-rw-r--r-- | sql/sql_base.cc | 11 | ||||
-rw-r--r-- | sql/sql_derived.cc | 1 | ||||
-rw-r--r-- | sql/sql_select.cc | 19 | ||||
-rw-r--r-- | sql/table.cc | 4 | ||||
-rw-r--r-- | sql/table.h | 2 | ||||
-rw-r--r-- | sql/winservice.c | 39 |
20 files changed, 239 insertions, 102 deletions
diff --git a/sql/field.cc b/sql/field.cc index f0f0ca2c8f4..f5b43c69f63 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1496,11 +1496,13 @@ Field::pack(uchar *to, const uchar *from, uint max_length) data @return New pointer into memory based on from + length of the data + @return 0 if wrong data */ const uchar * -Field::unpack(uchar* to, const uchar *from, uint param_data) +Field::unpack(uchar* to, const uchar *from, const uchar *from_end, + uint param_data) { - uint length=pack_length(); + uint length=pack_length(), len; int from_type= 0; /* If from length is > 255, it has encoded data in the upper bits. Need @@ -1516,14 +1518,19 @@ Field::unpack(uchar* to, const uchar *from, uint param_data) (length == param_data) || (from_type != real_type())) { + if (from + length > from_end) + return 0; // Error in data + memcpy(to, from, length); return from+length; } - uint len= (param_data && (param_data < length)) ? - param_data : length; + len= (param_data && (param_data < length)) ? param_data : length; + + if (from + len > from_end) + return 0; // Error in data - memcpy(to, from, param_data > length ? length : len); + memcpy(to, from, len); return from+len; } @@ -2907,10 +2914,11 @@ uint Field_new_decimal::is_equal(Create_field *new_field) @return New pointer into memory based on from + length of the data */ const uchar * -Field_new_decimal::unpack(uchar* to, const uchar *from, uint param_data) +Field_new_decimal::unpack(uchar* to, const uchar *from, const uchar *from_end, + uint param_data) { if (param_data == 0) - return Field::unpack(to, from, param_data); + return Field::unpack(to, from, from_end, param_data); uint from_precision= (param_data & 0xff00) >> 8U; uint from_decimal= param_data & 0x00ff; @@ -2940,7 +2948,11 @@ Field_new_decimal::unpack(uchar* to, const uchar *from, uint param_data) decimal2bin(&dec_val, to, precision, decimals()); } else + { + if (from + len > from_end) + return 0; // Wrong data memcpy(to, from, len); // Sizes are the same, just copy the data. + } return from+len; } @@ -6369,7 +6381,8 @@ uchar *Field_string::pack(uchar *to, const uchar *from, uint max_length) @return New pointer into memory based on from + length of the data */ const uchar * -Field_string::unpack(uchar *to, const uchar *from, uint param_data) +Field_string::unpack(uchar *to, const uchar *from, const uchar *from_end, + uint param_data) { uint from_length, length; @@ -6391,11 +6404,19 @@ Field_string::unpack(uchar *to, const uchar *from, uint param_data) */ if (from_length > 255) { + if (from + 2 > from_end) + return 0; length= uint2korr(from); from+= 2; } else + { + if (from + 1 > from_end) + return 0; length= (uint) *from++; + } + if (from + length > from_end || length > field_length) + return 0; memcpy(to, from, length); // Pad the string with the pad character of the fields charset @@ -6818,11 +6839,16 @@ uchar *Field_varstring::pack(uchar *to, const uchar *from, uint max_length) @return New pointer into memory based on from + length of the data */ const uchar * -Field_varstring::unpack(uchar *to, const uchar *from, uint param_data) +Field_varstring::unpack(uchar *to, const uchar *from, const uchar *from_end, + uint param_data) { uint length; uint l_bytes= (param_data && (param_data < field_length)) ? (param_data <= 255) ? 1 : 2 : length_bytes; + + if (from + l_bytes > from_end) + return 0; // Error in data + if (l_bytes == 1) { to[0]= *from++; @@ -6837,7 +6863,11 @@ Field_varstring::unpack(uchar *to, const uchar *from, uint param_data) to[1]= *from++; } if (length) + { + if (from + length > from_end || length > field_length) + return 0; // Error in data memcpy(to+ length_bytes, from, length); + } return from+length; } @@ -7414,16 +7444,21 @@ uchar *Field_blob::pack(uchar *to, const uchar *from, uint max_length) @return New pointer into memory based on from + length of the data */ -const uchar *Field_blob::unpack(uchar *to, const uchar *from, uint param_data) +const uchar *Field_blob::unpack(uchar *to, const uchar *from, + const uchar *from_end, uint param_data) { DBUG_ENTER("Field_blob::unpack"); DBUG_PRINT("enter", ("to: 0x%lx; from: 0x%lx; param_data: %u", (ulong) to, (ulong) from, param_data)); uint const master_packlength= param_data > 0 ? param_data & 0xFF : packlength; + if (from + master_packlength > from_end) + DBUG_RETURN(0); // Error in data uint32 const length= get_length(from, master_packlength); DBUG_DUMP("packed", from, length + master_packlength); bitmap_set_bit(table->write_set, field_index); + if (from + master_packlength + length > from_end) + DBUG_RETURN(0); store(reinterpret_cast<const char*>(from) + master_packlength, length, field_charset); DBUG_DUMP("record", to, table->s->reclength); @@ -7971,12 +8006,13 @@ uchar *Field_enum::pack(uchar *to, const uchar *from, uint max_length) DBUG_RETURN(pack_int(to, from, packlength)); } -const uchar *Field_enum::unpack(uchar *to, const uchar *from, uint param_data) +const uchar *Field_enum::unpack(uchar *to, const uchar *from, + const uchar *from_end, uint param_data) { DBUG_ENTER("Field_enum::unpack"); DBUG_PRINT("debug", ("packlength: %d", packlength)); DBUG_DUMP("from", from, packlength); - DBUG_RETURN(unpack_int(to, from, packlength)); + DBUG_RETURN(unpack_int(to, from, from_end, packlength)); } @@ -8472,7 +8508,8 @@ Field_bit::pack(uchar *to, const uchar *from, uint max_length) @return New pointer into memory based on from + length of the data */ const uchar * -Field_bit::unpack(uchar *to, const uchar *from, uint param_data) +Field_bit::unpack(uchar *to, const uchar *from, const uchar *from_end, + uint param_data) { DBUG_ENTER("Field_bit::unpack"); DBUG_PRINT("enter", ("to: %p, from: %p, param_data: 0x%x", @@ -8490,6 +8527,9 @@ Field_bit::unpack(uchar *to, const uchar *from, uint param_data) if (param_data == 0 || ((from_bit_len == bit_len) && (from_len == bytes_in_rec))) { + if (from + bytes_in_rec + test(bit_len) > from_end) + return 0; // Error in data + if (bit_len > 0) { /* @@ -8514,10 +8554,16 @@ Field_bit::unpack(uchar *to, const uchar *from, uint param_data) Lastly the odd bits need to be masked out if the bytes_in_rec > 0. Otherwise stray bits can cause spurious values. */ + + uint len= from_len + ((from_bit_len > 0) ? 1 : 0); uint new_len= (field_length + 7) / 8; + + if (from + len > from_end || new_len < len) + return 0; // Error in data + char *value= (char *)my_alloca(new_len); bzero(value, new_len); - uint len= from_len + ((from_bit_len > 0) ? 1 : 0); + memcpy(value + (new_len - len), from, len); /* Mask out the unused bits in the partial byte. diff --git a/sql/field.h b/sql/field.h index fee141d30b0..0b32aab0337 100644 --- a/sql/field.h +++ b/sql/field.h @@ -504,16 +504,8 @@ public: DBUG_RETURN(result); } - virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data); - /** - @overload Field::unpack(uchar*, const uchar*, uint, bool) - */ - const uchar *unpack(uchar* to, const uchar *from) - { - DBUG_ENTER("Field::unpack"); - const uchar *result= unpack(to, from, 0); - DBUG_RETURN(result); - } + virtual const uchar *unpack(uchar* to, const uchar *from, + const uchar *from_end, uint param_data=0); virtual uint packed_col_length(const uchar *to, uint length) { return length;} @@ -644,28 +636,31 @@ protected: return to + size; } - const uchar *unpack_int(uchar* to, const uchar *from, size_t size) + const uchar *unpack_int(uchar* to, const uchar *from, + const uchar *from_end, size_t size) { + if (from + size > from_end) + return 0; memcpy(to, from, size); return from + size; } uchar *pack_int16(uchar *to, const uchar *from) { return pack_int(to, from, 2); } - const uchar *unpack_int16(uchar* to, const uchar *from) - { return unpack_int(to, from, 2); } + const uchar *unpack_int16(uchar* to, const uchar *from, const uchar *from_end) + { return unpack_int(to, from, from_end, 2); } uchar *pack_int24(uchar *to, const uchar *from) { return pack_int(to, from, 3); } - const uchar *unpack_int24(uchar* to, const uchar *from) - { return unpack_int(to, from, 3); } + const uchar *unpack_int24(uchar* to, const uchar *from, const uchar *from_end) + { return unpack_int(to, from, from_end, 3); } uchar *pack_int32(uchar *to, const uchar *from) { return pack_int(to, from, 4); } - const uchar *unpack_int32(uchar* to, const uchar *from) - { return unpack_int(to, from, 4); } + const uchar *unpack_int32(uchar* to, const uchar *from, const uchar *from_end) + { return unpack_int(to, from, from_end, 4); } uchar *pack_int64(uchar* to, const uchar *from) { return pack_int(to, from, 8); } - const uchar *unpack_int64(uchar* to, const uchar *from) - { return unpack_int(to, from, 8); } + const uchar *unpack_int64(uchar* to, const uchar *from, const uchar *from_end) + { return unpack_int(to, from, from_end, 8); } bool field_flags_are_binary() { @@ -824,10 +819,6 @@ public: void overflow(bool negative); bool zero_pack() const { return 0; } void sql_type(String &str) const; - virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data) - { - return Field::unpack(to, from, param_data); - } virtual uchar *pack(uchar* to, const uchar *from, uint max_length) { return Field::pack(to, from, max_length); @@ -883,7 +874,7 @@ public: bool compatible_field_size(uint field_metadata, Relay_log_info *rli, uint16 mflags, int *order_var); uint is_equal(Create_field *new_field); - virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data); + virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data); static Field *create_from_item (Item *); }; @@ -921,8 +912,11 @@ public: return to + 1; } - virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data) + virtual const uchar *unpack(uchar* to, const uchar *from, + const uchar *from_end, uint param_data) { + if (from == from_end) + return 0; *to= *from; return from + 1; } @@ -964,8 +958,9 @@ public: virtual uchar *pack(uchar* to, const uchar *from, uint max_length) { return pack_int16(to, from); } - virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data) - { return unpack_int16(to, from); } + virtual const uchar *unpack(uchar* to, const uchar *from, + const uchar *from_end, uint param_data) + { return unpack_int16(to, from, from_end); } }; class Field_medium :public Field_num { @@ -999,11 +994,6 @@ public: { return Field::pack(to, from, max_length); } - - virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data) - { - return Field::unpack(to, from, param_data); - } }; @@ -1044,9 +1034,10 @@ public: return pack_int32(to, from); } virtual const uchar *unpack(uchar* to, const uchar *from, + const uchar *from_end, uint param_data __attribute__((unused))) { - return unpack_int32(to, from); + return unpack_int32(to, from, from_end); } }; @@ -1092,10 +1083,10 @@ public: { return pack_int64(to, from); } - virtual const uchar *unpack(uchar* to, const uchar *from, - uint param_data __attribute__((unused))) + const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, + uint param_data __attribute__((unused))) { - return unpack_int64(to, from); + return unpack_int64(to, from, from_end); } }; @@ -1264,10 +1255,10 @@ public: { return pack_int32(to, from); } - const uchar *unpack(uchar* to, const uchar *from, + const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data __attribute__((unused))) { - return unpack_int32(to, from); + return unpack_int32(to, from, from_end); } }; @@ -1303,8 +1294,9 @@ public: uint32 pack_length() const; uchar *pack(uchar *to, const uchar *from, uint max_length) { return Field::pack(to, from, max_length); } - const uchar *unpack(uchar* to, const uchar *from, uint param_data) - { return Field::unpack(to, from, param_data); } + const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, + uint param_data) + { return Field::unpack(to, from, from_end, param_data); } uint size_of() const { return sizeof(*this); } bool eq_def(Field *field) { return Field_str::eq_def(field) && dec == field->decimals(); } @@ -1389,10 +1381,10 @@ public: { return pack_int32(to, from); } - const uchar *unpack(uchar* to, const uchar *from, + const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data __attribute__((unused))) { - return unpack_int32(to, from); + return unpack_int32(to, from, from_end); } }; @@ -1513,10 +1505,10 @@ public: { return pack_int64(to, from); } - const uchar *unpack(uchar* to, const uchar *from, + const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data __attribute__((unused))) { - return unpack_int64(to, from); + return unpack_int64(to, from, from_end); } }; @@ -1551,8 +1543,9 @@ public: bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); uchar *pack(uchar *to, const uchar *from, uint max_length) { return Field::pack(to, from, max_length); } - const uchar *unpack(uchar* to, const uchar *from, uint param_data) - { return Field::unpack(to, from, param_data); } + const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, + uint param_data) + { return Field::unpack(to, from, from_end, param_data); } uint size_of() const { return sizeof(*this); } }; @@ -1644,7 +1637,8 @@ public: void sql_type(String &str) const; virtual uchar *pack(uchar *to, const uchar *from, uint max_length); - virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data); + virtual const uchar *unpack(uchar* to, const uchar *from, + const uchar *from_end,uint param_data); uint pack_length_from_metadata(uint field_metadata) { DBUG_PRINT("debug", ("field_metadata: 0x%04x", field_metadata)); @@ -1730,8 +1724,9 @@ public: uint get_key_image(uchar *buff,uint length, imagetype type); void set_key_image(const uchar *buff,uint length); void sql_type(String &str) const; - uchar *pack(uchar *to, const uchar *from, uint max_length); - const uchar *unpack(uchar* to, const uchar *from, uint param_data); + virtual uchar *pack(uchar *to, const uchar *from, uint max_length); + virtual const uchar *unpack(uchar* to, const uchar *from, + const uchar *from_end, uint param_data); int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0L); int key_cmp(const uchar *,const uchar*); int key_cmp(const uchar *str, uint length); @@ -1898,8 +1893,9 @@ public: memcpy(ptr+packlength, &tmp, sizeof(char*)); return 0; } - uchar *pack(uchar *to, const uchar *from, uint max_length); - const uchar *unpack(uchar *to, const uchar *from, uint param_data); + virtual uchar *pack(uchar *to, const uchar *from, uint max_length); + virtual const uchar *unpack(uchar *to, const uchar *from, + const uchar *from_end, uint param_data); uint packed_col_length(const uchar *col_ptr, uint length); uint max_packed_col_length(uint max_length); void free() { value.free(); } @@ -2001,7 +1997,8 @@ public: CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } virtual uchar *pack(uchar *to, const uchar *from, uint max_length); - virtual const uchar *unpack(uchar *to, const uchar *from, uint param_data); + virtual const uchar *unpack(uchar *to, const uchar *from, + const uchar *from_end, uint param_data); private: int do_save_field_metadata(uchar *first_byte); @@ -2113,7 +2110,8 @@ public: uint16 mflags, int *order_var); void sql_type(String &str) const; virtual uchar *pack(uchar *to, const uchar *from, uint max_length); - virtual const uchar *unpack(uchar *to, const uchar *from, uint param_data); + virtual const uchar *unpack(uchar *to, const uchar *from, + const uchar *from_end, uint param_data); virtual void set_default(); Field *new_key_field(MEM_ROOT *root, TABLE *new_table, diff --git a/sql/filesort.cc b/sql/filesort.cc index b531c4d8026..2ef9a48e6a2 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -63,7 +63,7 @@ static uint sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength); static void unpack_addon_fields(struct st_sort_addon_field *addon_field, - uchar *buff); + uchar *buff, uchar *buff_end); /** Sort a table. Creates a set of pointers that can be used to read the rows @@ -1753,7 +1753,8 @@ get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength) */ static void -unpack_addon_fields(struct st_sort_addon_field *addon_field, uchar *buff) +unpack_addon_fields(struct st_sort_addon_field *addon_field, uchar *buff, + uchar *buff_end) { Field *field; SORT_ADDON_FIELD *addonf= addon_field; @@ -1766,7 +1767,7 @@ unpack_addon_fields(struct st_sort_addon_field *addon_field, uchar *buff) continue; } field->set_notnull(); - field->unpack(field->ptr, buff + addonf->offset); + field->unpack(field->ptr, buff + addonf->offset, buff_end, 0); } } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index f2d7d69e173..d5f85e7ff5d 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -2389,7 +2389,8 @@ Item_in_subselect::select_in_like_transformer(JOIN *join) object, but we can't know it here, but here we need address correct reference on left expresion. - //psergey: he means degenerate cases like "... IN (SELECT 1)" + note: we won't need Item_in_optimizer when handling degenerate cases + like "... IN (SELECT 1)" */ if (!optimizer) { diff --git a/sql/log_event.h b/sql/log_event.h index 7866a7d7efa..de9cd65514c 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -3847,7 +3847,8 @@ protected: DBUG_ASSERT(m_table); ASSERT_OR_RETURN_ERROR(m_curr_row < m_rows_end, HA_ERR_CORRUPT_EVENT); - int const result= ::unpack_row(rli, m_table, m_width, m_curr_row, &m_cols, + int const result= ::unpack_row(rli, m_table, m_width, m_curr_row, + m_rows_end, &m_cols, &m_curr_row_end, &m_master_reclength); if (m_curr_row_end > m_rows_end) my_error(ER_SLAVE_CORRUPT_EVENT, MYF(0)); diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 09a58e29c18..104a77c65a7 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -975,7 +975,8 @@ Write_rows_log_event_old::do_prepare_row(THD *thd_arg, int error; 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, + row_start, m_rows_end, + &m_cols, row_end, &m_master_reclength, table->write_set, PRE_GA_WRITE_ROWS_EVENT); bitmap_copy(table->read_set, table->write_set); return error; @@ -1062,7 +1063,8 @@ Delete_rows_log_event_old::do_prepare_row(THD *thd_arg, 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, + row_start, m_rows_end, + &m_cols, row_end, &m_master_reclength, table->read_set, PRE_GA_DELETE_ROWS_EVENT); /* If we will access rows using the random access method, m_key will @@ -1161,13 +1163,15 @@ int Update_rows_log_event_old::do_prepare_row(THD *thd_arg, /* record[0] is the before image for the update */ 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, + row_start, m_rows_end, + &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), table, m_width, m_after_image, - row_start, &m_cols, row_end, &m_master_reclength, + row_start, m_rows_end, + &m_cols, row_end, &m_master_reclength, table->write_set, PRE_GA_UPDATE_ROWS_EVENT); DBUG_DUMP("record[0]", table->record[0], table->s->reclength); diff --git a/sql/log_event_old.h b/sql/log_event_old.h index da5cf403fdb..8fe2e9e0a75 100644 --- a/sql/log_event_old.h +++ b/sql/log_event_old.h @@ -203,7 +203,8 @@ protected: { DBUG_ASSERT(m_table); ASSERT_OR_RETURN_ERROR(m_curr_row < m_rows_end, HA_ERR_CORRUPT_EVENT); - int const result= ::unpack_row(rli, m_table, m_width, m_curr_row, &m_cols, + int const result= ::unpack_row(rli, m_table, m_width, m_curr_row, + m_rows_end, &m_cols, &m_curr_row_end, &m_master_reclength); ASSERT_OR_RETURN_ERROR(m_curr_row_end <= m_rows_end, HA_ERR_CORRUPT_EVENT); return result; diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index bdc8b768849..430c201d3e6 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -486,8 +486,8 @@ int opt_sum_query(THD *thd, 'const op field' @retval - 0 func_item is a simple predicate: a field is compared with - constants + 0 func_item is a simple predicate: a field is compared with a constant + whose length does not exceed the max length of the field values @retval 1 Otherwise */ @@ -507,6 +507,8 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) if (!(item= it++)) return 0; args[0]= item->real_item(); + if (args[0]->max_length < args[1]->max_length) + return 0; if (it++) return 0; } @@ -540,6 +542,8 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) } else return 0; + if (args[0]->max_length < args[1]->max_length) + return 0; break; case 3: /* field BETWEEN const AND const */ @@ -553,6 +557,8 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) if (!item->const_item()) return 0; args[i]= item; + if (args[0]->max_length < args[i]->max_length) + return 0; } } else diff --git a/sql/records.cc b/sql/records.cc index 5050064926b..77fdc427b86 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -507,7 +507,8 @@ static int rr_unpack_from_tempfile(READ_RECORD *info) if (my_b_read(info->io_cache, info->rec_buf, info->ref_length)) return -1; TABLE *table= info->table; - (*table->sort.unpack)(table->sort.addon_field, info->rec_buf); + (*table->sort.unpack)(table->sort.addon_field, info->rec_buf, + info->rec_buf + info->ref_length); return 0; } @@ -558,7 +559,8 @@ static int rr_unpack_from_buffer(READ_RECORD *info) if (info->cache_pos == info->cache_end) return -1; /* End of buffer */ TABLE *table= info->table; - (*table->sort.unpack)(table->sort.addon_field, info->cache_pos); + (*table->sort.unpack)(table->sort.addon_field, info->cache_pos, + info->cache_end); info->cache_pos+= info->ref_length; return 0; diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index d51e5a5ba4c..a49f10db440 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -181,12 +181,15 @@ pack_row(TABLE *table, MY_BITMAP const* cols, @retval HA_ERR_GENERIC A generic, internal, error caused the unpacking to fail. + @retval ER_SLAVE_CORRUPT_EVENT + Found error when trying to unpack fields. */ #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) 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_data, uchar const *const row_buffer_end, + MY_BITMAP const *cols, uchar const **const row_end, ulong *const master_reclength) { DBUG_ENTER("unpack_row"); @@ -257,9 +260,6 @@ unpack_row(Relay_log_info const *rli, DBUG_ASSERT(null_mask & 0xFF); // One of the 8 LSB should be set - /* Field...::unpack() cannot return 0 */ - DBUG_ASSERT(pack_ptr != NULL); - if (null_bits & null_mask) { if (f->maybe_null()) @@ -305,12 +305,20 @@ unpack_row(Relay_log_info const *rli, #ifndef DBUG_OFF uchar const *const old_pack_ptr= pack_ptr; #endif - pack_ptr= f->unpack(f->ptr, pack_ptr, metadata); + pack_ptr= f->unpack(f->ptr, pack_ptr, row_buffer_end, metadata); DBUG_PRINT("debug", ("field: %s; metadata: 0x%x;" " pack_ptr: 0x%lx; pack_ptr': 0x%lx; bytes: %d", f->field_name, metadata, (ulong) old_pack_ptr, (ulong) pack_ptr, (int) (pack_ptr - old_pack_ptr))); + if (!pack_ptr) + { + rli->report(ERROR_LEVEL, ER_SLAVE_CORRUPT_EVENT, + "Could not read field `%s` of table `%s`.`%s`", + f->field_name, table->s->db.str, + table->s->table_name.str); + DBUG_RETURN(ER_SLAVE_CORRUPT_EVENT); + } } /* diff --git a/sql/rpl_record.h b/sql/rpl_record.h index efe2a1da72c..4b34dcd0a96 100644 --- a/sql/rpl_record.h +++ b/sql/rpl_record.h @@ -33,7 +33,8 @@ size_t pack_row(TABLE* table, MY_BITMAP const* cols, #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) 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_data, uchar const *row_buffer_end, + MY_BITMAP const *cols, uchar const **const row_end, ulong *const master_reclength); // Fill table's record[0] with default values. diff --git a/sql/rpl_record_old.cc b/sql/rpl_record_old.cc index b91006d46d1..fa0c49b413c 100644 --- a/sql/rpl_record_old.cc +++ b/sql/rpl_record_old.cc @@ -83,12 +83,15 @@ pack_row_old(TABLE *table, MY_BITMAP const* cols, ER_NO_DEFAULT_FOR_FIELD Returned if one of the fields existing on the slave but not on the master does not have a default value (and isn't nullable) + ER_SLAVE_CORRUPT_EVENT + Wrong data for field found. */ #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) 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, const uchar *row_buffer_end, + MY_BITMAP const *cols, uchar const **row_end, ulong *master_reclength, MY_BITMAP* const rw_set, Log_event_type const event_type) { @@ -134,10 +137,16 @@ unpack_row_old(Relay_log_info *rli, if (bitmap_is_set(cols, field_ptr - begin_ptr)) { f->move_field_offset(offset); - ptr= f->unpack(f->ptr, ptr); + ptr= f->unpack(f->ptr, ptr, row_buffer_end, 0); f->move_field_offset(-offset); - /* Field...::unpack() cannot return 0 */ - DBUG_ASSERT(ptr != NULL); + if (!ptr) + { + rli->report(ERROR_LEVEL, ER_SLAVE_CORRUPT_EVENT, + "Could not read field `%s` of table `%s`.`%s`", + f->field_name, table->s->db.str, + table->s->table_name.str); + return(ER_SLAVE_CORRUPT_EVENT); + } } else bitmap_clear_bit(rw_set, field_ptr - begin_ptr); diff --git a/sql/rpl_record_old.h b/sql/rpl_record_old.h index 201f62b1946..ea981fb23c3 100644 --- a/sql/rpl_record_old.h +++ b/sql/rpl_record_old.h @@ -25,7 +25,8 @@ size_t pack_row_old(TABLE *table, MY_BITMAP const* cols, #ifdef HAVE_REPLICATION 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, uchar const *row_buffer_end, + MY_BITMAP const *cols, uchar const **row_end, ulong *master_reclength, MY_BITMAP* const rw_set, Log_event_type const event_type); diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index 61b67c9d229..0b5fce7758f 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -77,7 +77,7 @@ extern "C" sig_handler handle_fatal_signal(int sig) curr_time= my_time(0); localtime_r(&curr_time, &tm); - my_safe_printf_stderr("%02d%02d%02d %2d:%02d:%02d ", + fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d ", tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); if (opt_expect_abort diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9fd6e0efafe..9298d3ccb72 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8662,6 +8662,17 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves, goto err_no_arena; select_lex->cond_count++; } + /* + If it's a semi-join nest, fix its "left expression", as it is used by + the SJ-Materialization + */ + if (embedded->sj_subq_pred) + { + Item **left_expr= &embedded->sj_subq_pred->left_expr; + if (!(*left_expr)->fixed && (*left_expr)->fix_fields(thd, left_expr)) + goto err_no_arena; + } + embedding= embedded->embedding; } while (embedding && diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 9f06c99c472..526d2445d3d 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -807,6 +807,7 @@ bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived) select_union *result= (select_union*)unit->result; if (table->s->db_type() == TMP_ENGINE_HTON) { + result->tmp_table_param.keyinfo= table->s->key_info; if (create_internal_tmp_table(table, result->tmp_table_param.keyinfo, result->tmp_table_param.start_recinfo, &result->tmp_table_param.recinfo, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2e63a16d4e6..35c45a9033c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3558,12 +3558,16 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, Perform range analysis if there are keys it could use (1). Don't do range analysis if we're on the inner side of an outer join (2). Do range analysis if we're on the inner side of a semi-join (3). + Don't do range analysis for materialized subqueries (4). + Don't do range analysis for materialized derived tables (5) */ - if (!s->const_keys.is_clear_all() && // (1) - (!s->table->pos_in_table_list->embedding || // (2) - (s->table->pos_in_table_list->embedding && // (3) - s->table->pos_in_table_list->embedding->sj_on_expr)) && // (3) - !s->table->is_filled_at_execution()) + if (!s->const_keys.is_clear_all() && // (1) + (!s->table->pos_in_table_list->embedding || // (2) + (s->table->pos_in_table_list->embedding && // (3) + s->table->pos_in_table_list->embedding->sj_on_expr)) && // (3) + !s->table->is_filled_at_execution() && // (4) + !(s->table->pos_in_table_list->derived && // (5) + s->table->pos_in_table_list->is_materialized_derived())) // (5) { ha_rows records; SQL_SELECT *select; @@ -16093,8 +16097,13 @@ int report_error(TABLE *table, int error) print them to the .err log */ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT) + { + push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN, error, + "Got error %d when reading table `%s`.`%s`", + error, table->s->db.str, table->s->table_name.str); sql_print_error("Got error %d when reading table '%s'", error, table->s->path.str); + } table->file->print_error(error,MYF(0)); return 1; } diff --git a/sql/table.cc b/sql/table.cc index 016f79607d0..f8430b9575a 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2559,8 +2559,8 @@ partititon_err: /* Check virtual columns against table's storage engine. */ if (share->vfields && - !(outparam->file && - (outparam->file->ha_table_flags() & HA_CAN_VIRTUAL_COLUMNS))) + (outparam->file && + !(outparam->file->ha_table_flags() & HA_CAN_VIRTUAL_COLUMNS))) { my_error(ER_UNSUPPORTED_ENGINE_FOR_VIRTUAL_COLUMNS, MYF(0), plugin_name(share->db_plugin)->str); diff --git a/sql/table.h b/sql/table.h index 124f1c54de2..d2337022724 100644 --- a/sql/table.h +++ b/sql/table.h @@ -308,7 +308,7 @@ typedef struct st_filesort_info uchar *addon_buf; /* Pointer to a buffer if sorted with fields */ size_t addon_length; /* Length of the buffer */ struct st_sort_addon_field *addon_field; /* Pointer to the fields info */ - void (*unpack)(struct st_sort_addon_field *, uchar *); /* To unpack back */ + void (*unpack)(struct st_sort_addon_field *, uchar *, uchar *); /* To unpack back */ uchar *record_pointers; /* If sorted in memory */ ha_rows found_records; /* How many records in sort */ } FILESORT_INFO; diff --git a/sql/winservice.c b/sql/winservice.c index 1f41cf61ea4..1cf9f8d7823 100644 --- a/sql/winservice.c +++ b/sql/winservice.c @@ -75,6 +75,41 @@ void normalize_path(char *path, size_t size) } /* + Exclusion rules. + + Some hardware manufacturers deliver systems with own preinstalled MySQL copy + and services. We do not want to mess up with these installations. We will + just ignore such services, pretending it is not MySQL. + + ´@return + TRUE, if this service should be excluded from UI lists etc (OEM install) + FALSE otherwise. +*/ +BOOL exclude_service(mysqld_service_properties *props) +{ + static const char* exclude_patterns[] = + { + "common files\\dell\\mysql\\bin\\", /* Dell's private installation */ + NULL + }; + int i; + char buf[MAX_PATH]; + + /* Convert mysqld path to lower case, rules for paths are case-insensitive. */ + memcpy(buf, props->mysqld_exe, sizeof(props->mysqld_exe)); + _strlwr(buf); + + for(i= 0; exclude_patterns[i]; i++) + { + if (strstr(buf, exclude_patterns[i])) + return TRUE; + } + + return FALSE; +} + + +/* Retrieve some properties from windows mysqld service binary path. We're interested in ini file location and datadir, and also in version of the data. We tolerate missing mysqld.exe. @@ -256,7 +291,9 @@ int get_mysql_service_properties(const wchar_t *bin_path, } } } - retval = 0; + + if (!exclude_service(props)) + retval = 0; end: LocalFree((HLOCAL)args); return retval; |