diff options
-rw-r--r-- | mysql-test/r/plugin.result | 27 | ||||
-rw-r--r-- | mysql-test/t/plugin.test | 35 | ||||
-rw-r--r-- | sql/set_var.cc | 41 | ||||
-rw-r--r-- | sql/sql_parse.cc | 12 | ||||
-rw-r--r-- | sql/sql_plugin.cc | 39 | ||||
-rw-r--r-- | storage/example/ha_example.cc | 14 |
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 }; |