diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-04-09 23:27:24 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-04-09 23:27:24 +0200 |
commit | 5f293dd694f9b1b4a0bdf73bb6ae80cda70f21d4 (patch) | |
tree | 24dde5c436f3c2687619de02e4ab5f4f957ff789 /sql/create_options.cc | |
parent | 7d3288129f6e5b52c7377ff68295f51606c7f002 (diff) | |
download | mariadb-git-5f293dd694f9b1b4a0bdf73bb6ae80cda70f21d4.tar.gz |
MDEV-4022 table attributes with sysvar as a default value
Diffstat (limited to 'sql/create_options.cc')
-rw-r--r-- | sql/create_options.cc | 175 |
1 files changed, 158 insertions, 17 deletions
diff --git a/sql/create_options.cc b/sql/create_options.cc index 47d3a2d06ea..f12120bd0a1 100644 --- a/sql/create_options.cc +++ b/sql/create_options.cc @@ -21,6 +21,7 @@ #include "create_options.h" #include <my_getopt.h> +#include "set_var.h" #define FRM_QUOTED_VALUE 0x8000 @@ -115,7 +116,7 @@ static bool report_unknown_option(THD *thd, engine_option_value *val, } static bool set_one_value(ha_create_table_option *opt, - THD *thd, LEX_STRING *value, void *base, + THD *thd, const LEX_STRING *value, void *base, bool suppress_warning, MEM_ROOT *root) { @@ -126,6 +127,8 @@ static bool set_one_value(ha_create_table_option *opt, (value->str ? value->str : "<DEFAULT>"))); switch (opt->type) { + case HA_OPTION_TYPE_SYSVAR: + DBUG_ASSERT(0); // HA_OPTION_TYPE_SYSVAR's are replaced in resolve_sysvars() case HA_OPTION_TYPE_ULL: { ulonglong *val= (ulonglong*)((char*)base + opt->offset); @@ -257,51 +260,92 @@ static const size_t ha_option_type_sizeof[]= @retval FALSE OK */ -bool parse_option_list(THD* thd, void *option_struct_arg, - engine_option_value *option_list, +bool parse_option_list(THD* thd, handlerton *hton, void *option_struct_arg, + engine_option_value **option_list, ha_create_table_option *rules, bool suppress_warning, MEM_ROOT *root) { ha_create_table_option *opt; size_t option_struct_size= 0; - engine_option_value *val= option_list; + engine_option_value *val, *last; void **option_struct= (void**)option_struct_arg; DBUG_ENTER("parse_option_list"); DBUG_PRINT("enter", ("struct: %p list: %p rules: %p suppress_warning: %u root: %p", - *option_struct, option_list, rules, + *option_struct, *option_list, rules, (uint) suppress_warning, root)); if (rules) { - LEX_STRING default_val= null_lex_str; for (opt= rules; opt->name; opt++) set_if_bigger(option_struct_size, opt->offset + ha_option_type_sizeof[opt->type]); *option_struct= alloc_root(root, option_struct_size); - - /* set all values to default */ - for (opt= rules; opt->name; opt++) - set_one_value(opt, thd, &default_val, *option_struct, - suppress_warning, root); } - for (; val; val= val->next) + for (opt= rules; opt && opt->name; opt++) { - for (opt= rules; opt && opt->name; opt++) + bool seen=false; + for (val= *option_list; val; val= val->next) { + last= val; if (my_strnncoll(system_charset_info, (uchar*)opt->name, opt->name_length, (uchar*)val->name.str, val->name.length)) continue; + seen=true; + + if (val->parsed && !val->value.str) + continue; + if (set_one_value(opt, thd, &val->value, *option_struct, suppress_warning || val->parsed, root)) DBUG_RETURN(TRUE); val->parsed= true; break; } + if (!seen) + { + LEX_STRING default_val= null_lex_str; + + /* + If it's CREATE/ALTER TABLE parsing mode (options are created in the + transient thd->mem_root, not in the long living TABLE_SHARE::mem_root), + and variable-backed option was not explicitly set. + + If it's not create, but opening of the existing frm (that was, + probably, created with the older version of the storage engine and + does not have this option stored), we take the *default* value of the + sysvar, not the *current* value. Because we don't want to have + different option values for the same table if it's opened many times. + */ + if (root == thd->mem_root && opt->var) + { + // take a value from the variable and add it to the list + sys_var *sysvar= find_hton_sysvar(hton, opt->var); + DBUG_ASSERT(sysvar); + + char buf[256]; + String sbuf(buf, sizeof(buf), system_charset_info), *str; + if ((str= sysvar->val_str(&sbuf, thd, OPT_SESSION, 0))) + { + LEX_STRING name= { const_cast<char*>(opt->name), opt->name_length }; + default_val.str= strmake_root(root, str->ptr(), str->length()); + default_val.length= str->length(); + val= new (root) engine_option_value(name, default_val, true, + option_list, &last); + val->parsed= true; + } + } + set_one_value(opt, thd, &default_val, *option_struct, + suppress_warning, root); + } + } + + for (val= *option_list; val; val= val->next) + { if (report_unknown_option(thd, val, suppress_warning)) DBUG_RETURN(TRUE); val->parsed= true; @@ -312,6 +356,102 @@ bool parse_option_list(THD* thd, void *option_struct_arg, /** + Resolves all HA_OPTION_TYPE_SYSVAR elements. + + This is done when an engine is loaded. +*/ +static bool resolve_sysvars(handlerton *hton, ha_create_table_option *rules) +{ + for (ha_create_table_option *opt= rules; opt && opt->name; opt++) + { + if (opt->type == HA_OPTION_TYPE_SYSVAR) + { + struct my_option optp; + plugin_opt_set_limits(&optp, opt->var); + switch(optp.var_type) { + case GET_ULL: + case GET_ULONG: + case GET_UINT: + opt->type= HA_OPTION_TYPE_ULL; + opt->def_value= (ulonglong)optp.def_value; + opt->min_value= (ulonglong)optp.min_value; + opt->max_value= (ulonglong)optp.max_value; + opt->block_size= (ulonglong)optp.block_size; + break; + case GET_STR: + case GET_STR_ALLOC: + opt->type= HA_OPTION_TYPE_STRING; + break; + case GET_BOOL: + opt->type= HA_OPTION_TYPE_BOOL; + opt->def_value= optp.def_value; + break; + case GET_ENUM: + { + opt->type= HA_OPTION_TYPE_ENUM; + opt->def_value= optp.def_value; + + char buf[256]; + String str(buf, sizeof(buf), system_charset_info); + for (const char **s= optp.typelib->type_names; *s; s++) + { + if (str.append(*s) || str.append(',')) + return 1; + } + DBUG_ASSERT(str.length()); + opt->values= my_strndup(str.ptr(), str.length()-1, MYF(MY_WME)); + if (!opt->values) + return 1; + break; + } + default: + DBUG_ASSERT(0); + } + } + } + return 0; +} + +bool resolve_sysvar_table_options(handlerton *hton) +{ + return resolve_sysvars(hton, hton->table_options) || + resolve_sysvars(hton, hton->field_options) || + resolve_sysvars(hton, hton->index_options); +} + +/* + Restore HA_OPTION_TYPE_SYSVAR options back as they were + before resolve_sysvars(). + + This is done when the engine is unloaded, so that we could + call resolve_sysvars() if the engine is installed again. +*/ +static void free_sysvars(handlerton *hton, ha_create_table_option *rules) +{ + for (ha_create_table_option *opt= rules; opt && opt->name; opt++) + { + if (opt->var) + { + my_free(const_cast<char*>(opt->values)); + opt->type= HA_OPTION_TYPE_SYSVAR; + opt->def_value= 0; + opt->min_value= 0; + opt->max_value= 0; + opt->block_size= 0; + opt->values= 0; + } + } +} + +void free_sysvar_table_options(handlerton *hton) +{ + free_sysvars(hton, hton->table_options); + free_sysvars(hton, hton->field_options); + free_sysvars(hton, hton->index_options); +} + + +/** Parses all table/fields/keys options @param thd thread handler @@ -327,21 +467,22 @@ bool parse_engine_table_options(THD *thd, handlerton *ht, TABLE_SHARE *share) MEM_ROOT *root= &share->mem_root; DBUG_ENTER("parse_engine_table_options"); - if (parse_option_list(thd, &share->option_struct, share->option_list, + if (parse_option_list(thd, ht, &share->option_struct, & share->option_list, ht->table_options, TRUE, root)) DBUG_RETURN(TRUE); for (Field **field= share->field; *field; field++) { - if (parse_option_list(thd, &(*field)->option_struct, (*field)->option_list, + if (parse_option_list(thd, ht, &(*field)->option_struct, + & (*field)->option_list, ht->field_options, TRUE, root)) DBUG_RETURN(TRUE); } for (uint index= 0; index < share->keys; index ++) { - if (parse_option_list(thd, &share->key_info[index].option_struct, - share->key_info[index].option_list, + if (parse_option_list(thd, ht, &share->key_info[index].option_struct, + & share->key_info[index].option_list, ht->index_options, TRUE, root)) DBUG_RETURN(TRUE); } |