From ce2c46ddd6676960e0c002aa83c7913e85ebdc47 Mon Sep 17 00:00:00 2001 From: unknown <bell@sanja.is.com.ua> Date: Fri, 24 Oct 2003 17:28:32 +0300 Subject: [PATCH] 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 --- mysql-test/r/variables.result | 24 ++++++++++++ mysql-test/t/variables.test | 17 +++++++++ sql/item_func.cc | 71 +++++++++++++++++++++++++++++------ sql/item_func.h | 9 +++++ sql/set_var.cc | 71 ++++++++++++----------------------- sql/set_var.h | 3 +- 6 files changed, 136 insertions(+), 59 deletions(-) diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index d65b44e784..52ea28e607 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -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 diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 396fb3ac72..c53559ed4c 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -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; + diff --git a/sql/item_func.cc b/sql/item_func.cc index 929f85a112..ce0614f1e7 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -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); } diff --git a/sql/item_func.h b/sql/item_func.h index 8086e65786..fe9c264521 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -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 @@ public: 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); diff --git a/sql/set_var.cc b/sql/set_var.cc index d4030c9d1a..d09544697e 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -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; } diff --git a/sql/set_var.h b/sql/set_var.h index 4c67c5ccc5..752f275c9f 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -57,7 +57,7 @@ public: :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 @@ public: { CHARSET_INFO *charset; ulong ulong_value; + ulonglong ulonglong_value; } save_result; LEX_STRING base; /* for structs */ -- 2.30.9