Commit d27bf14e authored by unknown's avatar unknown

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:
  Bug #29878 Garbage data generation when executing SESSION_USER() on a slave.
  
  test result
mysql-test/t/rpl_session_var.test:
  Bug #29878 Garbage data generation when executing SESSION_USER() on a slave.
  
  test case
sql/item.cc:
  Bug #29878 Garbage data generation when executing SESSION_USER() on a slave.
  
  duplicating code moved to Item::save_str_in_field
sql/item.h:
  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:
  Bug #29878 Garbage data generation when executing SESSION_USER() on a slave.
  
  Item_func_user::save_in_field implemented as simple storing str_value
parent eee081da
...@@ -41,3 +41,13 @@ select * from t2 order by b; ...@@ -41,3 +41,13 @@ select * from t2 order by b;
b a b a
1 1 1 1
drop table t1,t2; 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;
...@@ -40,3 +40,25 @@ drop table t1,t2; ...@@ -40,3 +40,25 @@ drop table t1,t2;
save_master_pos; save_master_pos;
connection slave; connection slave;
sync_with_master; 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;
...@@ -336,6 +336,37 @@ int Item::save_date_in_field(Field *field) ...@@ -336,6 +336,37 @@ int Item::save_date_in_field(Field *field)
} }
/*
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(): Item::Item():
rsize(0), name(0), orig_name(0), name_length(0), fixed(0), rsize(0), name(0), orig_name(0), name_length(0), fixed(0),
is_autogenerated_name(TRUE), is_autogenerated_name(TRUE),
...@@ -3009,16 +3040,6 @@ my_decimal *Item_copy_string::val_decimal(my_decimal *decimal_value) ...@@ -3009,16 +3040,6 @@ my_decimal *Item_copy_string::val_decimal(my_decimal *decimal_value)
} }
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) Functions to convert item to field (for send_fields)
*/ */
...@@ -4417,6 +4438,12 @@ int Item_null::save_safe_in_field(Field *field) ...@@ -4417,6 +4438,12 @@ int Item_null::save_safe_in_field(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 Item::save_in_field(Field *field, bool no_conversions)
{ {
int error; int error;
...@@ -4474,10 +4501,7 @@ int Item_string::save_in_field(Field *field, bool no_conversions) ...@@ -4474,10 +4501,7 @@ int Item_string::save_in_field(Field *field, bool no_conversions)
{ {
String *result; String *result;
result=val_str(&str_value); result=val_str(&str_value);
if (null_value) return save_str_value_in_field(field, result);
return set_field_to_null(field);
field->set_notnull();
return field->store(result->ptr(),result->length(),collation.collation);
} }
......
...@@ -612,6 +612,7 @@ public: ...@@ -612,6 +612,7 @@ public:
int save_time_in_field(Field *field); int save_time_in_field(Field *field);
int save_date_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; } virtual Field *get_tmp_table_field() { return 0; }
/* This is also used to create fields in CREATE ... SELECT: */ /* This is also used to create fields in CREATE ... SELECT: */
...@@ -2166,7 +2167,10 @@ public: ...@@ -2166,7 +2167,10 @@ public:
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
void make_field(Send_field *field) { item->make_field(field); } void make_field(Send_field *field) { item->make_field(field); }
void copy(); 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; } table_map used_tables() const { return (table_map) 1L; }
bool const_item() const { return 0; } bool const_item() const { return 0; }
bool is_null() { return null_value; } bool is_null() { return null_value; }
......
...@@ -434,6 +434,10 @@ public: ...@@ -434,6 +434,10 @@ public:
} }
const char *func_name() const { return "user"; } const char *func_name() const { return "user"; }
const char *fully_qualified_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);
}
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment