Commit 7722d99e authored by unknown's avatar unknown

Merge gbichot@213.136.52.20:/home/bk/mysql-4.1

into mysql.com:/home/mysql_src/mysql-4.1

parents dcf02aa5 311cd84d
...@@ -21,6 +21,7 @@ set @q:='abc'; ...@@ -21,6 +21,7 @@ set @q:='abc';
insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2')); insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'));
set @a:=5; set @a:=5;
insert into t1 values (@a),(@a); insert into t1 values (@a),(@a);
insert into t1 values (@a),(@a),(@a*5);
select * from t1; select * from t1;
n n
12345678901234 12345678901234
...@@ -45,6 +46,36 @@ abcn1 ...@@ -45,6 +46,36 @@ abcn1
abcn1n2 abcn1n2
5 5
5 5
NULL
NULL
NULL
select * from t1;
n
12345678901234
-12345678901234
0
-1
12.5
-12.5
This is a test
abc'def
abc\def
abc'def
NULL
NULL
0
1
2
5
abc
abcn1
abcn1n2
5
5
NULL
NULL
NULL
show binlog events from 141; show binlog events from 141;
Log_name Pos Event_type Server_id Orig_log_pos Info Log_name Pos Event_type Server_id Orig_log_pos Info
slave-bin.000001 141 User var 2 141 @i1=12345678901234 slave-bin.000001 141 User var 2 141 @i1=12345678901234
...@@ -63,13 +94,16 @@ slave-bin.000001 719 User var 2 719 @s5='abc'def' ...@@ -63,13 +94,16 @@ slave-bin.000001 719 User var 2 719 @s5='abc'def'
slave-bin.000001 761 Query 1 761 use `test`; insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5) slave-bin.000001 761 Query 1 761 use `test`; insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5)
slave-bin.000001 851 User var 2 851 @n1=NULL slave-bin.000001 851 User var 2 851 @n1=NULL
slave-bin.000001 877 Query 1 877 use `test`; insert into t1 values (@n1) slave-bin.000001 877 Query 1 877 use `test`; insert into t1 values (@n1)
slave-bin.000001 939 Query 1 939 use `test`; insert into t1 values (@n2) slave-bin.000001 939 User var 2 939 @n2=NULL
slave-bin.000001 1001 Query 1 1001 use `test`; insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1) slave-bin.000001 965 Query 1 965 use `test`; insert into t1 values (@n2)
slave-bin.000001 1089 User var 2 1089 @a=2 slave-bin.000001 1027 Query 1 1027 use `test`; insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1)
slave-bin.000001 1131 Query 1 1131 use `test`; insert into t1 values (@a+(@b:=@a+1)) slave-bin.000001 1115 User var 2 1115 @a=2
slave-bin.000001 1203 User var 2 1203 @q='abc' slave-bin.000001 1157 Query 1 1157 use `test`; insert into t1 values (@a+(@b:=@a+1))
slave-bin.000001 1240 Query 1 1240 use `test`; insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2')) slave-bin.000001 1229 User var 2 1229 @q='abc'
slave-bin.000001 1344 User var 2 1344 @a=5 slave-bin.000001 1266 Query 1 1266 use `test`; insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'))
slave-bin.000001 1386 Query 1 1386 use `test`; insert into t1 values (@a),(@a) slave-bin.000001 1370 User var 2 1370 @a=5
slave-bin.000001 1412 Query 1 1412 use `test`; insert into t1 values (@a),(@a)
slave-bin.000001 1478 User var 2 1478 @a=NULL
slave-bin.000001 1503 Query 1 1503 use `test`; insert into t1 values (@a),(@a),(@a*5)
drop table t1; drop table t1;
stop slave; stop slave;
...@@ -5,6 +5,10 @@ set @a := connection_id() + 3; ...@@ -5,6 +5,10 @@ set @a := connection_id() + 3;
select @a - connection_id(); select @a - connection_id();
@a - connection_id() @a - connection_id()
3 3
set @b := 1;
select @b;
@b
1
CREATE TABLE t1 ( i int not null, v int not null,index (i)); CREATE TABLE t1 ( i int not null, v int not null,index (i));
insert into t1 values (1,1),(1,3),(2,1); insert into t1 values (1,1),(1,3),(2,1);
create table t2 (i int not null, unique (i)); create table t2 (i int not null, unique (i));
......
...@@ -29,13 +29,16 @@ insert into t1 values (@i1), (@i2), (@i3), (@i4); ...@@ -29,13 +29,16 @@ insert into t1 values (@i1), (@i2), (@i3), (@i4);
insert into t1 values (@r1), (@r2); insert into t1 values (@r1), (@r2);
insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5); insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5);
insert into t1 values (@n1); insert into t1 values (@n1);
insert into t1 values (@n2); insert into t1 values (@n2); # not explicitely set before
insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1); insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1);
insert into t1 values (@a+(@b:=@a+1)); insert into t1 values (@a+(@b:=@a+1));
set @q:='abc'; set @q:='abc';
insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2')); insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'));
set @a:=5; set @a:=5;
insert into t1 values (@a),(@a); insert into t1 values (@a),(@a);
connection master1; # see if variable is reset in binlog when thread changes
insert into t1 values (@a),(@a),(@a*5);
select * from t1;
save_master_pos; save_master_pos;
connection slave; connection slave;
sync_with_master; sync_with_master;
......
...@@ -8,6 +8,9 @@ set @a := foo; ...@@ -8,6 +8,9 @@ set @a := foo;
set @a := connection_id() + 3; set @a := connection_id() + 3;
select @a - connection_id(); select @a - connection_id();
set @b := 1;
select @b;
# Check using and setting variables with SELECT DISTINCT # Check using and setting variables with SELECT DISTINCT
CREATE TABLE t1 ( i int not null, v int not null,index (i)); CREATE TABLE t1 ( i int not null, v int not null,index (i));
......
...@@ -2071,6 +2071,16 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, ...@@ -2071,6 +2071,16 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
entry->value=0; entry->value=0;
entry->length=0; entry->length=0;
entry->update_query_id=0; entry->update_query_id=0;
/*
If we are here, we were called from a SET or a query which sets a
variable. Imagine it is this:
INSERT INTO t SELECT @a:=10, @a:=@a+1.
Then when we have a Item_func_get_user_var (because of the @a+1) so we
think we have to write the value of @a to the binlog. But before that,
we have a Item_func_set_user_var to create @a (@a:=10), in this we mark
the variable as "already logged" (line below) so that it won't be logged
by Item_func_get_user_var (because that's not necessary).
*/
entry->used_query_id=current_thd->query_id; entry->used_query_id=current_thd->query_id;
entry->type=STRING_RESULT; entry->type=STRING_RESULT;
memcpy(entry->name.str, name.str, name.length+1); memcpy(entry->name.str, name.str, name.length+1);
...@@ -2083,7 +2093,10 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, ...@@ -2083,7 +2093,10 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
return entry; return entry;
} }
/*
When a user variable is updated (in a SET command or a query like SELECT @a:=
).
*/
bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables, bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
Item **ref) Item **ref)
...@@ -2093,6 +2106,11 @@ bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables, ...@@ -2093,6 +2106,11 @@ bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
!(entry= get_variable(&thd->user_vars, name, 1))) !(entry= get_variable(&thd->user_vars, name, 1)))
return 1; return 1;
entry->type= cached_result_type; entry->type= cached_result_type;
/*
Remember the last query which updated it, this way a query can later know
if this variable is a constant item in the query (it is if update_query_id
is different from query_id).
*/
entry->update_query_id=thd->query_id; entry->update_query_id=thd->query_id;
return 0; return 0;
} }
...@@ -2315,53 +2333,92 @@ longlong Item_func_get_user_var::val_int() ...@@ -2315,53 +2333,92 @@ longlong Item_func_get_user_var::val_int()
} }
/*
When a user variable is invoked from an update query (INSERT, UPDATE etc),
stores this variable and its value in thd->user_var_events, so that it can be
written to the binlog (will be written just before the query is written, see
log.cc).
*/
void Item_func_get_user_var::fix_length_and_dec() void Item_func_get_user_var::fix_length_and_dec()
{ {
BINLOG_USER_VAR_EVENT *user_var_event;
THD *thd=current_thd; THD *thd=current_thd;
BINLOG_USER_VAR_EVENT *user_var_event;
maybe_null=1; maybe_null=1;
decimals=NOT_FIXED_DEC; decimals=NOT_FIXED_DEC;
max_length=MAX_BLOB_WIDTH; max_length=MAX_BLOB_WIDTH;
if ((var_entry= get_variable(&thd->user_vars, name, 0))) var_entry= get_variable(&thd->user_vars, name, 0);
if (!(opt_bin_log && is_update_query(thd->lex.sql_command)))
return;
if (!var_entry)
{ {
if (opt_bin_log && is_update_query(thd->lex.sql_command) && /*
var_entry->used_query_id != thd->query_id) If the variable does not exist, it's NULL, but we want to create it so
{ that it gets into the binlog (if it didn't, the slave could be
uint size; influenced by a variable of the same name previously set by another
/* thread).
First we need to store value of var_entry, when the next situation We create it like if it had been explicitely set with SET before.
appers: The 'new' mimicks what sql_yacc.yy does when 'SET @a=10;'.
> set @a:=1; sql_set_variables() is what is called from 'case SQLCOM_SET_OPTION'
> insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1); in dispatch_command()). Instead of building a one-element list to pass to
We have to write to binlog value @a= 1; sql_set_variables(), we could instead manually call check() and update();
*/ this would save memory and time; but calling sql_set_variables() makes one
size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length; unique place to maintain (sql_set_variables()).
if (!(user_var_event= (BINLOG_USER_VAR_EVENT *) thd->alloc(size))) */
goto err;
List<set_var_base> tmp_var_list;
user_var_event->value= (char*) user_var_event + tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)); new Item_null())));
user_var_event->user_var_event= var_entry; if (sql_set_variables(thd, &tmp_var_list)) /* this will create the variable */
user_var_event->type= var_entry->type; goto err;
user_var_event->charset_number= var_entry->collation.collation->number; if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
if (!var_entry->value) goto err;
{ }
/* NULL value*/ /*
user_var_event->length= 0; If this variable was already stored in user_var_events by this query
user_var_event->value= 0; (because it's used in more than one place in the query), don't store
} it.
else */
{ else if (var_entry->used_query_id == thd->query_id)
user_var_event->length= var_entry->length; return;
memcpy(user_var_event->value, var_entry->value,
var_entry->length); uint size;
} /*
var_entry->used_query_id= thd->query_id; First we need to store value of var_entry, when the next situation
if (insert_dynamic(&thd->user_var_events, (gptr) &user_var_event)) appers:
goto err; > set @a:=1;
} > insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
We have to write to binlog value @a= 1;
*/
size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
if (!(user_var_event= (BINLOG_USER_VAR_EVENT *) thd->alloc(size)))
goto err;
user_var_event->value= (char*) user_var_event +
ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
user_var_event->user_var_event= var_entry;
user_var_event->type= var_entry->type;
user_var_event->charset_number= var_entry->collation.collation->number;
if (!var_entry->value)
{
/* NULL value*/
user_var_event->length= 0;
user_var_event->value= 0;
} }
else
{
user_var_event->length= var_entry->length;
memcpy(user_var_event->value, var_entry->value,
var_entry->length);
}
/* Mark that this variable has been used by this query */
var_entry->used_query_id= thd->query_id;
if (insert_dynamic(&thd->user_var_events, (gptr) &user_var_event))
goto err;
return; return;
err: err:
......
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