diff options
author | unknown <monty@mashka.mysql.fi> | 2003-07-06 19:09:57 +0300 |
---|---|---|
committer | unknown <monty@mashka.mysql.fi> | 2003-07-06 19:09:57 +0300 |
commit | e17562b55af10d9415e9dfefe7cba0ade1e49bca (patch) | |
tree | 48933b768c9d8efcf591c87e96b857a99e6977bb | |
parent | e25c83e0c6b6db5c5aec223b8f4d18210017181d (diff) | |
download | mariadb-git-e17562b55af10d9415e9dfefe7cba0ade1e49bca.tar.gz |
Support for variables with components
Added framework to create/drop and manager buffers for multiple key caches
include/my_getopt.h:
Fixed prototype
include/my_sys.h:
Added (temporary) KEY_CACHE type
include/mysqld_error.h:
New error messages
mysql-test/r/select_safe.result:
Updated test results
mysql-test/r/variables.result:
Updated test results
mysys/my_getopt.c:
Fixed bugs with GET_ASK_ADDR
sql/Makefile.am:
Make sql_yacc.o depend on all header files in sql directory
sql/item_func.cc:
Added support for variable components
sql/mysql_priv.h:
Added support for variable components
sql/mysqld.cc:
Added support for multiple key caches
sql/set_var.cc:
Added support for multiple key caches
sql/set_var.h:
Added support for multiple key caches
sql/share/czech/errmsg.txt:
New error messages
sql/share/danish/errmsg.txt:
New error messages
sql/share/dutch/errmsg.txt:
New error messages
sql/share/english/errmsg.txt:
New error messages
sql/share/estonian/errmsg.txt:
New error messages
sql/share/french/errmsg.txt:
New error messages
sql/share/german/errmsg.txt:
New error messages
sql/share/greek/errmsg.txt:
New error messages
sql/share/hungarian/errmsg.txt:
New error messages
sql/share/italian/errmsg.txt:
New error messages
sql/share/japanese/errmsg.txt:
New error messages
sql/share/korean/errmsg.txt:
New error messages
sql/share/norwegian-ny/errmsg.txt:
New error messages
sql/share/norwegian/errmsg.txt:
New error messages
sql/share/polish/errmsg.txt:
New error messages
sql/share/portuguese/errmsg.txt:
New error messages
sql/share/romanian/errmsg.txt:
New error messages
sql/share/russian/errmsg.txt:
New error messages
sql/share/serbian/errmsg.txt:
New error messages
sql/share/slovak/errmsg.txt:
New error messages
sql/share/spanish/errmsg.txt:
New error messages
sql/share/swedish/errmsg.txt:
New error messages
sql/share/ukrainian/errmsg.txt:
New error messages
sql/sql_lex.cc:
Fixes for quoting of variables.
sql/sql_parse.cc:
Fix after changing prototype for get_system_var
sql/sql_show.cc:
Fix after introducing variable components
sql/sql_yacc.yy:
Support for variables with components (To support multiple key caches)
42 files changed, 572 insertions, 127 deletions
diff --git a/include/my_getopt.h b/include/my_getopt.h index 213c8c3570e..148238f8d1b 100644 --- a/include/my_getopt.h +++ b/include/my_getopt.h @@ -53,7 +53,7 @@ extern int handle_options (int *argc, char ***argv, char *)); extern void my_print_help(const struct my_option *options); extern void my_print_variables(const struct my_option *options); -extern void my_getopt_register_get_addr(gptr* (*func_addr)(char *, uint, +extern void my_getopt_register_get_addr(gptr* (*func_addr)(const char *, uint, const struct my_option *)); ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp); diff --git a/include/my_sys.h b/include/my_sys.h index 48ebdc22f37..7ea9f63a50f 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -501,6 +501,12 @@ my_off_t my_b_append_tell(IO_CACHE* info); #define my_b_bytes_in_cache(info) (uint) (*(info)->current_end - \ *(info)->current_pos) +/* key_cache_variables */ +typedef struct st_keycache +{ + ulonglong size; +} KEY_CACHE; + #include <my_alloc.h> /* Prototypes for mysys and my_func functions */ diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 565c2812c50..0468663239b 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -286,4 +286,5 @@ #define ER_REVOKE_GRANTS 1267 #define ER_CANT_AGGREGATE_3COLLATIONS 1268 #define ER_CANT_AGGREGATE_NCOLLATIONS 1269 -#define ER_ERROR_MESSAGES 270 +#define ER_VARIABLE_IS_NOT_STRUCT 1270 +#define ER_ERROR_MESSAGES 271 diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result new file mode 100644 index 00000000000..8ec507b2a3f --- /dev/null +++ b/mysql-test/r/key_cache.result @@ -0,0 +1,43 @@ +SET @save_key_buffer=@@key_buffer_size; +SELECT @@key_buffer_size, @@small.key_buffer_size; +@@key_buffer_size @@small.key_buffer_size +2097152 131072 +SET @@global.key_buffer_size=16*1024*1024; +SET @@global.default.key_buffer_size=16*1024*1024; +SET @@global.default.key_buffer_size=16*1024*1024; +SET @@global.small.key_buffer_size=1*1024*1024; +SET @@global.medium.key_buffer_size=4*1024*1024; +SET @@global.medium.key_buffer_size=0; +SET @@global.medium.key_buffer_size=0; +SHOW VARIABLES like "key_buffer_size"; +Variable_name Value +key_buffer_size 16777216 +SELECT @@key_buffer_size; +@@key_buffer_size +16777216 +SELECT @@global.key_buffer_size; +@@global.key_buffer_size +16777216 +SELECT @@global.default.key_buffer_size; +@@global.default.key_buffer_size +16777216 +SELECT @@global.default.`key_buffer_size`; +@@global.default.key_buffer_size +16777216 +SELECT @@global.`default`.`key_buffer_size`; +@@global.default.key_buffer_size +16777216 +SELECT @@`default`.key_buffer_size; +@@default.key_buffer_size +16777216 +SELECT @@small.key_buffer_size; +@@small.key_buffer_size +1048576 +SELECT @@medium.key_buffer_size; +@@medium.key_buffer_size +4194304 +SET @@global.key_buffer_size=@save_key_buffer; +SELECT @@default.key_buffer_size; +ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'default.key_buffer_size' at line 1 +SELECT @@skr.table_type="test"; +ERROR HY000: Variable 'table_type' is not a variable component (Can't be used as XXXX.variable_name) diff --git a/mysql-test/r/select_safe.result b/mysql-test/r/select_safe.result index e73161996b8..0f2a781d073 100644 --- a/mysql-test/r/select_safe.result +++ b/mysql-test/r/select_safe.result @@ -37,7 +37,7 @@ delete from t1 where b="test" limit 1; delete from t1 where a+0=1 limit 2; SET MAX_JOIN_SIZE=2; SELECT @@MAX_JOIN_SIZE, @@SQL_BIG_SELECTS; -@@max_join_size @@sql_big_selects +@@MAX_JOIN_SIZE @@SQL_BIG_SELECTS 2 0 insert into t1 values (null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"); SELECT * from t1; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 1a773acd23e..4db791c993e 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -77,7 +77,7 @@ select last_insert_id(345); last_insert_id(345) 345 select @@IDENTITY,last_insert_id(), @@identity; -@@identity last_insert_id() @@identity +@@IDENTITY last_insert_id() @@identity 345 345 345 set big_tables=OFF, big_tables=ON, big_tables=0, big_tables=1, big_tables="OFF", big_tables="ON"; set global concurrent_insert=ON; diff --git a/mysql-test/t/key_cache-master.opt b/mysql-test/t/key_cache-master.opt new file mode 100644 index 00000000000..66e19c18a8a --- /dev/null +++ b/mysql-test/t/key_cache-master.opt @@ -0,0 +1 @@ +--key_buffer_size=2M --small.key_buffer_size=256K --small.key_buffer_size=128K diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test new file mode 100644 index 00000000000..2da18b68624 --- /dev/null +++ b/mysql-test/t/key_cache.test @@ -0,0 +1,42 @@ +# +# Test of key cache +# + +SET @save_key_buffer=@@key_buffer_size; + +SELECT @@key_buffer_size, @@small.key_buffer_size; + +# Change default key cache size +SET @@global.key_buffer_size=16*1024*1024; +SET @@global.default.key_buffer_size=16*1024*1024; +SET @@global.default.key_buffer_size=16*1024*1024; + +SET @@global.small.key_buffer_size=1*1024*1024; +SET @@global.medium.key_buffer_size=4*1024*1024; +# Drop buffer +SET @@global.medium.key_buffer_size=0; +# Test double drop +SET @@global.medium.key_buffer_size=0; + +# Print key buffer with different syntaxes +SHOW VARIABLES like "key_buffer_size"; +SELECT @@key_buffer_size; +SELECT @@global.key_buffer_size; +SELECT @@global.default.key_buffer_size; +SELECT @@global.default.`key_buffer_size`; +SELECT @@global.`default`.`key_buffer_size`; +SELECT @@`default`.key_buffer_size; + +SELECT @@small.key_buffer_size; +SELECT @@medium.key_buffer_size; + +SET @@global.key_buffer_size=@save_key_buffer; + +# +# Errors +# + +--error 1064 +SELECT @@default.key_buffer_size; +--error 1270 +SELECT @@skr.table_type="test"; diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 83ba8b98843..d539489cf1e 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -32,7 +32,7 @@ static longlong getopt_ll(char *arg, const struct my_option *optp, int *err); static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err); static void init_variables(const struct my_option *options); -static int setval(const struct my_option *opts, char *argument, +static int setval(const struct my_option *opts, gptr *value, char *argument, my_bool set_maximum_value); static char *check_struct_option(char *cur_arg, char *key_name); @@ -68,9 +68,9 @@ my_bool my_getopt_print_errors= 1; one. Call function 'get_one_option()' once for each option. */ -static gptr* (*getopt_get_addr)(char *, uint, const struct my_option *); +static gptr* (*getopt_get_addr)(const char *, uint, const struct my_option *); -void my_getopt_register_get_addr(gptr* (*func_addr)(char *, uint, +void my_getopt_register_get_addr(gptr* (*func_addr)(const char *, uint, const struct my_option *)) { getopt_get_addr= func_addr; @@ -395,7 +395,8 @@ int handle_options(int *argc, char ***argv, /* the other loop will break, because *optend + 1 == 0 */ } } - if ((error= setval(optp, argument, set_maximum_value))) + if ((error= setval(optp, optp->value, argument, + set_maximum_value))) { fprintf(stderr, "%s: Error while setting value '%s' to '%s'\n", @@ -417,7 +418,7 @@ int handle_options(int *argc, char ***argv, (*argc)--; /* option handled (short), decrease argument count */ continue; } - if ((error= setval(optp, argument, set_maximum_value))) + if ((error= setval(optp, value, argument, set_maximum_value))) { fprintf(stderr, "%s: Error while setting value '%s' to '%s'\n", @@ -473,13 +474,13 @@ static char *check_struct_option(char *cur_arg, char *key_name) if (end - ptr > 1) { uint len= ptr - cur_arg; - strnmov(key_name, cur_arg, len); - key_name[len]= '\0'; + set_if_smaller(len, FN_REFLEN-1); + strmake(key_name, cur_arg, len); return ++ptr; } else { - key_name= 0; + key_name[0]= 0; return cur_arg; } } @@ -491,15 +492,15 @@ static char *check_struct_option(char *cur_arg, char *key_name) Will set the option value to given value */ -static int setval(const struct my_option *opts, char *argument, +static int setval(const struct my_option *opts, gptr *value, char *argument, my_bool set_maximum_value) { int err= 0; - if (opts->value && argument) + if (value && argument) { gptr *result_pos= ((set_maximum_value) ? - opts->u_max_value : opts->value); + opts->u_max_value : value); if (!result_pos) return EXIT_NO_PTR_TO_VARIABLE; @@ -692,43 +693,45 @@ static void init_variables(const struct my_option *options) { for (; options->name; options++) { - if (options->value) + gptr *value= (options->var_type & GET_ASK_ADDR ? + (*getopt_get_addr)("", 0, options) : options->value); + if (value) { switch ((options->var_type & GET_TYPE_MASK)) { case GET_BOOL: if (options->u_max_value) *((my_bool*) options->u_max_value)= (my_bool) options->max_value; - *((my_bool*) options->value)= (my_bool) options->def_value; + *((my_bool*) value)= (my_bool) options->def_value; break; case GET_INT: if (options->u_max_value) *((int*) options->u_max_value)= (int) options->max_value; - *((int*) options->value)= (int) options->def_value; + *((int*) value)= (int) options->def_value; break; case GET_UINT: if (options->u_max_value) *((uint*) options->u_max_value)= (uint) options->max_value; - *((uint*) options->value)= (uint) options->def_value; + *((uint*) value)= (uint) options->def_value; break; case GET_LONG: if (options->u_max_value) *((long*) options->u_max_value)= (long) options->max_value; - *((long*) options->value)= (long) options->def_value; + *((long*) value)= (long) options->def_value; break; case GET_ULONG: if (options->u_max_value) *((ulong*) options->u_max_value)= (ulong) options->max_value; - *((ulong*) options->value)= (ulong) options->def_value; + *((ulong*) value)= (ulong) options->def_value; break; case GET_LL: if (options->u_max_value) *((longlong*) options->u_max_value)= (longlong) options->max_value; - *((longlong*) options->value)= (longlong) options->def_value; + *((longlong*) value)= (longlong) options->def_value; break; case GET_ULL: if (options->u_max_value) *((ulonglong*) options->u_max_value)= (ulonglong) options->max_value; - *((ulonglong*) options->value)= (ulonglong) options->def_value; + *((ulonglong*) value)= (ulonglong) options->def_value; break; default: /* dummy default to avoid compiler warnings */ break; @@ -831,7 +834,9 @@ void my_print_variables(const struct my_option *options) printf("--------------------------------- -----------------------------\n"); for (optp= options; optp->id; optp++) { - if (optp->value) + gptr *value= (optp->var_type & GET_ASK_ADDR ? + (*getopt_get_addr)("", 0, optp) : optp->value); + if (value) { printf("%s", optp->name); length= strlen(optp->name); @@ -840,29 +845,29 @@ void my_print_variables(const struct my_option *options) switch ((optp->var_type & GET_TYPE_MASK)) { case GET_STR: case GET_STR_ALLOC: /* fall through */ - printf("%s\n", *((char**) optp->value) ? *((char**) optp->value) : + printf("%s\n", *((char**) value) ? *((char**) value) : "(No default value)"); break; case GET_BOOL: - printf("%s\n", *((my_bool*) optp->value) ? "TRUE" : "FALSE"); + printf("%s\n", *((my_bool*) value) ? "TRUE" : "FALSE"); break; case GET_INT: - printf("%d\n", *((int*) optp->value)); + printf("%d\n", *((int*) value)); break; case GET_UINT: - printf("%d\n", *((uint*) optp->value)); + printf("%d\n", *((uint*) value)); break; case GET_LONG: - printf("%lu\n", *((long*) optp->value)); + printf("%lu\n", *((long*) value)); break; case GET_ULONG: - printf("%lu\n", *((ulong*) optp->value)); + printf("%lu\n", *((ulong*) value)); break; case GET_LL: - printf("%s\n", llstr(*((longlong*) optp->value), buff)); + printf("%s\n", llstr(*((longlong*) value), buff)); break; case GET_ULL: - longlong2str(*((ulonglong*) optp->value), buff, 10); + longlong2str(*((ulonglong*) value), buff, 10); printf("%s\n", buff); break; default: /* dummy default to avoid compiler warnings */ diff --git a/sql/Makefile.am b/sql/Makefile.am index fd02cc906d7..5781b6181d2 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -117,7 +117,7 @@ gen_lex_hash.o: gen_lex_hash.cc lex.h sql_yacc.cc: sql_yacc.yy sql_yacc.h: sql_yacc.yy -sql_yacc.o: sql_yacc.cc sql_yacc.h +sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS) @echo "Note: The following compile may take a long time." @echo "If it fails, re-run configure with --with-low-memory" $(CXXCOMPILE) $(LM_CFLAGS) -c $< diff --git a/sql/item_func.cc b/sql/item_func.cc index ad2bebf9efb..7264a3b5225 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2694,21 +2694,61 @@ longlong Item_func_bit_xor::val_int() System variables ****************************************************************************/ -Item *get_system_var(enum_var_type var_type, LEX_STRING name) +/* + Return value of an system variable base[.name] as a constant item + + SYNOPSIS + get_system_var() + thd Thread handler + var_type global / session + name Name of base or system variable + component Component. + + NOTES + If component.str = 0 then the variable name is in 'name' + + RETURN + 0 error + # constant item +*/ + + +Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name, + LEX_STRING component) { - if (!my_strcasecmp(system_charset_info, name.str, "VERSION")) + if (component.str == 0 && + !my_strcasecmp(system_charset_info, name.str, "VERSION")) return new Item_string("@@VERSION", server_version, (uint) strlen(server_version), system_charset_info); - THD *thd=current_thd; Item *item; sys_var *var; - char buff[MAX_SYS_VAR_LENGTH+3+8], *pos; + char buff[MAX_SYS_VAR_LENGTH*2+4+8], *pos; + LEX_STRING *base_name, *component_name; + + if (component.str) + { + base_name= &component; + component_name= &name; + } + else + { + base_name= &name; + component_name= &component; // Empty string + } - if (!(var= find_sys_var(name.str, name.length))) + if (!(var= find_sys_var(base_name->str, base_name->length))) return 0; - if (!(item=var->item(thd, var_type))) + if (component.str) + { + if (!var->is_struct()) + { + net_printf(thd, ER_VARIABLE_IS_NOT_STRUCT, base_name->str); + return 0; + } + } + if (!(item=var->item(thd, var_type, component_name))) return 0; // Impossible thd->lex.uncacheable(); buff[0]='@'; @@ -2718,23 +2758,37 @@ Item *get_system_var(enum_var_type var_type, LEX_STRING name) pos=strmov(pos,"session."); else if (var_type == OPT_GLOBAL) pos=strmov(pos,"global."); - memcpy(pos, var->name, var->name_length+1); + + set_if_smaller(component_name->length, MAX_SYS_VAR_LENGTH); + set_if_smaller(base_name->length, MAX_SYS_VAR_LENGTH); + + if (component_name->str) + { + memcpy(pos, component_name->str, component_name->length); + pos+= component_name->length; + *pos++= '.'; + } + memcpy(pos, base_name->str, base_name->length); + pos+= base_name->length; + // set_name() will allocate the name - item->set_name(buff,(uint) (pos-buff)+var->name_length, system_charset_info); + item->set_name(buff,(uint) (pos-buff), system_charset_info); return item; } -Item *get_system_var(enum_var_type var_type, const char *var_name, uint length, - const char *item_name) +Item *get_system_var(THD *thd, enum_var_type var_type, const char *var_name, + uint length, const char *item_name) { - THD *thd=current_thd; Item *item; sys_var *var; + LEX_STRING null_lex_string; + + null_lex_string.str= 0; var= find_sys_var(var_name, length); DBUG_ASSERT(var != 0); - if (!(item=var->item(thd, var_type))) + if (!(item=var->item(thd, var_type, &null_lex_string))) return 0; // Impossible thd->lex.uncacheable(); item->set_name(item_name, 0, system_charset_info); // Will use original name diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 5ad2cc56b8c..e54e66a236a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -770,6 +770,7 @@ extern rw_lock_t LOCK_grant; extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager; extern pthread_attr_t connection_attrib; extern I_List<THD> threads; +extern I_List<NAMED_LIST> key_caches; extern MY_BITMAP temp_pool; extern DATE_FORMAT dayord; extern String empty_string; @@ -903,9 +904,10 @@ extern void sql_cache_free(); extern int sql_cache_hit(THD *thd, char *inBuf, uint length); /* item.cc */ -Item *get_system_var(enum_var_type var_type, LEX_STRING name); -Item *get_system_var(enum_var_type var_type, const char *var_name, uint length, - const char *item_name); +Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name, + LEX_STRING component); +Item *get_system_var(THD *thd, enum_var_type var_type, const char *var_name, + uint length, const char *item_name); /* log.cc */ bool flush_error_log(void); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 0a3985c3ee9..709ba036f7e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -312,11 +312,12 @@ const char *sql_mode_str="OFF"; FILE *bootstrap_file; -I_List <i_string_pair> replicate_rewrite_db; +I_List<i_string_pair> replicate_rewrite_db; I_List<i_string> replicate_do_db, replicate_ignore_db; // allow the user to tell us which db to replicate and which to ignore I_List<i_string> binlog_do_db, binlog_ignore_db; I_List<THD> threads,thread_cache; +I_List<NAMED_LIST> key_caches; struct system_variables global_system_variables; struct system_variables max_system_variables; @@ -875,6 +876,7 @@ void clean_up(bool print_message) #endif (void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */ end_key_cache(); + delete_elements(&key_caches, free_key_cache); end_thr_alarm(1); /* Free allocated memory */ #ifdef USE_RAID end_raid(); @@ -4103,7 +4105,7 @@ replicating a LOAD DATA INFILE command.", REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0}, {"key_buffer_size", OPT_KEY_BUFFER_SIZE, - "The size of the buffer used for index blocks. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.", + "The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.", (gptr*) &keybuff_size, (gptr*) &keybuff_size, 0, (enum get_opt_var_type) (GET_ULL | GET_ASK_ADDR), REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD, @@ -4679,6 +4681,9 @@ static void mysql_init_variables(void) my_bind_addr = htonl(INADDR_ANY); threads.empty(); thread_cache.empty(); + key_caches.empty(); + if (!get_or_create_key_cache("default", 7)) + exit(1); /* Initialize structures that is used when processing options */ replicate_rewrite_db.empty(); @@ -5309,16 +5314,30 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } return 0; } - /* Initiates DEBUG - but no debugging here ! */ extern "C" gptr * -mysql_getopt_value(char *keyname, uint key_length, +mysql_getopt_value(const char *keyname, uint key_length, const struct my_option *option) { + if (!key_length) + { + keyname= "default"; + key_length= 7; + } + switch (option->id) { + case OPT_KEY_BUFFER_SIZE: + { + KEY_CACHE *key_cache; + if (!(key_cache= get_or_create_key_cache(keyname, key_length))) + exit(1); + return (gptr*) &key_cache->size; + } + } return option->value; } + static void get_options(int argc,char **argv) { int ho_error; @@ -5366,6 +5385,8 @@ static void get_options(int argc,char **argv) table_alias_charset= (lower_case_table_names ? files_charset_info : &my_charset_bin); + /* QQ To be deleted when we have key cache variables in a struct */ + keybuff_size= (((KEY_CACHE *) find_named(&key_caches, "default", 7))->size); } @@ -5580,6 +5601,6 @@ template class I_List<THD>; template class I_List_iterator<THD>; template class I_List<i_string>; template class I_List<i_string_pair>; - +template class I_List<NAMED_LIST>; FIX_GCC_LINKING_PROBLEM #endif diff --git a/sql/set_var.cc b/sql/set_var.cc index a281fac530a..cb6c875d513 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +/* Copyright (C) 2000-2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -86,9 +86,9 @@ static void fix_net_retry_count(THD *thd, enum_var_type type); static void fix_max_join_size(THD *thd, enum_var_type type); static void fix_query_cache_size(THD *thd, enum_var_type type); static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type); -static void fix_key_buffer_size(THD *thd, enum_var_type type); static void fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type); static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type); +static KEY_CACHE *create_key_cache(const char *name, uint length); void fix_sql_mode_var(THD *thd, enum_var_type type); static byte *get_error_count(THD *thd); static byte *get_warning_count(THD *thd); @@ -136,9 +136,7 @@ sys_var_thd_ulong sys_interactive_timeout("interactive_timeout", &SV::net_interactive_timeout); sys_var_thd_ulong sys_join_buffer_size("join_buffer_size", &SV::join_buff_size); -sys_var_ulonglong_ptr sys_key_buffer_size("key_buffer_size", - &keybuff_size, - fix_key_buffer_size); +sys_var_key_buffer_size sys_key_buffer_size("key_buffer_size"); sys_var_bool_ptr sys_local_infile("local_infile", &opt_local_infile); sys_var_thd_bool sys_log_warnings("log_warnings", &SV::log_warnings); @@ -793,12 +791,6 @@ static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type) #endif -static void fix_key_buffer_size(THD *thd, enum_var_type type) -{ - ha_resize_key_cache(); -} - - void fix_delay_key_write(THD *thd, enum_var_type type) { switch ((enum_delay_key_write) delay_key_write_options) { @@ -870,7 +862,7 @@ bool sys_var_enum::update(THD *thd, set_var *var) } -byte *sys_var_enum::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { return (byte*) enum_names->type_names[*value]; } @@ -906,7 +898,8 @@ void sys_var_thd_ulong::set_default(THD *thd, enum_var_type type) } -byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { if (type == OPT_GLOBAL) return (byte*) &(global_system_variables.*offset); @@ -951,7 +944,8 @@ void sys_var_thd_ha_rows::set_default(THD *thd, enum_var_type type) } -byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { if (type == OPT_GLOBAL) return (byte*) &(global_system_variables.*offset); @@ -994,7 +988,8 @@ void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type) } -byte *sys_var_thd_ulonglong::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_thd_ulonglong::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { if (type == OPT_GLOBAL) return (byte*) &(global_system_variables.*offset); @@ -1021,7 +1016,8 @@ void sys_var_thd_bool::set_default(THD *thd, enum_var_type type) } -byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { if (type == OPT_GLOBAL) return (byte*) &(global_system_variables.*offset); @@ -1115,7 +1111,7 @@ err: to create an item that gets the current value at fix_fields() stage. */ -Item *sys_var::item(THD *thd, enum_var_type var_type) +Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) { if (check_type(var_type)) { @@ -1131,16 +1127,16 @@ Item *sys_var::item(THD *thd, enum_var_type var_type) } switch (type()) { case SHOW_LONG: - return new Item_uint((int32) *(ulong*) value_ptr(thd, var_type)); + return new Item_uint((int32) *(ulong*) value_ptr(thd, var_type, base)); case SHOW_LONGLONG: - return new Item_int(*(longlong*) value_ptr(thd, var_type)); + return new Item_int(*(longlong*) value_ptr(thd, var_type, base)); case SHOW_HA_ROWS: - return new Item_int((longlong) *(ha_rows*) value_ptr(thd, var_type)); + return new Item_int((longlong) *(ha_rows*) value_ptr(thd, var_type, base)); case SHOW_MY_BOOL: - return new Item_int((int32) *(my_bool*) value_ptr(thd, var_type),1); + return new Item_int((int32) *(my_bool*) value_ptr(thd, var_type, base),1); case SHOW_CHAR: { - char *str= (char*) value_ptr(thd, var_type); + char *str= (char*) value_ptr(thd, var_type, base); return new Item_string(str, strlen(str), system_charset_info); } default: @@ -1169,7 +1165,8 @@ void sys_var_thd_enum::set_default(THD *thd, enum_var_type type) } -byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { ulong tmp= ((type == OPT_GLOBAL) ? global_system_variables.*offset : @@ -1186,7 +1183,8 @@ bool sys_var_thd_bit::update(THD *thd, set_var *var) } -byte *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { /* If reverse is 0 (default) return 1 if bit is set. @@ -1249,6 +1247,7 @@ bool sys_var_collation::check(THD *thd, set_var *var) return 0; } + bool sys_var_character_set::check(THD *thd, set_var *var) { CHARSET_INFO *tmp; @@ -1274,20 +1273,24 @@ bool sys_var_character_set::check(THD *thd, set_var *var) return 0; } + bool sys_var_character_set::update(THD *thd, set_var *var) { ci_ptr(thd,var->type)[0]= var->save_result.charset; return 0; } -byte *sys_var_character_set::value_ptr(THD *thd, enum_var_type type) + +byte *sys_var_character_set::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { CHARSET_INFO *cs= ci_ptr(thd,type)[0]; return cs ? (byte*) cs->csname : (byte*) "NULL"; } -CHARSET_INFO ** sys_var_character_set_connection::ci_ptr(THD *thd, enum_var_type type) +CHARSET_INFO ** sys_var_character_set_connection::ci_ptr(THD *thd, + enum_var_type type) { if (type == OPT_GLOBAL) return &global_system_variables.collation_connection; @@ -1295,7 +1298,9 @@ CHARSET_INFO ** sys_var_character_set_connection::ci_ptr(THD *thd, enum_var_type return &thd->variables.collation_connection; } -void sys_var_character_set_connection::set_default(THD *thd, enum_var_type type) + +void sys_var_character_set_connection::set_default(THD *thd, + enum_var_type type) { if (type == OPT_GLOBAL) global_system_variables.collation_connection= default_charset_info; @@ -1304,7 +1309,8 @@ void sys_var_character_set_connection::set_default(THD *thd, enum_var_type type) } -CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd, enum_var_type type) +CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd, + enum_var_type type) { if (type == OPT_GLOBAL) return &global_system_variables.character_set_client; @@ -1312,6 +1318,7 @@ CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd, enum_var_type typ return &thd->variables.character_set_client; } + void sys_var_character_set_client::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) @@ -1320,6 +1327,7 @@ void sys_var_character_set_client::set_default(THD *thd, enum_var_type type) thd->variables.character_set_client= global_system_variables.character_set_client; } + CHARSET_INFO ** sys_var_character_set_results::ci_ptr(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) @@ -1328,6 +1336,7 @@ CHARSET_INFO ** sys_var_character_set_results::ci_ptr(THD *thd, enum_var_type ty return &thd->variables.character_set_results; } + void sys_var_character_set_results::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) @@ -1336,6 +1345,7 @@ void sys_var_character_set_results::set_default(THD *thd, enum_var_type type) thd->variables.character_set_results= global_system_variables.character_set_results; } + CHARSET_INFO ** sys_var_character_set_server::ci_ptr(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) @@ -1344,6 +1354,7 @@ CHARSET_INFO ** sys_var_character_set_server::ci_ptr(THD *thd, enum_var_type typ return &thd->variables.character_set_server; } + void sys_var_character_set_server::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) @@ -1352,7 +1363,9 @@ void sys_var_character_set_server::set_default(THD *thd, enum_var_type type) thd->variables.character_set_server= global_system_variables.character_set_server; } -CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type type) + +CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, + enum_var_type type) { if (type == OPT_GLOBAL) return &global_system_variables.character_set_database; @@ -1360,6 +1373,7 @@ CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type t return &thd->variables.character_set_database; } + void sys_var_character_set_database::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) @@ -1368,6 +1382,7 @@ void sys_var_character_set_database::set_default(THD *thd, enum_var_type type) thd->variables.character_set_database= thd->db_charset; } + bool sys_var_collation_connection::update(THD *thd, set_var *var) { if (var->type == OPT_GLOBAL) @@ -1377,7 +1392,9 @@ bool sys_var_collation_connection::update(THD *thd, set_var *var) return 0; } -byte *sys_var_collation_connection::value_ptr(THD *thd, enum_var_type type) + +byte *sys_var_collation_connection::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { CHARSET_INFO *cs= ((type == OPT_GLOBAL) ? global_system_variables.collation_connection : @@ -1385,6 +1402,7 @@ byte *sys_var_collation_connection::value_ptr(THD *thd, enum_var_type type) return cs ? (byte*) cs->name : (byte*) "NULL"; } + void sys_var_collation_connection::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) @@ -1394,6 +1412,71 @@ void sys_var_collation_connection::set_default(THD *thd, enum_var_type type) } +bool sys_var_key_buffer_size::update(THD *thd, set_var *var) +{ + ulonglong tmp= var->value->val_int(); + if (!base_name.length) + { + base_name.str= (char*) "default"; + base_name.length= 7; + } + KEY_CACHE *key_cache= (KEY_CACHE*) find_named(&key_caches, base_name.str, + base_name.length); + if (!key_cache) + { + if (!tmp) // Tried to delete cache + return 0; // Ok, nothing to do + if (!(key_cache= create_key_cache(base_name.str, + base_name.length))) + return 1; + } + if (!tmp) + { + /* Delete not default key caches */ + if (base_name.length != 7 || memcpy(base_name.str, "default", 7)) + { + /* + QQ: Here we should move tables using this key cache to default + key cache + */ + delete key_cache; + return 0; + } + } + + key_cache->size= (ulonglong) getopt_ull_limit_value(tmp, option_limits); + + /* QQ: Needs to be updated when we have multiple key caches */ + keybuff_size= key_cache->size; + ha_resize_key_cache(); + return 0; +} + +static ulonglong zero=0; + +byte *sys_var_key_buffer_size::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) +{ + const char *name; + uint length; + + if (!base->str) + { + name= "default"; + length= 7; + } + else + { + name= base->str; + length= base->length; + } + KEY_CACHE *key_cache= (KEY_CACHE*) find_named(&key_caches, name, length); + if (!key_cache) + return (byte*) &zero; + return (byte*) &key_cache->size; +} + + /***************************************************************************** Functions to handle SET NAMES and SET CHARACTER SET @@ -1429,7 +1512,8 @@ void sys_var_timestamp::set_default(THD *thd, enum_var_type type) } -byte *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { thd->sys_var_tmp.long_value= (long) thd->start_time; return (byte*) &thd->sys_var_tmp.long_value; @@ -1443,7 +1527,8 @@ bool sys_var_last_insert_id::update(THD *thd, set_var *var) } -byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { thd->sys_var_tmp.long_value= (long) thd->insert_id(); return (byte*) &thd->last_insert_id; @@ -1457,7 +1542,8 @@ bool sys_var_insert_id::update(THD *thd, set_var *var) } -byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { return (byte*) &thd->current_insert_id; } @@ -1848,7 +1934,8 @@ int set_var_password::update(THD *thd) Functions to handle sql_mode ****************************************************************************/ -byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { ulong val; char buff[256]; @@ -1945,6 +2032,68 @@ ulong fix_sql_mode(ulong sql_mode) } +/**************************************************************************** + Named list handling +****************************************************************************/ + +gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length) +{ + I_List_iterator<NAMED_LIST> it(*list); + NAMED_LIST *element; + while ((element= it++)) + { + if (element->cmp(name, length)) + return element->data; + } + return 0; +} + + +void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr)) +{ + NAMED_LIST *element; + while ((element= list->get())) + { + (*free_element)(element->data); + delete element; + } +} + + +/* Key cache functions */ + +static KEY_CACHE *create_key_cache(const char *name, uint length) +{ + KEY_CACHE *key_cache; + DBUG_PRINT("info",("Creating key cache: %s", name)); + if ((key_cache= (KEY_CACHE*) my_malloc(sizeof(KEY_CACHE), + MYF(MY_ZEROFILL | MY_WME)))) + { + if (!new NAMED_LIST(&key_caches, name, length, (gptr) key_cache)) + { + my_free((char*) key_cache, MYF(0)); + key_cache= 0; + } + } + return key_cache; +} + + +KEY_CACHE *get_or_create_key_cache(const char *name, uint length) +{ + KEY_CACHE *key_cache= (KEY_CACHE*) find_named(&key_caches, name, + length); + if (!key_cache) + key_cache= create_key_cache(name, length); + return key_cache; +} + + +void free_key_cache(gptr key_cache) +{ + my_free(key_cache, MYF(0)); +} + /**************************************************************************** Used templates @@ -1953,4 +2102,5 @@ ulong fix_sql_mode(ulong sql_mode) #ifdef __GNUC__ template class List<set_var_base>; template class List_iterator_fast<set_var_base>; +template class I_List_iterator<NAMED_LIST>; #endif diff --git a/sql/set_var.h b/sql/set_var.h index 5a0fbd21809..978aba3384a 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -47,12 +47,18 @@ public: struct my_option *option_limits; /* Updated by by set_var_init() */ uint name_length; /* Updated by by set_var_init() */ const char *name; + LEX_STRING base_name; /* for structs */ + sys_after_update_func after_update; sys_var(const char *name_arg) :name(name_arg),after_update(0) - {} + { + base_name.length=0; + } sys_var(const char *name_arg,sys_after_update_func func) :name(name_arg),after_update(func) - {} + { + base_name.length=0; + } virtual ~sys_var() {} virtual bool check(THD *thd, set_var *var) { return 0; } bool check_enum(THD *thd, set_var *var, TYPELIB *enum_names); @@ -60,14 +66,16 @@ public: virtual bool update(THD *thd, set_var *var)=0; virtual void set_default(THD *thd, enum_var_type type) {} virtual SHOW_TYPE type() { return SHOW_UNDEF; } - virtual byte *value_ptr(THD *thd, enum_var_type type) { return 0; } + virtual byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + { return 0; } virtual bool check_type(enum_var_type type) { return type != OPT_GLOBAL; } /* Error if not GLOBAL */ virtual bool check_update_type(Item_result type) { return type != INT_RESULT; } /* Assume INT */ virtual bool check_default(enum_var_type type) { return option_limits == 0; } - Item *item(THD *thd, enum_var_type type); + Item *item(THD *thd, enum_var_type type, LEX_STRING *base); + virtual bool is_struct() { return 0; } }; @@ -83,7 +91,8 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE type() { return SHOW_LONG; } - byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; } + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + { return (byte*) value; } }; @@ -99,7 +108,8 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE type() { return SHOW_LONGLONG; } - byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; } + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + { return (byte*) value; } }; @@ -117,7 +127,8 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE type() { return SHOW_MY_BOOL; } - byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; } + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + { return (byte*) value; } bool check_update_type(Item_result type) { return 0; } }; @@ -149,7 +160,8 @@ public: (*set_default_func)(thd, type); } SHOW_TYPE type() { return SHOW_CHAR; } - byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; } + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) + { return (byte*) value; } bool check_update_type(Item_result type) { return type != STRING_RESULT; /* Only accept strings */ @@ -173,7 +185,7 @@ public: } bool update(THD *thd, set_var *var); SHOW_TYPE type() { return SHOW_CHAR; } - byte *value_ptr(THD *thd, enum_var_type type); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); bool check_update_type(Item_result type) { return 0; } }; @@ -209,7 +221,7 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE type() { return SHOW_LONG; } - byte *value_ptr(THD *thd, enum_var_type type); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; class sys_var_pseudo_thread_id :public sys_var_thd_ulong @@ -236,7 +248,7 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE type() { return SHOW_HA_ROWS; } - byte *value_ptr(THD *thd, enum_var_type type); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; @@ -256,7 +268,7 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE type() { return SHOW_LONGLONG; } - byte *value_ptr(THD *thd, enum_var_type type); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); bool check_default(enum_var_type type) { return type == OPT_GLOBAL && !option_limits; @@ -282,7 +294,7 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE type() { return SHOW_MY_BOOL; } - byte *value_ptr(THD *thd, enum_var_type type); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); bool check(THD *thd, set_var *var) { return check_enum(thd, var, &bool_typelib); @@ -313,7 +325,7 @@ public: bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE type() { return SHOW_CHAR; } - byte *value_ptr(THD *thd, enum_var_type type); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); bool check_update_type(Item_result type) { return 0; } }; @@ -332,7 +344,7 @@ public: return check_set(thd, var, enum_names); } void set_default(THD *thd, enum_var_type type); - byte *value_ptr(THD *thd, enum_var_type type); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; @@ -355,7 +367,7 @@ public: bool check_update_type(Item_result type) { return 0; } bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } SHOW_TYPE type() { return SHOW_MY_BOOL; } - byte *value_ptr(THD *thd, enum_var_type type); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; @@ -370,7 +382,7 @@ public: bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } bool check_default(enum_var_type type) { return 0; } SHOW_TYPE type() { return SHOW_LONG; } - byte *value_ptr(THD *thd, enum_var_type type); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; @@ -381,7 +393,7 @@ public: bool update(THD *thd, set_var *var); bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } SHOW_TYPE type() { return SHOW_LONGLONG; } - byte *value_ptr(THD *thd, enum_var_type type); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; @@ -392,7 +404,7 @@ public: bool update(THD *thd, set_var *var); bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } SHOW_TYPE type() { return SHOW_LONGLONG; } - byte *value_ptr(THD *thd, enum_var_type type); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; @@ -456,7 +468,7 @@ SHOW_TYPE type() { return SHOW_CHAR; } } bool check_default(enum_var_type type) { return 0; } bool update(THD *thd, set_var *var); - byte *value_ptr(THD *thd, enum_var_type type); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); virtual void set_default(THD *thd, enum_var_type type)= 0; virtual CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type)= 0; }; @@ -513,9 +525,24 @@ public: sys_var_collation_connection(const char *name_arg) :sys_var_collation(name_arg) {} bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); - byte *value_ptr(THD *thd, enum_var_type type); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; + +class sys_var_key_buffer_size :public sys_var +{ +public: + sys_var_key_buffer_size(const char *name_arg) + :sys_var(name_arg) + {} + bool update(THD *thd, set_var *var); + SHOW_TYPE type() { return SHOW_LONGLONG; } + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + bool check_default(enum_var_type type) { return 1; } + bool is_struct() { return 1; } +}; + + /* Variable that you can only read from */ class sys_var_readonly: public sys_var @@ -534,7 +561,7 @@ public: bool check_default(enum_var_type type) { return 1; } bool check_type(enum_var_type type) { return type != var_type; } bool check_update_type(Item_result type) { return 1; } - byte *value_ptr(THD *thd, enum_var_type type) + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { return (*value_ptr_func)(thd); } @@ -639,6 +666,33 @@ public: }; +/* Named lists (used for keycaches) */ + +class NAMED_LIST :public ilink +{ + const char *name; + uint name_length; +public: + gptr data; + + NAMED_LIST(I_List<NAMED_LIST> *links, const char *name_arg, + uint name_length_arg, gptr data_arg): + name_length(name_length_arg), data(data_arg) + { + name=my_strdup(name_arg,MYF(MY_WME)); + links->push_back(this); + } + inline bool cmp(const char *name_cmp, uint length) + { + return length == name_length && !memcmp(name, name_cmp, length); + } + ~NAMED_LIST() + { + my_free((char*) name, MYF(0)); + } +}; + + /* Prototypes for helper functions */ @@ -649,6 +703,11 @@ sys_var *find_sys_var(const char *str, uint length=0); int sql_set_variables(THD *thd, List<set_var_base> *var_list); void fix_delay_key_write(THD *thd, enum_var_type type); ulong fix_sql_mode(ulong sql_mode); - extern sys_var_str sys_charset_system; CHARSET_INFO *get_old_charset_by_name(const char *old_name); +gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length); +void delete_elements(I_List<NAMED_LIST> *list, void (*free_element)(gptr)); + +/* key_cache functions */ +KEY_CACHE *get_or_create_key_cache(const char *name, uint length); +void free_key_cache(gptr key_cache); diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 641b1384e9a..0bd8b70a96f 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -275,3 +275,4 @@ v/* "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 574d26b7c1c..64ffdea0d71 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -269,3 +269,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index c6c975cb141..3a506c7ef69 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -277,3 +277,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index f39c415fa55..83b90089701 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -271,3 +271,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index de22d6fd111..f4107e91d5b 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -271,3 +271,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 6c1187cd0e4..9549e98326c 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -266,3 +266,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 78d53034a71..0c60685d520 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -275,3 +275,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 347370f1ac8..873f8385462 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -266,3 +266,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 313275b3cb6..93ab550b60f 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -268,3 +268,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 8af7e3ba9f7..d1a5b1b301f 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -266,3 +266,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 417a03978fb..b8bc6e1d761 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -268,3 +268,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 22395d0fb6a..9bbcaa16076 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -266,3 +266,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index de6db62cdce..53b46d3f943 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -268,3 +268,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 28db8caa8bc..26e6b39a77f 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -268,3 +268,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index fdf856c7e56..60b0779db99 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -270,3 +270,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 397784dc7dd..904d7107893 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -266,3 +266,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 8f1cdb7b259..28bb5750d41 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -270,3 +270,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index ec41a6acb34..e193eac6793 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -268,3 +268,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 77d35be2fc9..3fbd7635ce9 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -262,3 +262,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 33cabdfc752..b25935131d5 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -274,3 +274,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 35e26f35ff7..777ef612a76 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -267,3 +267,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 9cdcb20db35..2166d7fe143 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -266,3 +266,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 5a614714de2..2fc14372f54 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -271,3 +271,4 @@ "Can't revoke all privileges, grant for one or more of the requested users" "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", +"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 2eeb57f34a7..425890ab446 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -557,10 +557,12 @@ int yylex(void *arg, void *yythd) return(IDENT); case MY_LEX_IDENT_SEP: // Found ident and now '.' - lex->next_state=MY_LEX_IDENT_START;// Next is an ident (not a keyword) yylval->lex_str.str=(char*) lex->ptr; yylval->lex_str.length=1; c=yyGet(); // should be '.' + lex->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword) + if (!ident_map[yyPeek()]) // Probably ` or " + lex->next_state= MY_LEX_START; return((int) c); case MY_LEX_NUMBER_IDENT: // number or ident which num-start @@ -601,7 +603,7 @@ int yylex(void *arg, void *yythd) yyUnget(); } // fall through - case MY_LEX_IDENT_START: // Incomplete ident + case MY_LEX_IDENT_START: // We come here after '.' #if defined(USE_MB) && defined(USE_MB_IDENT) if (use_mb(cs)) { @@ -689,6 +691,7 @@ int yylex(void *arg, void *yythd) } if (c == delim) yySkip(); // Skip end ` + lex->next_state= MY_LEX_START; return(IDENT); } case MY_LEX_SIGNED_NUMBER: // Incomplete signed number @@ -707,9 +710,9 @@ int yylex(void *arg, void *yythd) if (c != '.') { if (c == '-' && my_isspace(cs,yyPeek())) - state=MY_LEX_COMMENT; + state= MY_LEX_COMMENT; else - state = MY_LEX_CHAR; // Return sign as single char + state= MY_LEX_CHAR; // Return sign as single char break; } yyUnget(); // Fix for next loop @@ -868,7 +871,7 @@ int yylex(void *arg, void *yythd) else state=MY_LEX_CHAR; // Return '*' break; - case MY_LEX_SET_VAR: // Check if ':=' + case MY_LEX_SET_VAR: // Check if ':=' if (yyPeek() != '=') { state=MY_LEX_CHAR; // Return ':' @@ -904,8 +907,8 @@ int yylex(void *arg, void *yythd) state = MY_LEX_REAL; // Real else { - state = MY_LEX_CHAR; // return '.' - lex->next_state=MY_LEX_IDENT_START;// Next is an ident (not a keyword) + state= MY_LEX_IDENT_SEP; // return '.' + yyUnget(); // Put back '.' } break; case MY_LEX_USER_END: // end '@' of user@hostname @@ -933,8 +936,11 @@ int yylex(void *arg, void *yythd) case MY_LEX_SYSTEM_VAR: yylval->lex_str.str=(char*) lex->ptr; yylval->lex_str.length=1; - lex->next_state=MY_LEX_IDENT_OR_KEYWORD; yySkip(); // Skip '@' + lex->next_state= (state_map[yyPeek()] == + MY_LEX_USER_VARIABLE_DELIMITER ? + MY_LEX_OPERATOR_OR_IDENT : + MY_LEX_IDENT_OR_KEYWORD); return((int) '@'); case MY_LEX_IDENT_OR_KEYWORD: /* @@ -942,7 +948,6 @@ int yylex(void *arg, void *yythd) We should now be able to handle: [(global | local | session) .]variable_name */ - while (ident_map[c=yyGet()]) ; if (c == '.') lex->next_state=MY_LEX_IDENT_SEP; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0db6ce8a642..3593087d332 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3570,15 +3570,20 @@ mysql_new_select(LEX *lex, bool move_down) void create_select_for_variable(const char *var_name) { + THD *thd; LEX *lex; - LEX_STRING tmp; + LEX_STRING tmp, null_lex_string; DBUG_ENTER("create_select_for_variable"); - lex= current_lex; + + thd= current_thd; + lex= &thd->lex; mysql_init_select(lex); lex->sql_command= SQLCOM_SELECT; tmp.str= (char*) var_name; tmp.length=strlen(var_name); - add_item_to_list(lex->thd, get_system_var(OPT_SESSION, tmp)); + bzero((char*) &null_lex_string.str, sizeof(null_lex_string)); + add_item_to_list(thd, get_system_var(thd, OPT_SESSION, tmp, + null_lex_string)); DBUG_VOID_RETURN; } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index fae01936357..e8cb59e387e 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1527,12 +1527,14 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, char buff[1024]; List<Item> field_list; Protocol *protocol= thd->protocol; + LEX_STRING null_lex_str; DBUG_ENTER("mysqld_show"); field_list.push_back(new Item_empty_string("Variable_name",30)); field_list.push_back(new Item_empty_string("Value",256)); if (protocol->send_fields(&field_list,1)) DBUG_RETURN(1); /* purecov: inspected */ + null_lex_str.str= 0; // For sys_var->value_ptr() /* pthread_mutex_lock(&THR_LOCK_keycache); */ pthread_mutex_lock(&LOCK_status); @@ -1551,7 +1553,8 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, if (show_type == SHOW_SYS) { show_type= ((sys_var*) value)->type(); - value= (char*) ((sys_var*) value)->value_ptr(thd, value_type); + value= (char*) ((sys_var*) value)->value_ptr(thd, value_type, + &null_lex_str); } pos= end= buff; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6072be28dca..0651672a305 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -561,7 +561,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal - NCHAR_STRING + NCHAR_STRING opt_component %type <lex_str_ptr> opt_table_alias @@ -1532,6 +1532,10 @@ opt_ident: /* empty */ { $$=(char*) 0; } /* Defaultlength */ | field_ident { $$=$1.str; }; +opt_component: + /* empty */ { $$.str= 0; $$.length= 0; } + | '.' ident { $$=$2; }; + string_list: text_string { Lex->interval_list.push_back($1); } | string_list ',' text_string { Lex->interval_list.push_back($3); }; @@ -2276,9 +2280,9 @@ simple_expr: $$= new Item_func_get_user_var($2); Lex->uncacheable(); } - | '@' '@' opt_var_ident_type ident_or_text + | '@' '@' opt_var_ident_type ident_or_text opt_component { - if (!($$= get_system_var((enum_var_type) $3, $4))) + if (!($$= get_system_var(YYTHD, (enum_var_type) $3, $4, $5))) YYABORT; } | sum_expr @@ -2440,7 +2444,7 @@ simple_expr: } | LAST_INSERT_ID '(' ')' { - $$= get_system_var(OPT_SESSION, "last_insert_id", 14, + $$= get_system_var(YYTHD, OPT_SESSION, "last_insert_id", 14, "last_insert_id()"); Lex->safe_to_cache_query= 0; } @@ -4590,6 +4594,27 @@ internal_variable_name: YYABORT; $$=tmp; } + | ident '.' ident + { + sys_var *tmp=find_sys_var($3.str, $3.length); + if (!tmp) + YYABORT; + if (!tmp->is_struct()) + net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str); + tmp->base_name= $1; + $$=tmp; + } + | DEFAULT '.' ident + { + sys_var *tmp=find_sys_var($3.str, $3.length); + if (!tmp) + YYABORT; + if (!tmp->is_struct()) + net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str); + tmp->base_name.str= (char*) "default"; + tmp->base_name.length= 7; + $$=tmp; + } ; isolation_types: |