diff --git a/sql/set_var.cc b/sql/set_var.cc index ff32ec2458e3523d717b1209290ea19107a7d174..01cdecfca5b3335b35a64d080edf6826ec896057 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1405,22 +1405,38 @@ bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd, /** check an unsigned user-supplied value for a systemvariable against bounds. + TODO: This is a wrapper function to call clipping from within an update() + function. Calling bounds from within update() is fair game in theory, + but we can only send warnings from in there, not errors, and besides, + it violates our model of separating check from update phase. + To avoid breaking out of the server with an ASSERT() in strict mode, + we pretend we're not in strict mode when we go through here. Bug#43233 + was opened to remind us to replace this kludge with The Right Thing, + which of course is to do the check in the actual check phase, and then + throw an error or warning accordingly. + @param thd thread handle @param num the value to limit - @param option_limits the bounds-record, or NULL - - @retval whether or not we needed to bound + @param option_limits the bounds-record, or NULL if none */ -static my_bool bound_unsigned(THD *thd, ulonglong *num, +static void bound_unsigned(THD *thd, ulonglong *num, const struct my_option *option_limits) { - my_bool fixed = FALSE; - ulonglong unadjusted= *num; - if (option_limits) + { + my_bool fixed = FALSE; + ulonglong unadjusted= *num; + *num= getopt_ull_limit_value(unadjusted, option_limits, &fixed); - return fixed; + if (fixed) + { + ulong ssm= thd->variables.sql_mode; + thd->variables.sql_mode&= ~MODE_STRICT_ALL_TABLES; + throw_bounds_warning(thd, fixed, TRUE, option_limits->name, unadjusted); + thd->variables.sql_mode= ssm; + } + } } @@ -1445,6 +1461,7 @@ static bool get_unsigned(THD *thd, set_var *var, ulonglong user_max, int warnings= 0; ulonglong unadjusted; const struct my_option *limits= var->var->option_limits; + struct my_option fallback; /* get_unsigned() */ if (var->value->unsigned_flag) @@ -1477,32 +1494,33 @@ static bool get_unsigned(THD *thd, set_var *var, ulonglong user_max, warnings++; } + /* + if the sysvar doesn't have a proper bounds record but the check + function would like bounding to ULONG where its size differs from + that of ULONGLONG, we make up a bogus limits record here and let + the usual suspects handle the actual limiting. + */ + + if (!limits && bound2ulong) + { + bzero(&fallback, sizeof(fallback)); + fallback.var_type= GET_ULONG; + limits= &fallback; + } + /* fix_unsigned() */ if (limits) { my_bool fixed; - var->save_result.ulonglong_value= getopt_ull_limit_value(unadjusted, + var->save_result.ulonglong_value= getopt_ull_limit_value(var->save_result. + ulonglong_value, limits, &fixed); if ((warnings == 0) && throw_bounds_warning(thd, fixed, TRUE, limits->name, (longlong) unadjusted)) return TRUE; } - else if (bound2ulong) - { -#if SIZEOF_LONG < SIZEOF_LONG_LONG - /* Avoid overflows on 32 bit systems */ - if (var->save_result.ulonglong_value > ULONG_MAX) - { - var->save_result.ulonglong_value= ULONG_MAX; - if ((warnings == 0) && throw_bounds_warning(thd, TRUE, TRUE, - var->var->name, - (longlong) unadjusted)) - return TRUE; - } -#endif - } return FALSE; } @@ -2334,7 +2352,7 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) bound_unsigned(thd, &tmp, option_limits); key_cache->param_buff_size= (ulonglong) tmp; - /* If key cache didn't existed initialize it, else resize it */ + /* If key cache didn't exist initialize it, else resize it */ key_cache->in_init= 1; pthread_mutex_unlock(&LOCK_global_system_variables);