diff options
Diffstat (limited to 'sql/set_var.cc')
-rw-r--r-- | sql/set_var.cc | 440 |
1 files changed, 377 insertions, 63 deletions
diff --git a/sql/set_var.cc b/sql/set_var.cc index 7ad528f0eae..b5430c56865 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -35,6 +35,7 @@ #include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone #include "sql_acl.h" // SUPER_ACL #include "sql_select.h" // free_underlaid_joins +#include "sql_show.h" #include "sql_view.h" // updatable_views_with_limit_typelib #include "lock.h" // lock_global_read_lock, // make_global_read_lock_block_commit, @@ -142,8 +143,7 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg, on_check_function on_check_func, on_update_function on_update_func, const char *substitute) : - next(0), - binlog_status(binlog_status_arg), + next(0), binlog_status(binlog_status_arg), value_origin(COMPILE_TIME), flags(flags_arg), show_val_type(show_val_type_arg), guard(lock), offset(off), on_check(on_check_func), on_update(on_update_func), deprecation_substitute(substitute), @@ -171,6 +171,8 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg, option.arg_type= getopt_arg_type; option.value= (uchar **)global_var_ptr(); option.def_value= def_val; + option.app_type= this; + option.var_type= flags & AUTO_SET ? GET_AUTO : 0; if (chain->last) chain->last->next= this; @@ -192,6 +194,7 @@ bool sys_var::update(THD *thd, set_var *var) */ AutoWLock lock1(&PLock_global_system_variables); AutoWLock lock2(guard); + value_origin= SQL; return global_update(thd, var) || (on_update && on_update(this, thd, OPT_GLOBAL)); } @@ -200,12 +203,12 @@ bool sys_var::update(THD *thd, set_var *var) (on_update && on_update(this, thd, OPT_SESSION)); } -uchar *sys_var::session_value_ptr(THD *thd, LEX_STRING *base) +uchar *sys_var::session_value_ptr(THD *thd, const LEX_STRING *base) { return session_var_ptr(thd); } -uchar *sys_var::global_value_ptr(THD *thd, LEX_STRING *base) +uchar *sys_var::global_value_ptr(THD *thd, const LEX_STRING *base) { return global_var_ptr(); } @@ -238,8 +241,9 @@ bool sys_var::check(THD *thd, set_var *var) return false; } -uchar *sys_var::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) +uchar *sys_var::value_ptr(THD *thd, enum_var_type type, const LEX_STRING *base) { + DBUG_ASSERT(base); if (type == OPT_GLOBAL || scope() == GLOBAL) { mysql_mutex_assert_owner(&LOCK_global_system_variables); @@ -261,12 +265,10 @@ bool sys_var::set_default(THD *thd, set_var* var) } -#define do_num_val(T,CMD) \ -do { \ - mysql_mutex_lock(&LOCK_global_system_variables); \ - T val= *(T*) value_ptr(thd, type, base); \ - mysql_mutex_unlock(&LOCK_global_system_variables); \ - CMD; \ +#define do_num_val(T,CMD) \ +do { \ + T val= *(T*) value; \ + CMD; \ } while (0) #define case_for_integers(CMD) \ @@ -276,39 +278,38 @@ do { \ case SHOW_UINT: do_num_val (uint,CMD); \ case SHOW_ULONG: do_num_val (ulong,CMD); \ case SHOW_ULONGLONG:do_num_val (ulonglong,CMD); \ - case SHOW_HA_ROWS: do_num_val (ha_rows,CMD); \ - case SHOW_BOOL: do_num_val (bool,CMD); \ - case SHOW_MY_BOOL: do_num_val (my_bool,CMD) + case SHOW_HA_ROWS: do_num_val (ha_rows,CMD); -#define case_for_double(CMD) \ +#define case_for_double(CMD) \ case SHOW_DOUBLE: do_num_val (double,CMD) -#define case_get_string_as_lex_string \ - case SHOW_CHAR: \ - mysql_mutex_lock(&LOCK_global_system_variables); \ - sval.str= (char*) value_ptr(thd, type, base); \ - sval.length= sval.str ? strlen(sval.str) : 0; \ - break; \ - case SHOW_CHAR_PTR: \ - mysql_mutex_lock(&LOCK_global_system_variables); \ - sval.str= *(char**) value_ptr(thd, type, base); \ - sval.length= sval.str ? strlen(sval.str) : 0; \ - break; \ - case SHOW_LEX_STRING: \ - mysql_mutex_lock(&LOCK_global_system_variables); \ - sval= *(LEX_STRING *) value_ptr(thd, type, base); \ +#define case_get_string_as_lex_string \ + case SHOW_CHAR: \ + sval.str= (char*) value; \ + sval.length= sval.str ? strlen(sval.str) : 0; \ + break; \ + case SHOW_CHAR_PTR: \ + sval.str= *(char**) value; \ + sval.length= sval.str ? strlen(sval.str) : 0; \ + break; \ + case SHOW_LEX_STRING: \ + sval= *(LEX_STRING *) value; \ break longlong sys_var::val_int(bool *is_null, - THD *thd, enum_var_type type, LEX_STRING *base) + THD *thd, enum_var_type type, const LEX_STRING *base) { LEX_STRING sval; + AutoWLock lock(&PLock_global_system_variables); + const uchar *value= value_ptr(thd, type, base); *is_null= false; + switch (show_type()) { case_get_string_as_lex_string; case_for_integers(return val); case_for_double(return (longlong) val); + case SHOW_MY_BOOL: return *(my_bool*)value; default: my_error(ER_VAR_CANT_BE_READ, MYF(0), name.str); return 0; @@ -316,44 +317,63 @@ longlong sys_var::val_int(bool *is_null, longlong ret= 0; if (!(*is_null= !sval.str)) - ret= longlong_from_string_with_check(system_charset_info, + ret= longlong_from_string_with_check(charset(thd), sval.str, sval.str + sval.length); - mysql_mutex_unlock(&LOCK_global_system_variables); return ret; } -String *sys_var::val_str(String *str, - THD *thd, enum_var_type type, LEX_STRING *base) +String *sys_var::val_str_nolock(String *str, THD *thd, const uchar *value) { + static LEX_STRING bools[]= + { + { C_STRING_WITH_LEN("OFF") }, + { C_STRING_WITH_LEN("ON") } + }; + LEX_STRING sval; switch (show_type()) { case_get_string_as_lex_string; - case_for_integers(return str->set((ulonglong)val, system_charset_info) ? 0 : str); + case_for_integers(return str->set(val, system_charset_info) ? 0 : str); case_for_double(return str->set_real(val, 6, system_charset_info) ? 0 : str); + case SHOW_MY_BOOL: + sval= bools[(int)*(my_bool*)value]; + break; default: my_error(ER_VAR_CANT_BE_READ, MYF(0), name.str); return 0; } - if (!sval.str || str->copy(sval.str, sval.length, system_charset_info)) + if (!sval.str || str->copy(sval.str, sval.length, charset(thd))) str= NULL; - mysql_mutex_unlock(&LOCK_global_system_variables); return str; } +String *sys_var::val_str(String *str, + THD *thd, enum_var_type type, const LEX_STRING *base) +{ + AutoWLock lock(&PLock_global_system_variables); + const uchar *value= value_ptr(thd, type, base); + return val_str_nolock(str, thd, value); +} + + double sys_var::val_real(bool *is_null, - THD *thd, enum_var_type type, LEX_STRING *base) + THD *thd, enum_var_type type, const LEX_STRING *base) { LEX_STRING sval; + AutoWLock lock(&PLock_global_system_variables); + const uchar *value= value_ptr(thd, type, base); *is_null= false; + switch (show_type()) { case_get_string_as_lex_string; case_for_integers(return val); case_for_double(return val); + case SHOW_MY_BOOL: return *(my_bool*)value; default: my_error(ER_VAR_CANT_BE_READ, MYF(0), name.str); return 0; @@ -361,9 +381,8 @@ double sys_var::val_real(bool *is_null, double ret= 0; if (!(*is_null= !sval.str)) - ret= double_from_string_with_check(system_charset_info, + ret= double_from_string_with_check(charset(thd), sval.str, sval.str + sval.length); - mysql_mutex_unlock(&LOCK_global_system_variables); return ret; } @@ -384,7 +403,7 @@ void sys_var::do_deprecated_warning(THD *thd) : ER_WARN_DEPRECATED_SYNTAX; if (thd) push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_WARN_DEPRECATED_SYNTAX, ER(errmsg), + ER_WARN_DEPRECATED_SYNTAX, ER_THD(thd, errmsg), buf1, deprecation_substitute); else sql_print_warning(ER_DEFAULT(errmsg), buf1, deprecation_substitute); @@ -422,7 +441,7 @@ bool throw_bounds_warning(THD *thd, const char *name, } push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_TRUNCATED_WRONG_VALUE, - ER(ER_TRUNCATED_WRONG_VALUE), name, buf); + ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), name, buf); } return false; } @@ -442,7 +461,7 @@ bool throw_bounds_warning(THD *thd, const char *name, bool fixed, double v) } push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_TRUNCATED_WRONG_VALUE, - ER(ER_TRUNCATED_WRONG_VALUE), name, buf); + ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), name, buf); } return false; } @@ -453,6 +472,7 @@ CHARSET_INFO *sys_var::charset(THD *thd) system_charset_info; } + typedef struct old_names_map_st { const char *old_name; @@ -556,11 +576,7 @@ int mysql_del_sys_var_chain(sys_var *first) static int show_cmp(SHOW_VAR *a, SHOW_VAR *b) { -#ifdef WITH_WSREP - return my_strcasecmp(system_charset_info, a->name, b->name); -#else return strcmp(a->name, b->name); -#endif /* WITH_WSREP */ } @@ -569,7 +585,7 @@ static int show_cmp(SHOW_VAR *a, SHOW_VAR *b) @param thd current thread @param sorted If TRUE, the system variables should be sorted - @param type OPT_GLOBAL or OPT_SESSION for SHOW GLOBAL|SESSION VARIABLES + @param scope OPT_GLOBAL or OPT_SESSION for SHOW GLOBAL|SESSION VARIABLES @retval pointer Array of SHOW_VAR elements for display @@ -577,7 +593,7 @@ static int show_cmp(SHOW_VAR *a, SHOW_VAR *b) NULL FAILURE */ -SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type type) +SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type scope) { int count= system_variable_hash.records, i; int size= sizeof(SHOW_VAR) * (count + 1); @@ -592,7 +608,7 @@ SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type type) sys_var *var= (sys_var*) my_hash_element(&system_variable_hash, i); // don't show session-only variables in SHOW GLOBAL VARIABLES - if (type == OPT_GLOBAL && var->check_type(type)) + if (scope == OPT_GLOBAL && var->check_type(scope)) continue; show->name= var->name.str; @@ -660,9 +676,10 @@ sys_var *intern_find_sys_var(const char *str, uint length) -1 ERROR, message not sent */ -int sql_set_variables(THD *thd, List<set_var_base> *var_list) +int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free) { - int error; + int error= 0; + bool was_error= thd->is_error(); List_iterator_fast<set_var_base> it(*var_list); DBUG_ENTER("sql_set_variables"); @@ -672,7 +689,7 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list) if ((error= var->check(thd))) goto err; } - if (!(error= MY_TEST(thd->is_error()))) + if (was_error || !(error= MY_TEST(thd->is_error()))) { it.rewind(); while ((var= it++)) @@ -680,7 +697,8 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list) } err: - free_underlaid_joins(thd, &thd->lex->select_lex); + if (free) + free_underlaid_joins(thd, &thd->lex->select_lex); DBUG_RETURN(error); } @@ -721,7 +739,7 @@ int set_var::check(THD *thd) if ((!value->fixed && value->fix_fields(thd, &value)) || value->check_cols(1)) return -1; - if (var->check_update_type(value->result_type())) + if (var->check_update_type(value)) { my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name.str); return -1; @@ -771,12 +789,33 @@ int set_var::light_check(THD *thd) Consider set_var::check() method if there is a need to return an error due to logics. */ + int set_var::update(THD *thd) { return value ? var->update(thd, this) : var->set_default(thd, this); } +set_var::set_var(THD *thd, enum_var_type type_arg, sys_var *var_arg, + const LEX_STRING *base_name_arg, Item *value_arg) + :var(var_arg), type(type_arg), base(*base_name_arg) +{ + /* + If the set value is a field, change it to a string to allow things like + SET table_type=MYISAM; + */ + if (value_arg && value_arg->type() == Item::FIELD_ITEM) + { + Item_field *item= (Item_field*) value_arg; + // names are utf8 + if (!(value= new (thd->mem_root) Item_string_sys(thd, item->field_name))) + value=value_arg; /* Give error message later */ + } + else + value=value_arg; +} + + /***************************************************************************** Functions to handle SET @user_variable=const_expr *****************************************************************************/ @@ -819,7 +858,8 @@ int set_var_user::update(THD *thd) if (user_var_item->update()) { /* Give an error if it's not given already */ - my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), MYF(0)); + my_message(ER_SET_CONSTANTS_ONLY, ER_THD(thd, ER_SET_CONSTANTS_ONLY), + MYF(0)); return -1; } return 0; @@ -833,10 +873,7 @@ int set_var_user::update(THD *thd) int set_var_password::check(THD *thd) { #ifndef NO_EMBEDDED_ACCESS_CHECKS - user= get_current_user(thd, user); - /* Returns 1 as the function sends error to client */ - return check_change_password(thd, user->host.str, user->user.str, - password, strlen(password)) ? 1 : 0; + return check_change_password(thd, user); #else return 0; #endif @@ -845,9 +882,11 @@ int set_var_password::check(THD *thd) int set_var_password::update(THD *thd) { #ifndef NO_EMBEDDED_ACCESS_CHECKS - /* Returns 1 as the function sends error to client */ - return change_password(thd, user->host.str, user->user.str, password) ? - 1 : 0; + Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer; + thd->m_reprepare_observer= 0; + int res= change_password(thd, user); + thd->m_reprepare_observer= save_reprepare_observer; + return res; #else return 0; #endif @@ -856,6 +895,7 @@ int set_var_password::update(THD *thd) /***************************************************************************** Functions to handle SET ROLE *****************************************************************************/ + int set_var_role::check(THD *thd) { #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -875,6 +915,33 @@ int set_var_role::update(THD *thd) #endif } +/***************************************************************************** + Functions to handle SET DEFAULT ROLE +*****************************************************************************/ + +int set_var_default_role::check(THD *thd) +{ +#ifndef NO_EMBEDDED_ACCESS_CHECKS + real_user= get_current_user(thd, user); + int status= acl_check_set_default_role(thd, real_user->host.str, real_user->user.str); + return status; +#else + return 0; +#endif +} + +int set_var_default_role::update(THD *thd) +{ +#ifndef NO_EMBEDDED_ACCESS_CHECKS + Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer; + thd->m_reprepare_observer= 0; + int res= acl_set_default_role(thd, real_user->host.str, real_user->user.str, role.str); + thd->m_reprepare_observer= save_reprepare_observer; + return res; +#else + return 0; +#endif +} /***************************************************************************** Functions to handle SET NAMES and SET CHARACTER SET @@ -903,3 +970,250 @@ int set_var_collation_client::update(THD *thd) return 0; } +/***************************************************************************** + INFORMATION_SCHEMA.SYSTEM_VARIABLES +*****************************************************************************/ +static void store_value_ptr(Field *field, sys_var *var, String *str, + uchar *value_ptr) +{ + field->set_notnull(); + str= var->val_str_nolock(str, field->table->in_use, value_ptr); + if (str) + field->store(str->ptr(), str->length(), str->charset()); +} + +static void store_var(Field *field, sys_var *var, enum_var_type scope, + String *str) +{ + if (var->check_type(scope)) + return; + + store_value_ptr(field, var, str, + var->value_ptr(field->table->in_use, scope, &null_lex_str)); +} + +int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond) +{ + char name_buffer[NAME_CHAR_LEN]; + enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; + bool res= 1; + CHARSET_INFO *scs= system_charset_info; + StringBuffer<STRING_BUFFER_USUAL_SIZE> strbuf(scs); + const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : 0; + Field **fields=tables->table->field; + + DBUG_ASSERT(tables->table->in_use == thd); + + cond= make_cond_for_info_schema(thd, cond, tables); + thd->count_cuted_fields= CHECK_FIELD_WARN; + mysql_rwlock_rdlock(&LOCK_system_variables_hash); + + for (uint i= 0; i < system_variable_hash.records; i++) + { + sys_var *var= (sys_var*) my_hash_element(&system_variable_hash, i); + + strmake_buf(name_buffer, var->name.str); + my_caseup_str(system_charset_info, name_buffer); + + /* this must be done before evaluating cond */ + restore_record(tables->table, s->default_values); + fields[0]->store(name_buffer, strlen(name_buffer), scs); + + if ((wild && wild_case_compare(system_charset_info, name_buffer, wild)) + || (cond && !cond->val_int())) + continue; + + mysql_mutex_lock(&LOCK_global_system_variables); + + // SESSION_VALUE + store_var(fields[1], var, OPT_SESSION, &strbuf); + + // GLOBAL_VALUE + store_var(fields[2], var, OPT_GLOBAL, &strbuf); + + // GLOBAL_VALUE_ORIGIN + static const LEX_CSTRING origins[]= + { + { STRING_WITH_LEN("CONFIG") }, + { STRING_WITH_LEN("AUTO") }, + { STRING_WITH_LEN("SQL") }, + { STRING_WITH_LEN("COMPILE-TIME") }, + { STRING_WITH_LEN("ENVIRONMENT") } + }; + const LEX_CSTRING *origin= origins + var->value_origin; + fields[3]->store(origin->str, origin->length, scs); + + // DEFAULT_VALUE + uchar *def= var->is_readonly() && var->option.id < 0 + ? 0 : var->default_value_ptr(thd); + if (def) + store_value_ptr(fields[4], var, &strbuf, def); + + mysql_mutex_unlock(&LOCK_global_system_variables); + + // VARIABLE_SCOPE + static const LEX_CSTRING scopes[]= + { + { STRING_WITH_LEN("GLOBAL") }, + { STRING_WITH_LEN("SESSION") }, + { STRING_WITH_LEN("SESSION ONLY") } + }; + const LEX_CSTRING *scope= scopes + var->scope(); + fields[5]->store(scope->str, scope->length, scs); + + // VARIABLE_TYPE +#if SIZEOF_LONG == SIZEOF_INT +#define LONG_TYPE "INT" +#else +#define LONG_TYPE "BIGINT" +#endif + + static const LEX_CSTRING types[]= + { + { 0, 0 }, // unused 0 + { 0, 0 }, // GET_NO_ARG 1 + { STRING_WITH_LEN("BOOLEAN") }, // GET_BOOL 2 + { STRING_WITH_LEN("INT") }, // GET_INT 3 + { STRING_WITH_LEN("INT UNSIGNED") }, // GET_UINT 4 + { STRING_WITH_LEN(LONG_TYPE) }, // GET_LONG 5 + { STRING_WITH_LEN(LONG_TYPE " UNSIGNED") }, // GET_ULONG 6 + { STRING_WITH_LEN("BIGINT") }, // GET_LL 7 + { STRING_WITH_LEN("BIGINT UNSIGNED") }, // GET_ULL 8 + { STRING_WITH_LEN("VARCHAR") }, // GET_STR 9 + { STRING_WITH_LEN("VARCHAR") }, // GET_STR_ALLOC 10 + { 0, 0 }, // GET_DISABLED 11 + { STRING_WITH_LEN("ENUM") }, // GET_ENUM 12 + { STRING_WITH_LEN("SET") }, // GET_SET 13 + { STRING_WITH_LEN("DOUBLE") }, // GET_DOUBLE 14 + { STRING_WITH_LEN("FLAGSET") }, // GET_FLAGSET 15 + }; + const ulong vartype= (var->option.var_type & GET_TYPE_MASK); + const LEX_CSTRING *type= types + vartype; + fields[6]->store(type->str, type->length, scs); + + // VARIABLE_COMMENT + fields[7]->store(var->option.comment, strlen(var->option.comment), + scs); + + // NUMERIC_MIN_VALUE + // NUMERIC_MAX_VALUE + // NUMERIC_BLOCK_SIZE + bool is_unsigned= true; + switch (vartype) + { + case GET_INT: + case GET_LONG: + case GET_LL: + is_unsigned= false; + /* fall through */ + case GET_UINT: + case GET_ULONG: + case GET_ULL: + fields[8]->set_notnull(); + fields[9]->set_notnull(); + fields[10]->set_notnull(); + fields[8]->store(var->option.min_value, is_unsigned); + fields[9]->store(var->option.max_value, is_unsigned); + fields[10]->store(var->option.block_size, is_unsigned); + break; + case GET_DOUBLE: + fields[8]->set_notnull(); + fields[9]->set_notnull(); + fields[8]->store(getopt_ulonglong2double(var->option.min_value)); + fields[9]->store(getopt_ulonglong2double(var->option.max_value)); + } + + // ENUM_VALUE_LIST + TYPELIB *tl= var->option.typelib; + if (tl) + { + uint i; + strbuf.length(0); + for (i=0; i + 1 < tl->count; i++) + { + strbuf.append(tl->type_names[i]); + strbuf.append(','); + } + strbuf.append(tl->type_names[i]); + fields[11]->set_notnull(); + fields[11]->store(strbuf.ptr(), strbuf.length(), scs); + } + + // READ_ONLY + static const LEX_CSTRING yesno[]= + { + { STRING_WITH_LEN("NO") }, + { STRING_WITH_LEN("YES") } + }; + const LEX_CSTRING *yn = yesno + var->is_readonly(); + fields[12]->store(yn->str, yn->length, scs); + + // COMMAND_LINE_ARGUMENT + if (var->option.id >= 0) + { + static const LEX_CSTRING args[]= + { + { STRING_WITH_LEN("NONE") }, // NO_ARG + { STRING_WITH_LEN("OPTIONAL") }, // OPT_ARG + { STRING_WITH_LEN("REQUIRED") } // REQUIRED_ARG + }; + const LEX_CSTRING *arg= args + var->option.arg_type; + fields[13]->set_notnull(); + fields[13]->store(arg->str, arg->length, scs); + } + + if (schema_table_store_record(thd, tables->table)) + goto end; + thd->get_stmt_da()->inc_current_row_for_warning(); + } + res= 0; +end: + mysql_rwlock_unlock(&LOCK_system_variables_hash); + thd->count_cuted_fields= save_count_cuted_fields; + return res; +} + +/* + This is a simple and inefficient helper that sets sys_var::value_origin + for a specific sysvar. + It should *only* be used on server startup, if you need to do this later, + get yourself a pointer to your sysvar (see e.g. Sys_autocommit_ptr) + and update it directly. +*/ + +void set_sys_var_value_origin(void *ptr, enum sys_var::where here) +{ + bool found __attribute__((unused))= false; + DBUG_ASSERT(!mysqld_server_started); // only to be used during startup + + for (uint i= 0; i < system_variable_hash.records; i++) + { + sys_var *var= (sys_var*) my_hash_element(&system_variable_hash, i); + if (var->option.value == ptr) + { + found= true; + var->value_origin= here; + /* don't break early, search for all matches */ + } + } + + DBUG_ASSERT(found); // variable must have been found +} + +enum sys_var::where get_sys_var_value_origin(void *ptr) +{ + DBUG_ASSERT(!mysqld_server_started); // only to be used during startup + + for (uint i= 0; i < system_variable_hash.records; i++) + { + sys_var *var= (sys_var*) my_hash_element(&system_variable_hash, i); + if (var->option.value == ptr) + { + return var->value_origin; //first match + } + } + + DBUG_ASSERT(0); // variable must have been found + return sys_var::CONFIG; +} + |