diff options
Diffstat (limited to 'sql/set_var.cc')
-rw-r--r-- | sql/set_var.cc | 284 |
1 files changed, 253 insertions, 31 deletions
diff --git a/sql/set_var.cc b/sql/set_var.cc index 036cc5f1d43..3272d0dfe5b 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -16,7 +16,7 @@ /* variable declarations are in sys_vars.cc now !!! */ -#include "sql_plugin.h" // Includes my_global.h +#include "sql_plugin.h" #include "sql_class.h" // set_var.h: session_var_ptr #include "set_var.h" #include "sql_priv.h" @@ -233,22 +233,22 @@ bool sys_var::update(THD *thd, set_var *var) } } -uchar *sys_var::session_value_ptr(THD *thd, const LEX_STRING *base) +uchar *sys_var::session_value_ptr(THD *thd, const LEX_CSTRING *base) { return session_var_ptr(thd); } -uchar *sys_var::global_value_ptr(THD *thd, const LEX_STRING *base) +uchar *sys_var::global_value_ptr(THD *thd, const LEX_CSTRING *base) { return global_var_ptr(); } bool sys_var::check(THD *thd, set_var *var) { - if ((var->value && do_check(thd, var)) - || (on_check && on_check(this, thd, var))) + if (unlikely((var->value && do_check(thd, var)) || + (on_check && on_check(this, thd, var)))) { - if (!thd->is_error()) + if (likely(!thd->is_error())) { char buff[STRING_BUFFER_USUAL_SIZE]; String str(buff, sizeof(buff), system_charset_info), *res; @@ -271,7 +271,8 @@ bool sys_var::check(THD *thd, set_var *var) return false; } -uchar *sys_var::value_ptr(THD *thd, enum_var_type type, const LEX_STRING *base) +uchar *sys_var::value_ptr(THD *thd, enum_var_type type, + const LEX_CSTRING *base) { DBUG_ASSERT(base); if (type == OPT_GLOBAL || scope() == GLOBAL) @@ -323,13 +324,14 @@ do { \ sval.length= sval.str ? strlen(sval.str) : 0; \ break; \ case SHOW_LEX_STRING: \ - sval= *(LEX_STRING *) value; \ + sval= *(LEX_CSTRING *) value; \ break longlong sys_var::val_int(bool *is_null, - THD *thd, enum_var_type type, const LEX_STRING *base) + THD *thd, enum_var_type type, + const LEX_CSTRING *base) { - LEX_STRING sval; + LEX_CSTRING sval; AutoWLock lock(&PLock_global_system_variables); const uchar *value= value_ptr(thd, type, base); *is_null= false; @@ -355,13 +357,13 @@ longlong sys_var::val_int(bool *is_null, String *sys_var::val_str_nolock(String *str, THD *thd, const uchar *value) { - static LEX_STRING bools[]= + static LEX_CSTRING bools[]= { - { C_STRING_WITH_LEN("OFF") }, - { C_STRING_WITH_LEN("ON") } + { STRING_WITH_LEN("OFF") }, + { STRING_WITH_LEN("ON") } }; - LEX_STRING sval; + LEX_CSTRING sval; switch (show_type()) { case_get_string_as_lex_string; @@ -382,7 +384,7 @@ String *sys_var::val_str_nolock(String *str, THD *thd, const uchar *value) String *sys_var::val_str(String *str, - THD *thd, enum_var_type type, const LEX_STRING *base) + THD *thd, enum_var_type type, const LEX_CSTRING *base) { AutoWLock lock(&PLock_global_system_variables); const uchar *value= value_ptr(thd, type, base); @@ -391,9 +393,9 @@ String *sys_var::val_str(String *str, double sys_var::val_real(bool *is_null, - THD *thd, enum_var_type type, const LEX_STRING *base) + THD *thd, enum_var_type type, const LEX_CSTRING *base) { - LEX_STRING sval; + LEX_CSTRING sval; AutoWLock lock(&PLock_global_system_variables); const uchar *value= value_ptr(thd, type, base); *is_null= false; @@ -683,7 +685,7 @@ SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type scope) 0 Unknown variable (error message is given) */ -sys_var *intern_find_sys_var(const char *str, uint length) +sys_var *intern_find_sys_var(const char *str, size_t length) { sys_var *var; @@ -728,10 +730,10 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free) set_var_base *var; while ((var=it++)) { - if ((error= var->check(thd))) + if (unlikely((error= var->check(thd)))) goto err; } - if (was_error || !(error= MY_TEST(thd->is_error()))) + if (unlikely(was_error) || likely(!(error= MY_TEST(thd->is_error())))) { it.rewind(); while ((var= it++)) @@ -778,8 +780,7 @@ int set_var::check(THD *thd) if (!value) return 0; - if ((!value->fixed && - value->fix_fields(thd, &value)) || value->check_cols(1)) + if (value->fix_fields_if_needed_for_scalar(thd, &value)) return -1; if (var->check_update_type(value)) { @@ -813,8 +814,7 @@ int set_var::light_check(THD *thd) if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)) return 1; - if (value && ((!value->fixed && value->fix_fields(thd, &value)) || - value->check_cols(1))) + if (value && value->fix_fields_if_needed_for_scalar(thd, &value)) return -1; return 0; } @@ -839,7 +839,7 @@ int set_var::update(THD *thd) set_var::set_var(THD *thd, enum_var_type type_arg, sys_var *var_arg, - const LEX_STRING *base_name_arg, Item *value_arg) + const LEX_CSTRING *base_name_arg, Item *value_arg) :var(var_arg), type(type_arg), base(*base_name_arg) { /* @@ -850,7 +850,9 @@ set_var::set_var(THD *thd, enum_var_type type_arg, sys_var *var_arg, { Item_field *item= (Item_field*) value_arg; // names are utf8 - if (!(value= new (thd->mem_root) Item_string_sys(thd, item->field_name))) + if (!(value= new (thd->mem_root) Item_string_sys(thd, + item->field_name.str, + (uint)item->field_name.length))) value=value_arg; /* Give error message later */ } else @@ -1014,13 +1016,13 @@ int set_var_collation_client::update(THD *thd) /* Mark client collation variables as changed */ #ifndef EMBEDDED_LIBRARY - if (thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled()) + if (thd->session_tracker.sysvars.is_enabled()) { - thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)-> + thd->session_tracker.sysvars. mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_client_ptr); - thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)-> + thd->session_tracker.sysvars. mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_results_ptr); - thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)-> + thd->session_tracker.sysvars. mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_connection_ptr); } thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL); @@ -1050,7 +1052,7 @@ static void store_var(Field *field, sys_var *var, enum_var_type scope, return; store_value_ptr(field, var, str, - var->value_ptr(field->table->in_use, scope, &null_lex_str)); + var->value_ptr(field->table->in_use, scope, &null_clex_str)); } int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond) @@ -1147,6 +1149,7 @@ int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond) { STRING_WITH_LEN("SET") }, // GET_SET 13 { STRING_WITH_LEN("DOUBLE") }, // GET_DOUBLE 14 { STRING_WITH_LEN("FLAGSET") }, // GET_FLAGSET 15 + { STRING_WITH_LEN("BOOLEAN") }, // GET_BIT 16 }; const ulong vartype= (var->option.var_type & GET_TYPE_MASK); const LEX_CSTRING *type= types + vartype; @@ -1278,3 +1281,222 @@ enum sys_var::where get_sys_var_value_origin(void *ptr) return sys_var::CONFIG; } + +/* + Find the next item in string of comma-separated items. + END_POS points at the end of the string. + ITEM_START and ITEM_END return the limits of the next item. + Returns true while items are available, false at the end. +*/ +static bool +engine_list_next_item(const char **pos, const char *end_pos, + const char **item_start, const char **item_end) +{ + if (*pos >= end_pos) + return false; + *item_start= *pos; + while (*pos < end_pos && **pos != ',') + ++*pos; + *item_end= *pos; + ++*pos; + return true; +} + + +static bool +resolve_engine_list_item(THD *thd, plugin_ref *list, uint32 *idx, + const char *pos, const char *pos_end, + bool error_on_unknown_engine, bool temp_copy) +{ + LEX_CSTRING item_str; + plugin_ref ref; + uint32 i; + THD *thd_or_null = (temp_copy ? thd : NULL); + + item_str.str= pos; + item_str.length= pos_end-pos; + ref= ha_resolve_by_name(thd_or_null, &item_str, false); + if (!ref) + { + if (error_on_unknown_engine) + { + ErrConvString err(pos, pos_end-pos, system_charset_info); + my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), err.ptr()); + return true; + } + return false; + } + /* Ignore duplicates, like --plugin-load does. */ + for (i= 0; i < *idx; ++i) + { + if (plugin_hton(list[i]) == plugin_hton(ref)) + { + if (!temp_copy) + plugin_unlock(NULL, ref); + return false; + } + } + list[*idx]= ref; + ++*idx; + return false; +} + + +/* + Helper for class Sys_var_pluginlist. + Resolve a comma-separated list of storage engine names to a null-terminated + array of plugin_ref. + + If TEMP_COPY is true, a THD must be given as well. In this case, the + allocated memory and locked plugins are registered in the THD and will + be freed / unlocked automatically. If TEMP_COPY is true, THD can be + passed as NULL, and resources must be freed explicitly later with + free_engine_list(). +*/ +plugin_ref * +resolve_engine_list(THD *thd, const char *str_arg, size_t str_arg_len, + bool error_on_unknown_engine, bool temp_copy) +{ + uint32 count, idx; + const char *pos, *item_start, *item_end; + const char *str_arg_end= str_arg + str_arg_len; + plugin_ref *res; + + count= 0; + pos= str_arg; + for (;;) + { + if (!engine_list_next_item(&pos, str_arg_end, &item_start, &item_end)) + break; + ++count; + } + + if (temp_copy) + res= (plugin_ref *)thd->calloc((count+1)*sizeof(*res)); + else + res= (plugin_ref *)my_malloc((count+1)*sizeof(*res), MYF(MY_ZEROFILL|MY_WME)); + if (!res) + { + my_error(ER_OUTOFMEMORY, MYF(0), (int)((count+1)*sizeof(*res))); + goto err; + } + + idx= 0; + pos= str_arg; + for (;;) + { + if (!engine_list_next_item(&pos, str_arg_end, &item_start, &item_end)) + break; + DBUG_ASSERT(idx < count); + if (idx >= count) + break; + if (resolve_engine_list_item(thd, res, &idx, item_start, item_end, + error_on_unknown_engine, temp_copy)) + goto err; + } + + return res; + +err: + if (!temp_copy) + free_engine_list(res); + return NULL; +} + + +void +free_engine_list(plugin_ref *list) +{ + plugin_ref *p; + + if (!list) + return; + for (p= list; *p; ++p) + plugin_unlock(NULL, *p); + my_free(list); +} + + +plugin_ref * +copy_engine_list(plugin_ref *list) +{ + plugin_ref *p; + uint32 count, i; + + for (p= list, count= 0; *p; ++p, ++count) + ; + p= (plugin_ref *)my_malloc((count+1)*sizeof(*p), MYF(0)); + if (!p) + { + my_error(ER_OUTOFMEMORY, MYF(0), (int)((count+1)*sizeof(*p))); + return NULL; + } + for (i= 0; i < count; ++i) + p[i]= my_plugin_lock(NULL, list[i]); + p[i] = NULL; + return p; +} + + +/* + Create a temporary copy of an engine list. The memory will be freed + (and the plugins unlocked) automatically, on the passed THD. +*/ +plugin_ref * +temp_copy_engine_list(THD *thd, plugin_ref *list) +{ + plugin_ref *p; + uint32 count, i; + + for (p= list, count= 0; *p; ++p, ++count) + ; + p= (plugin_ref *)thd->alloc((count+1)*sizeof(*p)); + if (!p) + { + my_error(ER_OUTOFMEMORY, MYF(0), (int)((count+1)*sizeof(*p))); + return NULL; + } + for (i= 0; i < count; ++i) + p[i]= my_plugin_lock(thd, list[i]); + p[i] = NULL; + return p; +} + + +char * +pretty_print_engine_list(THD *thd, plugin_ref *list) +{ + plugin_ref *p; + size_t size; + char *buf, *pos; + + if (!list || !*list) + return thd->strmake("", 0); + + size= 0; + for (p= list; *p; ++p) + size+= plugin_name(*p)->length + 1; + buf= static_cast<char *>(thd->alloc(size)); + if (!buf) + return NULL; + pos= buf; + for (p= list; *p; ++p) + { + LEX_CSTRING *name; + size_t remain; + + remain= buf + size - pos; + DBUG_ASSERT(remain > 0); + if (remain <= 1) + break; + if (pos != buf) + { + pos= strmake(pos, ",", remain-1); + --remain; + } + name= plugin_name(*p); + pos= strmake(pos, name->str, MY_MIN(name->length, remain-1)); + } + *pos= '\0'; + return buf; +} |