summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbell@sanja.is.com.ua <>2003-10-24 17:28:32 +0300
committerbell@sanja.is.com.ua <>2003-10-24 17:28:32 +0300
commitf349adf8de5be3d5f1a5ba09913828795a59c8d3 (patch)
tree63bd3fb6c3566519729c8f88b30bbb74d936361e
parent4e1920762ab8af492181d9d32261a64ce7e3ddb2 (diff)
downloadmariadb-git-f349adf8de5be3d5f1a5ba09913828795a59c8d3.tar.gz
support 'parallel' updates and rallback of whole statement in case of error in evalueting value which should be assigned
(BUG#1484)
-rw-r--r--mysql-test/r/variables.result24
-rw-r--r--mysql-test/t/variables.test17
-rw-r--r--sql/item_func.cc71
-rw-r--r--sql/item_func.h9
-rw-r--r--sql/set_var.cc71
-rw-r--r--sql/set_var.h3
6 files changed, 136 insertions, 59 deletions
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index d65b44e7846..52ea28e6076 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 396fb3ac722..c53559ed4cf 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 929f85a112d..ce0614f1e7c 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 8086e65786d..fe9c2645216 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 d4030c9d1a6..d09544697ea 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 4c67c5ccc59..752f275c9f2 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 */