mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge gbichot@213.136.52.20:/home/bk/mysql-4.1
into mysql.com:/home/mysql_src/mysql-4.1
This commit is contained in:
@ -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
|
|||||||
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'
|
|||||||
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;
|
|||||||
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);
|
|||||||
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;
|
|||||||
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));
|
||||||
|
135
sql/item_func.cc
135
sql/item_func.cc
@ -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,
|
|||||||
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,
|
|||||||
!(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()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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) &&
|
|
||||||
var_entry->used_query_id != thd->query_id)
|
|
||||||
{
|
|
||||||
uint size;
|
|
||||||
/*
|
|
||||||
First we need to store value of var_entry, when the next situation
|
|
||||||
appers:
|
|
||||||
> 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 +
|
if (!(opt_bin_log && is_update_query(thd->lex.sql_command)))
|
||||||
ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
|
return;
|
||||||
user_var_event->user_var_event= var_entry;
|
|
||||||
user_var_event->type= var_entry->type;
|
if (!var_entry)
|
||||||
user_var_event->charset_number= var_entry->collation.collation->number;
|
{
|
||||||
if (!var_entry->value)
|
/*
|
||||||
{
|
If the variable does not exist, it's NULL, but we want to create it so
|
||||||
/* NULL value*/
|
that it gets into the binlog (if it didn't, the slave could be
|
||||||
user_var_event->length= 0;
|
influenced by a variable of the same name previously set by another
|
||||||
user_var_event->value= 0;
|
thread).
|
||||||
}
|
We create it like if it had been explicitely set with SET before.
|
||||||
else
|
The 'new' mimicks what sql_yacc.yy does when 'SET @a=10;'.
|
||||||
{
|
sql_set_variables() is what is called from 'case SQLCOM_SET_OPTION'
|
||||||
user_var_event->length= var_entry->length;
|
in dispatch_command()). Instead of building a one-element list to pass to
|
||||||
memcpy(user_var_event->value, var_entry->value,
|
sql_set_variables(), we could instead manually call check() and update();
|
||||||
var_entry->length);
|
this would save memory and time; but calling sql_set_variables() makes one
|
||||||
}
|
unique place to maintain (sql_set_variables()).
|
||||||
var_entry->used_query_id= thd->query_id;
|
*/
|
||||||
if (insert_dynamic(&thd->user_var_events, (gptr) &user_var_event))
|
|
||||||
goto err;
|
List<set_var_base> tmp_var_list;
|
||||||
}
|
tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
|
||||||
|
new Item_null())));
|
||||||
|
if (sql_set_variables(thd, &tmp_var_list)) /* this will create the variable */
|
||||||
|
goto err;
|
||||||
|
if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
If this variable was already stored in user_var_events by this query
|
||||||
|
(because it's used in more than one place in the query), don't store
|
||||||
|
it.
|
||||||
|
*/
|
||||||
|
else if (var_entry->used_query_id == thd->query_id)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint size;
|
||||||
|
/*
|
||||||
|
First we need to store value of var_entry, when the next situation
|
||||||
|
appers:
|
||||||
|
> 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:
|
||||||
|
Reference in New Issue
Block a user