From: Date: July 27 2007 3:42pm Subject: bk commit into 5.0 tree (holyfoot:1.2476) BUG#29878 List-Archive: http://lists.mysql.com/commits/31710 X-Bug: 29878 Message-Id: <20070727134231.74B9B2C380A5@hfmain.localdomain> Below is the list of changes that have just been committed into a local 5.0 repository of hf. When hf does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet@stripped, 2007-07-27 18:42:25+05:00, holyfoot@stripped +5 -0 Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. Item_func_user doesn't calculate anything in it's val_str() method, just returns saved str_value. Though Item::save_in_field method can destroy str_value, relying on val_str() return. As a result we get the garbage stored in field. We cannot use Item::save_in_field implementation for Item_func_user, reimplement it in simpler way. mysql-test/r/rpl_session_var.result@stripped, 2007-07-27 18:42:24+05:00, holyfoot@stripped +10 -0 Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. test result mysql-test/t/rpl_session_var.test@stripped, 2007-07-27 18:42:24+05:00, holyfoot@stripped +22 -0 Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. test case sql/item.cc@stripped, 2007-07-27 18:42:24+05:00, holyfoot@stripped +38 -14 Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. duplicating code moved to Item::save_str_in_field sql/item.h@stripped, 2007-07-27 18:42:24+05:00, holyfoot@stripped +5 -1 Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. duplicating code moved to Item::save_str_in_field sql/item_strfunc.h@stripped, 2007-07-27 18:42:24+05:00, holyfoot@stripped +4 -0 Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. Item_func_user::save_in_field implemented as simple storing str_value diff -Nrup a/mysql-test/r/rpl_session_var.result b/mysql-test/r/rpl_session_var.result --- a/mysql-test/r/rpl_session_var.result 2005-10-17 20:08:51 +05:00 +++ b/mysql-test/r/rpl_session_var.result 2007-07-27 18:42:24 +05:00 @@ -41,3 +41,13 @@ select * from t2 order by b; b a 1 1 drop table t1,t2; +CREATE TABLE t1 ( +`id` int(11) NOT NULL auto_increment, +`data` varchar(100), +PRIMARY KEY (`id`) +) ENGINE=MyISAM; +INSERT INTO t1(data) VALUES(SESSION_USER()); +SELECT * FROM t1; +id data +1 +drop table t1; diff -Nrup a/mysql-test/t/rpl_session_var.test b/mysql-test/t/rpl_session_var.test --- a/mysql-test/t/rpl_session_var.test 2005-10-17 20:08:54 +05:00 +++ b/mysql-test/t/rpl_session_var.test 2007-07-27 18:42:24 +05:00 @@ -40,3 +40,25 @@ drop table t1,t2; save_master_pos; connection slave; sync_with_master; + +# +# Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. +# + +connection master; +CREATE TABLE t1 ( + `id` int(11) NOT NULL auto_increment, + `data` varchar(100), + PRIMARY KEY (`id`) + ) ENGINE=MyISAM; + +INSERT INTO t1(data) VALUES(SESSION_USER()); +save_master_pos; +connection slave; +sync_with_master; +SELECT * FROM t1; +connection master; +drop table t1; +save_master_pos; +connection slave; +sync_with_master; diff -Nrup a/sql/item.cc b/sql/item.cc --- a/sql/item.cc 2007-07-06 17:18:44 +05:00 +++ b/sql/item.cc 2007-07-27 18:42:24 +05:00 @@ -336,6 +336,37 @@ int Item::save_date_in_field(Field *fiel } +/* + Store the string value in field directly + + SYNOPSIS + Item::save_str_value_in_field() + field a pointer to field where to store + result the pointer to the string value to be stored + + DESCRIPTION + The method is used by Item_*::save_in_field implementations + when we don't need to calculate the value to store + See Item_string::save_in_field() implementation for example + + IMPLEMENTATION + Check if the Item is null and stores the NULL or the + result value in the field accordingly. + + RETURN + Nonzero value if error +*/ + +int Item::save_str_value_in_field(Field *field, String *result) +{ + if (null_value) + return set_field_to_null(field); + field->set_notnull(); + return field->store(result->ptr(), result->length(), + collation.collation); +} + + Item::Item(): rsize(0), name(0), orig_name(0), name_length(0), fixed(0), is_autogenerated_name(TRUE), @@ -3009,16 +3040,6 @@ my_decimal *Item_copy_string::val_decima } - -int Item_copy_string::save_in_field(Field *field, bool no_conversions) -{ - if (null_value) - return set_field_to_null(field); - field->set_notnull(); - return field->store(str_value.ptr(),str_value.length(), - collation.collation); -} - /* Functions to convert item to field (for send_fields) */ @@ -4417,6 +4438,12 @@ int Item_null::save_safe_in_field(Field } +/* + This implementation can lose str_value content, so if the + Item uses str_value to store something, it should + reimplement it's ::save_in_field() as Item_string, for example, does +*/ + int Item::save_in_field(Field *field, bool no_conversions) { int error; @@ -4474,10 +4501,7 @@ int Item_string::save_in_field(Field *fi { String *result; result=val_str(&str_value); - if (null_value) - return set_field_to_null(field); - field->set_notnull(); - return field->store(result->ptr(),result->length(),collation.collation); + return save_str_value_in_field(field, result); } diff -Nrup a/sql/item.h b/sql/item.h --- a/sql/item.h 2007-07-17 00:40:30 +05:00 +++ b/sql/item.h 2007-07-27 18:42:24 +05:00 @@ -612,6 +612,7 @@ public: int save_time_in_field(Field *field); int save_date_in_field(Field *field); + int save_str_value_in_field(Field *field, String *result); virtual Field *get_tmp_table_field() { return 0; } /* This is also used to create fields in CREATE ... SELECT: */ @@ -2166,7 +2167,10 @@ public: my_decimal *val_decimal(my_decimal *); void make_field(Send_field *field) { item->make_field(field); } void copy(); - int save_in_field(Field *field, bool no_conversions); + int save_in_field(Field *field, bool no_conversions) + { + return save_str_value_in_field(field, &str_value); + } table_map used_tables() const { return (table_map) 1L; } bool const_item() const { return 0; } bool is_null() { return null_value; } diff -Nrup a/sql/item_strfunc.h b/sql/item_strfunc.h --- a/sql/item_strfunc.h 2007-04-11 15:58:15 +05:00 +++ b/sql/item_strfunc.h 2007-07-27 18:42:24 +05:00 @@ -434,6 +434,10 @@ public: } const char *func_name() const { return "user"; } const char *fully_qualified_func_name() const { return "user()"; } + int save_in_field(Field *field, bool no_conversions) + { + return save_str_value_in_field(field, &str_value); + } };