summaryrefslogtreecommitdiff
path: root/sql/set_var.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/set_var.cc')
-rw-r--r--sql/set_var.cc236
1 files changed, 159 insertions, 77 deletions
diff --git a/sql/set_var.cc b/sql/set_var.cc
index f14068fcfcb..84e628fbddf 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -110,6 +110,7 @@ static void sys_default_init_connect(THD*, enum_var_type type);
static bool sys_update_init_slave(THD*, set_var*);
static void sys_default_init_slave(THD*, enum_var_type type);
static bool set_option_bit(THD *thd, set_var *var);
+static bool set_option_log_bin_bit(THD *thd, set_var *var);
static bool set_option_autocommit(THD *thd, set_var *var);
static int check_log_update(THD *thd, set_var *var);
static bool set_log_update(THD *thd, set_var *var);
@@ -134,8 +135,6 @@ static int check_max_delayed_threads(THD *thd, set_var *var);
static void fix_thd_mem_root(THD *thd, enum_var_type type);
static void fix_trans_mem_root(THD *thd, enum_var_type type);
static void fix_server_id(THD *thd, enum_var_type type);
-static ulonglong fix_unsigned(THD *, ulonglong, const struct my_option *);
-static bool get_unsigned(THD *thd, set_var *var);
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);
@@ -731,7 +730,7 @@ static sys_var_thd_bit sys_log_update(&vars, "sql_log_update",
OPTION_BIN_LOG);
static sys_var_thd_bit sys_log_binlog(&vars, "sql_log_bin",
check_log_update,
- set_option_bit,
+ set_option_log_bin_bit,
OPTION_BIN_LOG);
static sys_var_thd_bit sys_sql_warnings(&vars, "sql_warnings", 0,
set_option_bit,
@@ -1370,6 +1369,19 @@ static void fix_server_id(THD *thd, enum_var_type type)
}
+/**
+ Throw warning (error in STRICT mode) if value for variable needed bounding.
+ Only call from check(), not update(), because an error in update() would be
+ bad mojo. Plug-in interface also uses this.
+
+ @param thd thread handle
+ @param fixed did we have to correct the value? (throw warn/err if so)
+ @param unsignd is value's type unsigned?
+ @param name variable's name
+ @param val variable's value
+
+ @retval TRUE on error, FALSE otherwise (warning or OK)
+ */
bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
const char *name, longlong val)
{
@@ -1395,26 +1407,128 @@ bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
return FALSE;
}
-static ulonglong fix_unsigned(THD *thd, ulonglong num,
+
+/**
+ 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 if none
+ */
+static void bound_unsigned(THD *thd, ulonglong *num,
const struct my_option *option_limits)
{
- my_bool fixed= FALSE;
- ulonglong out= getopt_ull_limit_value(num, option_limits, &fixed);
+ if (option_limits)
+ {
+ my_bool fixed = FALSE;
+ ulonglong unadjusted= *num;
+
+ *num= getopt_ull_limit_value(unadjusted, option_limits, &fixed);
- throw_bounds_warning(thd, fixed, TRUE, option_limits->name, (longlong) num);
- return out;
+ 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;
+ }
+ }
}
-static bool get_unsigned(THD *thd, set_var *var)
-{
+
+/**
+ Get unsigned system-variable.
+ Negative value does not wrap around, but becomes zero.
+ Check user-supplied value for a systemvariable against bounds.
+ If we needed to adjust the value, throw a warning or error depending
+ on SQL-mode.
+
+ @param thd thread handle
+ @param var the system-variable to get
+ @param user_max a limit given with --maximum-variable-name=... or 0
+ @param var_type function will bound on systems where necessary.
+
+ @retval TRUE on error, FALSE otherwise (warning or OK)
+ */
+static bool get_unsigned(THD *thd, set_var *var, ulonglong user_max,
+ ulong var_type)
+{
+ 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)
var->save_result.ulonglong_value= (ulonglong) var->value->val_int();
else
{
longlong v= var->value->val_int();
var->save_result.ulonglong_value= (ulonglong) ((v < 0) ? 0 : v);
+ if (v < 0)
+ {
+ warnings++;
+ if (throw_bounds_warning(thd, TRUE, FALSE, var->var->name, v))
+ return TRUE; /* warning was promoted to error, give up */
+ }
}
- return 0;
+
+ unadjusted= var->save_result.ulonglong_value;
+
+ /* max, if any */
+
+ if ((user_max > 0) && (unadjusted > user_max))
+ {
+ var->save_result.ulonglong_value= user_max;
+
+ if ((warnings == 0) && throw_bounds_warning(thd, TRUE, TRUE,
+ var->var->name,
+ (longlong) unadjusted))
+ return TRUE;
+
+ 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 && var_type != GET_ULL)
+ {
+ bzero(&fallback, sizeof(fallback));
+ fallback.var_type= var_type;
+ limits= &fallback;
+ }
+
+ /* fix_unsigned() */
+ if (limits)
+ {
+ my_bool fixed;
+
+ 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,
+ var->var->name,
+ (longlong) unadjusted))
+ return TRUE;
+ }
+
+ return FALSE;
}
@@ -1428,29 +1542,13 @@ sys_var_long_ptr(sys_var_chain *chain, const char *name_arg, ulong *value_ptr_ar
bool sys_var_long_ptr_global::check(THD *thd, set_var *var)
{
- return get_unsigned(thd, var);
+ return get_unsigned(thd, var, 0, GET_ULONG);
}
bool sys_var_long_ptr_global::update(THD *thd, set_var *var)
{
- ulonglong tmp= var->save_result.ulonglong_value;
pthread_mutex_lock(guard);
- if (option_limits)
- *value= (ulong) fix_unsigned(thd, tmp, option_limits);
- else
- {
-#if SIZEOF_LONG < SIZEOF_LONG_LONG
- /* Avoid overflows on 32 bit systems */
- if (tmp > ULONG_MAX)
- {
- tmp= ULONG_MAX;
- throw_bounds_warning(thd, TRUE, TRUE, name,
- (longlong) var->save_result.ulonglong_value);
- }
-#endif
- *value= (ulong) tmp;
- }
-
+ *value= (ulong) var->save_result.ulonglong_value;
pthread_mutex_unlock(guard);
return 0;
}
@@ -1470,10 +1568,8 @@ bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var)
{
ulonglong tmp= var->save_result.ulonglong_value;
pthread_mutex_lock(&LOCK_global_system_variables);
- if (option_limits)
- *value= (ulonglong) fix_unsigned(thd, tmp, option_limits);
- else
- *value= (ulonglong) tmp;
+ bound_unsigned(thd, &tmp, option_limits);
+ *value= (ulonglong) tmp;
pthread_mutex_unlock(&LOCK_global_system_variables);
return 0;
}
@@ -1523,36 +1619,18 @@ uchar *sys_var_enum_const::value_ptr(THD *thd, enum_var_type type,
bool sys_var_thd_ulong::check(THD *thd, set_var *var)
{
- return (get_unsigned(thd, var) ||
- (check_func && (*check_func)(thd, var)));
+ if (get_unsigned(thd, var, max_system_variables.*offset, GET_ULONG))
+ return TRUE;
+ DBUG_ASSERT(var->save_result.ulonglong_value <= ULONG_MAX);
+ return ((check_func && (*check_func)(thd, var)));
}
bool sys_var_thd_ulong::update(THD *thd, set_var *var)
{
- ulonglong tmp= var->save_result.ulonglong_value;
-
- /* Don't use bigger value than given with --maximum-variable-name=.. */
- if (tmp > max_system_variables.*offset)
- {
- throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) tmp);
- tmp= max_system_variables.*offset;
- }
-
- if (option_limits)
- tmp= fix_unsigned(thd, tmp, option_limits);
-#if SIZEOF_LONG < SIZEOF_LONG_LONG
- else if (tmp > ULONG_MAX)
- {
- tmp= ULONG_MAX;
- throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) var->save_result.ulonglong_value);
- }
-#endif
-
- DBUG_ASSERT(tmp <= ULONG_MAX);
if (var->type == OPT_GLOBAL)
- global_system_variables.*offset= (ulong) tmp;
+ global_system_variables.*offset= (ulong) var->save_result.ulonglong_value;
else
- thd->variables.*offset= (ulong) tmp;
+ thd->variables.*offset= (ulong) var->save_result.ulonglong_value;
return 0;
}
@@ -1590,8 +1668,8 @@ bool sys_var_thd_ha_rows::update(THD *thd, set_var *var)
if ((ha_rows) tmp > max_system_variables.*offset)
tmp= max_system_variables.*offset;
- if (option_limits)
- tmp= (ha_rows) fix_unsigned(thd, tmp, option_limits);
+ bound_unsigned(thd, &tmp, option_limits);
+
if (var->type == OPT_GLOBAL)
{
/* Lock is needed to make things safe on 32 bit systems */
@@ -1632,27 +1710,21 @@ uchar *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type,
bool sys_var_thd_ulonglong::check(THD *thd, set_var *var)
{
- return get_unsigned(thd, var);
+ return get_unsigned(thd, var, max_system_variables.*offset, GET_ULL);
}
bool sys_var_thd_ulonglong::update(THD *thd, set_var *var)
{
- ulonglong tmp= var->save_result.ulonglong_value;
-
- if (tmp > max_system_variables.*offset)
- tmp= max_system_variables.*offset;
-
- if (option_limits)
- tmp= fix_unsigned(thd, tmp, option_limits);
if (var->type == OPT_GLOBAL)
{
/* Lock is needed to make things safe on 32 bit systems */
pthread_mutex_lock(&LOCK_global_system_variables);
- global_system_variables.*offset= (ulonglong) tmp;
+ global_system_variables.*offset= (ulonglong)
+ var->save_result.ulonglong_value;
pthread_mutex_unlock(&LOCK_global_system_variables);
}
else
- thd->variables.*offset= (ulonglong) tmp;
+ thd->variables.*offset= (ulonglong) var->save_result.ulonglong_value;
return 0;
}
@@ -2284,10 +2356,10 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
goto end;
}
- key_cache->param_buff_size=
- (ulonglong) fix_unsigned(thd, tmp, option_limits);
+ 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);
@@ -2313,7 +2385,7 @@ end:
*/
bool sys_var_key_cache_long::update(THD *thd, set_var *var)
{
- ulong tmp= (ulong) var->value->val_int();
+ ulonglong tmp= var->value->val_int();
LEX_STRING *base_name= &var->base;
bool error= 0;
@@ -2338,8 +2410,8 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var)
if (key_cache->in_init)
goto end;
- *((ulong*) (((char*) key_cache) + offset))=
- (ulong) fix_unsigned(thd, tmp, option_limits);
+ bound_unsigned(thd, &tmp, option_limits);
+ *((ulong*) (((char*) key_cache) + offset))= (ulong) tmp;
/*
Don't create a new key cache if it didn't exist
@@ -2963,6 +3035,16 @@ static bool set_option_bit(THD *thd, set_var *var)
return 0;
}
+/*
+ Functions to be only used to update thd->options OPTION_BIN_LOG bit
+*/
+static bool set_option_log_bin_bit(THD *thd, set_var *var)
+{
+ set_option_bit(thd, var);
+ if (!thd->in_sub_stmt)
+ thd->sql_log_bin_toplevel= thd->options & OPTION_BIN_LOG;
+ return 0;
+}
static bool set_option_autocommit(THD *thd, set_var *var)
{
@@ -3682,7 +3764,7 @@ bool sys_var_thd_storage_engine::update(THD *thd, set_var *var)
void sys_var_thd_table_type::warn_deprecated(THD *thd)
{
- WARN_DEPRECATED(thd, "5.2", "@@table_type", "'@@storage_engine'");
+ WARN_DEPRECATED(thd, "6.0", "@@table_type", "'@@storage_engine'");
}
void sys_var_thd_table_type::set_default(THD *thd, enum_var_type type)
@@ -3944,7 +4026,7 @@ bool process_key_caches(process_key_cache_t func)
void sys_var_trust_routine_creators::warn_deprecated(THD *thd)
{
- WARN_DEPRECATED(thd, "5.2", "@@log_bin_trust_routine_creators",
+ WARN_DEPRECATED(thd, "6.0", "@@log_bin_trust_routine_creators",
"'@@log_bin_trust_function_creators'");
}