summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/plugin.result27
-rw-r--r--mysql-test/t/plugin.test35
-rw-r--r--sql/set_var.cc41
-rw-r--r--sql/sql_parse.cc12
-rw-r--r--sql/sql_plugin.cc39
-rw-r--r--storage/example/ha_example.cc14
6 files changed, 125 insertions, 43 deletions
diff --git a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result
index e4af1535775..782d2a5a9a4 100644
--- a/mysql-test/r/plugin.result
+++ b/mysql-test/r/plugin.result
@@ -27,3 +27,30 @@ SET GLOBAL example_enum_var= e2;
SET GLOBAL example_enum_var= impossible;
ERROR 42000: Variable 'enum_var' can't be set to the value of 'impossible'
UNINSTALL PLUGIN example;
+INSTALL PLUGIN example SONAME 'ha_example.so';
+select @@session.sql_mode into @old_sql_mode;
+set session sql_mode='';
+set global example_ulong_var=500;
+select @@global.example_ulong_var;
+@@global.example_ulong_var
+500
+set global example_ulong_var=1111;
+Warnings:
+Warning 1292 Truncated incorrect ulong_var value: '1111'
+select @@global.example_ulong_var;
+@@global.example_ulong_var
+1000
+set session sql_mode='STRICT_ALL_TABLES';
+set global example_ulong_var=500;
+select @@global.example_ulong_var;
+@@global.example_ulong_var
+500
+set global example_ulong_var=1111;
+ERROR 42000: Variable 'ulong_var' can't be set to the value of '1111'
+select @@global.example_ulong_var;
+@@global.example_ulong_var
+500
+set session sql_mode=@old_sql_mode;
+set session old=bla;
+ERROR HY000: Variable 'old' is a read only variable
+UNINSTALL PLUGIN example;
diff --git a/mysql-test/t/plugin.test b/mysql-test/t/plugin.test
index d8d6d069676..0635a58a4a6 100644
--- a/mysql-test/t/plugin.test
+++ b/mysql-test/t/plugin.test
@@ -39,3 +39,38 @@ SET GLOBAL example_enum_var= e2;
SET GLOBAL example_enum_var= impossible;
UNINSTALL PLUGIN example;
+
+
+
+#
+# Bug #32757 hang with sql_mode set when setting some global variables
+#
+INSTALL PLUGIN example SONAME 'ha_example.so';
+
+select @@session.sql_mode into @old_sql_mode;
+
+# first, try normal sql_mode (no error, send OK)
+set session sql_mode='';
+set global example_ulong_var=500;
+select @@global.example_ulong_var;
+# overflow -- correct value, but throw warning
+set global example_ulong_var=1111;
+select @@global.example_ulong_var;
+
+# now, try STRICT (error occurrs, no message is sent, so send default)
+set session sql_mode='STRICT_ALL_TABLES';
+set global example_ulong_var=500;
+select @@global.example_ulong_var;
+# overflow -- throw warning, do NOT change value
+--error ER_WRONG_VALUE_FOR_VAR
+set global example_ulong_var=1111;
+select @@global.example_ulong_var;
+
+set session sql_mode=@old_sql_mode;
+
+# finally, show that conditions that already raised an error are not
+# adversely affected (error was already sent, do nothing)
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+set session old=bla;
+
+UNINSTALL PLUGIN example;
diff --git a/sql/set_var.cc b/sql/set_var.cc
index a01a0b49dbc..a25bbee3350 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -123,7 +123,8 @@ static void fix_server_id(THD *thd, enum_var_type type);
static ulonglong fix_unsigned(THD *thd, ulonglong num,
const struct my_option *option_limits);
static bool get_unsigned(THD *thd, set_var *var);
-static void throw_bounds_warning(THD *thd, const char *name, ulonglong num);
+bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
+ const char *name, longlong val);
static KEY_CACHE *create_key_cache(const char *name, uint length);
void fix_sql_mode_var(THD *thd, enum_var_type type);
static uchar *get_error_count(THD *thd);
@@ -1106,13 +1107,29 @@ static void fix_server_id(THD *thd, enum_var_type type)
}
-static void throw_bounds_warning(THD *thd, const char *name, ulonglong num)
+bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
+ const char *name, longlong val)
{
- char buf[22];
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE,
- ER(ER_TRUNCATED_WRONG_VALUE), name,
- ullstr(num, buf));
+ if (fixed)
+ {
+ char buf[22];
+
+ if (unsignd)
+ ullstr((ulonglong) val, buf);
+ else
+ llstr(val, buf);
+
+ if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES)
+ {
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf);
+ return TRUE;
+ }
+
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE), name, buf);
+ }
+ return FALSE;
}
static ulonglong fix_unsigned(THD *thd, ulonglong num,
@@ -1121,8 +1138,7 @@ static ulonglong fix_unsigned(THD *thd, ulonglong num,
bool fixed= FALSE;
ulonglong out= getopt_ull_limit_value(num, option_limits, &fixed);
- if (fixed)
- throw_bounds_warning(thd, option_limits->name, num);
+ throw_bounds_warning(thd, fixed, TRUE, option_limits->name, (longlong) num);
return out;
}
@@ -1165,7 +1181,8 @@ bool sys_var_long_ptr_global::update(THD *thd, set_var *var)
if (tmp > ULONG_MAX)
{
tmp= ULONG_MAX;
- throw_bounds_warning(thd, name, var->save_result.ulonglong_value);
+ throw_bounds_warning(thd, TRUE, TRUE, name,
+ (longlong) var->save_result.ulonglong_value);
}
#endif
*value= (ulong) tmp;
@@ -1250,7 +1267,7 @@ bool sys_var_thd_ulong::update(THD *thd, set_var *var)
/* Don't use bigger value than given with --maximum-variable-name=.. */
if ((ulong) tmp > max_system_variables.*offset)
{
- throw_bounds_warning(thd, name, tmp);
+ throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) tmp);
tmp= max_system_variables.*offset;
}
@@ -1260,7 +1277,7 @@ bool sys_var_thd_ulong::update(THD *thd, set_var *var)
else if (tmp > ULONG_MAX)
{
tmp= ULONG_MAX;
- throw_bounds_warning(thd, name, var->save_result.ulonglong_value);
+ throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) var->save_result.ulonglong_value);
}
#endif
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index b60a72e4c53..a74c4a01699 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3185,6 +3185,18 @@ end_with_restore_list:
thd->one_shot_set|= lex->one_shot_set;
send_ok(thd);
}
+ else
+ {
+ /*
+ We encountered some sort of error, but no message was sent.
+ Send something semi-generic here since we don't know which
+ assignment in the list caused the error.
+ */
+ if (!thd->is_error())
+ my_error(ER_WRONG_ARGUMENTS,MYF(0),"SET");
+ goto error;
+ }
+
break;
}
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 2a86844c8c6..5fafa751379 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -210,6 +210,8 @@ static void reap_plugins(void);
/* declared in set_var.cc */
extern sys_var *intern_find_sys_var(const char *str, uint length, bool no_error);
+extern bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
+ const char *name, longlong val);
#ifdef EMBEDDED_LIBRARY
/* declared in sql_base.cc */
@@ -1888,16 +1890,8 @@ static int check_func_int(THD *thd, struct st_mysql_sys_var *var,
else
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
- if (fixed)
- {
- char buf[22];
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE,
- ER(ER_TRUNCATED_WRONG_VALUE), var->name,
- ullstr(tmp, buf));
- }
- return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) &&
- (*(int *)save != (int) tmp);
+ return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
+ var->name, (longlong) tmp);
}
@@ -1916,16 +1910,8 @@ static int check_func_long(THD *thd, struct st_mysql_sys_var *var,
else
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
- if (fixed)
- {
- char buf[22];
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE,
- ER(ER_TRUNCATED_WRONG_VALUE), var->name,
- ullstr(tmp, buf));
- }
- return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) &&
- (*(long *)save != (long) tmp);
+ return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
+ var->name, (longlong) tmp);
}
@@ -1937,7 +1923,6 @@ static int check_func_longlong(THD *thd, struct st_mysql_sys_var *var,
struct my_option options;
value->val_int(value, &tmp);
plugin_opt_set_limits(&options, var);
- *(ulonglong *)save= getopt_ull_limit_value(tmp, &options, &fixed);
if (var->flags & PLUGIN_VAR_UNSIGNED)
*(ulonglong *)save= getopt_ull_limit_value((ulonglong) tmp, &options,
@@ -1945,16 +1930,8 @@ static int check_func_longlong(THD *thd, struct st_mysql_sys_var *var,
else
*(longlong *)save= getopt_ll_limit_value(tmp, &options, &fixed);
- if (fixed)
- {
- char buf[22];
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE,
- ER(ER_TRUNCATED_WRONG_VALUE), var->name,
- ullstr(tmp, buf));
- }
- return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) &&
- (*(long long *)save != tmp);
+ return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED,
+ var->name, (longlong) tmp);
}
static int check_func_str(THD *thd, struct st_mysql_sys_var *var,
diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc
index 6d9f4841e06..604722c3c8c 100644
--- a/storage/example/ha_example.cc
+++ b/storage/example/ha_example.cc
@@ -849,6 +849,7 @@ struct st_mysql_storage_engine example_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
static ulong srv_enum_var= 0;
+static ulong srv_ulong_var= 0;
const char *enum_var_names[]=
{
@@ -871,8 +872,21 @@ static MYSQL_SYSVAR_ENUM(
0, // def
&enum_var_typelib); // typelib
+static MYSQL_SYSVAR_ULONG(
+ ulong_var,
+ srv_ulong_var,
+ PLUGIN_VAR_RQCMDARG,
+ "0..1000",
+ NULL,
+ NULL,
+ 8,
+ 0,
+ 1000,
+ 0);
+
static struct st_mysql_sys_var* example_system_variables[]= {
MYSQL_SYSVAR(enum_var),
+ MYSQL_SYSVAR(ulong_var),
NULL
};