diff options
author | Igor Babaev <igor@askmonty.org> | 2012-03-15 21:40:15 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2012-03-15 21:40:15 -0700 |
commit | 7b845f551b8f206c886366499e21b790991f5418 (patch) | |
tree | 177dfebab940f05af1e92161c93e6f46b7af5eb3 /sql | |
parent | e6578a345c807987cc6e7fb4e9504f03b36dfa00 (diff) | |
parent | 5338a28912589f1169b66b880a489ec5636bcd83 (diff) | |
download | mariadb-git-7b845f551b8f206c886366499e21b790991f5418.tar.gz |
Merge
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 74 | ||||
-rw-r--r-- | sql/field.h | 90 | ||||
-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 | 20 | ||||
-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, 240 insertions, 89 deletions
diff --git a/sql/field.cc b/sql/field.cc index cb0b467f7ca..ed932ff139b 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1473,11 +1473,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 @@ -1493,14 +1495,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; - memcpy(to, from, param_data > length ? length : len); + if (from + len > from_end) + return 0; // Error in data + + memcpy(to, from, len); return from+len; } @@ -2932,10 +2939,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; @@ -2965,7 +2973,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; } @@ -6558,7 +6570,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; @@ -6580,11 +6593,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 @@ -7076,6 +7097,7 @@ Field_varstring::pack_key(uchar *to, const uchar *key, uint max_length) Pointer to end of 'key' (To the next key part if multi-segment key) */ +#ifdef NOT_USED const uchar * Field_varstring::unpack_key(uchar *to, const uchar *key, uint max_length) { @@ -7092,6 +7114,7 @@ Field_varstring::unpack_key(uchar *to, const uchar *key, uint max_length) memcpy(ptr + length_bytes, key, length); return key + length; } +#endif /** Create a packed key that will be used for storage in the index tree. @@ -7136,11 +7159,16 @@ uchar * Field_varstring::pack_key_from_key_image(uchar *to, const uchar *from, @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++; @@ -7155,7 +7183,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; } @@ -7787,16 +7819,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); @@ -7894,6 +7931,7 @@ Field_blob::pack_key(uchar *to, const uchar *from, uint max_length) Pointer into 'from' past the last byte copied from packed key. */ +#ifdef NOT_USED const uchar * Field_blob::unpack_key(uchar *to, const uchar *from, uint max_length) { @@ -7914,7 +7952,7 @@ Field_blob::unpack_key(uchar *to, const uchar *from, uint max_length) /* point to first byte of next field in 'from' */ return from + length; } - +#endif /** Create a packed key that will be used for storage from a MySQL key. */ @@ -8956,7 +8994,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) { uint const from_len= (param_data >> 8U) & 0x00ff; uint const from_bit_len= param_data & 0x00ff; @@ -8967,6 +9006,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) { /* @@ -8991,10 +9033,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 9f5ab19cf6c..cc612e38c1d 100644 --- a/sql/field.h +++ b/sql/field.h @@ -587,17 +587,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 uchar *pack_key(uchar* to, const uchar *from, uint max_length) { return pack(to, from, max_length); @@ -606,10 +597,12 @@ public: { return pack(to, from, max_length); } +#ifdef NOT_USED virtual const uchar *unpack_key(uchar* to, const uchar *from, uint max_length) { - return unpack(to, from, max_length); + return unpack(to, from, from + max_length+2, max_length); } +#endif virtual uint packed_col_length(const uchar *to, uint length) { return length;} virtual uint max_packed_col_length(uint max_length) @@ -890,10 +883,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); @@ -949,7 +938,7 @@ public: int compatible_field_size(uint field_metadata, const Relay_log_info *rli, uint16 mflags); 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 *); }; @@ -987,8 +976,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; } @@ -1032,15 +1024,19 @@ public: int16 val; val = sint2korr(from); int2store(to, val); - return to + sizeof(val); + return to + 2; } - 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) { int16 val; + if (from +2 > from_end) + return 0; + val = sint2korr(from); int2store(to, val); - return from + sizeof(val); + return from + 2; } }; @@ -1075,11 +1071,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); - } }; @@ -1120,8 +1111,11 @@ public: return pack_int32(to, from); } virtual const uchar *unpack(uchar* to, const uchar *from, + const uchar *from_end, uint param_data __attribute__((unused))) { + if (from + 4 > from_end) + return 0; return unpack_int32(to, from); } }; @@ -1168,9 +1162,11 @@ 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))) { + if (from + 8 > from_end) + return 0; return unpack_int64(to, from); } }; @@ -1334,9 +1330,11 @@ 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))) { + if (from + 4 > from_end) + return 0; return unpack_int32(to, from); } }; @@ -1373,8 +1371,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(); } @@ -1457,9 +1456,11 @@ 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))) { + if (from + 4 > from_end) + return 0; return unpack_int32(to, from); } }; @@ -1586,9 +1587,11 @@ 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))) { + if (from + 8 > from_end) + return 0; return unpack_int64(to, from); } }; @@ -1624,8 +1627,9 @@ public: bool get_date(MYSQL_TIME *ltime,uint 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); } }; @@ -1716,7 +1720,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)); @@ -1804,8 +1809,11 @@ public: virtual uchar *pack(uchar *to, const uchar *from, uint max_length); uchar *pack_key(uchar *to, const uchar *from, uint max_length); uchar *pack_key_from_key_image(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); +#ifdef NOT_USED const uchar *unpack_key(uchar* to, const uchar *from, uint max_length); +#endif int pack_cmp(const uchar *a, const uchar *b, uint key_length, bool insert_or_update); int pack_cmp(const uchar *b, uint key_length,bool insert_or_update); @@ -1982,8 +1990,11 @@ public: virtual uchar *pack(uchar *to, const uchar *from, uint max_length); uchar *pack_key(uchar *to, const uchar *from, uint max_length); uchar *pack_key_from_key_image(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); +#ifdef NOT_USED const uchar *unpack_key(uchar* to, const uchar *from, uint max_length); +#endif int pack_cmp(const uchar *a, const uchar *b, uint key_length, bool insert_or_update); int pack_cmp(const uchar *b, uint key_length,bool insert_or_update); @@ -2208,7 +2219,8 @@ public: const Relay_log_info *rli, uint16 mflags); 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, struct st_table *new_table, diff --git a/sql/filesort.cc b/sql/filesort.cc index 86d2fb1a8d0..c12337ee9be 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -60,7 +60,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 @@ -1732,7 +1732,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; @@ -1745,7 +1746,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 b40467eb21c..a97393fa94c 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -2377,7 +2377,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 5dcf8c736a1..1ce17bd7e35 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -3752,7 +3752,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 b81d99a47a9..7328d3451f1 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -998,7 +998,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; @@ -1085,7 +1086,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 @@ -1184,13 +1186,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 5298c57954d..9e097af1e6e 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -482,8 +482,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 */ @@ -503,6 +503,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; } @@ -536,6 +538,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 */ @@ -549,6 +553,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 01c260a7e90..10817dd8e51 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -447,7 +447,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; } @@ -498,7 +499,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 cbbf2dcec48..ea8324a1fc7 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -176,13 +176,15 @@ pack_row(TABLE *table, MY_BITMAP const* cols, @retval 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) - + @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"); @@ -224,9 +226,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()) @@ -272,14 +271,21 @@ 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); + } } - null_mask <<= 1; } i++; diff --git a/sql/rpl_record.h b/sql/rpl_record.h index 6005d57daf3..eefcdebc114 100644 --- a/sql/rpl_record.h +++ b/sql/rpl_record.h @@ -29,7 +29,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 f861ffb10f7..6709c4f6e1a 100644 --- a/sql/rpl_record_old.cc +++ b/sql/rpl_record_old.cc @@ -82,12 +82,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) { @@ -133,10 +136,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 300c9d9a1a6..c9c2f5739cb 100644 --- a/sql/rpl_record_old.h +++ b/sql/rpl_record_old.h @@ -23,7 +23,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 819b87e3fdc..d58c28c2936 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -72,7 +72,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 e1db2b2b77a..a95a0223bc3 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8513,6 +8513,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 02a26254336..99d20090623 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -811,6 +811,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 437833eb90c..f05e8ad34b2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3513,12 +3513,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; @@ -15763,8 +15767,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_ERROR, 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 6b8adaa7c79..db86f55c236 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2353,8 +2353,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 0d5d4fe26b4..09006ab778f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -166,7 +166,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 3ec91c26835..f70f8018509 100644 --- a/sql/winservice.c +++ b/sql/winservice.c @@ -59,6 +59,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. @@ -240,7 +275,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; |