Commit f349adf8 authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

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)
parent 4e192076
...@@ -365,3 +365,27 @@ ERROR HY000: Unknown system variable 'xxxxxxxxxx' ...@@ -365,3 +365,27 @@ ERROR HY000: Unknown system variable 'xxxxxxxxxx'
select 1; select 1;
1 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; ...@@ -263,3 +263,20 @@ drop table t1,t2;
--error 1193 --error 1193
select @@xxxxxxxxxx; select @@xxxxxxxxxx;
select 1; 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, ...@@ -2255,6 +2255,54 @@ String *user_var_entry::val_str(my_bool *null_value, String *str,
return(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. This functions is invoked on SET @variable or @variable:= expression.
...@@ -2282,29 +2330,27 @@ Item_func_set_user_var::update() ...@@ -2282,29 +2330,27 @@ Item_func_set_user_var::update()
switch (cached_result_type) { switch (cached_result_type) {
case REAL_RESULT: case REAL_RESULT:
{ {
double value=args[0]->val(); res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
res= update_hash((void*) &value,sizeof(value), REAL_RESULT, REAL_RESULT, &my_charset_bin, DERIVATION_NONE);
&my_charset_bin, DERIVATION_NONE);
break; break;
} }
case INT_RESULT: case INT_RESULT:
{ {
longlong value=args[0]->val_int(); res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
res= update_hash((void*) &value, sizeof(longlong), INT_RESULT, INT_RESULT, &my_charset_bin, DERIVATION_NONE);
&my_charset_bin, DERIVATION_NONE);
break; break;
} }
break; break;
case STRING_RESULT: case STRING_RESULT:
{ {
String *tmp; if (!save_result.vstr) // Null value
tmp=args[0]->val_str(&value);
if (!tmp) // Null value
res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
DERIVATION_NONE); DERIVATION_NONE);
else else
res= update_hash((void*) tmp->ptr(), tmp->length(), STRING_RESULT, res= update_hash((void*) save_result.vstr->ptr(),
tmp->charset(), args[0]->collation.derivation); save_result.vstr->length(), STRING_RESULT,
save_result.vstr->charset(),
args[0]->collation.derivation);
break; break;
} }
case ROW_RESULT: case ROW_RESULT:
...@@ -2319,18 +2365,21 @@ Item_func_set_user_var::update() ...@@ -2319,18 +2365,21 @@ Item_func_set_user_var::update()
double Item_func_set_user_var::val() double Item_func_set_user_var::val()
{ {
check();
update(); // Store expression update(); // Store expression
return entry->val(&null_value); return entry->val(&null_value);
} }
longlong Item_func_set_user_var::val_int() longlong Item_func_set_user_var::val_int()
{ {
check();
update(); // Store expression update(); // Store expression
return entry->val_int(&null_value); return entry->val_int(&null_value);
} }
String *Item_func_set_user_var::val_str(String *str) String *Item_func_set_user_var::val_str(String *str)
{ {
check();
update(); // Store expression update(); // Store expression
return entry->val_str(&null_value, str, decimals); return entry->val_str(&null_value, str, decimals);
} }
......
...@@ -900,6 +900,14 @@ class Item_func_set_user_var :public Item_func ...@@ -900,6 +900,14 @@ class Item_func_set_user_var :public Item_func
user_var_entry *entry; user_var_entry *entry;
char buffer[MAX_FIELD_WIDTH]; char buffer[MAX_FIELD_WIDTH];
String value; String value;
union
{
longlong vint;
double vreal;
String *vstr;
} save_result;
String save_buff;
public: public:
Item_func_set_user_var(LEX_STRING a,Item *b) Item_func_set_user_var(LEX_STRING a,Item *b)
...@@ -910,6 +918,7 @@ class Item_func_set_user_var :public Item_func ...@@ -910,6 +918,7 @@ class Item_func_set_user_var :public Item_func
String *val_str(String *str); String *val_str(String *str);
bool update_hash(void *ptr, uint length, enum Item_result type, bool update_hash(void *ptr, uint length, enum Item_result type,
CHARSET_INFO *cs, Derivation dv); CHARSET_INFO *cs, Derivation dv);
bool check();
bool update(); bool update();
enum Item_result result_type () const { return cached_result_type; } enum Item_result result_type () const { return cached_result_type; }
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref); bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
......
...@@ -716,6 +716,12 @@ struct show_var_st init_vars[]= { ...@@ -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 Functions to check and update variables
*/ */
...@@ -964,12 +970,9 @@ static void fix_max_connections(THD *thd, enum_var_type type) ...@@ -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); resize_thr_alarm(max_connections + max_insert_delayed_threads + 10);
} }
bool sys_var_long_ptr::update(THD *thd, set_var *var) bool sys_var_long_ptr::update(THD *thd, set_var *var)
{ {
ulonglong tmp= var->value->val_int(); ulonglong tmp= var->save_result.ulonglong_value;
if (thd->net.report_error)
return 1;
pthread_mutex_lock(&LOCK_global_system_variables); pthread_mutex_lock(&LOCK_global_system_variables);
if (option_limits) if (option_limits)
*value= (ulong) getopt_ull_limit_value(tmp, 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) ...@@ -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) bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var)
{ {
ulonglong tmp= var->value->val_int(); ulonglong tmp= var->save_result.ulonglong_value;
if (thd->net.report_error)
return 1;
pthread_mutex_lock(&LOCK_global_system_variables); pthread_mutex_lock(&LOCK_global_system_variables);
if (option_limits) if (option_limits)
*value= (ulonglong) getopt_ull_limit_value(tmp, 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) ...@@ -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) bool sys_var_thd_ulong::update(THD *thd, set_var *var)
{ {
ulonglong tmp= var->value->val_int(); ulonglong tmp= var->save_result.ulonglong_value;
if (thd->net.report_error)
return 1;
/* Don't use bigger value than given with --maximum-variable-name=.. */ /* Don't use bigger value than given with --maximum-variable-name=.. */
if ((ulong) tmp > max_system_variables.*offset) if ((ulong) tmp > max_system_variables.*offset)
...@@ -1078,9 +1077,7 @@ byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type, ...@@ -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) bool sys_var_thd_ha_rows::update(THD *thd, set_var *var)
{ {
ulonglong tmp= var->value->val_int(); ulonglong tmp= var->save_result.ulonglong_value;
if (thd->net.report_error)
return 1;
/* Don't use bigger value than given with --maximum-variable-name=.. */ /* Don't use bigger value than given with --maximum-variable-name=.. */
if ((ha_rows) tmp > max_system_variables.*offset) 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, ...@@ -1123,12 +1120,9 @@ byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type,
return (byte*) &(thd->variables.*offset); return (byte*) &(thd->variables.*offset);
} }
bool sys_var_thd_ulonglong::update(THD *thd, set_var *var) bool sys_var_thd_ulonglong::update(THD *thd, set_var *var)
{ {
ulonglong tmp= var->value->val_int(); ulonglong tmp= var->save_result.ulonglong_value;
if (thd->net.report_error)
return 1;
if ((ulonglong) tmp > max_system_variables.*offset) if ((ulonglong) tmp > max_system_variables.*offset)
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) ...@@ -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) bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
{ {
ulonglong tmp= var->value->val_int(); ulonglong tmp= var->save_result.ulonglong_value;
if (thd->net.report_error)
return 1;
NAMED_LIST *list; NAMED_LIST *list;
LEX_STRING *base_name= &var->base; LEX_STRING *base_name= &var->base;
...@@ -1799,11 +1791,7 @@ int set_var_collation_client::update(THD *thd) ...@@ -1799,11 +1791,7 @@ int set_var_collation_client::update(THD *thd)
bool sys_var_timestamp::update(THD *thd, set_var *var) bool sys_var_timestamp::update(THD *thd, set_var *var)
{ {
time_t tmp= (time_t) var->value->val_int(); thd->set_time((time_t) var->save_result.ulonglong_value);
if (thd->net.report_error)
return 1;
thd->set_time(tmp);
return 0; return 0;
} }
...@@ -1824,11 +1812,7 @@ byte *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type, ...@@ -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) bool sys_var_last_insert_id::update(THD *thd, set_var *var)
{ {
ulonglong tmp= var->value->val_int(); thd->insert_id(var->save_result.ulonglong_value);
if (thd->net.report_error)
return 1;
thd->insert_id(tmp);
return 0; return 0;
} }
...@@ -1843,11 +1827,7 @@ byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type, ...@@ -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) bool sys_var_insert_id::update(THD *thd, set_var *var)
{ {
ulonglong tmp= var->value->val_int(); thd->next_insert_id= var->save_result.ulonglong_value;
if (thd->net.report_error)
return 1;
thd->next_insert_id= tmp;
return 0; return 0;
} }
...@@ -1860,6 +1840,7 @@ byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type, ...@@ -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) 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 #ifndef NO_EMBEDDED_ACCESS_CHECKS
if (thd->master_access & SUPER_ACL) if (thd->master_access & SUPER_ACL)
return 0; return 0;
...@@ -1887,6 +1868,7 @@ bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) ...@@ -1887,6 +1868,7 @@ bool sys_var_slave_skip_counter::check(THD *thd, set_var *var)
} }
pthread_mutex_unlock(&active_mi->rli.run_lock); pthread_mutex_unlock(&active_mi->rli.run_lock);
UNLOCK_ACTIVE_MI; UNLOCK_ACTIVE_MI;
var->save_result.ulong_value= (ulong) var->value->val_int();
return result; return result;
} }
...@@ -1903,7 +1885,7 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) ...@@ -1903,7 +1885,7 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
if (!active_mi->rli.slave_running) if (!active_mi->rli.slave_running)
{ {
pthread_mutex_lock(&active_mi->rli.data_lock); 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.data_lock);
} }
pthread_mutex_unlock(&active_mi->rli.run_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) ...@@ -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) bool sys_var_rand_seed1::update(THD *thd, set_var *var)
{ {
ulong tmp= (ulong) var->value->val_int(); thd->rand.seed1= (ulong) var->save_result.ulonglong_value;
if (thd->net.report_error)
return 1;
thd->rand.seed1= tmp;
return 0; return 0;
} }
bool sys_var_rand_seed2::update(THD *thd, set_var *var) bool sys_var_rand_seed2::update(THD *thd, set_var *var)
{ {
ulong tmp= (ulong) var->value->val_int(); thd->rand.seed2= (ulong) var->save_result.ulonglong_value;
if (thd->net.report_error)
return 1;
thd->rand.seed2= tmp;
return 0; return 0;
} }
...@@ -2153,6 +2127,8 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list) ...@@ -2153,6 +2127,8 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list)
if ((error=var->check(thd))) if ((error=var->check(thd)))
DBUG_RETURN(error); DBUG_RETURN(error);
} }
if (thd->net.report_error)
DBUG_RETURN(1);
it.rewind(); it.rewind();
while ((var=it++)) while ((var=it++))
error|= var->update(thd); // Returns 0, -1 or 1 error|= var->update(thd); // Returns 0, -1 or 1
...@@ -2215,7 +2191,8 @@ int set_var::update(THD *thd) ...@@ -2215,7 +2191,8 @@ int set_var::update(THD *thd)
int set_var_user::check(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 ...@@ -57,7 +57,7 @@ class sys_var
:name(name_arg),after_update(func) :name(name_arg),after_update(func)
{} {}
virtual ~sys_var() {} 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_enum(THD *thd, set_var *var, TYPELIB *enum_names);
bool check_set(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; virtual bool update(THD *thd, set_var *var)=0;
...@@ -656,6 +656,7 @@ class set_var :public set_var_base ...@@ -656,6 +656,7 @@ class set_var :public set_var_base
{ {
CHARSET_INFO *charset; CHARSET_INFO *charset;
ulong ulong_value; ulong ulong_value;
ulonglong ulonglong_value;
} save_result; } save_result;
LEX_STRING base; /* for structs */ 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