Commit ce2c46dd authored by unknown's avatar unknown

support 'parallel' updates and rallback of whole statement in case of error in...

support 'parallel' updates and rallback of whole statement in case of error in evalueting value which should be assigned
(BUG#1484)


mysql-test/r/variables.result:
  test of swaping variables
mysql-test/t/variables.test:
  test of swaping variables
sql/item_func.cc:
  new method of user variables to pre-fetch value
sql/item_func.h:
  new method of user variables to pre-fetch value
sql/set_var.cc:
  check() methods fetch & store value
sql/set_var.h:
  check() methods fetch & store value
parent 5ee2807c
......@@ -365,3 +365,27 @@ ERROR HY000: Unknown system variable 'xxxxxxxxxx'
select 1;
1
1
select @@global.max_user_connections,@@local.max_join_size;
@@global.max_user_connections @@session.max_join_size
100 200
set @svc=@@global.max_user_connections, @svj=@@local.max_join_size;
select @@global.max_user_connections,@@local.max_join_size;
@@global.max_user_connections @@session.max_join_size
100 200
set @@global.max_user_connections=111,@@local.max_join_size=222;
select @@global.max_user_connections,@@local.max_join_size;
@@global.max_user_connections @@session.max_join_size
111 222
set @@global.max_user_connections=@@local.max_join_size,@@local.max_join_size=@@global.max_user_connections;
select @@global.max_user_connections,@@local.max_join_size;
@@global.max_user_connections @@session.max_join_size
222 111
set @@global.max_user_connections=@svc, @@local.max_join_size=@svj;
select @@global.max_user_connections,@@local.max_join_size;
@@global.max_user_connections @@session.max_join_size
100 200
set @a=1, @b=2;
set @a=@b, @b=@a;
select @a, @b;
@a @b
2 1
......@@ -263,3 +263,20 @@ drop table t1,t2;
--error 1193
select @@xxxxxxxxxx;
select 1;
#
# swap
#
select @@global.max_user_connections,@@local.max_join_size;
set @svc=@@global.max_user_connections, @svj=@@local.max_join_size;
select @@global.max_user_connections,@@local.max_join_size;
set @@global.max_user_connections=111,@@local.max_join_size=222;
select @@global.max_user_connections,@@local.max_join_size;
set @@global.max_user_connections=@@local.max_join_size,@@local.max_join_size=@@global.max_user_connections;
select @@global.max_user_connections,@@local.max_join_size;
set @@global.max_user_connections=@svc, @@local.max_join_size=@svj;
select @@global.max_user_connections,@@local.max_join_size;
set @a=1, @b=2;
set @a=@b, @b=@a;
select @a, @b;
......@@ -2255,6 +2255,54 @@ String *user_var_entry::val_str(my_bool *null_value, String *str,
return(str);
}
/*
This functions is invoked on SET @variable or @variable:= expression.
Evaluete (and check expression), store results.
SYNOPSYS
Item_func_set_user_var::check()
NOTES
For now it always return OK. All problem with value evalueting
will be catched by thd->net.report_error check in sql_set_variables().
RETURN
0 - OK.
*/
bool
Item_func_set_user_var::check()
{
bool res;
DBUG_ENTER("Item_func_set_user_var::check");
LINT_INIT(res);
switch (cached_result_type) {
case REAL_RESULT:
{
save_result.vreal= args[0]->val();
break;
}
case INT_RESULT:
{
save_result.vint= args[0]->val_int();
break;
}
break;
case STRING_RESULT:
{
save_result.vstr= args[0]->val_str(&value);
break;
}
case ROW_RESULT:
default:
// This case should never be choosen
DBUG_ASSERT(0);
break;
}
DBUG_RETURN(0);
}
/*
This functions is invoked on SET @variable or @variable:= expression.
......@@ -2282,29 +2330,27 @@ Item_func_set_user_var::update()
switch (cached_result_type) {
case REAL_RESULT:
{
double value=args[0]->val();
res= update_hash((void*) &value,sizeof(value), REAL_RESULT,
&my_charset_bin, DERIVATION_NONE);
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
REAL_RESULT, &my_charset_bin, DERIVATION_NONE);
break;
}
case INT_RESULT:
{
longlong value=args[0]->val_int();
res= update_hash((void*) &value, sizeof(longlong), INT_RESULT,
&my_charset_bin, DERIVATION_NONE);
res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
INT_RESULT, &my_charset_bin, DERIVATION_NONE);
break;
}
break;
case STRING_RESULT:
{
String *tmp;
tmp=args[0]->val_str(&value);
if (!tmp) // Null value
if (!save_result.vstr) // Null value
res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
DERIVATION_NONE);
else
res= update_hash((void*) tmp->ptr(), tmp->length(), STRING_RESULT,
tmp->charset(), args[0]->collation.derivation);
res= update_hash((void*) save_result.vstr->ptr(),
save_result.vstr->length(), STRING_RESULT,
save_result.vstr->charset(),
args[0]->collation.derivation);
break;
}
case ROW_RESULT:
......@@ -2319,18 +2365,21 @@ Item_func_set_user_var::update()
double Item_func_set_user_var::val()
{
check();
update(); // Store expression
return entry->val(&null_value);
}
longlong Item_func_set_user_var::val_int()
{
check();
update(); // Store expression
return entry->val_int(&null_value);
}
String *Item_func_set_user_var::val_str(String *str)
{
check();
update(); // Store expression
return entry->val_str(&null_value, str, decimals);
}
......
......@@ -900,6 +900,14 @@ class Item_func_set_user_var :public Item_func
user_var_entry *entry;
char buffer[MAX_FIELD_WIDTH];
String value;
union
{
longlong vint;
double vreal;
String *vstr;
} save_result;
String save_buff;
public:
Item_func_set_user_var(LEX_STRING a,Item *b)
......@@ -910,6 +918,7 @@ class Item_func_set_user_var :public Item_func
String *val_str(String *str);
bool update_hash(void *ptr, uint length, enum Item_result type,
CHARSET_INFO *cs, Derivation dv);
bool check();
bool update();
enum Item_result result_type () const { return cached_result_type; }
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
......
......@@ -716,6 +716,12 @@ struct show_var_st init_vars[]= {
};
bool sys_var::check(THD *thd, set_var *var)
{
var->save_result.ulonglong_value= var->value->val_int();
return 0;
}
/*
Functions to check and update variables
*/
......@@ -964,12 +970,9 @@ static void fix_max_connections(THD *thd, enum_var_type type)
resize_thr_alarm(max_connections + max_insert_delayed_threads + 10);
}
bool sys_var_long_ptr::update(THD *thd, set_var *var)
{
ulonglong tmp= var->value->val_int();
if (thd->net.report_error)
return 1;
ulonglong tmp= var->save_result.ulonglong_value;
pthread_mutex_lock(&LOCK_global_system_variables);
if (option_limits)
*value= (ulong) getopt_ull_limit_value(tmp, option_limits);
......@@ -988,9 +991,7 @@ void sys_var_long_ptr::set_default(THD *thd, enum_var_type type)
bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var)
{
ulonglong tmp= var->value->val_int();
if (thd->net.report_error)
return 1;
ulonglong tmp= var->save_result.ulonglong_value;
pthread_mutex_lock(&LOCK_global_system_variables);
if (option_limits)
*value= (ulonglong) getopt_ull_limit_value(tmp, option_limits);
......@@ -1037,9 +1038,7 @@ byte *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
bool sys_var_thd_ulong::update(THD *thd, set_var *var)
{
ulonglong tmp= var->value->val_int();
if (thd->net.report_error)
return 1;
ulonglong tmp= var->save_result.ulonglong_value;
/* Don't use bigger value than given with --maximum-variable-name=.. */
if ((ulong) tmp > max_system_variables.*offset)
......@@ -1078,9 +1077,7 @@ byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type,
bool sys_var_thd_ha_rows::update(THD *thd, set_var *var)
{
ulonglong tmp= var->value->val_int();
if (thd->net.report_error)
return 1;
ulonglong tmp= var->save_result.ulonglong_value;
/* Don't use bigger value than given with --maximum-variable-name=.. */
if ((ha_rows) tmp > max_system_variables.*offset)
......@@ -1123,12 +1120,9 @@ byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type,
return (byte*) &(thd->variables.*offset);
}
bool sys_var_thd_ulonglong::update(THD *thd, set_var *var)
{
ulonglong tmp= var->value->val_int();
if (thd->net.report_error)
return 1;
ulonglong tmp= var->save_result.ulonglong_value;
if ((ulonglong) tmp > max_system_variables.*offset)
tmp= max_system_variables.*offset;
......@@ -1700,9 +1694,7 @@ void sys_var_collation_server::set_default(THD *thd, enum_var_type type)
bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
{
ulonglong tmp= var->value->val_int();
if (thd->net.report_error)
return 1;
ulonglong tmp= var->save_result.ulonglong_value;
NAMED_LIST *list;
LEX_STRING *base_name= &var->base;
......@@ -1799,11 +1791,7 @@ int set_var_collation_client::update(THD *thd)
bool sys_var_timestamp::update(THD *thd, set_var *var)
{
time_t tmp= (time_t) var->value->val_int();
if (thd->net.report_error)
return 1;
thd->set_time(tmp);
thd->set_time((time_t) var->save_result.ulonglong_value);
return 0;
}
......@@ -1824,11 +1812,7 @@ byte *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type,
bool sys_var_last_insert_id::update(THD *thd, set_var *var)
{
ulonglong tmp= var->value->val_int();
if (thd->net.report_error)
return 1;
thd->insert_id(tmp);
thd->insert_id(var->save_result.ulonglong_value);
return 0;
}
......@@ -1843,11 +1827,7 @@ byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type,
bool sys_var_insert_id::update(THD *thd, set_var *var)
{
ulonglong tmp= var->value->val_int();
if (thd->net.report_error)
return 1;
thd->next_insert_id= tmp;
thd->next_insert_id= var->save_result.ulonglong_value;
return 0;
}
......@@ -1860,6 +1840,7 @@ byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type,
bool sys_var_pseudo_thread_id::check(THD *thd, set_var *var)
{
var->save_result.ulonglong_value= var->value->val_int();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (thd->master_access & SUPER_ACL)
return 0;
......@@ -1887,6 +1868,7 @@ bool sys_var_slave_skip_counter::check(THD *thd, set_var *var)
}
pthread_mutex_unlock(&active_mi->rli.run_lock);
UNLOCK_ACTIVE_MI;
var->save_result.ulong_value= (ulong) var->value->val_int();
return result;
}
......@@ -1903,7 +1885,7 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
if (!active_mi->rli.slave_running)
{
pthread_mutex_lock(&active_mi->rli.data_lock);
active_mi->rli.slave_skip_counter= (ulong) var->value->val_int();
active_mi->rli.slave_skip_counter= var->save_result.ulong_value;
pthread_mutex_unlock(&active_mi->rli.data_lock);
}
pthread_mutex_unlock(&active_mi->rli.run_lock);
......@@ -1914,21 +1896,13 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
bool sys_var_rand_seed1::update(THD *thd, set_var *var)
{
ulong tmp= (ulong) var->value->val_int();
if (thd->net.report_error)
return 1;
thd->rand.seed1= tmp;
thd->rand.seed1= (ulong) var->save_result.ulonglong_value;
return 0;
}
bool sys_var_rand_seed2::update(THD *thd, set_var *var)
{
ulong tmp= (ulong) var->value->val_int();
if (thd->net.report_error)
return 1;
thd->rand.seed2= tmp;
thd->rand.seed2= (ulong) var->save_result.ulonglong_value;
return 0;
}
......@@ -2153,6 +2127,8 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list)
if ((error=var->check(thd)))
DBUG_RETURN(error);
}
if (thd->net.report_error)
DBUG_RETURN(1);
it.rewind();
while ((var=it++))
error|= var->update(thd); // Returns 0, -1 or 1
......@@ -2215,7 +2191,8 @@ int set_var::update(THD *thd)
int set_var_user::check(THD *thd)
{
return user_var_item->fix_fields(thd,0, (Item**) 0) ? -1 : 0;
return (user_var_item->fix_fields(thd,0, (Item**) 0) ||
user_var_item->check()) ? -1 : 0;
}
......
......@@ -57,7 +57,7 @@ class sys_var
:name(name_arg),after_update(func)
{}
virtual ~sys_var() {}
virtual bool check(THD *thd, set_var *var) { return 0; }
virtual bool check(THD *thd, set_var *var);
bool check_enum(THD *thd, set_var *var, TYPELIB *enum_names);
bool check_set(THD *thd, set_var *var, TYPELIB *enum_names);
virtual bool update(THD *thd, set_var *var)=0;
......@@ -656,6 +656,7 @@ class set_var :public set_var_base
{
CHARSET_INFO *charset;
ulong ulong_value;
ulonglong ulonglong_value;
} save_result;
LEX_STRING base; /* for structs */
......
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