diff options
62 files changed, 4544 insertions, 2152 deletions
diff --git a/include/hash.h b/include/hash.h index 97e947d7c6a..78499a4f810 100644 --- a/include/hash.h +++ b/include/hash.h @@ -27,6 +27,9 @@ extern "C" { */ #define HASH_OVERHEAD (sizeof(char*)*2) +/* flags for hash_init */ +#define HASH_UNIQUE 1 /* hash_insert fails on duplicate key */ + typedef byte *(*hash_get_key)(const byte *,uint*,my_bool); typedef void (*hash_free_key)(void *); diff --git a/include/my_getopt.h b/include/my_getopt.h index dcd6ad9d79b..fd523e08d7f 100644 --- a/include/my_getopt.h +++ b/include/my_getopt.h @@ -29,12 +29,16 @@ C_MODE_START #define GET_STR 9 #define GET_STR_ALLOC 10 #define GET_DISABLED 11 +#define GET_ENUM 12 +#define GET_SET 13 #define GET_ASK_ADDR 128 #define GET_TYPE_MASK 127 enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG }; +struct st_typelib; + struct my_option { const char *name; /* Name of the option */ @@ -42,7 +46,7 @@ struct my_option const char *comment; /* option comment, for autom. --help */ gptr *value; /* The variable value */ gptr *u_max_value; /* The user def. max variable value */ - const char **str_values; /* Pointer to possible values */ + struct st_typelib *typelib; /* Pointer to possible values */ ulong var_type; enum get_opt_arg_type arg_type; longlong def_value; /* Default value */ @@ -50,7 +54,7 @@ struct my_option longlong max_value; /* Max allowed value */ longlong sub_size; /* Subtract this from given value */ long block_size; /* Value should be a mult. of this */ - int app_type; /* To be used by an application */ + long app_type; /* To be used by an application */ }; typedef my_bool (* my_get_one_option) (int, const struct my_option *, char * ); @@ -58,6 +62,7 @@ typedef void (* my_error_reporter) (enum loglevel level, const char *format, ... extern char *disabled_my_option; extern my_bool my_getopt_print_errors; +extern my_bool my_getopt_skip_unknown; extern my_error_reporter my_getopt_error_reporter; extern int handle_options (int *argc, char ***argv, diff --git a/include/my_sys.h b/include/my_sys.h index 8e831b448d7..dd28ac7ef31 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -758,8 +758,15 @@ extern my_bool real_open_cached_file(IO_CACHE *cache); extern void close_cached_file(IO_CACHE *cache); File create_temp_file(char *to, const char *dir, const char *pfx, int mode, myf MyFlags); -#define my_init_dynamic_array(A,B,C,D) init_dynamic_array(A,B,C,D CALLER_INFO) -#define my_init_dynamic_array_ci(A,B,C,D) init_dynamic_array(A,B,C,D ORIG_CALLER_INFO) +#define my_init_dynamic_array(A,B,C,D) init_dynamic_array2(A,B,NULL,C,D CALLER_INFO) +#define my_init_dynamic_array_ci(A,B,C,D) init_dynamic_array2(A,B,NULL,C,D ORIG_CALLER_INFO) +#define my_init_dynamic_array2(A,B,C,D,E) init_dynamic_array2(A,B,C,D,E CALLER_INFO) +#define my_init_dynamic_array2_ci(A,B,C,D,E) init_dynamic_array2(A,B,C,D,E ORIG_CALLER_INFO) +extern my_bool init_dynamic_array2(DYNAMIC_ARRAY *array,uint element_size, + void *init_buffer, uint init_alloc, + uint alloc_increment + CALLER_INFO_PROTO); +/* init_dynamic_array() function is deprecated */ extern my_bool init_dynamic_array(DYNAMIC_ARRAY *array,uint element_size, uint init_alloc,uint alloc_increment CALLER_INFO_PROTO); diff --git a/include/mysql.h b/include/mysql.h index f76ae10ca16..352f9953d5a 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -67,7 +67,6 @@ typedef int my_socket; #include "mysql_version.h" #include "mysql_com.h" #include "mysql_time.h" -#include "typelib.h" #include "my_list.h" /* for LISTs used in 'MYSQL' and 'MYSQL_STMT' */ @@ -126,6 +125,8 @@ typedef unsigned long long my_ulonglong; #endif #endif +#include "typelib.h" + #define MYSQL_COUNT_ERROR (~(my_ulonglong) 0) /* backward compatibility define - to be removed eventually */ diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index 660ce49d7ee..6c75ca75a54 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -16,6 +16,15 @@ #ifndef _my_plugin_h #define _my_plugin_h +#ifdef __cplusplus +class THD; +class Item; +#define MYSQL_THD THD* +#else +#define MYSQL_THD void* +#endif + + /************************************************************************* Plugin API. Common for all plugin types. */ @@ -85,7 +94,225 @@ struct st_mysql_show_var { }; #define SHOW_VAR_FUNC_BUFF_SIZE 1024 -typedef int (*mysql_show_var_func)(void *, struct st_mysql_show_var*, char *); +typedef int (*mysql_show_var_func)(MYSQL_THD, struct st_mysql_show_var*, char *); + + +/* + declarations for server variables and command line options +*/ + + +#define PLUGIN_VAR_BOOL 0x0001 +#define PLUGIN_VAR_INT 0x0002 +#define PLUGIN_VAR_LONG 0x0003 +#define PLUGIN_VAR_LONGLONG 0x0004 +#define PLUGIN_VAR_STR 0x0005 +#define PLUGIN_VAR_ENUM 0x0006 +#define PLUGIN_VAR_SET 0x0007 +#define PLUGIN_VAR_UNSIGNED 0x0080 +#define PLUGIN_VAR_THDLOCAL 0x0100 /* Variable is per-connection */ +#define PLUGIN_VAR_READONLY 0x0200 /* Server variable is read only */ +#define PLUGIN_VAR_NOSYSVAR 0x0400 /* Not a server variable */ +#define PLUGIN_VAR_NOCMDOPT 0x0800 /* Not a command line option */ +#define PLUGIN_VAR_NOCMDARG 0x1000 /* No argument for cmd line */ +#define PLUGIN_VAR_RQCMDARG 0x0000 /* Argument required for cmd line */ +#define PLUGIN_VAR_OPCMDARG 0x2000 /* Argument optional for cmd line */ +#define PLUGIN_VAR_MEMALLOC 0x8000 /* String needs memory allocated */ + +struct st_mysql_sys_var; +struct st_mysql_value; + +typedef int (*mysql_var_check_func)(MYSQL_THD thd, + struct st_mysql_sys_var *var, + void *save, struct st_mysql_value *value); +typedef void (*mysql_var_update_func)(MYSQL_THD thd, + struct st_mysql_sys_var *var, + void *var_ptr, void *save); + + +/* the following declarations are for internal use only */ + + +#define PLUGIN_VAR_MASK \ + (PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR | \ + PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_NOCMDARG | \ + PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC) + +#define MYSQL_PLUGIN_VAR_HEADER \ + int flags; \ + const char *name; \ + const char *comment; \ + mysql_var_check_func check; \ + mysql_var_update_func update + +#define MYSQL_SYSVAR_NAME(name) mysql_sysvar_ ## name +#define MYSQL_SYSVAR(name) \ + ((struct st_mysql_sys_var *)&(MYSQL_SYSVAR_NAME(name))) + +/* + for global variables, the value pointer is the first + element after the header, the default value is the second. + for thread variables, the value offset is the first + element after the header, the default value is the second. +*/ + + +#define DECLARE_MYSQL_SYSVAR_BASIC(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + type *value, def_val; \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_SYSVAR_SIMPLE(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + type *value, def_val, min_val,\ + max_val, blk_sz; \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_SYSVAR_TYPELIB(name) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + unsigned long *value, def_val;\ + TYPELIB *typelib; \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_THDVAR_FUNC(type) \ + type *(*resolve)(MYSQL_THD thd, int offset) + +#define DECLARE_MYSQL_THDVAR_BASIC(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + int offset; \ + type def_val; \ + DECLARE_THDVAR_FUNC(type); \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_THDVAR_SIMPLE(name, type) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + int offset; \ + type def_val, min_val, max_val, blk_sz; \ + DECLARE_THDVAR_FUNC(type); \ +} MYSQL_SYSVAR_NAME(name) + +#define DECLARE_MYSQL_THDVAR_TYPELIB(name) struct { \ + MYSQL_PLUGIN_VAR_HEADER; \ + int offset; \ + unsigned long def_val; \ + DECLARE_THDVAR_FUNC(unsigned long); \ + TYPELIB *typelib; \ +} MYSQL_SYSVAR_NAME(name) + + +/* + the following declarations are for use by plugin implementors +*/ + +#define MYSQL_SYSVAR_BOOL(name, varname, opt, comment, check, update, def) \ +DECLARE_MYSQL_SYSVAR_BASIC(name, char) = { \ + PLUGIN_VAR_BOOL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def} + +#define MYSQL_SYSVAR_STR(name, varname, opt, comment, check, update, def) \ +DECLARE_MYSQL_SYSVAR_BASIC(name, char *) = { \ + PLUGIN_VAR_STR | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def} + +#define MYSQL_SYSVAR_INT(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, int) = { \ + PLUGIN_VAR_INT | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_UINT(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, unsigned int) = { \ + PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_LONG(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, long) = { \ + PLUGIN_VAR_LONG | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_ULONG(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, unsigned long) = { \ + PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_LONGLONG(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, longlong) = { \ + PLUGIN_VAR_LONGLONG | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_ULONGLONG(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, ulonglong) = { \ + PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + +#define MYSQL_SYSVAR_ENUM(name, varname, opt, comment, check, update, def, typelib) \ +DECLARE_MYSQL_SYSVAR_TYPELIB(name) = { \ + PLUGIN_VAR_ENUM | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, typelib } + +#define MYSQL_SYSVAR_SET(name, varname, opt, comment, check, update, def, typelib) \ +DECLARE_MYSQL_SYSVAR_TYPELIB(name) = { \ + PLUGIN_VAR_SET | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, typelib } + +#define MYSQL_THDVAR_BOOL(name, opt, comment, check, update, def) \ +DECLARE_MYSQL_THDVAR_BASIC(name, char) = { \ + PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, NULL} + +#define MYSQL_THDVAR_STR(name, opt, comment, check, update, def) \ +DECLARE_MYSQL_THDVAR_BASIC(name, char *) = { \ + PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, NULL} + +#define MYSQL_THDVAR_INT(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, int) = { \ + PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_UINT(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, unsigned int) = { \ + PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_LONG(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, long) = { \ + PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_ULONG(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, unsigned long) = { \ + PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_LONGLONG(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, longlong) = { \ + PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_ULONGLONG(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, ulonglong) = { \ + PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL | PLUGIN_VAR_UNSIGNED | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + +#define MYSQL_THDVAR_ENUM(name, opt, comment, check, update, def, typelib) \ +DECLARE_MYSQL_THDVAR_TYPELIB(name) = { \ + PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, NULL, typelib } + +#define MYSQL_THDVAR_SET(name, opt, comment, check, update, def, typelib) \ +DECLARE_MYSQL_THDVAR_TYPELIB(name) = { \ + PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, NULL, typelib } + +/* accessor macros */ + +#define SYSVAR(name) \ + (*(MYSQL_SYSVAR_NAME(name).value)) + +/* when thd == null, result points to global value */ +#define THDVAR(thd, name) \ + (*(MYSQL_SYSVAR_NAME(name).resolve(thd, MYSQL_SYSVAR_NAME(name).offset))) + /* Plugin description structure. @@ -103,8 +330,8 @@ struct st_mysql_plugin int (*deinit)(void *);/* the function to invoke when plugin is unloaded */ unsigned int version; /* plugin version (for SHOW PLUGINS) */ struct st_mysql_show_var *status_vars; - void * __reserved1; /* placeholder for system variables */ - void * __reserved2; /* placeholder for config options */ + struct st_mysql_sys_var **system_vars; + void * __reserved1; /* reserved for dependency checking */ }; /************************************************************************* @@ -328,6 +555,8 @@ struct st_mysql_storage_engine int interface_version; }; +struct handlerton; + /* Here we define only the descriptor structure, that is referred from st_mysql_plugin. @@ -348,5 +577,47 @@ struct st_mysql_information_schema int interface_version; }; + +/* + st_mysql_value struct for reading values from mysqld. + Used by server variables framework to parse user-provided values. + Will be used for arguments when implementing UDFs. +*/ + +#define MYSQL_VALUE_TYPE_STRING 0 +#define MYSQL_VALUE_TYPE_REAL 1 +#define MYSQL_VALUE_TYPE_INT 2 + +struct st_mysql_value +{ + int (*value_type)(struct st_mysql_value *); + const char *(*val_str)(struct st_mysql_value *, char *buffer, int *length); + int (*val_real)(struct st_mysql_value *, void *realbuf, int realsize); + int (*val_int)(struct st_mysql_value *, void *intbuf, int intsize); +}; + + +/************************************************************************* + Miscellaneous functions for plugin implementors +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +int thd_in_lock_tables(const MYSQL_THD thd); +int thd_tablespace_op(const MYSQL_THD thd); +long long thd_test_options(const MYSQL_THD thd, long long test_options); +int thd_sql_command(const MYSQL_THD thd); +const char *thd_proc_info(MYSQL_THD thd, const char *info); +void **thd_ha_data(const MYSQL_THD thd, const struct handlerton *hton); +char *thd_security_context(MYSQL_THD thd, char *buffer, int length, + int max_query_len); + + +#ifdef __cplusplus +}; +#endif + #endif diff --git a/include/mysys_err.h b/include/mysys_err.h index b92027a4e3c..09e77248c17 100644 --- a/include/mysys_err.h +++ b/include/mysys_err.h @@ -79,6 +79,7 @@ extern const char * NEAR globerrs[]; /* my_error_messages is here */ #define EXIT_NO_PTR_TO_VARIABLE 10 #define EXIT_CANNOT_CONNECT_TO_SERVICE 11 #define EXIT_OPTION_DISABLED 12 +#define EXIT_ARGUMENT_INVALID 13 #ifdef __cplusplus diff --git a/include/typelib.h b/include/typelib.h index 75d170e59d3..eb3f59722a3 100644 --- a/include/typelib.h +++ b/include/typelib.h @@ -26,6 +26,7 @@ typedef struct st_typelib { /* Different types saved here */ unsigned int *type_lengths; } TYPELIB; +extern my_ulonglong find_typeset(char *x, TYPELIB *typelib,int *error_position); extern int find_type(char *x,TYPELIB *typelib,unsigned int full_name); extern void make_type(char *to,unsigned int nr,TYPELIB *typelib); extern const char *get_type(TYPELIB *typelib,unsigned int nr); diff --git a/mysql-test/r/im_utils.result b/mysql-test/r/im_utils.result index b7c68965ada..b2885030637 100644 --- a/mysql-test/r/im_utils.result +++ b/mysql-test/r/im_utils.result @@ -20,8 +20,8 @@ character-sets-dir VALUE basedir VALUE server_id VALUE skip-stack-trace VALUE -skip-innodb VALUE -skip-ndbcluster VALUE +skip-plugin-innodb VALUE +skip-plugin-ndbcluster VALUE log-output VALUE SHOW INSTANCE OPTIONS mysqld2; option_name value @@ -38,8 +38,8 @@ character-sets-dir VALUE basedir VALUE server_id VALUE skip-stack-trace VALUE -skip-innodb VALUE -skip-ndbcluster VALUE +skip-plugin-innodb VALUE +skip-plugin-ndbcluster VALUE nonguarded VALUE log-output VALUE START INSTANCE mysqld2; diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result index 8264f252287..5a90c22fa06 100644 --- a/mysql-test/r/log_tables.result +++ b/mysql-test/r/log_tables.result @@ -169,6 +169,8 @@ lock tables mysql.slow_log READ LOCAL, mysql.general_log READ LOCAL; unlock tables; set global general_log='OFF'; set global slow_query_log='OFF'; +set @save_storage_engine= @@session.storage_engine; +set storage_engine= MEMORY; alter table mysql.slow_log engine=ndb; ERROR HY000: This storage engine cannot be used for log tables" alter table mysql.slow_log engine=innodb; @@ -177,6 +179,7 @@ alter table mysql.slow_log engine=archive; ERROR HY000: This storage engine cannot be used for log tables" alter table mysql.slow_log engine=blackhole; ERROR HY000: This storage engine cannot be used for log tables" +set storage_engine= @save_storage_engine; drop table mysql.slow_log; drop table mysql.general_log; drop table mysql.general_log; diff --git a/mysql-test/r/ndb_dd_basic.result b/mysql-test/r/ndb_dd_basic.result index 724b42b6db3..91bd111bbdf 100644 --- a/mysql-test/r/ndb_dd_basic.result +++ b/mysql-test/r/ndb_dd_basic.result @@ -10,9 +10,7 @@ ALTER LOGFILE GROUP lg1 ADD UNDOFILE 'undofile02.dat' INITIAL_SIZE = 4M ENGINE=XYZ; -Warnings: -Error 1286 Unknown table engine 'XYZ' -Error 1466 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP' +ERROR 42000: Unknown table engine 'XYZ' CREATE TABLESPACE ts1 ADD DATAFILE 'datafile.dat' USE LOGFILE GROUP lg1 diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index 8619d0909ee..799f1b2c76f 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -54,7 +54,7 @@ create table t1 (a int) engine = x partition by key (a); Warnings: -Error 1286 Unknown table engine 'x' +Warning 1266 Using storage engine MyISAM for table 't1' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -66,8 +66,7 @@ engine = innodb partition by list (a) (partition p0 values in (0)); alter table t1 engine = x; -Warnings: -Error 1286 Unknown table engine 'x' +ERROR 42000: Unknown table engine 'x' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index 762ceeaa03b..26692a992fe 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -303,8 +303,9 @@ prepare stmt4 from ' show variables like ''sql_mode'' '; execute stmt4; Variable_name Value sql_mode -prepare stmt4 from ' show engine bdb logs '; +prepare stmt4 from ' show engine myisam logs '; execute stmt4; +Type Name Status prepare stmt4 from ' show grants for user '; prepare stmt4 from ' show create table t2 '; prepare stmt4 from ' show master status '; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index ec4c7c9b2aa..dc5874436e4 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -236,7 +236,7 @@ net_buffer_length 1024 net_read_timeout 300 net_retry_count 10 net_write_timeout 200 -select * from information_schema.global_variables where variable_name like 'net_%'; +select * from information_schema.global_variables where variable_name like 'net_%' order by 1; VARIABLE_NAME VARIABLE_VALUE NET_BUFFER_LENGTH 1024 NET_READ_TIMEOUT 300 @@ -248,7 +248,7 @@ net_buffer_length 2048 net_read_timeout 600 net_retry_count 10 net_write_timeout 500 -select * from information_schema.session_variables where variable_name like 'net_%'; +select * from information_schema.session_variables where variable_name like 'net_%' order by 1; VARIABLE_NAME VARIABLE_VALUE NET_BUFFER_LENGTH 2048 NET_READ_TIMEOUT 600 @@ -261,7 +261,7 @@ net_buffer_length 1024 net_read_timeout 900 net_retry_count 10 net_write_timeout 1000 -select * from information_schema.global_variables where variable_name like 'net_%'; +select * from information_schema.global_variables where variable_name like 'net_%' order by 1; VARIABLE_NAME VARIABLE_VALUE NET_BUFFER_LENGTH 1024 NET_READ_TIMEOUT 900 @@ -273,7 +273,7 @@ net_buffer_length 7168 net_read_timeout 600 net_retry_count 10 net_write_timeout 500 -select * from information_schema.session_variables where variable_name like 'net_%'; +select * from information_schema.session_variables where variable_name like 'net_%' order by 1; VARIABLE_NAME VARIABLE_VALUE NET_BUFFER_LENGTH 7168 NET_READ_TIMEOUT 600 @@ -314,7 +314,7 @@ query_prealloc_size 8192 range_alloc_block_size 2048 transaction_alloc_block_size 8192 transaction_prealloc_size 4096 -select * from information_schema.session_variables where variable_name like '%alloc%'; +select * from information_schema.session_variables where variable_name like '%alloc%' order by 1; VARIABLE_NAME VARIABLE_VALUE QUERY_ALLOC_BLOCK_SIZE 8192 QUERY_PREALLOC_SIZE 8192 @@ -336,7 +336,7 @@ query_prealloc_size 18432 range_alloc_block_size 16384 transaction_alloc_block_size 19456 transaction_prealloc_size 20480 -select * from information_schema.session_variables where variable_name like '%alloc%'; +select * from information_schema.session_variables where variable_name like '%alloc%' order by 1; VARIABLE_NAME VARIABLE_VALUE QUERY_ALLOC_BLOCK_SIZE 17408 QUERY_PREALLOC_SIZE 18432 @@ -353,7 +353,7 @@ query_prealloc_size 8192 range_alloc_block_size 2048 transaction_alloc_block_size 8192 transaction_prealloc_size 4096 -select * from information_schema.session_variables where variable_name like '%alloc%'; +select * from information_schema.session_variables where variable_name like '%alloc%' order by 1; VARIABLE_NAME VARIABLE_VALUE QUERY_ALLOC_BLOCK_SIZE 8192 QUERY_PREALLOC_SIZE 8192 @@ -881,7 +881,7 @@ ssl_capath # ssl_cert # ssl_cipher # ssl_key # -select * from information_schema.session_variables where variable_name like 'ssl%'; +select * from information_schema.session_variables where variable_name like 'ssl%' order by 1; VARIABLE_NAME VARIABLE_VALUE SSL_CA # SSL_CAPATH # diff --git a/mysql-test/t/log_tables.test b/mysql-test/t/log_tables.test index f1ff91a6d1d..b02a47dde6b 100644 --- a/mysql-test/t/log_tables.test +++ b/mysql-test/t/log_tables.test @@ -252,6 +252,8 @@ set global general_log='OFF'; set global slow_query_log='OFF'; # check that alter table doesn't work for other engines +set @save_storage_engine= @@session.storage_engine; +set storage_engine= MEMORY; --error ER_UNSUPORTED_LOG_ENGINE alter table mysql.slow_log engine=ndb; --error ER_UNSUPORTED_LOG_ENGINE @@ -260,6 +262,7 @@ alter table mysql.slow_log engine=innodb; alter table mysql.slow_log engine=archive; --error ER_UNSUPORTED_LOG_ENGINE alter table mysql.slow_log engine=blackhole; +set storage_engine= @save_storage_engine; drop table mysql.slow_log; drop table mysql.general_log; diff --git a/mysql-test/t/ndb_dd_basic.test b/mysql-test/t/ndb_dd_basic.test index 5d43d7997b0..551c3c089ae 100644 --- a/mysql-test/t/ndb_dd_basic.test +++ b/mysql-test/t/ndb_dd_basic.test @@ -21,6 +21,7 @@ INITIAL_SIZE 16M UNDO_BUFFER_SIZE = 1M ENGINE=MYISAM; +--error ER_UNKNOWN_STORAGE_ENGINE ALTER LOGFILE GROUP lg1 ADD UNDOFILE 'undofile02.dat' INITIAL_SIZE = 4M diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test index 782e204742f..9f8792c924f 100644 --- a/mysql-test/t/partition_innodb.test +++ b/mysql-test/t/partition_innodb.test @@ -71,6 +71,7 @@ engine = innodb partition by list (a) (partition p0 values in (0)); +--error ER_UNKNOWN_STORAGE_ENGINE alter table t1 engine = x; show create table t1; drop table t1; diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test index a9d4488b1be..2d5dd14e847 100644 --- a/mysql-test/t/ps_1general.test +++ b/mysql-test/t/ps_1general.test @@ -321,14 +321,8 @@ prepare stmt4 from ' show status like ''Threads_running'' '; execute stmt4; prepare stmt4 from ' show variables like ''sql_mode'' '; execute stmt4; -# The output depends on the bdb being enabled and on the history -# history (actions of the bdb engine). -# That is the reason why, we switch the output here off. -# (The real output will be tested in ps_6bdb.test) ---disable_result_log -prepare stmt4 from ' show engine bdb logs '; +prepare stmt4 from ' show engine myisam logs '; execute stmt4; ---enable_result_log prepare stmt4 from ' show grants for user '; prepare stmt4 from ' show create table t2 '; prepare stmt4 from ' show master status '; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 4f91b75ced1..cde0d0f7374 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -151,14 +151,14 @@ set global net_retry_count=10, session net_retry_count=10; set global net_buffer_length=1024, net_write_timeout=200, net_read_timeout=300; set session net_buffer_length=2048, net_write_timeout=500, net_read_timeout=600; show global variables like 'net_%'; -select * from information_schema.global_variables where variable_name like 'net_%'; +select * from information_schema.global_variables where variable_name like 'net_%' order by 1; show session variables like 'net_%'; -select * from information_schema.session_variables where variable_name like 'net_%'; +select * from information_schema.session_variables where variable_name like 'net_%' order by 1; set session net_buffer_length=8000, global net_read_timeout=900, net_write_timeout=1000; show global variables like 'net_%'; -select * from information_schema.global_variables where variable_name like 'net_%'; +select * from information_schema.global_variables where variable_name like 'net_%' order by 1; show session variables like 'net_%'; -select * from information_schema.session_variables where variable_name like 'net_%'; +select * from information_schema.session_variables where variable_name like 'net_%' order by 1; set net_buffer_length=1; show variables like 'net_buffer_length'; select * from information_schema.session_variables where variable_name like 'net_buffer_length'; @@ -175,7 +175,7 @@ set @@rand_seed1=10000000,@@rand_seed2=1000000; select ROUND(RAND(),5); show variables like '%alloc%'; -select * from information_schema.session_variables where variable_name like '%alloc%'; +select * from information_schema.session_variables where variable_name like '%alloc%' order by 1; set @@range_alloc_block_size=1024*16; set @@query_alloc_block_size=1024*17+2; set @@query_prealloc_size=1024*18; @@ -183,12 +183,12 @@ set @@transaction_alloc_block_size=1024*20-1; set @@transaction_prealloc_size=1024*21-1; select @@query_alloc_block_size; show variables like '%alloc%'; -select * from information_schema.session_variables where variable_name like '%alloc%'; +select * from information_schema.session_variables where variable_name like '%alloc%' order by 1; set @@range_alloc_block_size=default; set @@query_alloc_block_size=default, @@query_prealloc_size=default; set transaction_alloc_block_size=default, @@transaction_prealloc_size=default; show variables like '%alloc%'; -select * from information_schema.session_variables where variable_name like '%alloc%'; +select * from information_schema.session_variables where variable_name like '%alloc%' order by 1; # # Bug #10904 Illegal mix of collations between @@ -669,7 +669,7 @@ select @@ssl_ca, @@ssl_capath, @@ssl_cert, @@ssl_cipher, @@ssl_key; --replace_column 2 # show variables like 'ssl%'; --replace_column 2 # -select * from information_schema.session_variables where variable_name like 'ssl%'; +select * from information_schema.session_variables where variable_name like 'ssl%' order by 1; # # Bug #19616: make log_queries_not_using_indexes available in SHOW VARIABLES diff --git a/mysql-test/t/warnings_engine_disabled-master.opt b/mysql-test/t/warnings_engine_disabled-master.opt index 99837e4a4cb..f51c1789a16 100644 --- a/mysql-test/t/warnings_engine_disabled-master.opt +++ b/mysql-test/t/warnings_engine_disabled-master.opt @@ -1 +1 @@ ---loose-skip-ndb +--loose-skip-plugin-ndbcluster diff --git a/mysys/array.c b/mysys/array.c index 8f4a6087c00..dd715452fec 100644 --- a/mysys/array.c +++ b/mysys/array.c @@ -26,9 +26,10 @@ Initiate dynamic array SYNOPSIS - init_dynamic_array() + init_dynamic_array2() array Pointer to an array element_size Size of element + init_buffer Initial buffer pointer init_alloc Number of initial elements alloc_increment Increment for adding new elements @@ -36,14 +37,15 @@ init_dynamic_array() initiates array and allocate space for init_alloc eilements. Array is usable even if space allocation failed. + Static buffers must begin immediately after the array structure. RETURN VALUE TRUE my_malloc_ci() failed FALSE Ok */ -my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, - uint init_alloc, +my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size, + void *init_buffer, uint init_alloc, uint alloc_increment CALLER_INFO_PROTO) { DBUG_ENTER("init_dynamic_array"); @@ -56,10 +58,14 @@ my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, if (!init_alloc) init_alloc=alloc_increment; + else + init_buffer= 0; array->elements=0; array->max_element=init_alloc; array->alloc_increment=alloc_increment; array->size_of_element=element_size; + if ((array->buffer= init_buffer)) + DBUG_RETURN(FALSE); if (!(array->buffer=(char*) my_malloc_ci(element_size*init_alloc,MYF(MY_WME)))) { array->max_element=0; @@ -68,6 +74,14 @@ my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, DBUG_RETURN(FALSE); } +my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, + uint init_alloc, + uint alloc_increment CALLER_INFO_PROTO) +{ + /* placeholder to preserve ABI */ + return my_init_dynamic_array_ci(array, element_size, init_alloc, + alloc_increment); +} /* Insert element at the end of array. Allocate memory if needed. @@ -121,6 +135,21 @@ byte *alloc_dynamic(DYNAMIC_ARRAY *array) if (array->elements == array->max_element) { char *new_ptr; + if (array->buffer == (char *)(array + 1)) + { + /* + In this senerio, the buffer is statically preallocated, + so we have to create an all-new malloc since we overflowed + */ + if (!(new_ptr= (char *) my_malloc((array->max_element+ + array->alloc_increment) * + array->size_of_element, + MYF(MY_WME)))) + return 0; + memcpy(new_ptr, array->buffer, + array->elements * array->size_of_element); + } + else if (!(new_ptr=(char*) my_realloc(array->buffer,(array->max_element+ array->alloc_increment)* array->size_of_element, @@ -180,6 +209,20 @@ my_bool set_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) char *new_ptr; size=(idx+array->alloc_increment)/array->alloc_increment; size*= array->alloc_increment; + if (array->buffer == (char *)(array + 1)) + { + /* + In this senerio, the buffer is statically preallocated, + so we have to create an all-new malloc since we overflowed + */ + if (!(new_ptr= (char *) my_malloc(size * + array->size_of_element, + MYF(MY_WME)))) + return 0; + memcpy(new_ptr, array->buffer, + array->elements * array->size_of_element); + } + else if (!(new_ptr=(char*) my_realloc(array->buffer,size* array->size_of_element, MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) @@ -230,6 +273,12 @@ void get_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) void delete_dynamic(DYNAMIC_ARRAY *array) { + /* + Just mark as empty if we are using a static buffer + */ + if (array->buffer == (char *)(array + 1)) + array->elements= 0; + else if (array->buffer) { my_free(array->buffer,MYF(MY_WME)); @@ -269,6 +318,12 @@ void freeze_size(DYNAMIC_ARRAY *array) { uint elements=max(array->elements,1); + /* + Do nothing if we are using a static buffer + */ + if (array->buffer == (char *)(array + 1)) + return; + if (array->buffer && array->max_element != elements) { array->buffer=(char*) my_realloc(array->buffer, diff --git a/mysys/hash.c b/mysys/hash.c index 60168e01e20..ab875848989 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -315,6 +315,10 @@ my_bool my_hash_insert(HASH *info,const byte *record) LINT_INIT(gpos); LINT_INIT(gpos2); LINT_INIT(ptr_to_rec); LINT_INIT(ptr_to_rec2); + if (HASH_UNIQUE & info->flags && + hash_search(info, hash_key(info, record, &idx, 1), idx)) + return(TRUE); /* Duplicate entry */ + flag=0; if (!(empty=(HASH_LINK*) alloc_dynamic(&info->array))) return(TRUE); /* No more memory */ @@ -530,6 +534,19 @@ my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length) uint idx,new_index,new_pos_index,blength,records,empty; HASH_LINK org_link,*data,*previous,*pos; DBUG_ENTER("hash_update"); + + if (HASH_UNIQUE & hash->flags) + { + HASH_SEARCH_STATE state; + byte *found, *new_key= hash_key(hash, record, &idx, 1); + if ((found= hash_first(hash, new_key, idx, &state))) + do + { + if (found != record) + DBUG_RETURN(1); /* Duplicate entry */ + } + while ((found= hash_next(hash, new_key, idx, &state))); + } data=dynamic_element(&hash->array,0,HASH_LINK*); blength=hash->blength; records=hash->records; diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index aa470282aa4..f893cf89b5c 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -58,6 +58,13 @@ char *disabled_my_option= (char*) "0"; my_bool my_getopt_print_errors= 1; +/* + This is a flag that can be set in client programs. 1 means that + my_getopt will skip over options it does not know how to handle. +*/ + +my_bool my_getopt_skip_unknown= 0; + static void default_reporter(enum loglevel level, const char *format, ...) { @@ -110,6 +117,7 @@ int handle_options(int *argc, char ***argv, for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) { + char **first= pos; char *cur_arg= *pos; if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */ { @@ -259,6 +267,19 @@ int handle_options(int *argc, char ***argv, } if (!opt_found) { + if (my_getopt_skip_unknown) + { + /* + preserve all the components of this unknown option, this may + occurr when the user provides options like: "-O foo" or + "--set-variable foo" (note that theres a space in there) + Generally, these kind of options are to be avoided + */ + do { + (*argv)[argvpos++]= *first++; + } while (first <= pos); + continue; + } if (must_be_var) { if (my_getopt_print_errors) @@ -596,6 +617,15 @@ static int setval(const struct my_option *opts, gptr *value, char *argument, if (!(*((char**) result_pos)= my_strdup(argument, MYF(MY_WME)))) return EXIT_OUT_OF_MEMORY; break; + case GET_ENUM: + if (((*(int*)result_pos)= find_type(argument, opts->typelib, 2) - 1) < 0) + return EXIT_ARGUMENT_INVALID; + break; + case GET_SET: + *((ulonglong*)result_pos)= find_typeset(argument, opts->typelib, &err); + if (err) + return EXIT_ARGUMENT_INVALID; + break; default: /* dummy default to avoid compiler warnings */ break; } @@ -788,6 +818,7 @@ static void init_one_value(const struct my_option *option, gptr *variable, *((int*) variable)= (int) value; break; case GET_UINT: + case GET_ENUM: *((uint*) variable)= (uint) value; break; case GET_LONG: @@ -800,6 +831,7 @@ static void init_one_value(const struct my_option *option, gptr *variable, *((longlong*) variable)= (longlong) value; break; case GET_ULL: + case GET_SET: *((ulonglong*) variable)= (ulonglong) value; break; default: /* dummy default to avoid compiler warnings */ @@ -928,7 +960,8 @@ void my_print_help(const struct my_option *options) void my_print_variables(const struct my_option *options) { - uint name_space= 34, length; + uint name_space= 34, length, nr; + ulonglong bit, llvalue; char buff[255]; const struct my_option *optp; @@ -946,6 +979,21 @@ void my_print_variables(const struct my_option *options) for (; length < name_space; length++) putchar(' '); switch ((optp->var_type & GET_TYPE_MASK)) { + case GET_SET: + if (!(llvalue= *(ulonglong*) value)) + printf("%s\n", "(No default value)"); + else + for (nr= 0, bit= 1; llvalue && nr < optp->typelib->count; nr++, bit<<=1) + { + if (!(bit & llvalue)) + continue; + llvalue&= ~bit; + printf( llvalue ? "%s," : "%s\n", get_type(optp->typelib, nr)); + } + break; + case GET_ENUM: + printf("%s\n", get_type(optp->typelib, *(uint*) value)); + break; case GET_STR: case GET_STR_ALLOC: /* fall through */ printf("%s\n", *((char**) value) ? *((char**) value) : diff --git a/mysys/typelib.c b/mysys/typelib.c index 4fab6f20493..5013423799c 100644 --- a/mysys/typelib.c +++ b/mysys/typelib.c @@ -120,6 +120,54 @@ const char *get_type(TYPELIB *typelib, uint nr) } +static const char field_separator=','; + +/* + Create an integer value to represent the supplied comma-seperated + string where each string in the TYPELIB denotes a bit position. + + SYNOPSIS + find_typeset() + x string to decompose + lib TYPELIB (struct of pointer to values + count) + err index (not char position) of string element which was not + found or 0 if there was no error + + RETURN + a integer representation of the supplied string +*/ + +my_ulonglong find_typeset(my_string x, TYPELIB *lib, int *err) +{ + my_ulonglong result; + int find; + my_string i; + DBUG_ENTER("find_set"); + DBUG_PRINT("enter",("x: '%s' lib: 0x%lx", x, (long) lib)); + + if (!lib->count) + { + DBUG_PRINT("exit",("no count")); + DBUG_RETURN(0); + } + result= 0; + *err= 0; + while (*x) + { + (*err)++; + i= x; + while (*x && *x != field_separator) x++; + if (*x) + *x++= 0; + if ((find= find_type(i, lib, 2) - 1) < 0) + DBUG_RETURN(0); + result|= (ULL(1) << find); + } + *err= 0; + DBUG_RETURN(result); +} /* find_set */ + + /* Create a copy of a specified TYPELIB structure. diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 393856e62ba..4f4f32c1fa5 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2629,7 +2629,7 @@ int ha_ndbcluster::write_row(byte *record) DBUG_RETURN(peek_res); } - statistic_increment(thd->status_var.ha_write_count, &LOCK_status); + ha_statistic_increment(&SSV::ha_write_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); @@ -2849,7 +2849,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) DBUG_RETURN(peek_res); } - statistic_increment(thd->status_var.ha_update_count, &LOCK_status); + ha_statistic_increment(&SSV::ha_update_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) { table->timestamp_field->set_time(); @@ -3016,7 +3016,7 @@ int ha_ndbcluster::delete_row(const byte *record) DBUG_ENTER("delete_row"); m_write_op= TRUE; - statistic_increment(thd->status_var.ha_delete_count,&LOCK_status); + ha_statistic_increment(&SSV::ha_delete_count); m_rows_changed++; if (m_use_partition_function && @@ -3372,7 +3372,7 @@ int ha_ndbcluster::index_read_idx(byte *buf, uint index_no, const byte *key, uint key_len, enum ha_rkey_function find_flag) { - statistic_increment(current_thd->status_var.ha_read_key_count, &LOCK_status); + ha_statistic_increment(&SSV::ha_read_key_count); DBUG_ENTER("ha_ndbcluster::index_read_idx"); DBUG_PRINT("enter", ("index_no: %u, key_len: %u", index_no, key_len)); close_scan(); @@ -3384,8 +3384,7 @@ int ha_ndbcluster::index_read_idx(byte *buf, uint index_no, int ha_ndbcluster::index_next(byte *buf) { DBUG_ENTER("ha_ndbcluster::index_next"); - statistic_increment(current_thd->status_var.ha_read_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_next_count); DBUG_RETURN(next_result(buf)); } @@ -3393,8 +3392,7 @@ int ha_ndbcluster::index_next(byte *buf) int ha_ndbcluster::index_prev(byte *buf) { DBUG_ENTER("ha_ndbcluster::index_prev"); - statistic_increment(current_thd->status_var.ha_read_prev_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_prev_count); DBUG_RETURN(next_result(buf)); } @@ -3402,8 +3400,7 @@ int ha_ndbcluster::index_prev(byte *buf) int ha_ndbcluster::index_first(byte *buf) { DBUG_ENTER("ha_ndbcluster::index_first"); - statistic_increment(current_thd->status_var.ha_read_first_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_first_count); // Start the ordered index scan and fetch the first row // Only HA_READ_ORDER indexes get called by index_first @@ -3414,7 +3411,7 @@ int ha_ndbcluster::index_first(byte *buf) int ha_ndbcluster::index_last(byte *buf) { DBUG_ENTER("ha_ndbcluster::index_last"); - statistic_increment(current_thd->status_var.ha_read_last_count,&LOCK_status); + ha_statistic_increment(&SSV::ha_read_last_count); DBUG_RETURN(ordered_index_scan(0, 0, TRUE, TRUE, buf, NULL)); } @@ -3600,8 +3597,7 @@ int ha_ndbcluster::rnd_end() int ha_ndbcluster::rnd_next(byte *buf) { DBUG_ENTER("rnd_next"); - statistic_increment(current_thd->status_var.ha_read_rnd_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_rnd_next_count); if (!m_active_cursor) DBUG_RETURN(full_table_scan(buf)); @@ -3619,8 +3615,7 @@ int ha_ndbcluster::rnd_next(byte *buf) int ha_ndbcluster::rnd_pos(byte *buf, byte *pos) { DBUG_ENTER("rnd_pos"); - statistic_increment(current_thd->status_var.ha_read_rnd_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_rnd_count); // The primary key for the record is stored in pos // Perform a pk_read using primary key "index" { @@ -6743,7 +6738,7 @@ static int ndbcluster_init(void *p) { handlerton *h= ndbcluster_hton; - h->state= have_ndbcluster; + h->state= SHOW_OPTION_YES; h->db_type= DB_TYPE_NDBCLUSTER; h->close_connection= ndbcluster_close_connection; h->commit= ndbcluster_commit; @@ -6765,9 +6760,6 @@ static int ndbcluster_init(void *p) h->table_exists_in_engine= ndbcluster_table_exists_in_engine; } - if (have_ndbcluster != SHOW_OPTION_YES) - DBUG_RETURN(0); // nothing else to do - // Initialize ndb interface ndb_init_internal(); @@ -6883,7 +6875,6 @@ ndbcluster_init_error: if (g_ndb_cluster_connection) delete g_ndb_cluster_connection; g_ndb_cluster_connection= NULL; - have_ndbcluster= SHOW_OPTION_DISABLED; // If we couldn't use handler ndbcluster_hton->state= SHOW_OPTION_DISABLED; // If we couldn't use handler DBUG_RETURN(TRUE); @@ -10220,10 +10211,6 @@ ndbcluster_show_status(handlerton *hton, THD* thd, stat_print_fn *stat_print, uint buflen; DBUG_ENTER("ndbcluster_show_status"); - if (have_ndbcluster != SHOW_OPTION_YES) - { - DBUG_RETURN(FALSE); - } if (stat_type != HA_ENGINE_STATUS) { DBUG_RETURN(FALSE); diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 87d24207dcd..d8fd3b5f934 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1987,6 +1987,8 @@ bool ha_partition::create_handler_file(const char *name) void ha_partition::clear_handler_file() { + if (m_engine_array) + plugin_unlock_list(NULL, m_engine_array, m_tot_parts); my_free((char*) m_file_buffer, MYF(MY_ALLOW_ZERO_PTR)); my_free((char*) m_engine_array, MYF(MY_ALLOW_ZERO_PTR)); m_file_buffer= NULL; @@ -2009,6 +2011,7 @@ bool ha_partition::create_handlers(MEM_ROOT *mem_root) { uint i; uint alloc_len= (m_tot_parts + 1) * sizeof(handler*); + handlerton *hton0; DBUG_ENTER("create_handlers"); if (!(m_file= (handler **) alloc_root(mem_root, alloc_len))) @@ -2017,19 +2020,21 @@ bool ha_partition::create_handlers(MEM_ROOT *mem_root) bzero((char*) m_file, alloc_len); for (i= 0; i < m_tot_parts; i++) { + handlerton *hton= plugin_data(m_engine_array[i], handlerton*); if (!(m_file[i]= get_new_handler(table_share, mem_root, - m_engine_array[i]))) + hton))) DBUG_RETURN(TRUE); - DBUG_PRINT("info", ("engine_type: %u", m_engine_array[i]->db_type)); + DBUG_PRINT("info", ("engine_type: %u", hton->db_type)); } /* For the moment we only support partition over the same table engine */ - if (m_engine_array[0] == myisam_hton) + hton0= plugin_data(m_engine_array[0], handlerton*); + if (hton0 == myisam_hton) { DBUG_PRINT("info", ("MyISAM")); m_myisam= TRUE; } /* INNODB may not be compiled in... */ - else if (ha_legacy_type(m_engine_array[0]) == DB_TYPE_INNODB) + else if (ha_legacy_type(hton0) == DB_TYPE_INNODB) { DBUG_PRINT("info", ("InnoDB")); m_innodb= TRUE; @@ -2160,8 +2165,7 @@ bool ha_partition::get_from_handler_file(const char *name, MEM_ROOT *mem_root) m_tot_parts= uint4korr((file_buffer) + 8); DBUG_PRINT("info", ("No of parts = %u", m_tot_parts)); tot_partition_words= (m_tot_parts + 3) / 4; - if (!(engine_array= (handlerton **) my_malloc(m_tot_parts * sizeof(handlerton*),MYF(0)))) - goto err2; + engine_array= (handlerton **) my_alloca(m_tot_parts * sizeof(handlerton*)); for (i= 0; i < m_tot_parts; i++) engine_array[i]= ha_resolve_by_legacy_type(current_thd, (enum legacy_db_type) @@ -2174,7 +2178,14 @@ bool ha_partition::get_from_handler_file(const char *name, MEM_ROOT *mem_root) VOID(my_close(file, MYF(0))); m_file_buffer= file_buffer; // Will be freed in clear_handler_file() m_name_buffer_ptr= name_buffer_ptr; - m_engine_array= engine_array; + + if (!(m_engine_array= (plugin_ref*) + my_malloc(m_tot_parts * sizeof(plugin_ref), MYF(MY_WME)))) + goto err2; + + for (i= 0; i < m_tot_parts; i++) + m_engine_array[i]= ha_lock_engine(NULL, engine_array[i]); + if (!m_file && create_handlers(mem_root)) { clear_handler_file(); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 4fdf325fa06..a2904562930 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -27,6 +27,7 @@ enum partition_keywords The partition implements the minimum of what you will probably need. */ +#ifdef NOT_USED typedef struct st_partition_share { char *table_name; @@ -34,6 +35,7 @@ typedef struct st_partition_share pthread_mutex_t mutex; THR_LOCK lock; } PARTITION_SHARE; +#endif #define PARTITION_BYTES_IN_POS 2 @@ -54,7 +56,7 @@ private: uint m_open_test_lock; // Open test_if_locked char *m_file_buffer; // Buffer with names char *m_name_buffer_ptr; // Pointer to first partition name - handlerton **m_engine_array; // Array of types of the handlers + plugin_ref *m_engine_array; // Array of types of the handlers handler **m_file; // Array of references to handler inst. uint m_file_tot_parts; // Debug handler **m_new_file; // Array of references to new handlers @@ -130,7 +132,9 @@ private: Variables for lock structures. */ THR_LOCK_DATA lock; /* MySQL lock */ +#ifdef NOT_USED PARTITION_SHARE *share; /* Shared lock info */ +#endif public: virtual void set_part_info(partition_info *part_info) diff --git a/sql/handler.cc b/sql/handler.cc index 2244aaa5311..bb7c39be262 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -77,6 +77,15 @@ static TYPELIB known_extensions= {0,"known_exts", NULL, NULL}; uint known_extensions_id= 0; + +static plugin_ref ha_default_plugin(THD *thd) +{ + if (thd->variables.table_plugin) + return thd->variables.table_plugin; + return my_plugin_lock(thd, &global_system_variables.table_plugin); +} + + /** @brief Return the default storage engine handlerton for thread @@ -89,10 +98,11 @@ uint known_extensions_id= 0; */ handlerton *ha_default_handlerton(THD *thd) { - return (thd->variables.table_type != NULL) ? - thd->variables.table_type : - (global_system_variables.table_type != NULL ? - global_system_variables.table_type : myisam_hton); + plugin_ref plugin= ha_default_plugin(thd); + DBUG_ASSERT(plugin); + handlerton *hton= plugin_data(plugin, handlerton*); + DBUG_ASSERT(hton); + return hton; } @@ -105,26 +115,30 @@ handlerton *ha_default_handlerton(THD *thd) name name of storage engine RETURN - pointer to handlerton + pointer to storage engine plugin handle */ -handlerton *ha_resolve_by_name(THD *thd, const LEX_STRING *name) +plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name) { const LEX_STRING *table_alias; - st_plugin_int *plugin; + plugin_ref plugin; redo: /* my_strnncoll is a macro and gcc doesn't do early expansion of macro */ if (thd && !my_charset_latin1.coll->strnncoll(&my_charset_latin1, (const uchar *)name->str, name->length, (const uchar *)STRING_WITH_LEN("DEFAULT"), 0)) - return ha_default_handlerton(thd); + return ha_default_plugin(thd); - if ((plugin= plugin_lock(name, MYSQL_STORAGE_ENGINE_PLUGIN))) + if ((plugin= my_plugin_lock_by_name(thd, name, MYSQL_STORAGE_ENGINE_PLUGIN))) { - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if (!(hton->flags & HTON_NOT_USER_SELECTABLE)) - return hton; - plugin_unlock(plugin); + return plugin; + + /* + unlocking plugin immediately after locking is relatively low cost. + */ + plugin_unlock(thd, plugin); } /* @@ -145,19 +159,19 @@ redo: } -const char *ha_get_storage_engine(enum legacy_db_type db_type) +plugin_ref ha_lock_engine(THD *thd, handlerton *hton) { - switch (db_type) { - case DB_TYPE_DEFAULT: - return "DEFAULT"; - default: - if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT && - installed_htons[db_type]) - return hton2plugin[installed_htons[db_type]->slot]->name.str; - /* fall through */ - case DB_TYPE_UNKNOWN: - return "UNKNOWN"; + if (hton) + { + st_plugin_int **plugin= hton2plugin + hton->slot; + +#ifdef DBUG_OFF; + return my_plugin_lock(thd, plugin); +#else + return my_plugin_lock(thd, &plugin); +#endif } + return NULL; } @@ -172,14 +186,16 @@ static handler *create_default(TABLE_SHARE *table, MEM_ROOT *mem_root) handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type) { + plugin_ref plugin; switch (db_type) { case DB_TYPE_DEFAULT: return ha_default_handlerton(thd); - case DB_TYPE_UNKNOWN: - return NULL; default: - if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT) - return installed_htons[db_type]; + if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT && + (plugin= ha_lock_engine(thd, installed_htons[db_type]))) + return plugin_data(plugin, handlerton*); + /* fall through */ + case DB_TYPE_UNKNOWN: return NULL; } } @@ -199,7 +215,7 @@ handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type, { if (report_error) { - const char *engine_name= ha_get_storage_engine(database_type); + const char *engine_name= ha_resolve_storage_engine_name(hton); my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name); } return NULL; @@ -238,8 +254,7 @@ handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc, Here the call to current_thd() is ok as we call this function a lot of times but we enter this branch very seldom. */ - DBUG_RETURN(get_new_handler(share, alloc, - current_thd->variables.table_type)); + DBUG_RETURN(get_new_handler(share, alloc, ha_default_handlerton(current_thd))); } @@ -522,10 +537,10 @@ int ha_end() DBUG_RETURN(error); } -static my_bool dropdb_handlerton(THD *unused1, st_plugin_int *plugin, +static my_bool dropdb_handlerton(THD *unused1, plugin_ref plugin, void *path) { - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if (hton->state == SHOW_OPTION_YES && hton->drop_database) hton->drop_database(hton, (char *)path); return FALSE; @@ -538,10 +553,10 @@ void ha_drop_database(char* path) } -static my_bool closecon_handlerton(THD *thd, st_plugin_int *plugin, +static my_bool closecon_handlerton(THD *thd, plugin_ref plugin, void *unused) { - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); /* there's no need to rollback here as all transactions must be rolled back already @@ -638,7 +653,7 @@ int ha_prepare(THD *thd) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), - hton2plugin[(*ht)->slot]->name.str); + ha_resolve_storage_engine_name(*ht)); } } } @@ -886,10 +901,10 @@ struct xahton_st { int result; }; -static my_bool xacommit_handlerton(THD *unused1, st_plugin_int *plugin, +static my_bool xacommit_handlerton(THD *unused1, plugin_ref plugin, void *arg) { - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if (hton->state == SHOW_OPTION_YES && hton->recover) { hton->commit_by_xid(hton, ((struct xahton_st *)arg)->xid); @@ -898,10 +913,10 @@ static my_bool xacommit_handlerton(THD *unused1, st_plugin_int *plugin, return FALSE; } -static my_bool xarollback_handlerton(THD *unused1, st_plugin_int *plugin, +static my_bool xarollback_handlerton(THD *unused1, plugin_ref plugin, void *arg) { - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if (hton->state == SHOW_OPTION_YES && hton->recover) { hton->rollback_by_xid(hton, ((struct xahton_st *)arg)->xid); @@ -1004,10 +1019,10 @@ struct xarecover_st bool dry_run; }; -static my_bool xarecover_handlerton(THD *unused, st_plugin_int *plugin, +static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, void *arg) { - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); struct xarecover_st *info= (struct xarecover_st *) arg; int got; @@ -1016,7 +1031,7 @@ static my_bool xarecover_handlerton(THD *unused, st_plugin_int *plugin, while ((got= hton->recover(hton, info->list, info->len)) > 0 ) { sql_print_information("Found %d prepared transaction(s) in %s", - got, hton2plugin[hton->slot]->name.str); + got, ha_resolve_storage_engine_name(hton)); for (int i=0; i < got; i ++) { my_xid x=info->list[i].get_my_xid(); @@ -1192,10 +1207,10 @@ bool mysql_xa_recover(THD *thd) thd: the thread handle of the current connection return value: always 0 */ -static my_bool release_temporary_latches(THD *thd, st_plugin_int *plugin, +static my_bool release_temporary_latches(THD *thd, plugin_ref plugin, void *unused) { - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches) hton->release_temporary_latches(hton, thd); @@ -1318,10 +1333,10 @@ int ha_release_savepoint(THD *thd, SAVEPOINT *sv) } -static my_bool snapshot_handlerton(THD *thd, st_plugin_int *plugin, +static my_bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg) { - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if (hton->state == SHOW_OPTION_YES && hton->start_consistent_snapshot) { @@ -1349,10 +1364,10 @@ int ha_start_consistent_snapshot(THD *thd) } -static my_bool flush_handlerton(THD *thd, st_plugin_int *plugin, +static my_bool flush_handlerton(THD *thd, plugin_ref plugin, void *arg) { - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if (hton->state == SHOW_OPTION_YES && hton->flush_logs && hton->flush_logs(hton)) return TRUE; @@ -1397,7 +1412,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, /* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */ if (table_type == NULL || - ! (file=get_new_handler(&dummy_share, thd->mem_root, table_type))) + ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type))) DBUG_RETURN(ENOENT); if (lower_case_table_names == 2 && !(file->ha_table_flags() & HA_FILE_BASED)) @@ -1438,6 +1453,8 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, dummy_share.table_name.length= strlen(alias); dummy_table.alias= alias; + file->table_share= &dummy_share; + file->table= &dummy_table; file->print_error(error, 0); strmake(new_error, thd->net.last_error, sizeof(buff)-1); @@ -1458,7 +1475,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, ****************************************************************************/ handler *handler::clone(MEM_ROOT *mem_root) { - handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type); + handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type()); if (new_handler && !new_handler->ha_open(table, table->s->normalized_path.str, table->db_stat, @@ -1474,6 +1491,26 @@ void handler::ha_statistic_increment(ulong SSV::*offset) const statistic_increment(table->in_use->status_var.*offset, &LOCK_status); } +enum enum_tx_isolation handler::ha_tx_isolation(void) const +{ + return (enum_tx_isolation) ha_thd()->variables.tx_isolation; +} + +uint handler::ha_sql_command(void) const +{ + return (uint) ha_thd()->lex->sql_command; +} + +void **handler::ha_data(void) const +{ + return (void **) ha_thd()->ha_data + ht->slot; +} + +THD *handler::ha_thd(void) const +{ + return (table && table->in_use) ? table->in_use : current_thd; +} + bool handler::check_if_log_table_locking_is_allowed(uint sql_command, ulong type, TABLE *table) @@ -1567,8 +1604,7 @@ int handler::read_first_row(byte * buf, uint primary_key) register int error; DBUG_ENTER("handler::read_first_row"); - statistic_increment(table->in_use->status_var.ha_read_first_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_first_count); /* If there is very few deleted rows in the table, find the first row by @@ -2785,11 +2821,11 @@ struct st_discover_args uint* frmlen; }; -static my_bool discover_handlerton(THD *thd, st_plugin_int *plugin, +static my_bool discover_handlerton(THD *thd, plugin_ref plugin, void *arg) { st_discover_args *vargs= (st_discover_args *)arg; - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if (hton->state == SHOW_OPTION_YES && hton->discover && (!(hton->discover(hton, thd, vargs->db, vargs->name, vargs->frmblob, @@ -2834,11 +2870,11 @@ struct st_find_files_args List<char> *files; }; -static my_bool find_files_handlerton(THD *thd, st_plugin_int *plugin, +static my_bool find_files_handlerton(THD *thd, plugin_ref plugin, void *arg) { st_find_files_args *vargs= (st_find_files_args *)arg; - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if (hton->state == SHOW_OPTION_YES && hton->find_files) @@ -2881,11 +2917,11 @@ struct st_table_exists_in_engine_args const char *name; }; -static my_bool table_exists_in_engine_handlerton(THD *thd, st_plugin_int *plugin, +static my_bool table_exists_in_engine_handlerton(THD *thd, plugin_ref plugin, void *arg) { st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg; - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine) if ((hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name)) == 1) @@ -2929,10 +2965,10 @@ struct binlog_func_st /** @brief Listing handlertons first to avoid recursive calls and deadlock */ -static my_bool binlog_func_list(THD *thd, st_plugin_int *plugin, void *arg) +static my_bool binlog_func_list(THD *thd, plugin_ref plugin, void *arg) { hton_list_st *hton_list= (hton_list_st *)arg; - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if (hton->state == SHOW_OPTION_YES && hton->binlog_func) { uint sz= hton_list->sz; @@ -3019,10 +3055,10 @@ static my_bool binlog_log_query_handlerton2(THD *thd, } static my_bool binlog_log_query_handlerton(THD *thd, - st_plugin_int *plugin, + plugin_ref plugin, void *args) { - return binlog_log_query_handlerton2(thd, (handlerton *)plugin->data, args); + return binlog_log_query_handlerton2(thd, plugin_data(plugin, handlerton *), args); } void ha_binlog_log_query(THD *thd, handlerton *hton, @@ -3310,11 +3346,11 @@ int handler::index_read_idx(byte * buf, uint index, const byte * key, RETURN VALUE pointer pointer to TYPELIB structure */ -static my_bool exts_handlerton(THD *unused, st_plugin_int *plugin, +static my_bool exts_handlerton(THD *unused, plugin_ref plugin, void *arg) { List<char> *found_exts= (List<char> *) arg; - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); handler *file; if (hton->state == SHOW_OPTION_YES && hton->create && (file= hton->create(hton, (TABLE_SHARE*) 0, current_thd->mem_root))) @@ -3385,11 +3421,11 @@ static bool stat_print(THD *thd, const char *type, uint type_len, } -static my_bool showstat_handlerton(THD *thd, st_plugin_int *plugin, +static my_bool showstat_handlerton(THD *thd, plugin_ref plugin, void *arg) { enum ha_stat_type stat= *(enum ha_stat_type *) arg; - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if (hton->state == SHOW_OPTION_YES && hton->show_status && hton->show_status(hton, thd, stat_print, stat)) return TRUE; diff --git a/sql/handler.h b/sql/handler.h index 82970cc1ac6..fbdd48fcc6d 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -876,6 +876,8 @@ public: class handler :public Sql_alloc { friend class ha_partition; + friend int ha_delete_table(THD*,handlerton*,const char*,const char*, + const char*,bool); protected: struct st_table_share *table_share; /* The table definition */ @@ -894,7 +896,12 @@ class handler :public Sql_alloc virtual int rnd_init(bool scan) =0; virtual int rnd_end() { return 0; } virtual ulonglong table_flags(void) const =0; + void ha_statistic_increment(ulong SSV::*offset) const; + enum enum_tx_isolation ha_tx_isolation(void) const; + uint ha_sql_command(void) const; + void **ha_data(void) const; + THD *ha_thd(void) const; ha_rows estimation_rows_to_insert; virtual void start_bulk_insert(ha_rows rows) {} @@ -1626,9 +1633,9 @@ extern ulong total_ha, total_ha_2pc; /* lookups */ handlerton *ha_default_handlerton(THD *thd); -handlerton *ha_resolve_by_name(THD *thd, const LEX_STRING *name); +plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name); +plugin_ref ha_lock_engine(THD *thd, handlerton *hton); handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type); -const char *ha_get_storage_engine(enum legacy_db_type db_type); handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc, handlerton *db_type); handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type, diff --git a/sql/item_func.cc b/sql/item_func.cc index aa344a343de..8272d15e5ae 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4887,7 +4887,7 @@ Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name, component_name= &component; // Empty string } - if (!(var= find_sys_var(base_name->str, base_name->length))) + if (!(var= find_sys_var(thd, base_name->str, base_name->length))) return 0; if (component.str) { diff --git a/sql/item_sum.cc b/sql/item_sum.cc index f34fc008186..27c48604907 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -2469,7 +2469,7 @@ bool Item_sum_count_distinct::setup(THD *thd) table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows table->no_rows=1; - if (table->s->db_type == heap_hton) + if (table->s->db_type() == heap_hton) { /* No blobs, otherwise it would have been MyISAM: set up a compare diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index bf6bd374ef8..4968fde7f64 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -546,11 +546,6 @@ inline THD *_current_thd(void) } #define current_thd _current_thd() -/* below functions are required for plugins as THD class is opaque */ -my_bool thd_in_lock_tables(const THD *thd); -my_bool thd_tablespace_op(const THD *thd); -const char *thd_proc_info(THD *thd, const char *info); -void **thd_ha_data(const THD *thd, const struct handlerton *hton); /* External variables @@ -1098,6 +1093,7 @@ int add_status_vars(SHOW_VAR *list); void remove_status_vars(SHOW_VAR *list); void init_status_vars(); void free_status_vars(); +void reset_status_vars(); /* information schema */ extern LEX_STRING information_schema_name; @@ -1659,6 +1655,7 @@ extern pthread_mutex_t LOCK_server_started; extern pthread_cond_t COND_server_started; extern int mysqld_server_started; extern rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; +extern rw_lock_t LOCK_system_variables_hash; extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager; extern pthread_cond_t COND_global_read_lock; extern pthread_attr_t connection_attrib; @@ -1667,7 +1664,7 @@ extern I_List<NAMED_LIST> key_caches; extern MY_BITMAP temp_pool; extern String my_empty_string; extern const String my_null_string; -extern SHOW_VAR init_vars[], status_vars[], internal_vars[]; +extern SHOW_VAR status_vars[]; extern struct system_variables global_system_variables; extern struct system_variables max_system_variables; extern struct system_status_var global_status_var; @@ -1690,11 +1687,6 @@ extern TYPELIB log_output_typelib; /* optional things, have_* variables */ -extern SHOW_COMP_OPTION have_innodb; -extern SHOW_COMP_OPTION have_csv_db; -extern SHOW_COMP_OPTION have_ndbcluster; -extern SHOW_COMP_OPTION have_partition_db; - extern handlerton *partition_hton; extern handlerton *myisam_hton; extern handlerton *heap_hton; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a6525c1c78c..c1ba05e24bd 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -29,22 +29,13 @@ #include "rpl_injector.h" -#ifdef WITH_INNOBASE_STORAGE_ENGINE -#define OPT_INNODB_DEFAULT 1 -#else -#define OPT_INNODB_DEFAULT 0 -#endif -#define OPT_BDB_DEFAULT 0 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE -#define OPT_NDBCLUSTER_DEFAULT 0 #if defined(NOT_ENOUGH_TESTED) \ && defined(NDB_SHM_TRANSPORTER) && MYSQL_VERSION_ID >= 50000 #define OPT_NDB_SHM_DEFAULT 1 #else #define OPT_NDB_SHM_DEFAULT 0 #endif -#else -#define OPT_NDBCLUSTER_DEFAULT 0 #endif #ifndef DEFAULT_SKIP_THREAD_PRIORITY @@ -323,7 +314,6 @@ static bool lower_case_table_names_used= 0; static bool volatile select_thread_in_use, signal_thread_in_use; static bool volatile ready_to_exit; static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0; -static my_bool opt_ndbcluster; static my_bool opt_short_log_format= 0; static uint kill_cached_threads, wake_thread; static ulong killed_threads, thread_created; @@ -366,7 +356,6 @@ my_bool opt_local_infile, opt_slave_compressed_protocol; my_bool opt_safe_user_create = 0, opt_no_mix_types = 0; my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0; my_bool opt_log_slave_updates= 0; -my_bool opt_innodb; /* Legacy global handlerton. These will be removed (please do not add more). @@ -375,44 +364,6 @@ handlerton *heap_hton; handlerton *myisam_hton; handlerton *partition_hton; -#ifdef WITH_INNOBASE_STORAGE_ENGINE -extern ulong innobase_fast_shutdown; -extern ulong innobase_large_page_size; -extern char *innobase_home, *innobase_tmpdir, *innobase_logdir; -extern long innobase_lock_scan_time; -extern long innobase_mirrored_log_groups, innobase_log_files_in_group; -extern longlong innobase_log_file_size; -extern long innobase_log_buffer_size; -extern longlong innobase_buffer_pool_size; -extern long innobase_additional_mem_pool_size; -extern long innobase_file_io_threads, innobase_lock_wait_timeout; -extern long innobase_force_recovery; -extern long innobase_open_files; -extern char *innobase_data_home_dir, *innobase_data_file_path; -extern char *innobase_log_group_home_dir, *innobase_log_arch_dir; -extern char *innobase_unix_file_flush_method; -/* The following variables have to be my_bool for SHOW VARIABLES to work */ -extern my_bool innobase_log_archive, - innobase_use_doublewrite, - innobase_use_checksums, - innobase_use_large_pages, - innobase_use_native_aio, - innobase_file_per_table, innobase_locks_unsafe_for_binlog, - innobase_rollback_on_timeout, - innobase_create_status_file; -extern "C" { -extern ulong srv_max_buf_pool_modified_pct; -extern ulong srv_max_purge_lag; -extern ulong srv_auto_extend_increment; -extern ulong srv_n_spin_wait_rounds; -extern ulong srv_n_free_tickets_to_enter; -extern ulong srv_thread_sleep_delay; -extern ulong srv_thread_concurrency; -extern ulong srv_commit_concurrency; -extern ulong srv_flush_log_at_trx_commit; -} -#endif - #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE const char *opt_ndbcluster_connectstring= 0; const char *opt_ndb_connectstring= 0; @@ -594,6 +545,7 @@ pthread_mutex_t LOCK_prepared_stmt_count; pthread_mutex_t LOCK_des_key_file; #endif rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; +rw_lock_t LOCK_system_variables_hash; pthread_cond_t COND_refresh, COND_thread_count, COND_global_read_lock; pthread_t signal_thread; pthread_attr_t connection_attrib; @@ -625,6 +577,7 @@ static ulong opt_specialflag, opt_myisam_block_size; static char *opt_update_logname, *opt_binlog_index_name; static char *opt_tc_heuristic_recover; static char *mysql_home_ptr, *pidfile_name_ptr; +static int defaults_argc; static char **defaults_argv; static char *opt_bin_logname; @@ -716,7 +669,9 @@ struct st_VioSSLFd *ssl_acceptor_fd; pthread_handler_t signal_hand(void *arg); static void mysql_init_variables(void); -static void get_options(int argc,char **argv); +static void get_options(int *argc,char **argv); +static my_bool get_one_option(int, const struct my_option *, char *); +static void usage(void); static void set_server_version(void); static int init_thread_environment(); static char *get_relative_path(const char *path); @@ -1161,6 +1116,8 @@ void unireg_end(void) extern "C" void unireg_abort(int exit_code) { DBUG_ENTER("unireg_abort"); + if (opt_help) + usage(); if (exit_code) sql_print_error("Aborting\n"); clean_up(exit_code || !opt_bootstrap); /* purecov: inspected */ @@ -1347,6 +1304,7 @@ static void clean_up_mutexes() (void) rwlock_destroy(&LOCK_sys_init_connect); (void) rwlock_destroy(&LOCK_sys_init_slave); (void) pthread_mutex_destroy(&LOCK_global_system_variables); + (void) rwlock_destroy(&LOCK_system_variables_hash); (void) pthread_mutex_destroy(&LOCK_global_read_lock); (void) pthread_mutex_destroy(&LOCK_uuid_generator); (void) pthread_mutex_destroy(&LOCK_prepared_stmt_count); @@ -2753,7 +2711,8 @@ static int init_common_variables(const char *conf_file_name, int argc, load_defaults(conf_file_name, groups, &argc, &argv); defaults_argv=argv; - get_options(argc,argv); + defaults_argc=argc; + get_options(&defaults_argc, defaults_argv); set_server_version(); DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname, @@ -2765,10 +2724,6 @@ static int init_common_variables(const char *conf_file_name, int argc, { my_use_large_pages= 1; my_large_page_size= opt_large_page_size; -#ifdef WITH_INNOBASE_STORAGE_ENGINE - innobase_use_large_pages= 1; - innobase_large_page_size= opt_large_page_size; -#endif } #endif /* HAVE_LARGE_PAGES */ @@ -2831,7 +2786,12 @@ static int init_common_variables(const char *conf_file_name, int argc, if (item_create_init()) return 1; item_init(); - set_var_init(); + if (set_var_init()) + return 1; +#ifdef HAVE_REPLICATION + if (init_replication_sys_vars()) + return 1; +#endif mysys_uses_curses=0; #ifdef USE_REGEX my_regex_init(&my_charset_latin1); @@ -2984,6 +2944,7 @@ static int init_thread_environment() (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST); + (void) my_rwlock_init(&LOCK_system_variables_hash, NULL); (void) pthread_mutex_init(&LOCK_global_read_lock, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_prepared_stmt_count, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST); @@ -3319,10 +3280,42 @@ server."); using_update_log=1; } - if (plugin_init(opt_bootstrap)) + if (plugin_init(&defaults_argc, defaults_argv, + (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) | + (opt_help ? PLUGIN_INIT_SKIP_INITIALIZATION : 0))) { - sql_print_error("Failed to init plugins."); - return 1; + sql_print_error("Failed to initialize plugins."); + unireg_abort(1); + } + + if (opt_help) + unireg_abort(0); + + /* we do want to exit if there are any other unknown options */ + if (defaults_argc > 1) + { + int ho_error; + struct my_option no_opts[] = + { + {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} + }; + /* + We need to eat any 'loose' arguments first before we conclude + that there are unprocessed options + */ + my_getopt_skip_unknown= 0; + + if ((ho_error= handle_options(&defaults_argc, &defaults_argv, no_opts, + get_one_option))) + unireg_abort(ho_error); + + if (defaults_argc) + { + fprintf(stderr, "%s: Too many arguments (first extra is '%s').\n" + "Use --verbose --help to get a list of available options\n", + my_progname, *defaults_argv); + unireg_abort(1); + } } /* We have to initialize the storage engines before CSV logging */ @@ -3353,7 +3346,8 @@ server."); else { /* fall back to the log files if tables are not present */ - if (have_csv_db == SHOW_OPTION_NO) + LEX_STRING csv_name={C_STRING_WITH_LEN("csv")}; + if (!plugin_is_ready(&csv_name, MYSQL_STORAGE_ENGINE_PLUGIN)) { /* purecov: begin inspected */ sql_print_error("CSV engine is not present, falling back to the " @@ -3373,11 +3367,16 @@ server."); /* Check that the default storage engine is actually available. */ + if (default_storage_engine_str) { LEX_STRING name= { default_storage_engine_str, strlen(default_storage_engine_str) }; - handlerton *hton= ha_resolve_by_name(0, &name); - if (hton == NULL) + plugin_ref plugin; + handlerton *hton; + + if ((plugin= ha_resolve_by_name(0, &name))) + hton= plugin_data(plugin, handlerton*); + else { sql_print_error("Unknown/unsupported table type: %s", default_storage_engine_str); @@ -3391,9 +3390,17 @@ server."); default_storage_engine_str); unireg_abort(1); } - hton= myisam_hton; + DBUG_ASSERT(global_system_variables.table_plugin); + } + else + { + /* + Need to unlock as global_system_variables.table_plugin + was acquired during plugin_init() + */ + plugin_unlock(0, global_system_variables.table_plugin); + global_system_variables.table_plugin= plugin; } - global_system_variables.table_type= hton; } tc_log= (total_ha_2pc > 1 ? (opt_bin_log ? @@ -4797,11 +4804,6 @@ enum options_mysqld OPT_STORAGE_ENGINE, OPT_INIT_FILE, OPT_DELAY_KEY_WRITE_ALL, OPT_SLOW_QUERY_LOG, OPT_DELAY_KEY_WRITE, OPT_CHARSETS_DIR, - OPT_BDB_HOME, OPT_BDB_LOG, - OPT_BDB_TMP, OPT_BDB_SYNC, - OPT_BDB_LOCK, OPT_BDB, - OPT_BDB_NO_RECOVER, OPT_BDB_SHARED, - OPT_BDB_DATA_DIRECT, OPT_BDB_LOG_DIRECT, OPT_MASTER_HOST, OPT_MASTER_USER, OPT_MASTER_PASSWORD, OPT_MASTER_PORT, OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY, @@ -4820,28 +4822,14 @@ enum options_mysqld OPT_WANT_CORE, OPT_CONCURRENT_INSERT, OPT_MEMLOCK, OPT_MYISAM_RECOVER, OPT_REPLICATE_REWRITE_DB, OPT_SERVER_ID, - OPT_SKIP_SLAVE_START, OPT_SKIP_INNOBASE, + OPT_SKIP_SLAVE_START, OPT_SAFE_SHOW_DB, OPT_SAFEMALLOC_MEM_LIMIT, OPT_REPLICATE_DO_TABLE, OPT_REPLICATE_IGNORE_TABLE, OPT_REPLICATE_WILD_DO_TABLE, OPT_REPLICATE_WILD_IGNORE_TABLE, OPT_REPLICATE_SAME_SERVER_ID, OPT_DISCONNECT_SLAVE_EVENT_COUNT, OPT_TC_HEURISTIC_RECOVER, OPT_ABORT_SLAVE_EVENT_COUNT, - OPT_INNODB_DATA_HOME_DIR, - OPT_INNODB_DATA_FILE_PATH, - OPT_INNODB_LOG_GROUP_HOME_DIR, - OPT_INNODB_LOG_ARCH_DIR, - OPT_INNODB_LOG_ARCHIVE, - OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT, - OPT_INNODB_FLUSH_METHOD, - OPT_INNODB_DOUBLEWRITE, - OPT_INNODB_CHECKSUMS, - OPT_INNODB_FAST_SHUTDOWN, - OPT_INNODB_FILE_PER_TABLE, OPT_CRASH_BINLOG_INNODB, - OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG, OPT_LOG_BIN_TRUST_FUNCTION_CREATORS, - OPT_SAFE_SHOW_DB, OPT_INNODB_SAFE_BINLOG, - OPT_INNODB, OPT_ISAM, - OPT_ENGINE_CONDITION_PUSHDOWN, OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING, + OPT_ENGINE_CONDITION_PUSHDOWN, OPT_NDB_CONNECTSTRING, OPT_NDB_USE_EXACT_COUNT, OPT_NDB_USE_TRANSACTIONS, OPT_NDB_FORCE_SEND, OPT_NDB_AUTOINCREMENT_PREFETCH_SZ, OPT_NDB_SHM, OPT_NDB_OPTIMIZED_NODE_SELECTION, OPT_NDB_CACHE_CHECK_TIME, @@ -4904,33 +4892,6 @@ enum options_mysqld OPT_THREAD_CONCURRENCY, OPT_THREAD_CACHE_SIZE, OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK, OPT_WAIT_TIMEOUT, OPT_MYISAM_REPAIR_THREADS, - OPT_INNODB_MIRRORED_LOG_GROUPS, - OPT_INNODB_LOG_FILES_IN_GROUP, - OPT_INNODB_LOG_FILE_SIZE, - OPT_INNODB_LOG_BUFFER_SIZE, - OPT_INNODB_BUFFER_POOL_SIZE, - OPT_INNODB_BUFFER_POOL_AWE_MEM_MB, - OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE, - OPT_INNODB_MAX_PURGE_LAG, - OPT_INNODB_FILE_IO_THREADS, - OPT_INNODB_LOCK_WAIT_TIMEOUT, - OPT_INNODB_THREAD_CONCURRENCY, - OPT_INNODB_COMMIT_CONCURRENCY, - OPT_INNODB_FORCE_RECOVERY, - OPT_INNODB_STATUS_FILE, - OPT_INNODB_MAX_DIRTY_PAGES_PCT, - OPT_INNODB_TABLE_LOCKS, - OPT_INNODB_SUPPORT_XA, - OPT_INNODB_OPEN_FILES, - OPT_INNODB_AUTOEXTEND_INCREMENT, - OPT_INNODB_SYNC_SPIN_LOOPS, - OPT_INNODB_CONCURRENCY_TICKETS, - OPT_INNODB_THREAD_SLEEP_DELAY, - OPT_BDB_CACHE_SIZE, - OPT_BDB_CACHE_PARTS, - OPT_BDB_LOG_BUFFER_SIZE, - OPT_BDB_MAX_LOCK, - OPT_BDB_REGION_SIZE, OPT_ERROR_LOG_FILE, OPT_DEFAULT_WEEK_FORMAT, OPT_RANGE_ALLOC_BLOCK_SIZE, OPT_ALLOW_SUSPICIOUS_UDFS, @@ -4940,7 +4901,6 @@ enum options_mysqld OPT_SYNC_REPLICATION, OPT_SYNC_REPLICATION_SLAVE_ID, OPT_SYNC_REPLICATION_TIMEOUT, - OPT_BDB_NOSYNC, OPT_ENABLE_SHARED_MEMORY, OPT_SHARED_MEMORY_BASE_NAME, OPT_OLD_PASSWORDS, @@ -4970,12 +4930,12 @@ enum options_mysqld OPT_OLD_STYLE_USER_LIMITS, OPT_LOG_SLOW_ADMIN_STATEMENTS, OPT_TABLE_LOCK_WAIT_TIMEOUT, + OPT_PLUGIN_LOAD, OPT_PLUGIN_DIR, OPT_LOG_OUTPUT, OPT_PORT_OPEN_TIMEOUT, OPT_GENERAL_LOG, OPT_SLOW_LOG, - OPT_MERGE, OPT_THREAD_HANDLING, OPT_INNODB_ROLLBACK_ON_TIMEOUT }; @@ -5193,94 +5153,6 @@ Disable with --skip-large-pages.", {"init-slave", OPT_INIT_SLAVE, "Command(s) that are executed when a slave connects to this master", (gptr*) &opt_init_slave, (gptr*) &opt_init_slave, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"innodb", OPT_INNODB, "Enable InnoDB (if this version of MySQL supports it). \ -Disable with --skip-innodb (will save memory).", - (gptr*) &opt_innodb, (gptr*) &opt_innodb, 0, GET_BOOL, NO_ARG, OPT_INNODB_DEFAULT, 0, 0, - 0, 0, 0}, -#ifdef WITH_INNOBASE_STORAGE_ENGINE - {"innodb_checksums", OPT_INNODB_CHECKSUMS, "Enable InnoDB checksums validation (enabled by default). \ -Disable with --skip-innodb-checksums.", (gptr*) &innobase_use_checksums, - (gptr*) &innobase_use_checksums, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, -#endif - {"innodb_data_file_path", OPT_INNODB_DATA_FILE_PATH, - "Path to individual files and their sizes.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef WITH_INNOBASE_STORAGE_ENGINE - {"innodb_data_home_dir", OPT_INNODB_DATA_HOME_DIR, - "The common part for InnoDB table spaces.", (gptr*) &innobase_data_home_dir, - (gptr*) &innobase_data_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, - 0}, - {"innodb_doublewrite", OPT_INNODB_DOUBLEWRITE, "Enable InnoDB doublewrite buffer (enabled by default). \ -Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite, - (gptr*) &innobase_use_doublewrite, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, - {"innodb_fast_shutdown", OPT_INNODB_FAST_SHUTDOWN, - "Speeds up the shutdown process of the InnoDB storage engine. Possible " - "values are 0, 1 (faster)" - /* - NetWare can't close unclosed files, can't automatically kill remaining - threads, etc, so on this OS we disable the crash-like InnoDB shutdown. - */ -#ifndef __NETWARE__ - " or 2 (fastest - crash-like)" -#endif - ".", - (gptr*) &innobase_fast_shutdown, - (gptr*) &innobase_fast_shutdown, 0, GET_ULONG, OPT_ARG, 1, 0, - IF_NETWARE(1,2), 0, 0, 0}, - {"innodb_file_per_table", OPT_INNODB_FILE_PER_TABLE, - "Stores each InnoDB table to an .ibd file in the database dir.", - (gptr*) &innobase_file_per_table, - (gptr*) &innobase_file_per_table, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"innodb_flush_log_at_trx_commit", OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT, - "Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second).", - (gptr*) &srv_flush_log_at_trx_commit, - (gptr*) &srv_flush_log_at_trx_commit, - 0, GET_ULONG, OPT_ARG, 1, 0, 2, 0, 0, 0}, - {"innodb_flush_method", OPT_INNODB_FLUSH_METHOD, - "With which method to flush data.", (gptr*) &innobase_unix_file_flush_method, - (gptr*) &innobase_unix_file_flush_method, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, - 0, 0, 0}, - {"innodb_locks_unsafe_for_binlog", OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG, - "Force InnoDB to not use next-key locking, to use only row-level locking.", - (gptr*) &innobase_locks_unsafe_for_binlog, - (gptr*) &innobase_locks_unsafe_for_binlog, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"innodb_log_arch_dir", OPT_INNODB_LOG_ARCH_DIR, - "Where full logs should be archived.", (gptr*) &innobase_log_arch_dir, - (gptr*) &innobase_log_arch_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"innodb_log_archive", OPT_INNODB_LOG_ARCHIVE, - "Set to 1 if you want to have logs archived.", 0, 0, 0, GET_LONG, OPT_ARG, - 0, 0, 0, 0, 0, 0}, - {"innodb_log_group_home_dir", OPT_INNODB_LOG_GROUP_HOME_DIR, - "Path to InnoDB log files.", (gptr*) &innobase_log_group_home_dir, - (gptr*) &innobase_log_group_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, - 0, 0}, - {"innodb_max_dirty_pages_pct", OPT_INNODB_MAX_DIRTY_PAGES_PCT, - "Percentage of dirty pages allowed in bufferpool.", (gptr*) &srv_max_buf_pool_modified_pct, - (gptr*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 100, 0, 0, 0}, - {"innodb_max_purge_lag", OPT_INNODB_MAX_PURGE_LAG, - "Desired maximum length of the purge queue (0 = no limit)", - (gptr*) &srv_max_purge_lag, - (gptr*) &srv_max_purge_lag, 0, GET_LONG, REQUIRED_ARG, 0, 0, ~0L, - 0, 1L, 0}, - {"innodb_rollback_on_timeout", OPT_INNODB_ROLLBACK_ON_TIMEOUT, - "Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)", - (gptr*) &innobase_rollback_on_timeout, (gptr*) &innobase_rollback_on_timeout, - 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"innodb_status_file", OPT_INNODB_STATUS_FILE, - "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file", - (gptr*) &innobase_create_status_file, (gptr*) &innobase_create_status_file, - 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"innodb_support_xa", OPT_INNODB_SUPPORT_XA, - "Enable InnoDB support for the XA two-phase commit", - (gptr*) &global_system_variables.innodb_support_xa, - (gptr*) &global_system_variables.innodb_support_xa, - 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, - {"innodb_table_locks", OPT_INNODB_TABLE_LOCKS, - "Enable InnoDB locking in LOCK TABLES", - (gptr*) &global_system_variables.innodb_table_locks, - (gptr*) &global_system_variables.innodb_table_locks, - 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, -#endif /* End WITH_INNOBASE_STORAGE_ENGINE */ {"language", 'L', "Client error messages in given language. May be given as a full path.", (gptr*) &language_ptr, (gptr*) &language_ptr, 0, GET_STR, REQUIRED_ARG, @@ -5454,10 +5326,6 @@ master-ssl", "Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP, FORCE or QUICK.", (gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"ndbcluster", OPT_NDBCLUSTER, "Enable NDB Cluster (if this version of MySQL supports it). \ -Disable with --skip-ndbcluster (will save memory).", - (gptr*) &opt_ndbcluster, (gptr*) &opt_ndbcluster, 0, GET_BOOL, NO_ARG, - OPT_NDBCLUSTER_DEFAULT, 0, 0, 0, 0, 0}, #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE {"ndb-connectstring", OPT_NDB_CONNECTSTRING, "Connect string for ndbcluster.", @@ -5913,84 +5781,6 @@ log and this option does nothing anymore.", (gptr*) &global_system_variables.group_concat_max_len, (gptr*) &max_system_variables.group_concat_max_len, 0, GET_ULONG, REQUIRED_ARG, 1024, 4, (long) ~0, 0, 1, 0}, -#ifdef WITH_INNOBASE_STORAGE_ENGINE - {"innodb_additional_mem_pool_size", OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE, - "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.", - (gptr*) &innobase_additional_mem_pool_size, - (gptr*) &innobase_additional_mem_pool_size, 0, GET_LONG, REQUIRED_ARG, - 1*1024*1024L, 512*1024L, ~0L, 0, 1024, 0}, - {"innodb_autoextend_increment", OPT_INNODB_AUTOEXTEND_INCREMENT, - "Data file autoextend increment in megabytes", - (gptr*) &srv_auto_extend_increment, - (gptr*) &srv_auto_extend_increment, - 0, GET_LONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0}, - {"innodb_buffer_pool_size", OPT_INNODB_BUFFER_POOL_SIZE, - "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", - (gptr*) &innobase_buffer_pool_size, (gptr*) &innobase_buffer_pool_size, 0, - GET_LL, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 0, - 1024*1024L, 0}, - {"innodb_commit_concurrency", OPT_INNODB_COMMIT_CONCURRENCY, - "Helps in performance tuning in heavily concurrent environments.", - (gptr*) &srv_commit_concurrency, (gptr*) &srv_commit_concurrency, - 0, GET_LONG, REQUIRED_ARG, 0, 0, 1000, 0, 1, 0}, - {"innodb_concurrency_tickets", OPT_INNODB_CONCURRENCY_TICKETS, - "Number of times a thread is allowed to enter InnoDB within the same \ - SQL query after it has once got the ticket", - (gptr*) &srv_n_free_tickets_to_enter, - (gptr*) &srv_n_free_tickets_to_enter, - 0, GET_LONG, REQUIRED_ARG, 500L, 1L, ~0L, 0, 1L, 0}, - {"innodb_file_io_threads", OPT_INNODB_FILE_IO_THREADS, - "Number of file I/O threads in InnoDB.", (gptr*) &innobase_file_io_threads, - (gptr*) &innobase_file_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 4, 64, 0, - 1, 0}, - {"innodb_force_recovery", OPT_INNODB_FORCE_RECOVERY, - "Helps to save your data in case the disk image of the database becomes corrupt.", - (gptr*) &innobase_force_recovery, (gptr*) &innobase_force_recovery, 0, - GET_LONG, REQUIRED_ARG, 0, 0, 6, 0, 1, 0}, - {"innodb_lock_wait_timeout", OPT_INNODB_LOCK_WAIT_TIMEOUT, - "Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back.", - (gptr*) &innobase_lock_wait_timeout, (gptr*) &innobase_lock_wait_timeout, - 0, GET_LONG, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0}, - {"innodb_log_buffer_size", OPT_INNODB_LOG_BUFFER_SIZE, - "The size of the buffer which InnoDB uses to write log to the log files on disk.", - (gptr*) &innobase_log_buffer_size, (gptr*) &innobase_log_buffer_size, 0, - GET_LONG, REQUIRED_ARG, 1024*1024L, 256*1024L, ~0L, 0, 1024, 0}, - {"innodb_log_file_size", OPT_INNODB_LOG_FILE_SIZE, - "Size of each log file in a log group.", - (gptr*) &innobase_log_file_size, (gptr*) &innobase_log_file_size, 0, - GET_LL, REQUIRED_ARG, 5*1024*1024L, 1*1024*1024L, LONGLONG_MAX, 0, - 1024*1024L, 0}, - {"innodb_log_files_in_group", OPT_INNODB_LOG_FILES_IN_GROUP, - "Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.", - (gptr*) &innobase_log_files_in_group, (gptr*) &innobase_log_files_in_group, - 0, GET_LONG, REQUIRED_ARG, 2, 2, 100, 0, 1, 0}, - {"innodb_mirrored_log_groups", OPT_INNODB_MIRRORED_LOG_GROUPS, - "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.", - (gptr*) &innobase_mirrored_log_groups, - (gptr*) &innobase_mirrored_log_groups, 0, GET_LONG, REQUIRED_ARG, 1, 1, 10, - 0, 1, 0}, - {"innodb_open_files", OPT_INNODB_OPEN_FILES, - "How many files at the maximum InnoDB keeps open at the same time.", - (gptr*) &innobase_open_files, (gptr*) &innobase_open_files, 0, - GET_LONG, REQUIRED_ARG, 300L, 10L, ~0L, 0, 1L, 0}, - {"innodb_sync_spin_loops", OPT_INNODB_SYNC_SPIN_LOOPS, - "Count of spin-loop rounds in InnoDB mutexes", - (gptr*) &srv_n_spin_wait_rounds, - (gptr*) &srv_n_spin_wait_rounds, - 0, GET_LONG, REQUIRED_ARG, 20L, 0L, ~0L, 0, 1L, 0}, - {"innodb_thread_concurrency", OPT_INNODB_THREAD_CONCURRENCY, - "Helps in performance tuning in heavily concurrent environments. " - "Sets the maximum number of threads allowed inside InnoDB. Value 0" - " will disable the thread throttling.", - (gptr*) &srv_thread_concurrency, (gptr*) &srv_thread_concurrency, - 0, GET_LONG, REQUIRED_ARG, 8, 0, 1000, 0, 1, 0}, - {"innodb_thread_sleep_delay", OPT_INNODB_THREAD_SLEEP_DELAY, - "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0" - " disable a sleep", - (gptr*) &srv_thread_sleep_delay, - (gptr*) &srv_thread_sleep_delay, - 0, GET_LONG, REQUIRED_ARG, 10000L, 0L, ~0L, 0, 1L, 0}, -#endif /* WITH_INNOBASE_STORAGE_ENGINE */ {"interactive_timeout", OPT_INTERACTIVE_TIMEOUT, "The number of seconds the server waits for activity on an interactive connection before closing it.", (gptr*) &global_system_variables.net_interactive_timeout, @@ -6216,6 +6006,11 @@ The minimum value for this variable is 4096.", "Directory for plugins.", (gptr*) &opt_plugin_dir_ptr, (gptr*) &opt_plugin_dir_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"plugin_load", OPT_PLUGIN_LOAD, + "Optional colon separated list of plugins to load, where each plugin is " + "identified by name and path to library seperated by an equals.", + (gptr*) &opt_plugin_load, (gptr*) &opt_plugin_load, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE, "The size of the buffer that is allocated when preloading indexes", (gptr*) &global_system_variables.preload_buff_size, @@ -7015,8 +6810,8 @@ Starts the MySQL database server\n"); fix_paths(); set_ports(); - my_print_help(my_long_options); - my_print_variables(my_long_options); + /* Print out all the options including plugin supplied options */ + my_print_help_inc_plugins(my_long_options, sizeof(my_long_options)/sizeof(my_option)); puts("\n\ To see what values a running MySQL server is using, type\n\ @@ -7058,6 +6853,7 @@ static void mysql_init_variables(void) mqh_used= 0; segfaulted= kill_in_progress= 0; cleanup_done= 0; + defaults_argc= 0; defaults_argv= 0; server_id_supplied= 0; test_flags= select_errors= dropping_tables= ha_open_options=0; @@ -7145,7 +6941,7 @@ static void mysql_init_variables(void) /* Set default values for some option variables */ default_storage_engine_str= (char*) "MyISAM"; - global_system_variables.table_type= myisam_hton; + global_system_variables.table_plugin= NULL; global_system_variables.tx_isolation= ISO_REPEATABLE_READ; global_system_variables.select_limit= (ulonglong) HA_POS_ERROR; max_system_variables.select_limit= (ulonglong) HA_POS_ERROR; @@ -7166,36 +6962,13 @@ static void mysql_init_variables(void) "d:t:i:o,/tmp/mysqld.trace"); #endif opt_error_log= IF_WIN(1,0); -#ifdef WITH_INNOBASE_STORAGE_ENGINE - have_innodb= SHOW_OPTION_YES; -#else - have_innodb= SHOW_OPTION_NO; -#endif -#ifdef WITH_CSV_STORAGE_ENGINE - have_csv_db= SHOW_OPTION_YES; -#else - have_csv_db= SHOW_OPTION_NO; -#endif #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE - have_ndbcluster= SHOW_OPTION_DISABLED; -#else - have_ndbcluster= SHOW_OPTION_NO; -#endif -#ifdef WITH_PARTITION_STORAGE_ENGINE - have_partition_db= SHOW_OPTION_YES; -#else - have_partition_db= SHOW_OPTION_NO; -#endif -#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE - have_ndbcluster=SHOW_OPTION_DISABLED; global_system_variables.ndb_index_stat_enable=FALSE; max_system_variables.ndb_index_stat_enable=TRUE; global_system_variables.ndb_index_stat_cache_entries=32; max_system_variables.ndb_index_stat_cache_entries=~0L; global_system_variables.ndb_index_stat_update_freq=20; max_system_variables.ndb_index_stat_update_freq=~0L; -#else - have_ndbcluster=SHOW_OPTION_NO; #endif #ifdef HAVE_OPENSSL have_openssl=SHOW_OPTION_YES; @@ -7655,17 +7428,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), global_system_variables.tx_isolation= (type-1); break; } - case OPT_MERGE: - case OPT_BDB: - break; - case OPT_NDBCLUSTER: -#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE - if (opt_ndbcluster) - have_ndbcluster= SHOW_OPTION_YES; - else - have_ndbcluster= SHOW_OPTION_DISABLED; -#endif - break; #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE case OPT_NDB_MGMD: case OPT_NDB_NODEID: @@ -7713,24 +7475,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ndb_extra_logging= atoi(argument); break; #endif - case OPT_INNODB: -#ifdef WITH_INNOBASE_STORAGE_ENGINE - if (opt_innodb) - have_innodb= SHOW_OPTION_YES; - else - have_innodb= SHOW_OPTION_DISABLED; -#endif - break; - case OPT_INNODB_DATA_FILE_PATH: -#ifdef WITH_INNOBASE_STORAGE_ENGINE - innobase_data_file_path= argument; -#endif - break; -#ifdef WITH_INNOBASE_STORAGE_ENGINE - case OPT_INNODB_LOG_ARCHIVE: - innobase_log_archive= argument ? test(atoi(argument)) : 1; - break; -#endif /* WITH_INNOBASE_STORAGE_ENGINE */ case OPT_MYISAM_RECOVER: { if (!argument || !argument[0]) @@ -7884,7 +7628,7 @@ static void option_error_reporter(enum loglevel level, const char *format, ...) } -static void get_options(int argc,char **argv) +static void get_options(int *argc,char **argv) { int ho_error; @@ -7892,34 +7636,20 @@ static void get_options(int argc,char **argv) strmake(def_ft_boolean_syntax, ft_boolean_syntax, sizeof(ft_boolean_syntax)-1); my_getopt_error_reporter= option_error_reporter; - if ((ho_error= handle_options(&argc, &argv, my_long_options, + + /* Skip unknown options so that they may be processed later by plugins */ + my_getopt_skip_unknown= TRUE; + + if ((ho_error= handle_options(argc, &argv, my_long_options, get_one_option))) exit(ho_error); + (*argc)++; /* add back one for the progname handle_options removes */ + /* no need to do this for argv as we are discarding it. */ -#ifndef WITH_NDBCLUSTER_STORAGE_ENGINE - if (opt_ndbcluster) - sql_print_warning("this binary does not contain NDBCLUSTER storage engine"); -#endif -#ifndef WITH_INNOBASE_STORAGE_ENGINE - if (opt_innodb) - sql_print_warning("this binary does not contain INNODB storage engine"); -#endif if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes) && !opt_slow_log) sql_print_warning("options --log-slow-admin-statements and --log-queries-not-using-indexes have no effect if --log-slow-queries is not set"); - if (argc > 0) - { - fprintf(stderr, "%s: Too many arguments (first extra is '%s').\nUse --help to get a list of available options\n", my_progname, *argv); - /* FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code? */ - exit(1); - } - - if (opt_help) - { - usage(); - exit(0); - } #if defined(HAVE_BROKEN_REALPATH) my_use_symdir=0; my_disable_symlinks=1; @@ -8238,12 +7968,7 @@ void refresh_status(THD *thd) bzero((char*) &thd->status_var, sizeof(thd->status_var)); /* Reset some global variables */ - for (SHOW_VAR *ptr= status_vars; ptr->name; ptr++) - { - /* Note that SHOW_LONG_NOFLUSH variables are not reset */ - if (ptr->type == SHOW_LONG) - *(ulong*) ptr->value= 0; - } + reset_status_vars(); /* Reset the counters of all key caches (default and named). */ process_key_caches(reset_key_cache_counters); @@ -8262,50 +7987,9 @@ void refresh_status(THD *thd) /***************************************************************************** - Instantiate have_xyx for missing storage engines + Instantiate variables for missing storage engines + This section should go away soon *****************************************************************************/ -#undef have_innodb -#undef have_ndbcluster -#undef have_csv_db - -SHOW_COMP_OPTION have_innodb= SHOW_OPTION_NO; -SHOW_COMP_OPTION have_ndbcluster= SHOW_OPTION_NO; -SHOW_COMP_OPTION have_csv_db= SHOW_OPTION_NO; -SHOW_COMP_OPTION have_partition_db= SHOW_OPTION_NO; - -#ifndef WITH_INNOBASE_STORAGE_ENGINE -uint innobase_flush_log_at_trx_commit; -ulong innobase_fast_shutdown; -long innobase_mirrored_log_groups, innobase_log_files_in_group; -longlong innobase_log_file_size; -long innobase_log_buffer_size; -longlong innobase_buffer_pool_size; -long innobase_additional_mem_pool_size; -long innobase_file_io_threads, innobase_lock_wait_timeout; -long innobase_force_recovery; -long innobase_open_files; -char *innobase_data_home_dir, *innobase_data_file_path; -char *innobase_log_group_home_dir, *innobase_log_arch_dir; -char *innobase_unix_file_flush_method; -my_bool innobase_log_archive, - innobase_use_doublewrite, - innobase_use_checksums, - innobase_file_per_table, - innobase_locks_unsafe_for_binlog, - innobase_rollback_on_timeout; - -extern "C" { -ulong srv_max_buf_pool_modified_pct; -ulong srv_max_purge_lag; -ulong srv_auto_extend_increment; -ulong srv_n_spin_wait_rounds; -ulong srv_n_free_tickets_to_enter; -ulong srv_thread_sleep_delay; -ulong srv_thread_concurrency; -ulong srv_commit_concurrency; -} - -#endif #ifndef WITH_NDBCLUSTER_STORAGE_ENGINE ulong ndb_cache_check_time; diff --git a/sql/set_var.cc b/sql/set_var.cc index ad5559165f3..8a51a0f2e62 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -58,39 +58,6 @@ #include "events.h" -/* WITH_INNOBASE_STORAGE_ENGINE */ -extern uint innobase_flush_log_at_trx_commit; -extern ulong innobase_fast_shutdown; -extern long innobase_mirrored_log_groups, innobase_log_files_in_group; -extern longlong innobase_log_file_size; -extern long innobase_log_buffer_size; -extern longlong innobase_buffer_pool_size; -extern long innobase_additional_mem_pool_size; -extern long innobase_file_io_threads, innobase_lock_wait_timeout; -extern long innobase_force_recovery; -extern long innobase_open_files; -extern char *innobase_data_home_dir, *innobase_data_file_path; -extern char *innobase_log_group_home_dir, *innobase_log_arch_dir; -extern char *innobase_unix_file_flush_method; -/* The following variables have to be my_bool for SHOW VARIABLES to work */ -extern my_bool innobase_log_archive, - innobase_use_doublewrite, - innobase_use_checksums, - innobase_file_per_table, - innobase_locks_unsafe_for_binlog, - innobase_rollback_on_timeout; - -extern "C" { -extern ulong srv_max_buf_pool_modified_pct; -extern ulong srv_max_purge_lag; -extern ulong srv_auto_extend_increment; -extern ulong srv_n_spin_wait_rounds; -extern ulong srv_n_free_tickets_to_enter; -extern ulong srv_thread_sleep_delay; -extern ulong srv_thread_concurrency; -extern ulong srv_commit_concurrency; -extern ulong srv_flush_log_at_trx_commit; -} /* WITH_NDBCLUSTER_STORAGE_ENGINE */ extern ulong ndb_cache_check_time; @@ -100,9 +67,12 @@ extern ulong ndb_report_thresh_binlog_epoch_slip; extern ulong ndb_report_thresh_binlog_mem_usage; #endif +extern CHARSET_INFO *character_set_filesystem; +static DYNAMIC_ARRAY fixed_show_vars; static HASH system_variable_hash; + const char *bool_type_names[]= { "OFF", "ON", NullS }; TYPELIB bool_typelib= { @@ -169,849 +139,554 @@ static void sys_default_slow_log_path(THD *thd, enum_var_type type); it in the constructor (see sys_var class for details). */ -sys_var *sys_var::first= NULL; -uint sys_var::sys_vars= 0; +static sys_var_chain vars = { NULL, NULL }; -sys_var_thd_ulong sys_auto_increment_increment("auto_increment_increment", +static sys_var_thd_ulong sys_auto_increment_increment(&vars, "auto_increment_increment", &SV::auto_increment_increment); -sys_var_thd_ulong sys_auto_increment_offset("auto_increment_offset", +static sys_var_thd_ulong sys_auto_increment_offset(&vars, "auto_increment_offset", &SV::auto_increment_offset); -sys_var_bool_ptr sys_automatic_sp_privileges("automatic_sp_privileges", +static sys_var_bool_ptr sys_automatic_sp_privileges(&vars, "automatic_sp_privileges", &sp_automatic_privileges); -sys_var_const_str sys_basedir("basedir", mysql_home); -sys_var_long_ptr sys_binlog_cache_size("binlog_cache_size", +static sys_var_const_str sys_basedir(&vars, "basedir", mysql_home); +static sys_var_long_ptr sys_binlog_cache_size(&vars, "binlog_cache_size", &binlog_cache_size); -sys_var_thd_binlog_format sys_binlog_format("binlog_format", +static sys_var_thd_binlog_format sys_binlog_format(&vars, "binlog_format", &SV::binlog_format); -sys_var_thd_ulong sys_bulk_insert_buff_size("bulk_insert_buffer_size", +static sys_var_thd_ulong sys_bulk_insert_buff_size(&vars, "bulk_insert_buffer_size", &SV::bulk_insert_buff_size); -sys_var_character_set_server sys_character_set_server("character_set_server"); -sys_var_const_str sys_charset_system("character_set_system", +static sys_var_character_set_sv sys_character_set_server(&vars, "character_set_server", + &SV::collation_server, + &default_charset_info); +sys_var_const_str sys_charset_system(&vars, "character_set_system", (char *)my_charset_utf8_general_ci.name); -sys_var_character_set_database sys_character_set_database("character_set_database"); -sys_var_character_set_client sys_character_set_client("character_set_client"); -sys_var_character_set_connection sys_character_set_connection("character_set_connection"); -sys_var_character_set_results sys_character_set_results("character_set_results"); -sys_var_character_set_filesystem sys_character_set_filesystem("character_set_filesystem"); -sys_var_thd_ulong sys_completion_type("completion_type", +static sys_var_character_set_database sys_character_set_database(&vars, "character_set_database"); +static sys_var_character_set_sv sys_character_set_client(&vars, "character_set_client", + &SV::character_set_client, + &default_charset_info); +static sys_var_character_set_sv sys_character_set_connection(&vars, "character_set_connection", + &SV::collation_connection, + &default_charset_info); +static sys_var_character_set_sv sys_character_set_results(&vars, "character_set_results", + &SV::character_set_results, + &default_charset_info, true); +static sys_var_character_set_sv sys_character_set_filesystem(&vars, "character_set_filesystem", + &SV::character_set_filesystem, + &character_set_filesystem); +static sys_var_thd_ulong sys_completion_type(&vars, "completion_type", &SV::completion_type, check_completion_type, fix_completion_type); -sys_var_collation_connection sys_collation_connection("collation_connection"); -sys_var_collation_database sys_collation_database("collation_database"); -sys_var_collation_server sys_collation_server("collation_server"); -sys_var_long_ptr sys_concurrent_insert("concurrent_insert", +static sys_var_collation_sv sys_collation_connection(&vars, "collation_connection", + &SV::collation_connection, + &default_charset_info); +static sys_var_collation_sv sys_collation_database(&vars, "collation_database", + &SV::collation_database, + &default_charset_info); +static sys_var_collation_sv sys_collation_server(&vars, "collation_server", + &SV::collation_server, + &default_charset_info); +static sys_var_long_ptr sys_concurrent_insert(&vars, "concurrent_insert", &myisam_concurrent_insert); -sys_var_long_ptr sys_connect_timeout("connect_timeout", +static sys_var_long_ptr sys_connect_timeout(&vars, "connect_timeout", &connect_timeout); -sys_var_const_str sys_datadir("datadir", mysql_real_data_home); +static sys_var_const_str sys_datadir(&vars, "datadir", mysql_real_data_home); #ifndef DBUG_OFF -sys_var_thd_dbug sys_dbug("debug"); +static sys_var_thd_dbug sys_dbug(&vars, "debug"); #endif -sys_var_enum sys_delay_key_write("delay_key_write", +static sys_var_enum sys_delay_key_write(&vars, "delay_key_write", &delay_key_write_options, &delay_key_write_typelib, fix_delay_key_write); -sys_var_long_ptr sys_delayed_insert_limit("delayed_insert_limit", +static sys_var_long_ptr sys_delayed_insert_limit(&vars, "delayed_insert_limit", &delayed_insert_limit); -sys_var_long_ptr sys_delayed_insert_timeout("delayed_insert_timeout", +static sys_var_long_ptr sys_delayed_insert_timeout(&vars, "delayed_insert_timeout", &delayed_insert_timeout); -sys_var_long_ptr sys_delayed_queue_size("delayed_queue_size", +static sys_var_long_ptr sys_delayed_queue_size(&vars, "delayed_queue_size", &delayed_queue_size); -sys_var_event_scheduler sys_event_scheduler("event_scheduler"); -sys_var_long_ptr sys_expire_logs_days("expire_logs_days", +static sys_var_event_scheduler sys_event_scheduler(&vars, "event_scheduler"); +static sys_var_long_ptr sys_expire_logs_days(&vars, "expire_logs_days", &expire_logs_days); -sys_var_bool_ptr sys_flush("flush", &myisam_flush); -sys_var_long_ptr sys_flush_time("flush_time", &flush_time); -sys_var_str sys_ft_boolean_syntax("ft_boolean_syntax", +static sys_var_bool_ptr sys_flush(&vars, "flush", &myisam_flush); +static sys_var_long_ptr sys_flush_time(&vars, "flush_time", &flush_time); +static sys_var_str sys_ft_boolean_syntax(&vars, "ft_boolean_syntax", sys_check_ftb_syntax, sys_update_ftb_syntax, sys_default_ftb_syntax, ft_boolean_syntax); -sys_var_str sys_init_connect("init_connect", 0, +sys_var_str sys_init_connect(&vars, "init_connect", 0, sys_update_init_connect, sys_default_init_connect,0); -sys_var_str sys_init_slave("init_slave", 0, +sys_var_str sys_init_slave(&vars, "init_slave", 0, sys_update_init_slave, sys_default_init_slave,0); -sys_var_thd_ulong sys_interactive_timeout("interactive_timeout", +static sys_var_thd_ulong sys_interactive_timeout(&vars, "interactive_timeout", &SV::net_interactive_timeout); -sys_var_thd_ulong sys_join_buffer_size("join_buffer_size", +static sys_var_thd_ulong sys_join_buffer_size(&vars, "join_buffer_size", &SV::join_buff_size); -sys_var_key_buffer_size sys_key_buffer_size("key_buffer_size"); -sys_var_key_cache_long sys_key_cache_block_size("key_cache_block_size", +static sys_var_key_buffer_size sys_key_buffer_size(&vars, "key_buffer_size"); +static sys_var_key_cache_long sys_key_cache_block_size(&vars, "key_cache_block_size", offsetof(KEY_CACHE, param_block_size)); -sys_var_key_cache_long sys_key_cache_division_limit("key_cache_division_limit", +static sys_var_key_cache_long sys_key_cache_division_limit(&vars, "key_cache_division_limit", offsetof(KEY_CACHE, param_division_limit)); -sys_var_key_cache_long sys_key_cache_age_threshold("key_cache_age_threshold", +static sys_var_key_cache_long sys_key_cache_age_threshold(&vars, "key_cache_age_threshold", offsetof(KEY_CACHE, param_age_threshold)); -sys_var_bool_ptr sys_local_infile("local_infile", +static sys_var_bool_ptr sys_local_infile(&vars, "local_infile", &opt_local_infile); -sys_var_trust_routine_creators -sys_trust_routine_creators("log_bin_trust_routine_creators", +static sys_var_trust_routine_creators +sys_trust_routine_creators(&vars, "log_bin_trust_routine_creators", &trust_function_creators); -sys_var_bool_ptr -sys_trust_function_creators("log_bin_trust_function_creators", +static sys_var_bool_ptr +sys_trust_function_creators(&vars, "log_bin_trust_function_creators", &trust_function_creators); -sys_var_bool_ptr - sys_log_queries_not_using_indexes("log_queries_not_using_indexes", +static sys_var_bool_ptr + sys_log_queries_not_using_indexes(&vars, "log_queries_not_using_indexes", &opt_log_queries_not_using_indexes); -sys_var_thd_ulong sys_log_warnings("log_warnings", &SV::log_warnings); -sys_var_thd_ulong sys_long_query_time("long_query_time", +static sys_var_thd_ulong sys_log_warnings(&vars, "log_warnings", &SV::log_warnings); +static sys_var_thd_ulong sys_long_query_time(&vars, "long_query_time", &SV::long_query_time); -sys_var_thd_bool sys_low_priority_updates("low_priority_updates", +static sys_var_thd_bool sys_low_priority_updates(&vars, "low_priority_updates", &SV::low_priority_updates, fix_low_priority_updates); #ifndef TO_BE_DELETED /* Alias for the low_priority_updates */ -sys_var_thd_bool sys_sql_low_priority_updates("sql_low_priority_updates", +static sys_var_thd_bool sys_sql_low_priority_updates(&vars, "sql_low_priority_updates", &SV::low_priority_updates, fix_low_priority_updates); #endif -sys_var_thd_ulong sys_max_allowed_packet("max_allowed_packet", +static sys_var_thd_ulong sys_max_allowed_packet(&vars, "max_allowed_packet", &SV::max_allowed_packet); -sys_var_long_ptr sys_max_binlog_cache_size("max_binlog_cache_size", +static sys_var_long_ptr sys_max_binlog_cache_size(&vars, "max_binlog_cache_size", &max_binlog_cache_size); -sys_var_long_ptr sys_max_binlog_size("max_binlog_size", +static sys_var_long_ptr sys_max_binlog_size(&vars, "max_binlog_size", &max_binlog_size, fix_max_binlog_size); -sys_var_long_ptr sys_max_connections("max_connections", +static sys_var_long_ptr sys_max_connections(&vars, "max_connections", &max_connections, fix_max_connections); -sys_var_long_ptr sys_max_connect_errors("max_connect_errors", +static sys_var_long_ptr sys_max_connect_errors(&vars, "max_connect_errors", &max_connect_errors); -sys_var_thd_ulong sys_max_insert_delayed_threads("max_insert_delayed_threads", +static sys_var_thd_ulong sys_max_insert_delayed_threads(&vars, "max_insert_delayed_threads", &SV::max_insert_delayed_threads, check_max_delayed_threads, fix_max_connections); -sys_var_thd_ulong sys_max_delayed_threads("max_delayed_threads", +static sys_var_thd_ulong sys_max_delayed_threads(&vars, "max_delayed_threads", &SV::max_insert_delayed_threads, check_max_delayed_threads, fix_max_connections); -sys_var_thd_ulong sys_max_error_count("max_error_count", +static sys_var_thd_ulong sys_max_error_count(&vars, "max_error_count", &SV::max_error_count); -sys_var_thd_ulonglong sys_max_heap_table_size("max_heap_table_size", +static sys_var_thd_ulonglong sys_max_heap_table_size(&vars, "max_heap_table_size", &SV::max_heap_table_size); -sys_var_thd_ulong sys_pseudo_thread_id("pseudo_thread_id", +static sys_var_thd_ulong sys_pseudo_thread_id(&vars, "pseudo_thread_id", &SV::pseudo_thread_id, check_pseudo_thread_id, 0); -sys_var_thd_ha_rows sys_max_join_size("max_join_size", +static sys_var_thd_ha_rows sys_max_join_size(&vars, "max_join_size", &SV::max_join_size, fix_max_join_size); -sys_var_thd_ulong sys_max_seeks_for_key("max_seeks_for_key", +static sys_var_thd_ulong sys_max_seeks_for_key(&vars, "max_seeks_for_key", &SV::max_seeks_for_key); -sys_var_thd_ulong sys_max_length_for_sort_data("max_length_for_sort_data", +static sys_var_thd_ulong sys_max_length_for_sort_data(&vars, "max_length_for_sort_data", &SV::max_length_for_sort_data); #ifndef TO_BE_DELETED /* Alias for max_join_size */ -sys_var_thd_ha_rows sys_sql_max_join_size("sql_max_join_size", +static sys_var_thd_ha_rows sys_sql_max_join_size(&vars, "sql_max_join_size", &SV::max_join_size, fix_max_join_size); #endif static sys_var_long_ptr_global -sys_max_prepared_stmt_count("max_prepared_stmt_count", +sys_max_prepared_stmt_count(&vars, "max_prepared_stmt_count", &max_prepared_stmt_count, &LOCK_prepared_stmt_count); -sys_var_long_ptr sys_max_relay_log_size("max_relay_log_size", +static sys_var_long_ptr sys_max_relay_log_size(&vars, "max_relay_log_size", &max_relay_log_size, fix_max_relay_log_size); -sys_var_thd_ulong sys_max_sort_length("max_sort_length", +static sys_var_thd_ulong sys_max_sort_length(&vars, "max_sort_length", &SV::max_sort_length); -sys_var_thd_ulong sys_max_sp_recursion_depth("max_sp_recursion_depth", +static sys_var_thd_ulong sys_max_sp_recursion_depth(&vars, "max_sp_recursion_depth", &SV::max_sp_recursion_depth); -sys_var_max_user_conn sys_max_user_connections("max_user_connections"); -sys_var_thd_ulong sys_max_tmp_tables("max_tmp_tables", +static sys_var_max_user_conn sys_max_user_connections(&vars, "max_user_connections"); +static sys_var_thd_ulong sys_max_tmp_tables(&vars, "max_tmp_tables", &SV::max_tmp_tables); -sys_var_long_ptr sys_max_write_lock_count("max_write_lock_count", +static sys_var_long_ptr sys_max_write_lock_count(&vars, "max_write_lock_count", &max_write_lock_count); -sys_var_thd_ulong sys_multi_range_count("multi_range_count", +static sys_var_thd_ulong sys_multi_range_count(&vars, "multi_range_count", &SV::multi_range_count); -sys_var_long_ptr sys_myisam_data_pointer_size("myisam_data_pointer_size", +static sys_var_long_ptr sys_myisam_data_pointer_size(&vars, "myisam_data_pointer_size", &myisam_data_pointer_size); -sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1); -sys_var_thd_ulong sys_myisam_repair_threads("myisam_repair_threads", &SV::myisam_repair_threads); -sys_var_thd_ulong sys_myisam_sort_buffer_size("myisam_sort_buffer_size", &SV::myisam_sort_buff_size); -sys_var_bool_ptr sys_myisam_use_mmap("myisam_use_mmap", +static sys_var_thd_ulonglong sys_myisam_max_sort_file_size(&vars, "myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1); +static sys_var_thd_ulong sys_myisam_repair_threads(&vars, "myisam_repair_threads", &SV::myisam_repair_threads); +static sys_var_thd_ulong sys_myisam_sort_buffer_size(&vars, "myisam_sort_buffer_size", &SV::myisam_sort_buff_size); +static sys_var_bool_ptr sys_myisam_use_mmap(&vars, "myisam_use_mmap", &opt_myisam_use_mmap); -sys_var_thd_enum sys_myisam_stats_method("myisam_stats_method", +static sys_var_thd_enum sys_myisam_stats_method(&vars, "myisam_stats_method", &SV::myisam_stats_method, &myisam_stats_method_typelib, NULL); -sys_var_thd_ulong sys_net_buffer_length("net_buffer_length", +static sys_var_thd_ulong sys_net_buffer_length(&vars, "net_buffer_length", &SV::net_buffer_length); -sys_var_thd_ulong sys_net_read_timeout("net_read_timeout", +static sys_var_thd_ulong sys_net_read_timeout(&vars, "net_read_timeout", &SV::net_read_timeout, 0, fix_net_read_timeout); -sys_var_thd_ulong sys_net_write_timeout("net_write_timeout", +static sys_var_thd_ulong sys_net_write_timeout(&vars, "net_write_timeout", &SV::net_write_timeout, 0, fix_net_write_timeout); -sys_var_thd_ulong sys_net_retry_count("net_retry_count", +static sys_var_thd_ulong sys_net_retry_count(&vars, "net_retry_count", &SV::net_retry_count, 0, fix_net_retry_count); -sys_var_thd_bool sys_new_mode("new", &SV::new_mode); -sys_var_thd_bool sys_old_alter_table("old_alter_table", +static sys_var_thd_bool sys_new_mode(&vars, "new", &SV::new_mode); +sys_var_thd_bool sys_old_alter_table(&vars, "old_alter_table", &SV::old_alter_table); -sys_var_thd_bool sys_old_passwords("old_passwords", &SV::old_passwords); -sys_var_thd_ulong sys_optimizer_prune_level("optimizer_prune_level", +sys_var_thd_bool sys_old_passwords(&vars, "old_passwords", &SV::old_passwords); +static sys_var_thd_ulong sys_optimizer_prune_level(&vars, "optimizer_prune_level", &SV::optimizer_prune_level); -sys_var_thd_ulong sys_optimizer_search_depth("optimizer_search_depth", +static sys_var_thd_ulong sys_optimizer_search_depth(&vars, "optimizer_search_depth", &SV::optimizer_search_depth); -sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size", +static sys_var_thd_ulong sys_preload_buff_size(&vars, "preload_buffer_size", &SV::preload_buff_size); -sys_var_thd_ulong sys_read_buff_size("read_buffer_size", +static sys_var_thd_ulong sys_read_buff_size(&vars, "read_buffer_size", &SV::read_buff_size); -sys_var_opt_readonly sys_readonly("read_only", &opt_readonly); -sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size", +static sys_var_opt_readonly sys_readonly(&vars, "read_only", &opt_readonly); +static sys_var_thd_ulong sys_read_rnd_buff_size(&vars, "read_rnd_buffer_size", &SV::read_rnd_buff_size); -sys_var_thd_ulong sys_div_precincrement("div_precision_increment", +static sys_var_thd_ulong sys_div_precincrement(&vars, "div_precision_increment", &SV::div_precincrement); -#ifdef HAVE_REPLICATION -sys_var_bool_ptr sys_relay_log_purge("relay_log_purge", - &relay_log_purge); -#endif -sys_var_long_ptr sys_rpl_recovery_rank("rpl_recovery_rank", +static sys_var_long_ptr sys_rpl_recovery_rank(&vars, "rpl_recovery_rank", &rpl_recovery_rank); -sys_var_long_ptr sys_query_cache_size("query_cache_size", +static sys_var_long_ptr sys_query_cache_size(&vars, "query_cache_size", &query_cache_size, fix_query_cache_size); -sys_var_thd_ulong sys_range_alloc_block_size("range_alloc_block_size", +static sys_var_thd_ulong sys_range_alloc_block_size(&vars, "range_alloc_block_size", &SV::range_alloc_block_size); -sys_var_thd_ulong sys_query_alloc_block_size("query_alloc_block_size", +static sys_var_thd_ulong sys_query_alloc_block_size(&vars, "query_alloc_block_size", &SV::query_alloc_block_size, 0, fix_thd_mem_root); -sys_var_thd_ulong sys_query_prealloc_size("query_prealloc_size", +static sys_var_thd_ulong sys_query_prealloc_size(&vars, "query_prealloc_size", &SV::query_prealloc_size, 0, fix_thd_mem_root); -sys_var_readonly sys_tmpdir("tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir); -sys_var_thd_ulong sys_trans_alloc_block_size("transaction_alloc_block_size", +static sys_var_readonly sys_tmpdir(&vars, "tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir); +static sys_var_thd_ulong sys_trans_alloc_block_size(&vars, "transaction_alloc_block_size", &SV::trans_alloc_block_size, 0, fix_trans_mem_root); -sys_var_thd_ulong sys_trans_prealloc_size("transaction_prealloc_size", +static sys_var_thd_ulong sys_trans_prealloc_size(&vars, "transaction_prealloc_size", &SV::trans_prealloc_size, 0, fix_trans_mem_root); -sys_var_thd_enum sys_thread_handling("thread_handling", +sys_var_thd_enum sys_thread_handling(&vars, "thread_handling", &SV::thread_handling, &thread_handling_typelib, NULL); #ifdef HAVE_QUERY_CACHE -sys_var_long_ptr sys_query_cache_limit("query_cache_limit", +static sys_var_long_ptr sys_query_cache_limit(&vars, "query_cache_limit", &query_cache.query_cache_limit); -sys_var_long_ptr sys_query_cache_min_res_unit("query_cache_min_res_unit", +static sys_var_long_ptr sys_query_cache_min_res_unit(&vars, "query_cache_min_res_unit", &query_cache_min_res_unit, fix_query_cache_min_res_unit); -sys_var_thd_enum sys_query_cache_type("query_cache_type", +static sys_var_thd_enum sys_query_cache_type(&vars, "query_cache_type", &SV::query_cache_type, &query_cache_type_typelib); -sys_var_thd_bool -sys_query_cache_wlock_invalidate("query_cache_wlock_invalidate", +static sys_var_thd_bool +sys_query_cache_wlock_invalidate(&vars, "query_cache_wlock_invalidate", &SV::query_cache_wlock_invalidate); #endif /* HAVE_QUERY_CACHE */ -sys_var_bool_ptr sys_secure_auth("secure_auth", &opt_secure_auth); -sys_var_long_ptr sys_server_id("server_id", &server_id, fix_server_id); -sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol", +static sys_var_bool_ptr sys_secure_auth(&vars, "secure_auth", &opt_secure_auth); +static sys_var_long_ptr sys_server_id(&vars, "server_id", &server_id, fix_server_id); +static sys_var_bool_ptr sys_slave_compressed_protocol(&vars, "slave_compressed_protocol", &opt_slave_compressed_protocol); -#ifdef HAVE_REPLICATION -sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout", - &slave_net_timeout); -sys_var_long_ptr sys_slave_trans_retries("slave_transaction_retries", - &slave_trans_retries); -#endif -sys_var_long_ptr sys_slow_launch_time("slow_launch_time", +static sys_var_long_ptr sys_slow_launch_time(&vars, "slow_launch_time", &slow_launch_time); -sys_var_thd_ulong sys_sort_buffer("sort_buffer_size", +static sys_var_thd_ulong sys_sort_buffer(&vars, "sort_buffer_size", &SV::sortbuff_size); -sys_var_thd_sql_mode sys_sql_mode("sql_mode", +static sys_var_thd_sql_mode sys_sql_mode(&vars, "sql_mode", &SV::sql_mode); #ifdef HAVE_OPENSSL extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher, *opt_ssl_key; -sys_var_const_str_ptr sys_ssl_ca("ssl_ca", &opt_ssl_ca); -sys_var_const_str_ptr sys_ssl_capath("ssl_capath", &opt_ssl_capath); -sys_var_const_str_ptr sys_ssl_cert("ssl_cert", &opt_ssl_cert); -sys_var_const_str_ptr sys_ssl_cipher("ssl_cipher", &opt_ssl_cipher); -sys_var_const_str_ptr sys_ssl_key("ssl_key", &opt_ssl_key); +static sys_var_const_str_ptr sys_ssl_ca(&vars, "ssl_ca", &opt_ssl_ca); +static sys_var_const_str_ptr sys_ssl_capath(&vars, "ssl_capath", &opt_ssl_capath); +static sys_var_const_str_ptr sys_ssl_cert(&vars, "ssl_cert", &opt_ssl_cert); +static sys_var_const_str_ptr sys_ssl_cipher(&vars, "ssl_cipher", &opt_ssl_cipher); +static sys_var_const_str_ptr sys_ssl_key(&vars, "ssl_key", &opt_ssl_key); #else -sys_var_const_str sys_ssl_ca("ssl_ca", NULL); -sys_var_const_str sys_ssl_capath("ssl_capath", NULL); -sys_var_const_str sys_ssl_cert("ssl_cert", NULL); -sys_var_const_str sys_ssl_cipher("ssl_cipher", NULL); -sys_var_const_str sys_ssl_key("ssl_key", NULL); +static sys_var_const_str sys_ssl_ca(&vars, "ssl_ca", NULL); +static sys_var_const_str sys_ssl_capath(&vars, "ssl_capath", NULL); +static sys_var_const_str sys_ssl_cert(&vars, "ssl_cert", NULL); +static sys_var_const_str sys_ssl_cipher(&vars, "ssl_cipher", NULL); +static sys_var_const_str sys_ssl_key(&vars, "ssl_key", NULL); #endif -sys_var_thd_enum -sys_updatable_views_with_limit("updatable_views_with_limit", +static sys_var_thd_enum +sys_updatable_views_with_limit(&vars, "updatable_views_with_limit", &SV::updatable_views_with_limit, &updatable_views_with_limit_typelib); -sys_var_thd_table_type sys_table_type("table_type", - &SV::table_type); -sys_var_thd_storage_engine sys_storage_engine("storage_engine", - &SV::table_type); -#ifdef HAVE_REPLICATION -sys_var_sync_binlog_period sys_sync_binlog_period("sync_binlog", &sync_binlog_period); -#endif -sys_var_bool_ptr sys_sync_frm("sync_frm", &opt_sync_frm); -sys_var_const_str sys_system_time_zone("system_time_zone", +static sys_var_thd_table_type sys_table_type(&vars, "table_type", + &SV::table_plugin); +static sys_var_thd_storage_engine sys_storage_engine(&vars, "storage_engine", + &SV::table_plugin); +static sys_var_bool_ptr sys_sync_frm(&vars, "sync_frm", &opt_sync_frm); +static sys_var_const_str sys_system_time_zone(&vars, "system_time_zone", system_time_zone); -sys_var_long_ptr sys_table_def_size("table_definition_cache", +static sys_var_long_ptr sys_table_def_size(&vars, "table_definition_cache", &table_def_size); -sys_var_long_ptr sys_table_cache_size("table_open_cache", +static sys_var_long_ptr sys_table_cache_size(&vars, "table_open_cache", &table_cache_size); -sys_var_long_ptr sys_table_lock_wait_timeout("table_lock_wait_timeout", +static sys_var_long_ptr sys_table_lock_wait_timeout(&vars, "table_lock_wait_timeout", &table_lock_wait_timeout); -sys_var_long_ptr sys_thread_cache_size("thread_cache_size", +static sys_var_long_ptr sys_thread_cache_size(&vars, "thread_cache_size", &thread_cache_size); #if HAVE_POOL_OF_THREADS == 1 -sys_var_long_ptr sys_thread_pool_size("thread_pool_size", +sys_var_long_ptr sys_thread_pool_size(&vars, "thread_pool_size", &thread_pool_size); #endif -sys_var_thd_enum sys_tx_isolation("tx_isolation", +static sys_var_thd_enum sys_tx_isolation(&vars, "tx_isolation", &SV::tx_isolation, &tx_isolation_typelib, fix_tx_isolation, check_tx_isolation); -sys_var_thd_ulonglong sys_tmp_table_size("tmp_table_size", +static sys_var_thd_ulonglong sys_tmp_table_size(&vars, "tmp_table_size", &SV::tmp_table_size); -sys_var_bool_ptr sys_timed_mutexes("timed_mutexes", +static sys_var_bool_ptr sys_timed_mutexes(&vars, "timed_mutexes", &timed_mutexes); -sys_var_const_str sys_version("version", server_version); -sys_var_const_str sys_version_comment("version_comment", +static sys_var_const_str sys_version(&vars, "version", server_version); +static sys_var_const_str sys_version_comment(&vars, "version_comment", MYSQL_COMPILATION_COMMENT); -sys_var_const_str sys_version_compile_machine("version_compile_machine", +static sys_var_const_str sys_version_compile_machine(&vars, "version_compile_machine", MACHINE_TYPE); -sys_var_const_str sys_version_compile_os("version_compile_os", +static sys_var_const_str sys_version_compile_os(&vars, "version_compile_os", SYSTEM_TYPE); -sys_var_thd_ulong sys_net_wait_timeout("wait_timeout", +static sys_var_thd_ulong sys_net_wait_timeout(&vars, "wait_timeout", &SV::net_wait_timeout); -#ifdef WITH_INNOBASE_STORAGE_ENGINE -sys_var_long_ptr sys_innodb_fast_shutdown("innodb_fast_shutdown", - &innobase_fast_shutdown); -sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_pct", - &srv_max_buf_pool_modified_pct); -sys_var_long_ptr sys_innodb_max_purge_lag("innodb_max_purge_lag", - &srv_max_purge_lag); -sys_var_thd_bool sys_innodb_table_locks("innodb_table_locks", - &SV::innodb_table_locks); -sys_var_thd_bool sys_innodb_support_xa("innodb_support_xa", - &SV::innodb_support_xa); -sys_var_long_ptr sys_innodb_autoextend_increment("innodb_autoextend_increment", - &srv_auto_extend_increment); -sys_var_long_ptr sys_innodb_sync_spin_loops("innodb_sync_spin_loops", - &srv_n_spin_wait_rounds); -sys_var_long_ptr sys_innodb_concurrency_tickets("innodb_concurrency_tickets", - &srv_n_free_tickets_to_enter); -sys_var_long_ptr sys_innodb_thread_sleep_delay("innodb_thread_sleep_delay", - &srv_thread_sleep_delay); -sys_var_long_ptr sys_innodb_thread_concurrency("innodb_thread_concurrency", - &srv_thread_concurrency); -sys_var_long_ptr sys_innodb_commit_concurrency("innodb_commit_concurrency", - &srv_commit_concurrency); -sys_var_long_ptr sys_innodb_flush_log_at_trx_commit( - "innodb_flush_log_at_trx_commit", - &srv_flush_log_at_trx_commit); -#endif + /* Condition pushdown to storage engine */ -sys_var_thd_bool -sys_engine_condition_pushdown("engine_condition_pushdown", +static sys_var_thd_bool +sys_engine_condition_pushdown(&vars, "engine_condition_pushdown", &SV::engine_condition_pushdown); /* ndb thread specific variable settings */ -sys_var_thd_ulong -sys_ndb_autoincrement_prefetch_sz("ndb_autoincrement_prefetch_sz", +static sys_var_thd_ulong +sys_ndb_autoincrement_prefetch_sz(&vars, "ndb_autoincrement_prefetch_sz", &SV::ndb_autoincrement_prefetch_sz); -sys_var_thd_bool -sys_ndb_force_send("ndb_force_send", &SV::ndb_force_send); +static sys_var_thd_bool +sys_ndb_force_send(&vars, "ndb_force_send", &SV::ndb_force_send); #ifdef HAVE_NDB_BINLOG -sys_var_long_ptr -sys_ndb_report_thresh_binlog_epoch_slip("ndb_report_thresh_binlog_epoch_slip", +static sys_var_long_ptr +sys_ndb_report_thresh_binlog_epoch_slip(&vars, "ndb_report_thresh_binlog_epoch_slip", &ndb_report_thresh_binlog_epoch_slip); -sys_var_long_ptr -sys_ndb_report_thresh_binlog_mem_usage("ndb_report_thresh_binlog_mem_usage", +static sys_var_long_ptr +sys_ndb_report_thresh_binlog_mem_usage(&vars, "ndb_report_thresh_binlog_mem_usage", &ndb_report_thresh_binlog_mem_usage); #endif -sys_var_thd_bool -sys_ndb_use_exact_count("ndb_use_exact_count", &SV::ndb_use_exact_count); -sys_var_thd_bool -sys_ndb_use_transactions("ndb_use_transactions", &SV::ndb_use_transactions); -sys_var_long_ptr -sys_ndb_cache_check_time("ndb_cache_check_time", &ndb_cache_check_time); -sys_var_thd_bool -sys_ndb_index_stat_enable("ndb_index_stat_enable", +static sys_var_thd_bool +sys_ndb_use_exact_count(&vars, "ndb_use_exact_count", &SV::ndb_use_exact_count); +static sys_var_thd_bool +sys_ndb_use_transactions(&vars, "ndb_use_transactions", &SV::ndb_use_transactions); +static sys_var_long_ptr +sys_ndb_cache_check_time(&vars, "ndb_cache_check_time", &ndb_cache_check_time); +static sys_var_thd_bool +sys_ndb_index_stat_enable(&vars, "ndb_index_stat_enable", &SV::ndb_index_stat_enable); -sys_var_thd_ulong -sys_ndb_index_stat_cache_entries("ndb_index_stat_cache_entries", +static sys_var_thd_ulong +sys_ndb_index_stat_cache_entries(&vars, "ndb_index_stat_cache_entries", &SV::ndb_index_stat_cache_entries); -sys_var_thd_ulong -sys_ndb_index_stat_update_freq("ndb_index_stat_update_freq", +static sys_var_thd_ulong +sys_ndb_index_stat_update_freq(&vars, "ndb_index_stat_update_freq", &SV::ndb_index_stat_update_freq); -sys_var_long_ptr -sys_ndb_extra_logging("ndb_extra_logging", &ndb_extra_logging); -sys_var_thd_bool -sys_ndb_use_copying_alter_table("ndb_use_copying_alter_table", &SV::ndb_use_copying_alter_table); +static sys_var_long_ptr +sys_ndb_extra_logging(&vars, "ndb_extra_logging", &ndb_extra_logging); +static sys_var_thd_bool +sys_ndb_use_copying_alter_table(&vars, "ndb_use_copying_alter_table", &SV::ndb_use_copying_alter_table); /* Time/date/datetime formats */ -sys_var_thd_date_time_format sys_time_format("time_format", +static sys_var_thd_date_time_format sys_time_format(&vars, "time_format", &SV::time_format, MYSQL_TIMESTAMP_TIME); -sys_var_thd_date_time_format sys_date_format("date_format", +static sys_var_thd_date_time_format sys_date_format(&vars, "date_format", &SV::date_format, MYSQL_TIMESTAMP_DATE); -sys_var_thd_date_time_format sys_datetime_format("datetime_format", +static sys_var_thd_date_time_format sys_datetime_format(&vars, "datetime_format", &SV::datetime_format, MYSQL_TIMESTAMP_DATETIME); /* Variables that are bits in THD */ -sys_var_thd_bit sys_autocommit("autocommit", 0, +sys_var_thd_bit sys_autocommit(&vars, "autocommit", 0, set_option_autocommit, OPTION_NOT_AUTOCOMMIT, 1); -static sys_var_thd_bit sys_big_tables("big_tables", 0, +static sys_var_thd_bit sys_big_tables(&vars, "big_tables", 0, set_option_bit, OPTION_BIG_TABLES); #ifndef TO_BE_DELETED /* Alias for big_tables */ -static sys_var_thd_bit sys_sql_big_tables("sql_big_tables", 0, +static sys_var_thd_bit sys_sql_big_tables(&vars, "sql_big_tables", 0, set_option_bit, OPTION_BIG_TABLES); #endif -static sys_var_thd_bit sys_big_selects("sql_big_selects", 0, +static sys_var_thd_bit sys_big_selects(&vars, "sql_big_selects", 0, set_option_bit, OPTION_BIG_SELECTS); -static sys_var_thd_bit sys_log_off("sql_log_off", +static sys_var_thd_bit sys_log_off(&vars, "sql_log_off", check_log_update, set_option_bit, OPTION_LOG_OFF); -static sys_var_thd_bit sys_log_update("sql_log_update", +static sys_var_thd_bit sys_log_update(&vars, "sql_log_update", check_log_update, set_log_update, OPTION_BIN_LOG); -static sys_var_thd_bit sys_log_binlog("sql_log_bin", +static sys_var_thd_bit sys_log_binlog(&vars, "sql_log_bin", check_log_update, set_option_bit, OPTION_BIN_LOG); -static sys_var_thd_bit sys_sql_warnings("sql_warnings", 0, +static sys_var_thd_bit sys_sql_warnings(&vars, "sql_warnings", 0, set_option_bit, OPTION_WARNINGS); -static sys_var_thd_bit sys_sql_notes("sql_notes", 0, +static sys_var_thd_bit sys_sql_notes(&vars, "sql_notes", 0, set_option_bit, OPTION_SQL_NOTES); -static sys_var_thd_bit sys_auto_is_null("sql_auto_is_null", 0, +static sys_var_thd_bit sys_auto_is_null(&vars, "sql_auto_is_null", 0, set_option_bit, OPTION_AUTO_IS_NULL); -static sys_var_thd_bit sys_safe_updates("sql_safe_updates", 0, +static sys_var_thd_bit sys_safe_updates(&vars, "sql_safe_updates", 0, set_option_bit, OPTION_SAFE_UPDATES); -static sys_var_thd_bit sys_buffer_results("sql_buffer_result", 0, +static sys_var_thd_bit sys_buffer_results(&vars, "sql_buffer_result", 0, set_option_bit, OPTION_BUFFER_RESULT); -static sys_var_thd_bit sys_quote_show_create("sql_quote_show_create", 0, +static sys_var_thd_bit sys_quote_show_create(&vars, "sql_quote_show_create", 0, set_option_bit, OPTION_QUOTE_SHOW_CREATE); -static sys_var_thd_bit sys_foreign_key_checks("foreign_key_checks", 0, +static sys_var_thd_bit sys_foreign_key_checks(&vars, "foreign_key_checks", 0, set_option_bit, OPTION_NO_FOREIGN_KEY_CHECKS, 1); -static sys_var_thd_bit sys_unique_checks("unique_checks", 0, +static sys_var_thd_bit sys_unique_checks(&vars, "unique_checks", 0, set_option_bit, OPTION_RELAXED_UNIQUE_CHECKS, 1); /* Local state variables */ -static sys_var_thd_ha_rows sys_select_limit("sql_select_limit", +static sys_var_thd_ha_rows sys_select_limit(&vars, "sql_select_limit", &SV::select_limit); -static sys_var_timestamp sys_timestamp("timestamp"); -static sys_var_last_insert_id sys_last_insert_id("last_insert_id"); -static sys_var_last_insert_id sys_identity("identity"); +static sys_var_timestamp sys_timestamp(&vars, "timestamp"); +static sys_var_last_insert_id sys_last_insert_id(&vars, "last_insert_id"); +static sys_var_last_insert_id sys_identity(&vars, "identity"); -static sys_var_thd_lc_time_names sys_lc_time_names("lc_time_names"); +static sys_var_thd_lc_time_names sys_lc_time_names(&vars, "lc_time_names"); -static sys_var_insert_id sys_insert_id("insert_id"); -static sys_var_readonly sys_error_count("error_count", +static sys_var_insert_id sys_insert_id(&vars, "insert_id"); +static sys_var_readonly sys_error_count(&vars, "error_count", OPT_SESSION, SHOW_LONG, get_error_count); -static sys_var_readonly sys_warning_count("warning_count", +static sys_var_readonly sys_warning_count(&vars, "warning_count", OPT_SESSION, SHOW_LONG, get_warning_count); /* alias for last_insert_id() to be compatible with Sybase */ -#ifdef HAVE_REPLICATION -static sys_var_slave_skip_counter sys_slave_skip_counter("sql_slave_skip_counter"); -#endif -static sys_var_rand_seed1 sys_rand_seed1("rand_seed1"); -static sys_var_rand_seed2 sys_rand_seed2("rand_seed2"); +static sys_var_rand_seed1 sys_rand_seed1(&vars, "rand_seed1"); +static sys_var_rand_seed2 sys_rand_seed2(&vars, "rand_seed2"); -static sys_var_thd_ulong sys_default_week_format("default_week_format", +static sys_var_thd_ulong sys_default_week_format(&vars, "default_week_format", &SV::default_week_format); -sys_var_thd_ulong sys_group_concat_max_len("group_concat_max_len", +sys_var_thd_ulong sys_group_concat_max_len(&vars, "group_concat_max_len", &SV::group_concat_max_len); -sys_var_thd_time_zone sys_time_zone("time_zone"); +sys_var_thd_time_zone sys_time_zone(&vars, "time_zone"); /* Read only variables */ -sys_var_have_variable sys_have_compress("have_compress", &have_compress); -sys_var_have_variable sys_have_crypt("have_crypt", &have_crypt); -sys_var_have_variable sys_have_csv_db("have_csv", &have_csv_db); -sys_var_have_variable sys_have_dlopen("have_dynamic_loading", &have_dlopen); -sys_var_have_variable sys_have_geometry("have_geometry", &have_geometry); -sys_var_have_variable sys_have_innodb("have_innodb", &have_innodb); -sys_var_have_variable sys_have_ndbcluster("have_ndbcluster", &have_ndbcluster); -sys_var_have_variable sys_have_openssl("have_openssl", &have_openssl); -sys_var_have_variable sys_have_partition_db("have_partitioning", - &have_partition_db); -sys_var_have_variable sys_have_query_cache("have_query_cache", +static sys_var_have_variable sys_have_compress(&vars, "have_compress", &have_compress); +static sys_var_have_variable sys_have_crypt(&vars, "have_crypt", &have_crypt); +static sys_var_have_plugin sys_have_csv(&vars, "have_csv", C_STRING_WITH_LEN("csv"), MYSQL_STORAGE_ENGINE_PLUGIN); +static sys_var_have_variable sys_have_dlopen(&vars, "have_dynamic_loading", &have_dlopen); +static sys_var_have_variable sys_have_geometry(&vars, "have_geometry", &have_geometry); +static sys_var_have_plugin sys_have_innodb(&vars, "have_innodb", C_STRING_WITH_LEN("innodb"), MYSQL_STORAGE_ENGINE_PLUGIN); +static sys_var_have_plugin sys_have_ndbcluster(&vars, "have_ndbcluster", C_STRING_WITH_LEN("ndbcluster"), MYSQL_STORAGE_ENGINE_PLUGIN); +static sys_var_have_variable sys_have_openssl(&vars, "have_openssl", &have_openssl); +static sys_var_have_plugin sys_have_partition_db(&vars, "have_partitioning", C_STRING_WITH_LEN("partition"), MYSQL_STORAGE_ENGINE_PLUGIN); +static sys_var_have_variable sys_have_query_cache(&vars, "have_query_cache", &have_query_cache); -sys_var_have_variable sys_have_rtree_keys("have_rtree_keys", &have_rtree_keys); -sys_var_have_variable sys_have_symlink("have_symlink", &have_symlink); +static sys_var_have_variable sys_have_rtree_keys(&vars, "have_rtree_keys", &have_rtree_keys); +static sys_var_have_variable sys_have_symlink(&vars, "have_symlink", &have_symlink); /* Global read-only variable describing server license */ -sys_var_const_str sys_license("license", STRINGIFY_ARG(LICENSE)); +static sys_var_const_str sys_license(&vars, "license", STRINGIFY_ARG(LICENSE)); /* Global variables which enable|disable logging */ -sys_var_log_state sys_var_general_log("general_log", &opt_log, +static sys_var_log_state sys_var_general_log(&vars, "general_log", &opt_log, QUERY_LOG_GENERAL); -sys_var_log_state sys_var_slow_query_log("slow_query_log", &opt_slow_log, +static sys_var_log_state sys_var_slow_query_log(&vars, "slow_query_log", &opt_slow_log, QUERY_LOG_SLOW); -sys_var_str sys_var_general_log_path("general_log_file", sys_check_log_path, +sys_var_str sys_var_general_log_path(&vars, "general_log_file", sys_check_log_path, sys_update_general_log_path, sys_default_general_log_path, opt_logname); -sys_var_str sys_var_slow_log_path("slow_query_log_file", sys_check_log_path, +sys_var_str sys_var_slow_log_path(&vars, "slow_query_log_file", sys_check_log_path, sys_update_slow_log_path, sys_default_slow_log_path, opt_slow_logname); -sys_var_log_output sys_var_log_output_state("log_output", &log_output_options, +static sys_var_log_output sys_var_log_output_state(&vars, "log_output", &log_output_options, &log_output_typelib, 0); -#ifdef HAVE_REPLICATION -static int show_slave_skip_errors(THD *thd, SHOW_VAR *var, char *buff) -{ - var->type=SHOW_CHAR; - var->value= buff; - if (!use_slave_mask || bitmap_is_clear_all(&slave_error_mask)) - { - var->value= const_cast<char *>("OFF"); - } - else if (bitmap_is_set_all(&slave_error_mask)) - { - var->value= const_cast<char *>("ALL"); - } - else - { - /* 10 is enough assuming errors are max 4 digits */ - int i; - var->value= buff; - for (i= 1; - i < MAX_SLAVE_ERROR && - (buff - var->value) < SHOW_VAR_FUNC_BUFF_SIZE; - i++) - { - if (bitmap_is_set(&slave_error_mask, i)) - { - buff= int10_to_str(i, buff, 10); - *buff++= ','; - } - } - if (var->value != buff) - buff--; // Remove last ',' - if (i < MAX_SLAVE_ERROR) - buff= strmov(buff, "..."); // Couldn't show all errors - *buff=0; - } - return 0; -} -#endif /* HAVE_REPLICATION */ /* - Variables shown by SHOW VARIABLES in alphabetical order + Additional variables (not derived from sys_var class, not accessible as + @@varname in SELECT or SET). Sorted in alphabetical order to facilitate + maintenance - SHOW VARIABLES will sort its output. + TODO: remove this list completely */ -SHOW_VAR init_vars[]= { - {"auto_increment_increment", (char*) &sys_auto_increment_increment, SHOW_SYS}, - {"auto_increment_offset", (char*) &sys_auto_increment_offset, SHOW_SYS}, - {sys_automatic_sp_privileges.name,(char*) &sys_automatic_sp_privileges, SHOW_SYS}, +#define FIXED_VARS_SIZE (sizeof(fixed_vars) / sizeof(SHOW_VAR)) +static SHOW_VAR fixed_vars[]= { {"back_log", (char*) &back_log, SHOW_LONG}, - {sys_basedir.name, (char*) &sys_basedir, SHOW_SYS}, - {sys_binlog_cache_size.name,(char*) &sys_binlog_cache_size, SHOW_SYS}, - {sys_binlog_format.name, (char*) &sys_binlog_format, SHOW_SYS}, - {sys_bulk_insert_buff_size.name,(char*) &sys_bulk_insert_buff_size,SHOW_SYS}, - {sys_character_set_client.name,(char*) &sys_character_set_client, SHOW_SYS}, - {sys_character_set_connection.name,(char*) &sys_character_set_connection,SHOW_SYS}, - {sys_character_set_database.name, (char*) &sys_character_set_database,SHOW_SYS}, - {sys_character_set_filesystem.name,(char*) &sys_character_set_filesystem, SHOW_SYS}, - {sys_character_set_results.name,(char*) &sys_character_set_results, SHOW_SYS}, - {sys_character_set_server.name, (char*) &sys_character_set_server,SHOW_SYS}, - {sys_charset_system.name, (char*) &sys_charset_system, SHOW_SYS}, {"character_sets_dir", mysql_charsets_dir, SHOW_CHAR}, - {sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS}, - {sys_collation_database.name,(char*) &sys_collation_database, SHOW_SYS}, - {sys_collation_server.name,(char*) &sys_collation_server, SHOW_SYS}, - {sys_completion_type.name, (char*) &sys_completion_type, SHOW_SYS}, - {sys_concurrent_insert.name,(char*) &sys_concurrent_insert, SHOW_SYS}, - {sys_connect_timeout.name, (char*) &sys_connect_timeout, SHOW_SYS}, - {sys_datadir.name, (char*) &sys_datadir, SHOW_SYS}, - {sys_date_format.name, (char*) &sys_date_format, SHOW_SYS}, - {sys_datetime_format.name, (char*) &sys_datetime_format, SHOW_SYS}, -#ifndef DBUG_OFF - {sys_dbug.name, (char*) &sys_dbug, SHOW_SYS}, -#endif - {sys_default_week_format.name, (char*) &sys_default_week_format, SHOW_SYS}, - {sys_delay_key_write.name, (char*) &sys_delay_key_write, SHOW_SYS}, - {sys_delayed_insert_limit.name, (char*) &sys_delayed_insert_limit,SHOW_SYS}, - {sys_delayed_insert_timeout.name, (char*) &sys_delayed_insert_timeout, SHOW_SYS}, - {sys_delayed_queue_size.name,(char*) &sys_delayed_queue_size, SHOW_SYS}, - {sys_div_precincrement.name,(char*) &sys_div_precincrement,SHOW_SYS}, - {sys_engine_condition_pushdown.name, - (char*) &sys_engine_condition_pushdown, SHOW_SYS}, - {sys_event_scheduler.name, (char*) &sys_event_scheduler, SHOW_SYS}, - {sys_expire_logs_days.name, (char*) &sys_expire_logs_days, SHOW_SYS}, - {sys_flush.name, (char*) &sys_flush, SHOW_SYS}, - {sys_flush_time.name, (char*) &sys_flush_time, SHOW_SYS}, - {sys_ft_boolean_syntax.name,(char*) &ft_boolean_syntax, SHOW_CHAR}, {"ft_max_word_len", (char*) &ft_max_word_len, SHOW_LONG}, {"ft_min_word_len", (char*) &ft_min_word_len, SHOW_LONG}, {"ft_query_expansion_limit",(char*) &ft_query_expansion_limit, SHOW_LONG}, {"ft_stopword_file", (char*) &ft_stopword_file, SHOW_CHAR_PTR}, - {sys_var_general_log.name, (char*) &opt_log, SHOW_MY_BOOL}, - {sys_var_general_log_path.name, (char*) &sys_var_general_log_path, SHOW_SYS}, - {sys_group_concat_max_len.name, (char*) &sys_group_concat_max_len, SHOW_SYS}, - {sys_have_compress.name, (char*) &have_compress, SHOW_HAVE}, - {sys_have_crypt.name, (char*) &have_crypt, SHOW_HAVE}, - {sys_have_csv_db.name, (char*) &have_csv_db, SHOW_HAVE}, - {sys_have_dlopen.name, (char*) &have_dlopen, SHOW_HAVE}, - {sys_have_geometry.name, (char*) &have_geometry, SHOW_HAVE}, - {sys_have_innodb.name, (char*) &have_innodb, SHOW_HAVE}, - {sys_have_ndbcluster.name, (char*) &have_ndbcluster, SHOW_HAVE}, - {sys_have_openssl.name, (char*) &have_openssl, SHOW_HAVE}, - {sys_have_partition_db.name,(char*) &have_partition_db, SHOW_HAVE}, - {sys_have_query_cache.name, (char*) &have_query_cache, SHOW_HAVE}, - {sys_have_rtree_keys.name, (char*) &have_rtree_keys, SHOW_HAVE}, - {sys_have_symlink.name, (char*) &have_symlink, SHOW_HAVE}, - {"init_connect", (char*) &sys_init_connect, SHOW_SYS}, {"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR}, - {"init_slave", (char*) &sys_init_slave, SHOW_SYS}, -#ifdef WITH_INNOBASE_STORAGE_ENGINE - {"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG }, - {sys_innodb_autoextend_increment.name, (char*) &sys_innodb_autoextend_increment, SHOW_SYS}, - {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONGLONG }, - {"innodb_checksums", (char*) &innobase_use_checksums, SHOW_MY_BOOL}, - {sys_innodb_commit_concurrency.name, (char*) &sys_innodb_commit_concurrency, SHOW_SYS}, - {sys_innodb_concurrency_tickets.name, (char*) &sys_innodb_concurrency_tickets, SHOW_SYS}, - {"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR}, - {"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR}, - {"innodb_doublewrite", (char*) &innobase_use_doublewrite, SHOW_MY_BOOL}, - {sys_innodb_fast_shutdown.name,(char*) &sys_innodb_fast_shutdown, SHOW_SYS}, - {"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG }, - {"innodb_file_per_table", (char*) &innobase_file_per_table, SHOW_MY_BOOL}, - {"innodb_flush_method", (char*) &innobase_unix_file_flush_method, SHOW_CHAR_PTR}, - {"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG }, - {"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG }, - {"innodb_locks_unsafe_for_binlog", (char*) &innobase_locks_unsafe_for_binlog, SHOW_MY_BOOL}, - {"innodb_log_arch_dir", (char*) &innobase_log_arch_dir, SHOW_CHAR_PTR}, - {"innodb_log_archive", (char*) &innobase_log_archive, SHOW_MY_BOOL}, - {"innodb_log_buffer_size", (char*) &innobase_log_buffer_size, SHOW_LONG }, - {"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONGLONG}, - {"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG}, - {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR}, - {sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS}, - {sys_innodb_max_purge_lag.name, (char*) &sys_innodb_max_purge_lag, SHOW_SYS}, - {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG}, - {"innodb_open_files", (char*) &innobase_open_files, SHOW_LONG }, - {"innodb_rollback_on_timeout", (char*) &innobase_rollback_on_timeout, SHOW_MY_BOOL}, - {sys_innodb_support_xa.name, (char*) &sys_innodb_support_xa, SHOW_SYS}, - {sys_innodb_sync_spin_loops.name, (char*) &sys_innodb_sync_spin_loops, SHOW_SYS}, - {sys_innodb_table_locks.name, (char*) &sys_innodb_table_locks, SHOW_SYS}, - {sys_innodb_thread_concurrency.name, (char*) &sys_innodb_thread_concurrency, SHOW_SYS}, - {sys_innodb_thread_sleep_delay.name, (char*) &sys_innodb_thread_sleep_delay, SHOW_SYS}, - {sys_innodb_flush_log_at_trx_commit.name, (char*) &sys_innodb_flush_log_at_trx_commit, SHOW_SYS}, -#endif - {sys_interactive_timeout.name,(char*) &sys_interactive_timeout, SHOW_SYS}, - {sys_join_buffer_size.name, (char*) &sys_join_buffer_size, SHOW_SYS}, - {sys_key_buffer_size.name, (char*) &sys_key_buffer_size, SHOW_SYS}, - {sys_key_cache_age_threshold.name, (char*) &sys_key_cache_age_threshold, - SHOW_SYS}, - {sys_key_cache_block_size.name, (char*) &sys_key_cache_block_size, - SHOW_SYS}, - {sys_key_cache_division_limit.name, (char*) &sys_key_cache_division_limit, - SHOW_SYS}, {"language", language, SHOW_CHAR}, {"large_files_support", (char*) &opt_large_files, SHOW_BOOL}, {"large_page_size", (char*) &opt_large_page_size, SHOW_INT}, {"large_pages", (char*) &opt_large_pages, SHOW_MY_BOOL}, - {sys_lc_time_names.name, (char*) &sys_lc_time_names, SHOW_SYS}, - {sys_license.name, (char*) &sys_license, SHOW_SYS}, - {sys_local_infile.name, (char*) &sys_local_infile, SHOW_SYS}, #ifdef HAVE_MLOCKALL - {"locked_in_memory", (char*) &locked_in_memory, SHOW_BOOL}, + {"locked_in_memory", (char*) &locked_in_memory, SHOW_MY_BOOL}, #endif - {"log", (char*) &opt_log, SHOW_BOOL}, + {"log", (char*) &opt_log, SHOW_MY_BOOL}, {"log_bin", (char*) &opt_bin_log, SHOW_BOOL}, - {sys_trust_function_creators.name,(char*) &sys_trust_function_creators, SHOW_SYS}, {"log_error", (char*) log_error_file, SHOW_CHAR}, - {sys_var_log_output_state.name, (char*) &sys_var_log_output_state, SHOW_SYS}, - {sys_log_queries_not_using_indexes.name, - (char*) &sys_log_queries_not_using_indexes, SHOW_SYS}, -#ifdef HAVE_REPLICATION - {"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_MY_BOOL}, -#endif - {"log_slow_queries", (char*) &opt_slow_log, SHOW_BOOL}, - {sys_log_warnings.name, (char*) &sys_log_warnings, SHOW_SYS}, - {sys_long_query_time.name, (char*) &sys_long_query_time, SHOW_SYS}, - {sys_low_priority_updates.name, (char*) &sys_low_priority_updates, SHOW_SYS}, + {"log_slow_queries", (char*) &opt_slow_log, SHOW_MY_BOOL}, {"lower_case_file_system", (char*) &lower_case_file_system, SHOW_MY_BOOL}, {"lower_case_table_names", (char*) &lower_case_table_names, SHOW_INT}, - {sys_max_allowed_packet.name,(char*) &sys_max_allowed_packet, SHOW_SYS}, - {sys_max_binlog_cache_size.name,(char*) &sys_max_binlog_cache_size, SHOW_SYS}, - {sys_max_binlog_size.name, (char*) &sys_max_binlog_size, SHOW_SYS}, - {sys_max_connect_errors.name, (char*) &sys_max_connect_errors, SHOW_SYS}, - {sys_max_connections.name, (char*) &sys_max_connections, SHOW_SYS}, - {sys_max_delayed_threads.name,(char*) &sys_max_delayed_threads, SHOW_SYS}, - {sys_max_error_count.name, (char*) &sys_max_error_count, SHOW_SYS}, - {sys_max_heap_table_size.name,(char*) &sys_max_heap_table_size, SHOW_SYS}, - {sys_max_insert_delayed_threads.name, - (char*) &sys_max_insert_delayed_threads, SHOW_SYS}, - {sys_max_join_size.name, (char*) &sys_max_join_size, SHOW_SYS}, - {sys_max_length_for_sort_data.name, (char*) &sys_max_length_for_sort_data, - SHOW_SYS}, - {sys_max_prepared_stmt_count.name, (char*) &sys_max_prepared_stmt_count, - SHOW_SYS}, - {sys_max_relay_log_size.name, (char*) &sys_max_relay_log_size, SHOW_SYS}, - {sys_max_seeks_for_key.name, (char*) &sys_max_seeks_for_key, SHOW_SYS}, - {sys_max_sort_length.name, (char*) &sys_max_sort_length, SHOW_SYS}, - {sys_max_sp_recursion_depth.name, - (char*) &sys_max_sp_recursion_depth, SHOW_SYS}, - {sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS}, - {sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS}, - {sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS}, - {sys_multi_range_count.name, (char*) &sys_multi_range_count, SHOW_SYS}, - {sys_myisam_data_pointer_size.name, (char*) &sys_myisam_data_pointer_size, SHOW_SYS}, - {sys_myisam_max_sort_file_size.name, (char*) &sys_myisam_max_sort_file_size, - SHOW_SYS}, {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR}, - {sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads, - SHOW_SYS}, - {sys_myisam_sort_buffer_size.name, (char*) &sys_myisam_sort_buffer_size, SHOW_SYS}, - - {sys_myisam_stats_method.name, (char*) &sys_myisam_stats_method, SHOW_SYS}, - {sys_myisam_use_mmap.name, (char*) &sys_myisam_use_mmap, SHOW_SYS}, - #ifdef __NT__ {"named_pipe", (char*) &opt_enable_named_pipe, SHOW_MY_BOOL}, #endif - {sys_ndb_autoincrement_prefetch_sz.name, - (char*) &sys_ndb_autoincrement_prefetch_sz, SHOW_SYS}, - {sys_ndb_cache_check_time.name,(char*) &sys_ndb_cache_check_time, SHOW_SYS}, - {sys_ndb_extra_logging.name,(char*) &sys_ndb_extra_logging, SHOW_SYS}, - {sys_ndb_force_send.name, (char*) &sys_ndb_force_send, SHOW_SYS}, - {sys_ndb_index_stat_cache_entries.name, (char*) &sys_ndb_index_stat_cache_entries, SHOW_SYS}, - {sys_ndb_index_stat_enable.name, (char*) &sys_ndb_index_stat_enable, SHOW_SYS}, - {sys_ndb_index_stat_update_freq.name, (char*) &sys_ndb_index_stat_update_freq, SHOW_SYS}, -#ifdef HAVE_NDB_BINLOG - {sys_ndb_report_thresh_binlog_epoch_slip.name, - (char*) &sys_ndb_report_thresh_binlog_epoch_slip, SHOW_SYS}, - {sys_ndb_report_thresh_binlog_mem_usage.name, - (char*) &sys_ndb_report_thresh_binlog_mem_usage, SHOW_SYS}, -#endif - {sys_ndb_use_copying_alter_table.name, - (char*) &sys_ndb_use_copying_alter_table, SHOW_SYS}, - {sys_ndb_use_exact_count.name,(char*) &sys_ndb_use_exact_count, SHOW_SYS}, - {sys_ndb_use_transactions.name,(char*) &sys_ndb_use_transactions, SHOW_SYS}, - {sys_net_buffer_length.name,(char*) &sys_net_buffer_length, SHOW_SYS}, - {sys_net_read_timeout.name, (char*) &sys_net_read_timeout, SHOW_SYS}, - {sys_net_retry_count.name, (char*) &sys_net_retry_count, SHOW_SYS}, - {sys_net_write_timeout.name,(char*) &sys_net_write_timeout, SHOW_SYS}, - {sys_new_mode.name, (char*) &sys_new_mode, SHOW_SYS}, - {sys_old_alter_table.name, (char*) &sys_old_alter_table, SHOW_SYS}, - {sys_old_passwords.name, (char*) &sys_old_passwords, SHOW_SYS}, {"open_files_limit", (char*) &open_files_limit, SHOW_LONG}, - {sys_optimizer_prune_level.name, (char*) &sys_optimizer_prune_level, - SHOW_SYS}, - {sys_optimizer_search_depth.name,(char*) &sys_optimizer_search_depth, - SHOW_SYS}, {"pid_file", (char*) pidfile_name, SHOW_CHAR}, {"plugin_dir", (char*) opt_plugin_dir, SHOW_CHAR}, - {"port", (char*) &mysqld_port, SHOW_INT}, - {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, + {"port", (char*) &mysqld_port, SHOW_INT}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, - {sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size, - SHOW_SYS}, -#ifdef HAVE_QUERY_CACHE - {sys_query_cache_limit.name,(char*) &sys_query_cache_limit, SHOW_SYS}, - {sys_query_cache_min_res_unit.name, (char*) &sys_query_cache_min_res_unit, - SHOW_SYS}, - {sys_query_cache_size.name, (char*) &sys_query_cache_size, SHOW_SYS}, - {sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS}, - {sys_query_cache_wlock_invalidate.name, - (char *) &sys_query_cache_wlock_invalidate, SHOW_SYS}, -#endif /* HAVE_QUERY_CACHE */ - {sys_query_prealloc_size.name, (char*) &sys_query_prealloc_size, SHOW_SYS}, - {sys_range_alloc_block_size.name, (char*) &sys_range_alloc_block_size, - SHOW_SYS}, - {sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS}, - {sys_readonly.name, (char*) &sys_readonly, SHOW_SYS}, - {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS}, -#ifdef HAVE_REPLICATION - {sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS}, - {"relay_log_space_limit", (char*) &relay_log_space_limit, SHOW_LONGLONG}, -#endif - {sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS}, - {"secure_auth", (char*) &sys_secure_auth, SHOW_SYS}, #ifdef HAVE_SMEM {"shared_memory", (char*) &opt_enable_shared_memory, SHOW_MY_BOOL}, {"shared_memory_base_name", (char*) &shared_memory_base_name, SHOW_CHAR_PTR}, #endif - {sys_server_id.name, (char*) &sys_server_id, SHOW_SYS}, {"skip_external_locking", (char*) &my_disable_locking, SHOW_MY_BOOL}, {"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL}, {"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL}, -#ifdef HAVE_REPLICATION - {sys_slave_compressed_protocol.name, - (char*) &sys_slave_compressed_protocol, SHOW_SYS}, - {"slave_load_tmpdir", (char*) &slave_load_tmpdir, SHOW_CHAR_PTR}, - {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS}, - {"slave_skip_errors", (char*) &show_slave_skip_errors, SHOW_FUNC}, - {sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries, SHOW_SYS}, -#endif - {sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS}, - {sys_var_slow_query_log.name, (char*) &opt_slow_log, SHOW_MY_BOOL}, - {sys_var_slow_log_path.name, (char*) &sys_var_slow_log_path, SHOW_SYS}, #ifdef HAVE_SYS_UN_H - {"socket", (char*) &mysqld_unix_port, SHOW_CHAR_PTR}, -#endif - {sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS}, - {sys_big_selects.name, (char*) &sys_big_selects, SHOW_SYS}, - {sys_sql_mode.name, (char*) &sys_sql_mode, SHOW_SYS}, - {"sql_notes", (char*) &sys_sql_notes, SHOW_SYS}, - {"sql_warnings", (char*) &sys_sql_warnings, SHOW_SYS}, - {sys_ssl_ca.name, (char*) &sys_ssl_ca, SHOW_SYS}, - {sys_ssl_capath.name, (char*) &sys_ssl_capath, SHOW_SYS}, - {sys_ssl_cert.name, (char*) &sys_ssl_cert, SHOW_SYS}, - {sys_ssl_cipher.name, (char*) &sys_ssl_cipher, SHOW_SYS}, - {sys_ssl_key.name, (char*) &sys_ssl_key, SHOW_SYS}, - {sys_storage_engine.name, (char*) &sys_storage_engine, SHOW_SYS}, -#ifdef HAVE_REPLICATION - {sys_sync_binlog_period.name,(char*) &sys_sync_binlog_period, SHOW_SYS}, -#endif - {sys_sync_frm.name, (char*) &sys_sync_frm, SHOW_SYS}, -#ifdef HAVE_TZNAME - {"system_time_zone", system_time_zone, SHOW_CHAR}, + {"socket", (char*) &mysqld_unix_port, SHOW_CHAR_PTR}, #endif {"table_definition_cache", (char*) &table_def_size, SHOW_LONG}, {"table_lock_wait_timeout", (char*) &table_lock_wait_timeout, SHOW_LONG }, - {"table_open_cache", (char*) &table_cache_size, SHOW_LONG}, - {sys_table_type.name, (char*) &sys_table_type, SHOW_SYS}, - {sys_thread_cache_size.name,(char*) &sys_thread_cache_size, SHOW_SYS}, #ifdef HAVE_THR_SETCONCURRENCY {"thread_concurrency", (char*) &concurrency, SHOW_LONG}, #endif @@ -1020,24 +695,6 @@ SHOW_VAR init_vars[]= { {sys_thread_pool_size.name, (char*) &sys_thread_pool_size, SHOW_SYS}, #endif {"thread_stack", (char*) &thread_stack, SHOW_LONG}, - {sys_time_format.name, (char*) &sys_time_format, SHOW_SYS}, - {"time_zone", (char*) &sys_time_zone, SHOW_SYS}, - {sys_timed_mutexes.name, (char*) &sys_timed_mutexes, SHOW_SYS}, - {sys_tmp_table_size.name, (char*) &sys_tmp_table_size, SHOW_SYS}, - {sys_tmpdir.name, (char*) &sys_tmpdir, SHOW_SYS}, - {sys_trans_alloc_block_size.name, (char*) &sys_trans_alloc_block_size, - SHOW_SYS}, - {sys_trans_prealloc_size.name, (char*) &sys_trans_prealloc_size, SHOW_SYS}, - {sys_tx_isolation.name, (char*) &sys_tx_isolation, SHOW_SYS}, - {sys_updatable_views_with_limit.name, - (char*) &sys_updatable_views_with_limit,SHOW_SYS}, - {sys_version.name, (char*) &sys_version, SHOW_SYS}, - {sys_version_comment.name, (char*) &sys_version_comment, SHOW_SYS}, - {sys_version_compile_machine.name, (char*) &sys_version_compile_machine, - SHOW_SYS}, - {sys_version_compile_os.name, (char*) &sys_version_compile_os, SHOW_SYS}, - {sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS}, - {NullS, NullS, SHOW_LONG} }; @@ -1332,7 +989,8 @@ bool sys_var_thd_binlog_format::is_readonly() const /* Cluster does not support changing the binlog format on the fly yet. */ - if (opt_bin_log && (have_ndbcluster == SHOW_OPTION_YES)) + LEX_STRING ndb_name= {(char*)STRING_WITH_LEN("ndbcluster")}; + if (opt_bin_log && plugin_is_ready(&ndb_name, MYSQL_STORAGE_ENGINE_PLUGIN)) { my_error(ER_NDB_CANT_SWITCH_BINLOG_FORMAT, MYF(0)); return 1; @@ -1423,9 +1081,9 @@ static void fix_server_id(THD *thd, enum_var_type type) sys_var_long_ptr:: -sys_var_long_ptr(const char *name_arg, ulong *value_ptr_arg, +sys_var_long_ptr(sys_var_chain *chain, const char *name_arg, ulong *value_ptr_arg, sys_after_update_func after_update_arg) - :sys_var_long_ptr_global(name_arg, value_ptr_arg, + :sys_var_long_ptr_global(chain, name_arg, value_ptr_arg, &LOCK_global_system_variables, after_update_arg) {} @@ -1809,7 +1467,13 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) return new Item_int((longlong) value); } case SHOW_MY_BOOL: - return new Item_int((int32) *(my_bool*) value_ptr(thd, var_type, base),1); + { + int32 value; + pthread_mutex_lock(&LOCK_global_system_variables); + value= *(my_bool*) value_ptr(thd, var_type, base); + pthread_mutex_unlock(&LOCK_global_system_variables); + return new Item_int(value,1); + } case SHOW_CHAR: { Item *tmp; @@ -2118,122 +1782,25 @@ byte *sys_var_character_set::value_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; - else - return &thd->variables.collation_connection; -} - - -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; - else - { - thd->variables.collation_connection= global_system_variables.collation_connection; - thd->update_charset(); - } -} - - -CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd, - enum_var_type type) +void sys_var_character_set_sv::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) - return &global_system_variables.character_set_client; + global_system_variables.*offset= *global_default; else - return &thd->variables.character_set_client; -} - - -void sys_var_character_set_client::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.character_set_client= default_charset_info; - else - { - thd->variables.character_set_client= (global_system_variables. - character_set_client); - thd->update_charset(); - } -} - - -CHARSET_INFO ** -sys_var_character_set_filesystem::ci_ptr(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - return &global_system_variables.character_set_filesystem; - else - return &thd->variables.character_set_filesystem; -} - - -extern CHARSET_INFO *character_set_filesystem; - -void -sys_var_character_set_filesystem::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.character_set_filesystem= character_set_filesystem; - else - { - thd->variables.character_set_filesystem= (global_system_variables. - character_set_filesystem); - thd->update_charset(); - } -} - - -CHARSET_INFO ** -sys_var_character_set_results::ci_ptr(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - return &global_system_variables.character_set_results; - else - return &thd->variables.character_set_results; -} - - -void sys_var_character_set_results::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.character_set_results= default_charset_info; - else - { - thd->variables.character_set_results= (global_system_variables. - character_set_results); - thd->update_charset(); - } + { + thd->variables.*offset= global_system_variables.*offset; + thd->update_charset(); + } } - - -CHARSET_INFO ** -sys_var_character_set_server::ci_ptr(THD *thd, enum_var_type type) +CHARSET_INFO **sys_var_character_set_sv::ci_ptr(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) - return &global_system_variables.collation_server; + return &(global_system_variables.*offset); else - return &thd->variables.collation_server; + return &(thd->variables.*offset); } -void sys_var_character_set_server::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.collation_server= default_charset_info; - else - { - thd->variables.collation_server= global_system_variables.collation_server; - thd->update_charset(); - } -} - CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type type) { @@ -2256,113 +1823,39 @@ void sys_var_character_set_database::set_default(THD *thd, enum_var_type type) } -bool sys_var_collation_connection::update(THD *thd, set_var *var) -{ - if (var->type == OPT_GLOBAL) - global_system_variables.collation_connection= var->save_result.charset; - else - { - thd->variables.collation_connection= var->save_result.charset; - thd->update_charset(); - } - return 0; -} - - -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 : - thd->variables.collation_connection); - return cs ? (byte*) cs->name : (byte*) "NULL"; -} - - -void sys_var_collation_connection::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.collation_connection= default_charset_info; - else - { - thd->variables.collation_connection= (global_system_variables. - collation_connection); - thd->update_charset(); - } -} - -bool sys_var_collation_database::update(THD *thd, set_var *var) +bool sys_var_collation_sv::update(THD *thd, set_var *var) { if (var->type == OPT_GLOBAL) - global_system_variables.collation_database= var->save_result.charset; + global_system_variables.*offset= var->save_result.charset; else { - thd->variables.collation_database= var->save_result.charset; + thd->variables.*offset= var->save_result.charset; thd->update_charset(); } return 0; } -byte *sys_var_collation_database::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - CHARSET_INFO *cs= ((type == OPT_GLOBAL) ? - global_system_variables.collation_database : - thd->variables.collation_database); - return cs ? (byte*) cs->name : (byte*) "NULL"; -} - - -void sys_var_collation_database::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.collation_database= default_charset_info; - else - { - thd->variables.collation_database= (global_system_variables. - collation_database); - thd->update_charset(); - } -} - - -bool sys_var_collation_server::update(THD *thd, set_var *var) +void sys_var_collation_sv::set_default(THD *thd, enum_var_type type) { - if (var->type == OPT_GLOBAL) - global_system_variables.collation_server= var->save_result.charset; + if (type == OPT_GLOBAL) + global_system_variables.*offset= *global_default; else { - thd->variables.collation_server= var->save_result.charset; + thd->variables.*offset= global_system_variables.*offset; thd->update_charset(); } - return 0; } -byte *sys_var_collation_server::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) +byte *sys_var_collation_sv::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { CHARSET_INFO *cs= ((type == OPT_GLOBAL) ? - global_system_variables.collation_server : - thd->variables.collation_server); + global_system_variables.*offset : thd->variables.*offset); return cs ? (byte*) cs->name : (byte*) "NULL"; } -void sys_var_collation_server::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.collation_server= default_charset_info; - else - { - thd->variables.collation_server= (global_system_variables. - collation_server); - thd->update_charset(); - } -} - - LEX_STRING default_key_cache_base= {(char *) "default", 7 }; static KEY_CACHE zero_key_cache; @@ -2804,52 +2297,6 @@ byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type, } -#ifdef HAVE_REPLICATION -bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) -{ - int result= 0; - pthread_mutex_lock(&LOCK_active_mi); - pthread_mutex_lock(&active_mi->rli.run_lock); - if (active_mi->rli.slave_running) - { - my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0)); - result=1; - } - pthread_mutex_unlock(&active_mi->rli.run_lock); - pthread_mutex_unlock(&LOCK_active_mi); - var->save_result.ulong_value= (ulong) var->value->val_int(); - return result; -} - - -bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) -{ - pthread_mutex_lock(&LOCK_active_mi); - pthread_mutex_lock(&active_mi->rli.run_lock); - /* - The following test should normally never be true as we test this - in the check function; To be safe against multiple - SQL_SLAVE_SKIP_COUNTER request, we do the check anyway - */ - if (!active_mi->rli.slave_running) - { - pthread_mutex_lock(&active_mi->rli.data_lock); - active_mi->rli.slave_skip_counter= var->save_result.ulong_value; - pthread_mutex_unlock(&active_mi->rli.data_lock); - } - pthread_mutex_unlock(&active_mi->rli.run_lock); - pthread_mutex_unlock(&LOCK_active_mi); - return 0; -} - - -bool sys_var_sync_binlog_period::update(THD *thd, set_var *var) -{ - sync_binlog_period= (ulong) var->save_result.ulonglong_value; - return 0; -} -#endif /* HAVE_REPLICATION */ - bool sys_var_rand_seed1::update(THD *thd, set_var *var) { thd->rand.seed1= (ulong) var->save_result.ulonglong_value; @@ -3234,22 +2681,151 @@ static byte *get_sys_var_length(const sys_var *var, uint *length, /* - Initialises sys variables and put them in system_variable_hash + Add variables to the dynamic hash of system variables + + SYNOPSIS + mysql_add_sys_var_chain() + first Pointer to first system variable to add + long_opt (optional)command line arguments may be tied for limit checks. + + RETURN VALUES + 0 SUCCESS + otherwise FAILURE */ - -void set_var_init() +int mysql_add_sys_var_chain(sys_var *first, struct my_option *long_options) { sys_var *var; - - hash_init(&system_variable_hash, system_charset_info, sys_var::sys_vars, 0, - 0, (hash_get_key) get_sys_var_length, 0, 0); - for (var= sys_var::first; var; var= var->next) + + /* A write lock should be held on LOCK_system_variables_hash */ + + for (var= first; var; var= var->next) { var->name_length= strlen(var->name); - var->option_limits= find_option(my_long_options, var->name); - my_hash_insert(&system_variable_hash, (byte*) var); + /* this fails if there is a conflicting variable name. see HASH_UNIQUE */ + if (my_hash_insert(&system_variable_hash, (byte*) var)) + goto error; + if (long_options) + var->option_limits= find_option(long_options, var->name); } + return 0; + +error: + for (; first != var; first= first->next) + hash_delete(&system_variable_hash, (byte*) first); + return 1; +} + + +/* + Remove variables to the dynamic hash of system variables + + SYNOPSIS + mysql_del_sys_var_chain() + first Pointer to first system variable to remove + + RETURN VALUES + 0 SUCCESS + otherwise FAILURE +*/ + +int mysql_del_sys_var_chain(sys_var *first) +{ + int result= 0; + + /* A write lock should be held on LOCK_system_variables_hash */ + + for (sys_var *var= first; var; var= var->next) + result|= hash_delete(&system_variable_hash, (byte*) var); + + return result; +} + + +static int show_cmp(SHOW_VAR *a, SHOW_VAR *b) +{ + return strcmp(a->name, b->name); +} + + +/* + Constructs an array of system variables for display to the user. + + SYNOPSIS + enumerate_sys_vars() + thd current thread + sorted If TRUE, the system variables should be sorted + + RETURN VALUES + pointer Array of SHOW_VAR elements for display + NULL FAILURE +*/ + +SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted) +{ + int count= system_variable_hash.records, i; + int fixed_count= fixed_show_vars.elements; + int size= sizeof(SHOW_VAR) * (count + fixed_count + 1); + SHOW_VAR *result= (SHOW_VAR*) thd->alloc(size); + + if (result) + { + SHOW_VAR *show= result + fixed_count; + memcpy(result, fixed_show_vars.buffer, fixed_count * sizeof(SHOW_VAR)); + + for (i= 0; i < count; i++) + { + sys_var *var= (sys_var*) hash_element(&system_variable_hash, i); + show->name= var->name; + show->value= (char*) var; + show->type= SHOW_SYS; + show++; + } + + /* sort into order */ + if (sorted) + qsort(result, count + fixed_count, sizeof(SHOW_VAR), (qsort_cmp)show_cmp); + + /* make last element empty */ + bzero(show, sizeof(SHOW_VAR)); + } + return result; +} + + +/* + Initialize the system variables + + SYNOPSIS + set_var_init() + + RETURN VALUES + 0 SUCCESS + otherwise FAILURE +*/ + +int set_var_init() +{ + uint count= 0; + DBUG_ENTER("set_var_init"); + + for (sys_var *var=vars.first; var; var= var->next, count++); + + if (my_init_dynamic_array(&fixed_show_vars, sizeof(SHOW_VAR), + FIXED_VARS_SIZE + 64, 64)) + goto error; + + fixed_show_vars.elements= FIXED_VARS_SIZE; + memcpy(fixed_show_vars.buffer, fixed_vars, sizeof(fixed_vars)); + + if (hash_init(&system_variable_hash, system_charset_info, count, 0, + 0, (hash_get_key) get_sys_var_length, 0, HASH_UNIQUE)) + goto error; + + vars.last->next= NULL; + if (mysql_add_sys_var_chain(vars.first, my_long_options)) + goto error; + /* Special cases Needed because MySQL can't find the limits for a variable it it has @@ -3257,12 +2833,41 @@ void set_var_init() As these variables are deprecated, this code will disappear soon... */ sys_sql_max_join_size.option_limits= sys_max_join_size.option_limits; + + DBUG_RETURN(0); + +error: + fprintf(stderr, "failed to initialize system variables"); + pthread_mutex_unlock(&LOCK_global_system_variables); + DBUG_RETURN(1); } void set_var_free() { hash_free(&system_variable_hash); + delete_dynamic(&fixed_show_vars); +} + + +/* + Add elements to the dynamic list of read-only system variables. + + SYNOPSIS + mysql_append_static_vars() + show_vars Pointer to start of array + count Number of elements + + RETURN VALUES + 0 SUCCESS + otherwise FAILURE +*/ +int mysql_append_static_vars(const SHOW_VAR *show_vars, uint count) +{ + for (; count > 0; count--, show_vars++) + if (insert_dynamic(&fixed_show_vars, (char*) show_vars)) + return 1; + return 0; } @@ -3270,7 +2875,7 @@ void set_var_free() Find a user set-table variable SYNOPSIS - find_sys_var() + intern_find_sys_var() str Name of system variable to find length Length of variable. zero means that we should use strlen() on the variable @@ -3280,14 +2885,19 @@ void set_var_free() 0 Unknown variable (error message is given) */ -sys_var *find_sys_var(const char *str, uint length) +sys_var *intern_find_sys_var(const char *str, uint length, bool no_error) { - sys_var *var= (sys_var*) hash_search(&system_variable_hash, - (byte*) str, - length ? length : - strlen(str)); - if (!var) + sys_var *var; + + /* + This function is only called from the sql_plugin.cc. + A lock on LOCK_system_variable_hash should be held + */ + var= (sys_var*) hash_search(&system_variable_hash, + (byte*) str, length ? length : strlen(str)); + if (!(var || no_error)) my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str); + return var; } @@ -3553,14 +3163,16 @@ bool sys_var_thd_storage_engine::check(THD *thd, set_var *var) const char *value; String str(buff, sizeof(buff), &my_charset_latin1), *res; + var->save_result.plugin= NULL; if (var->value->result_type() == STRING_RESULT) { LEX_STRING name; - handlerton *db_type; + handlerton *hton; if (!(res=var->value->val_str(&str)) || !(name.str= (char *)res->ptr()) || !(name.length= res->length()) || - !(var->save_result.hton= db_type= ha_resolve_by_name(thd, &name)) || - ha_checktype(thd, ha_legacy_type(db_type), 1, 0) != db_type) + !(var->save_result.plugin= ha_resolve_by_name(thd, &name)) || + !(hton= plugin_data(var->save_result.plugin, handlerton *)) || + ha_checktype(thd, ha_legacy_type(hton), 1, 0) != hton) { value= res ? res->c_ptr() : "NULL"; goto err; @@ -3578,28 +3190,52 @@ err: byte *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - handlerton *val; - val= (type == OPT_GLOBAL) ? global_system_variables.*offset : - thd->variables.*offset; - return (byte *) hton2plugin[val->slot]->name.str; + byte* result; + handlerton *hton; + LEX_STRING *name; + plugin_ref plugin= thd->variables.*offset; + if (type == OPT_GLOBAL) + plugin= my_plugin_lock(thd, &(global_system_variables.*offset)); + hton= plugin_data(plugin, handlerton*); + name= &hton2plugin[hton->slot]->name; + result= (byte *) thd->strmake(name->str, name->length); + if (type == OPT_GLOBAL) + plugin_unlock(thd, plugin); + return result; } void sys_var_thd_storage_engine::set_default(THD *thd, enum_var_type type) { + plugin_ref old_value, new_value, *value; if (type == OPT_GLOBAL) - global_system_variables.*offset= myisam_hton; + { + value= &(global_system_variables.*offset); + new_value= ha_lock_engine(NULL, myisam_hton); + } else - thd->variables.*offset= global_system_variables.*offset; + { + value= &(thd->variables.*offset); + new_value= my_plugin_lock(NULL, &(global_system_variables.*offset)); + } + DBUG_ASSERT(new_value); + old_value= *value; + *value= new_value; + plugin_unlock(NULL, old_value); } bool sys_var_thd_storage_engine::update(THD *thd, set_var *var) { - handlerton **value= &(global_system_variables.*offset); - if (var->type != OPT_GLOBAL) - value= &(thd->variables.*offset); - *value= var->save_result.hton; + plugin_ref *value= &(global_system_variables.*offset), old_value; + if (var->type != OPT_GLOBAL) + value= &(thd->variables.*offset); + old_value= *value; + if (old_value != var->save_result.plugin) + { + *value= my_plugin_lock(NULL, &var->save_result.plugin); + plugin_unlock(NULL, old_value); + } return 0; } diff --git a/sql/set_var.h b/sql/set_var.h index 8887d91ec69..2813a756b8e 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -26,6 +26,7 @@ class sys_var; class set_var; +class sys_var_pluginvar; /* opaque */ typedef struct system_variables SV; typedef struct my_locale_st MY_LOCALE; @@ -37,11 +38,15 @@ typedef void (*sys_after_update_func)(THD *,enum_var_type); typedef void (*sys_set_default_func)(THD *, enum_var_type); typedef byte *(*sys_value_ptr_func)(THD *thd); +struct sys_var_chain +{ + sys_var *first; + sys_var *last; +}; + class sys_var { public: - static sys_var *first; - static uint sys_vars; sys_var *next; struct my_option *option_limits; /* Updated by by set_var_init() */ uint name_length; /* Updated by by set_var_init() */ @@ -52,13 +57,15 @@ public: sys_var(const char *name_arg,sys_after_update_func func= NULL) :name(name_arg), after_update(func) , no_support_one_shot(1) - { add_sys_var(); } + {} virtual ~sys_var() {} - void add_sys_var() + void chain_sys_var(sys_var_chain *chain_arg) { - next= first; - first= this; - sys_vars++; + if (chain_arg->last) + chain_arg->last->next= this; + else + chain_arg->first= this; + chain_arg->last= this; } virtual bool check(THD *thd, set_var *var); bool check_enum(THD *thd, set_var *var, TYPELIB *enum_names); @@ -77,6 +84,7 @@ public: Item *item(THD *thd, enum_var_type type, LEX_STRING *base); virtual bool is_struct() { return 0; } virtual bool is_readonly() const { return 0; } + virtual sys_var_pluginvar *cast_pluginvar() { return 0; } }; @@ -105,12 +113,12 @@ class sys_var_long_ptr_global: public sys_var_global { public: ulong *value; - sys_var_long_ptr_global(const char *name_arg, ulong *value_ptr_arg, + sys_var_long_ptr_global(sys_var_chain *chain, const char *name_arg, ulong *value_ptr_arg, pthread_mutex_t *guard_arg, sys_after_update_func after_update_arg= NULL) :sys_var_global(name_arg, after_update_arg, guard_arg), value(value_ptr_arg) - {} + { chain_sys_var(chain); } bool check(THD *thd, set_var *var); bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); @@ -127,7 +135,7 @@ public: class sys_var_long_ptr :public sys_var_long_ptr_global { public: - sys_var_long_ptr(const char *name_arg, ulong *value_ptr, + sys_var_long_ptr(sys_var_chain *chain, const char *name_arg, ulong *value_ptr, sys_after_update_func after_update_arg= NULL); }; @@ -136,11 +144,13 @@ class sys_var_ulonglong_ptr :public sys_var { public: ulonglong *value; - sys_var_ulonglong_ptr(const char *name_arg, ulonglong *value_ptr_arg) - :sys_var(name_arg),value(value_ptr_arg) {} - sys_var_ulonglong_ptr(const char *name_arg, ulonglong *value_ptr_arg, + sys_var_ulonglong_ptr(sys_var_chain *chain, const char *name_arg, ulonglong *value_ptr_arg) + :sys_var(name_arg),value(value_ptr_arg) + { chain_sys_var(chain); } + sys_var_ulonglong_ptr(sys_var_chain *chain, const char *name_arg, ulonglong *value_ptr_arg, sys_after_update_func func) - :sys_var(name_arg,func), value(value_ptr_arg) {} + :sys_var(name_arg,func), value(value_ptr_arg) + { chain_sys_var(chain); } bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_LONGLONG; } @@ -153,9 +163,9 @@ class sys_var_bool_ptr :public sys_var { public: my_bool *value; - sys_var_bool_ptr(const char *name_arg, my_bool *value_arg) + sys_var_bool_ptr(sys_var_chain *chain, const char *name_arg, my_bool *value_arg) :sys_var(name_arg),value(value_arg) - {} + { chain_sys_var(chain); } bool check(THD *thd, set_var *var) { return check_enum(thd, var, &bool_typelib); @@ -177,14 +187,14 @@ public: sys_check_func check_func; sys_update_func update_func; sys_set_default_func set_default_func; - sys_var_str(const char *name_arg, + sys_var_str(sys_var_chain *chain, const char *name_arg, sys_check_func check_func_arg, sys_update_func update_func_arg, sys_set_default_func set_default_func_arg, char *value_arg) :sys_var(name_arg), value(value_arg), check_func(check_func_arg), update_func(update_func_arg),set_default_func(set_default_func_arg) - {} + { chain_sys_var(chain); } bool check(THD *thd, set_var *var); bool update(THD *thd, set_var *var) { @@ -209,9 +219,9 @@ class sys_var_const_str :public sys_var { public: char *value; // Pointer to const value - sys_var_const_str(const char *name_arg, const char *value_arg) + sys_var_const_str(sys_var_chain *chain, const char *name_arg, const char *value_arg) :sys_var(name_arg),value((char*) value_arg) - {} + { chain_sys_var(chain); } bool check(THD *thd, set_var *var) { return 1; @@ -238,9 +248,9 @@ class sys_var_const_str_ptr :public sys_var { public: char **value; // Pointer to const value - sys_var_const_str_ptr(const char *name_arg, char **value_arg) + sys_var_const_str_ptr(sys_var_chain *chain, const char *name_arg, char **value_arg) :sys_var(name_arg),value(value_arg) - {} + { chain_sys_var(chain); } bool check(THD *thd, set_var *var) { return 1; @@ -268,10 +278,10 @@ class sys_var_enum :public sys_var uint *value; TYPELIB *enum_names; public: - sys_var_enum(const char *name_arg, uint *value_arg, + sys_var_enum(sys_var_chain *chain, const char *name_arg, uint *value_arg, TYPELIB *typelib, sys_after_update_func func) :sys_var(name_arg,func), value(value_arg), enum_names(typelib) - {} + { chain_sys_var(chain); } bool check(THD *thd, set_var *var) { return check_enum(thd, var, enum_names); @@ -286,7 +296,8 @@ public: class sys_var_thd :public sys_var { public: - sys_var_thd(const char *name_arg, sys_after_update_func func= NULL) + sys_var_thd(const char *name_arg, + sys_after_update_func func= NULL) :sys_var(name_arg,func) {} bool check_type(enum_var_type type) { return 0; } @@ -302,13 +313,13 @@ class sys_var_thd_ulong :public sys_var_thd sys_check_func check_func; public: ulong SV::*offset; - sys_var_thd_ulong(const char *name_arg, ulong SV::*offset_arg) + sys_var_thd_ulong(sys_var_chain *chain, const char *name_arg, ulong SV::*offset_arg) :sys_var_thd(name_arg), check_func(0), offset(offset_arg) - {} - sys_var_thd_ulong(const char *name_arg, ulong SV::*offset_arg, + { chain_sys_var(chain); } + sys_var_thd_ulong(sys_var_chain *chain, const char *name_arg, ulong SV::*offset_arg, sys_check_func c_func, sys_after_update_func au_func) :sys_var_thd(name_arg,au_func), check_func(c_func), offset(offset_arg) - {} + { chain_sys_var(chain); } bool check(THD *thd, set_var *var); bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); @@ -321,13 +332,15 @@ class sys_var_thd_ha_rows :public sys_var_thd { public: ha_rows SV::*offset; - sys_var_thd_ha_rows(const char *name_arg, ha_rows SV::*offset_arg) + sys_var_thd_ha_rows(sys_var_chain *chain, const char *name_arg, + ha_rows SV::*offset_arg) :sys_var_thd(name_arg), offset(offset_arg) - {} - sys_var_thd_ha_rows(const char *name_arg, ha_rows SV::*offset_arg, + { chain_sys_var(chain); } + sys_var_thd_ha_rows(sys_var_chain *chain, const char *name_arg, + ha_rows SV::*offset_arg, sys_after_update_func func) :sys_var_thd(name_arg,func), offset(offset_arg) - {} + { chain_sys_var(chain); } bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_HA_ROWS; } @@ -340,14 +353,16 @@ class sys_var_thd_ulonglong :public sys_var_thd public: ulonglong SV::*offset; bool only_global; - sys_var_thd_ulonglong(const char *name_arg, ulonglong SV::*offset_arg) + sys_var_thd_ulonglong(sys_var_chain *chain, const char *name_arg, + ulonglong SV::*offset_arg) :sys_var_thd(name_arg), offset(offset_arg) - {} - sys_var_thd_ulonglong(const char *name_arg, ulonglong SV::*offset_arg, + { chain_sys_var(chain); } + sys_var_thd_ulonglong(sys_var_chain *chain, const char *name_arg, + ulonglong SV::*offset_arg, sys_after_update_func func, bool only_global_arg) :sys_var_thd(name_arg, func), offset(offset_arg), only_global(only_global_arg) - {} + { chain_sys_var(chain); } bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_LONGLONG; } @@ -367,13 +382,13 @@ class sys_var_thd_bool :public sys_var_thd { public: my_bool SV::*offset; - sys_var_thd_bool(const char *name_arg, my_bool SV::*offset_arg) + sys_var_thd_bool(sys_var_chain *chain, const char *name_arg, my_bool SV::*offset_arg) :sys_var_thd(name_arg), offset(offset_arg) - {} - sys_var_thd_bool(const char *name_arg, my_bool SV::*offset_arg, + { chain_sys_var(chain); } + sys_var_thd_bool(sys_var_chain *chain, const char *name_arg, my_bool SV::*offset_arg, sys_after_update_func func) :sys_var_thd(name_arg,func), offset(offset_arg) - {} + { chain_sys_var(chain); } bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_MY_BOOL; } @@ -393,23 +408,23 @@ protected: TYPELIB *enum_names; sys_check_func check_func; public: - sys_var_thd_enum(const char *name_arg, ulong SV::*offset_arg, + sys_var_thd_enum(sys_var_chain *chain, const char *name_arg, ulong SV::*offset_arg, TYPELIB *typelib) :sys_var_thd(name_arg), offset(offset_arg), enum_names(typelib), check_func(0) - {} - sys_var_thd_enum(const char *name_arg, ulong SV::*offset_arg, + { chain_sys_var(chain); } + sys_var_thd_enum(sys_var_chain *chain, const char *name_arg, ulong SV::*offset_arg, TYPELIB *typelib, sys_after_update_func func) :sys_var_thd(name_arg,func), offset(offset_arg), enum_names(typelib), check_func(0) - {} - sys_var_thd_enum(const char *name_arg, ulong SV::*offset_arg, + { chain_sys_var(chain); } + sys_var_thd_enum(sys_var_chain *chain, const char *name_arg, ulong SV::*offset_arg, TYPELIB *typelib, sys_after_update_func func, sys_check_func check) :sys_var_thd(name_arg,func), offset(offset_arg), enum_names(typelib), check_func(check) - {} + { chain_sys_var(chain); } bool check(THD *thd, set_var *var) { int ret= 0; @@ -430,8 +445,9 @@ extern void fix_sql_mode_var(THD *thd, enum_var_type type); class sys_var_thd_sql_mode :public sys_var_thd_enum { public: - sys_var_thd_sql_mode(const char *name_arg, ulong SV::*offset_arg) - :sys_var_thd_enum(name_arg, offset_arg, &sql_mode_typelib, + sys_var_thd_sql_mode(sys_var_chain *chain, const char *name_arg, + ulong SV::*offset_arg) + :sys_var_thd_enum(chain, name_arg, offset_arg, &sql_mode_typelib, fix_sql_mode_var) {} bool check(THD *thd, set_var *var) @@ -448,11 +464,12 @@ public: class sys_var_thd_storage_engine :public sys_var_thd { protected: - handlerton *SV::*offset; + plugin_ref SV::*offset; public: - sys_var_thd_storage_engine(const char *name_arg, handlerton *SV::*offset_arg) + sys_var_thd_storage_engine(sys_var_chain *chain, const char *name_arg, + plugin_ref SV::*offset_arg) :sys_var_thd(name_arg), offset(offset_arg) - {} + { chain_sys_var(chain); } bool check(THD *thd, set_var *var); SHOW_TYPE show_type() { return SHOW_CHAR; } bool check_update_type(Item_result type) @@ -467,8 +484,9 @@ public: class sys_var_thd_table_type :public sys_var_thd_storage_engine { public: - sys_var_thd_table_type(const char *name_arg, handlerton *SV::*offset_arg) - :sys_var_thd_storage_engine(name_arg, offset_arg) + sys_var_thd_table_type(sys_var_chain *chain, const char *name_arg, + plugin_ref SV::*offset_arg) + :sys_var_thd_storage_engine(chain, name_arg, offset_arg) {} void warn_deprecated(THD *thd); void set_default(THD *thd, enum_var_type type); @@ -482,12 +500,12 @@ class sys_var_thd_bit :public sys_var_thd public: ulonglong bit_flag; bool reverse; - sys_var_thd_bit(const char *name_arg, + sys_var_thd_bit(sys_var_chain *chain, const char *name_arg, sys_check_func c_func, sys_update_func u_func, ulonglong bit, bool reverse_arg=0) :sys_var_thd(name_arg), check_func(c_func), update_func(u_func), bit_flag(bit), reverse(reverse_arg) - {} + { chain_sys_var(chain); } bool check(THD *thd, set_var *var); bool update(THD *thd, set_var *var); bool check_update_type(Item_result type) { return 0; } @@ -499,7 +517,9 @@ public: class sys_var_thd_dbug :public sys_var_thd { public: - sys_var_thd_dbug(const char *name_arg) :sys_var_thd(name_arg) {} + sys_var_thd_dbug(sys_var_chain *chain, const char *name_arg) + :sys_var_thd(name_arg) + { chain_sys_var(chain); } bool check_update_type(Item_result type) { return type != STRING_RESULT; } bool check(THD *thd, set_var *var); SHOW_TYPE show_type() { return SHOW_CHAR; } @@ -515,7 +535,9 @@ public: class sys_var_timestamp :public sys_var { public: - sys_var_timestamp(const char *name_arg) :sys_var(name_arg) {} + sys_var_timestamp(sys_var_chain *chain, const char *name_arg) + :sys_var(name_arg) + { chain_sys_var(chain); } bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } @@ -528,7 +550,9 @@ public: class sys_var_last_insert_id :public sys_var { public: - sys_var_last_insert_id(const char *name_arg) :sys_var(name_arg) {} + sys_var_last_insert_id(sys_var_chain *chain, const char *name_arg) + :sys_var(name_arg) + { chain_sys_var(chain); } bool update(THD *thd, set_var *var); bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } SHOW_TYPE show_type() { return SHOW_LONGLONG; } @@ -539,7 +563,9 @@ public: class sys_var_insert_id :public sys_var { public: - sys_var_insert_id(const char *name_arg) :sys_var(name_arg) {} + sys_var_insert_id(sys_var_chain *chain, const char *name_arg) + :sys_var(name_arg) + { chain_sys_var(chain); } bool update(THD *thd, set_var *var); bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } SHOW_TYPE show_type() { return SHOW_LONGLONG; } @@ -547,33 +573,12 @@ public: }; -#ifdef HAVE_REPLICATION -class sys_var_slave_skip_counter :public sys_var -{ -public: - sys_var_slave_skip_counter(const char *name_arg) :sys_var(name_arg) {} - bool check(THD *thd, set_var *var); - bool update(THD *thd, set_var *var); - bool check_type(enum_var_type type) { return type != OPT_GLOBAL; } - /* - We can't retrieve the value of this, so we don't have to define - show_type() or value_ptr() - */ -}; - -class sys_var_sync_binlog_period :public sys_var_long_ptr -{ -public: - sys_var_sync_binlog_period(const char *name_arg, ulong *value_ptr_arg) - :sys_var_long_ptr(name_arg,value_ptr_arg) {} - bool update(THD *thd, set_var *var); -}; -#endif - class sys_var_rand_seed1 :public sys_var { public: - sys_var_rand_seed1(const char *name_arg) :sys_var(name_arg) {} + sys_var_rand_seed1(sys_var_chain *chain, const char *name_arg) + :sys_var(name_arg) + { chain_sys_var(chain); } bool update(THD *thd, set_var *var); bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } }; @@ -581,7 +586,9 @@ public: class sys_var_rand_seed2 :public sys_var { public: - sys_var_rand_seed2(const char *name_arg) :sys_var(name_arg) {} + sys_var_rand_seed2(sys_var_chain *chain, const char *name_arg) + :sys_var(name_arg) + { chain_sys_var(chain); } bool update(THD *thd, set_var *var); bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } }; @@ -590,7 +597,8 @@ public: class sys_var_collation :public sys_var_thd { public: - sys_var_collation(const char *name_arg) :sys_var_thd(name_arg) + sys_var_collation(const char *name_arg) + :sys_var_thd(name_arg) { no_support_one_shot= 0; } @@ -608,10 +616,9 @@ class sys_var_character_set :public sys_var_thd { public: bool nullable; - sys_var_character_set(const char *name_arg) : - sys_var_thd(name_arg) + sys_var_character_set(const char *name_arg, bool is_nullable= 0) : + sys_var_thd(name_arg), nullable(is_nullable) { - nullable= 0; /* In fact only almost all variables derived from sys_var_character_set support ONE_SHOT; character_set_results doesn't. But that's good enough. @@ -631,83 +638,47 @@ public: virtual CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type)= 0; }; -class sys_var_character_set_filesystem :public sys_var_character_set -{ -public: - sys_var_character_set_filesystem(const char *name_arg) : - sys_var_character_set(name_arg) {} - void set_default(THD *thd, enum_var_type type); - CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); -}; - -class sys_var_character_set_client :public sys_var_character_set -{ -public: - sys_var_character_set_client(const char *name_arg) : - sys_var_character_set(name_arg) {} - void set_default(THD *thd, enum_var_type type); - CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); -}; -class sys_var_character_set_results :public sys_var_character_set +class sys_var_character_set_sv :public sys_var_character_set { + CHARSET_INFO **global_default; + CHARSET_INFO *SV::*offset; public: - sys_var_character_set_results(const char *name_arg) : - sys_var_character_set(name_arg) - { nullable= 1; } + sys_var_character_set_sv(sys_var_chain *chain, const char *name_arg, + CHARSET_INFO *SV::*offset_arg, + CHARSET_INFO **global_default_arg, + bool is_nullable= 0) + : sys_var_character_set(name_arg, is_nullable), + offset(offset_arg), global_default(global_default_arg) + { chain_sys_var(chain); } void set_default(THD *thd, enum_var_type type); CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); }; -class sys_var_character_set_server :public sys_var_character_set -{ -public: - sys_var_character_set_server(const char *name_arg) : - sys_var_character_set(name_arg) {} - void set_default(THD *thd, enum_var_type type); - CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); -}; class sys_var_character_set_database :public sys_var_character_set { public: - sys_var_character_set_database(const char *name_arg) : - sys_var_character_set(name_arg) {} + sys_var_character_set_database(sys_var_chain *chain, const char *name_arg) : + sys_var_character_set(name_arg) + { chain_sys_var(chain); } void set_default(THD *thd, enum_var_type type); CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); }; -class sys_var_character_set_connection :public sys_var_character_set +class sys_var_collation_sv :public sys_var_collation { + CHARSET_INFO **global_default; + CHARSET_INFO *SV::*offset; public: - sys_var_character_set_connection(const char *name_arg) : - sys_var_character_set(name_arg) {} - void set_default(THD *thd, enum_var_type type); - CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); -}; - -class sys_var_collation_connection :public sys_var_collation -{ -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, LEX_STRING *base); -}; - -class sys_var_collation_server :public sys_var_collation -{ -public: - sys_var_collation_server(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, LEX_STRING *base); -}; - -class sys_var_collation_database :public sys_var_collation -{ -public: - sys_var_collation_database(const char *name_arg) :sys_var_collation(name_arg) {} + sys_var_collation_sv(sys_var_chain *chain, const char *name_arg, + CHARSET_INFO *SV::*offset_arg, + CHARSET_INFO **global_default_arg) + :sys_var_collation(name_arg), + offset(offset_arg), global_default(global_default_arg) + { + chain_sys_var(chain); + } 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, LEX_STRING *base); @@ -719,9 +690,10 @@ class sys_var_key_cache_param :public sys_var protected: size_t offset; public: - sys_var_key_cache_param(const char *name_arg, size_t offset_arg) + sys_var_key_cache_param(sys_var_chain *chain, const char *name_arg, + size_t offset_arg) :sys_var(name_arg), offset(offset_arg) - {} + { chain_sys_var(chain); } 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; } @@ -731,8 +703,9 @@ public: class sys_var_key_buffer_size :public sys_var_key_cache_param { public: - sys_var_key_buffer_size(const char *name_arg) - :sys_var_key_cache_param(name_arg, offsetof(KEY_CACHE, param_buff_size)) + sys_var_key_buffer_size(sys_var_chain *chain, const char *name_arg) + :sys_var_key_cache_param(chain, name_arg, + offsetof(KEY_CACHE, param_buff_size)) {} bool update(THD *thd, set_var *var); SHOW_TYPE show_type() { return SHOW_LONGLONG; } @@ -742,8 +715,8 @@ public: class sys_var_key_cache_long :public sys_var_key_cache_param { public: - sys_var_key_cache_long(const char *name_arg, size_t offset_arg) - :sys_var_key_cache_param(name_arg, offset_arg) + sys_var_key_cache_long(sys_var_chain *chain, const char *name_arg, size_t offset_arg) + :sys_var_key_cache_param(chain, name_arg, offset_arg) {} bool update(THD *thd, set_var *var); SHOW_TYPE show_type() { return SHOW_LONG; } @@ -755,12 +728,12 @@ class sys_var_thd_date_time_format :public sys_var_thd DATE_TIME_FORMAT *SV::*offset; timestamp_type date_time_type; public: - sys_var_thd_date_time_format(const char *name_arg, + sys_var_thd_date_time_format(sys_var_chain *chain, const char *name_arg, DATE_TIME_FORMAT *SV::*offset_arg, timestamp_type date_time_type_arg) :sys_var_thd(name_arg), offset(offset_arg), date_time_type(date_time_type_arg) - {} + { chain_sys_var(chain); } SHOW_TYPE show_type() { return SHOW_CHAR; } bool check_update_type(Item_result type) { @@ -779,8 +752,9 @@ class sys_var_log_state :public sys_var_bool_ptr { uint log_type; public: - sys_var_log_state(const char *name_arg, my_bool *value_arg, uint log_type_arg) - :sys_var_bool_ptr(name_arg, value_arg), log_type(log_type_arg) {} + sys_var_log_state(sys_var_chain *chain, const char *name_arg, my_bool *value_arg, + uint log_type_arg) + :sys_var_bool_ptr(chain, name_arg, value_arg), log_type(log_type_arg) {} bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); }; @@ -791,10 +765,10 @@ class sys_var_log_output :public sys_var ulong *value; TYPELIB *enum_names; public: - sys_var_log_output(const char *name_arg, ulong *value_arg, + sys_var_log_output(sys_var_chain *chain, const char *name_arg, ulong *value_arg, TYPELIB *typelib, sys_after_update_func func) :sys_var(name_arg,func), value(value_arg), enum_names(typelib) - {} + { chain_sys_var(chain); } bool check(THD *thd, set_var *var) { return check_set(thd, var, enum_names); @@ -815,12 +789,12 @@ public: enum_var_type var_type; SHOW_TYPE show_type_value; sys_value_ptr_func value_ptr_func; - sys_var_readonly(const char *name_arg, enum_var_type type, + sys_var_readonly(sys_var_chain *chain, const char *name_arg, enum_var_type type, SHOW_TYPE show_type_arg, sys_value_ptr_func value_ptr_func_arg) :sys_var(name_arg), var_type(type), show_type_value(show_type_arg), value_ptr_func(value_ptr_func_arg) - {} + { chain_sys_var(chain); } bool update(THD *thd, set_var *var) { return 1; } bool check_default(enum_var_type type) { return 1; } bool check_type(enum_var_type type) { return type != var_type; } @@ -834,19 +808,17 @@ public: }; -class sys_var_have_variable: public sys_var +class sys_var_have_option: public sys_var { - SHOW_COMP_OPTION *have_variable; - +protected: + virtual SHOW_COMP_OPTION get_option() = 0; public: - sys_var_have_variable(const char *variable_name, - SHOW_COMP_OPTION *have_variable_arg): - sys_var(variable_name), - have_variable(have_variable_arg) - { } + sys_var_have_option(sys_var_chain *chain, const char *variable_name): + sys_var(variable_name) + { chain_sys_var(chain); } byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - return (byte*) show_comp_option_name[*have_variable]; + return (byte*) show_comp_option_name[get_option()]; } bool update(THD *thd, set_var *var) { return 1; } bool check_default(enum_var_type type) { return 1; } @@ -857,13 +829,47 @@ public: }; +class sys_var_have_variable: public sys_var_have_option +{ + SHOW_COMP_OPTION *have_variable; + +public: + sys_var_have_variable(sys_var_chain *chain, const char *variable_name, + SHOW_COMP_OPTION *have_variable_arg): + sys_var_have_option(chain, variable_name), + have_variable(have_variable_arg) + { } + SHOW_COMP_OPTION get_option() { return *have_variable; } +}; + + +class sys_var_have_plugin: public sys_var_have_option +{ + const char *plugin_name_str; + const uint plugin_name_len; + const int plugin_type; + +public: + sys_var_have_plugin(sys_var_chain *chain, const char *variable_name, + const char *plugin_name_str_arg, uint plugin_name_len_arg, + int plugin_type_arg): + sys_var_have_option(chain, variable_name), + plugin_name_str(plugin_name_str_arg), plugin_name_len(plugin_name_len_arg), + plugin_type(plugin_type_arg) + { } + /* the following method is declared in sql_plugin.cc */ + SHOW_COMP_OPTION get_option(); +}; + + class sys_var_thd_time_zone :public sys_var_thd { public: - sys_var_thd_time_zone(const char *name_arg): + sys_var_thd_time_zone(sys_var_chain *chain, const char *name_arg): sys_var_thd(name_arg) { no_support_one_shot= 0; + chain_sys_var(chain); } bool check(THD *thd, set_var *var); SHOW_TYPE show_type() { return SHOW_CHAR; } @@ -881,8 +887,9 @@ public: class sys_var_max_user_conn : public sys_var_thd { public: - sys_var_max_user_conn(const char *name_arg): - sys_var_thd(name_arg) {} + sys_var_max_user_conn(sys_var_chain *chain, const char *name_arg): + sys_var_thd(name_arg) + { chain_sys_var(chain); } bool check(THD *thd, set_var *var); bool update(THD *thd, set_var *var); bool check_default(enum_var_type type) @@ -898,8 +905,9 @@ class sys_var_trust_routine_creators :public sys_var_bool_ptr { /* We need a derived class only to have a warn_deprecated() */ public: - sys_var_trust_routine_creators(const char *name_arg, my_bool *value_arg) : - sys_var_bool_ptr(name_arg, value_arg) {}; + sys_var_trust_routine_creators(sys_var_chain *chain, const char *name_arg, + my_bool *value_arg) : + sys_var_bool_ptr(chain, name_arg, value_arg) {}; void warn_deprecated(THD *thd); void set_default(THD *thd, enum_var_type type); bool update(THD *thd, set_var *var); @@ -913,8 +921,9 @@ public: class sys_var_opt_readonly :public sys_var_bool_ptr { public: - sys_var_opt_readonly(const char *name_arg, my_bool *value_arg) : - sys_var_bool_ptr(name_arg, value_arg) {}; + sys_var_opt_readonly(sys_var_chain *chain, const char *name_arg, + my_bool *value_arg) : + sys_var_bool_ptr(chain, name_arg, value_arg) {}; ~sys_var_opt_readonly() {}; bool update(THD *thd, set_var *var); }; @@ -923,12 +932,13 @@ public: class sys_var_thd_lc_time_names :public sys_var_thd { public: - sys_var_thd_lc_time_names(const char *name_arg): - sys_var_thd(name_arg) + sys_var_thd_lc_time_names(sys_var_chain *chain, const char *name_arg): + sys_var_thd(name_arg) { #if MYSQL_VERSION_ID < 50000 no_support_one_shot= 0; #endif + chain_sys_var(chain); } bool check(THD *thd, set_var *var); SHOW_TYPE show_type() { return SHOW_CHAR; } @@ -947,8 +957,8 @@ class sys_var_event_scheduler :public sys_var_long_ptr { /* We need a derived class only to have a warn_deprecated() */ public: - sys_var_event_scheduler(const char *name_arg) : - sys_var_long_ptr(name_arg, NULL, NULL) {}; + sys_var_event_scheduler(sys_var_chain *chain, const char *name_arg) : + sys_var_long_ptr(chain, name_arg, NULL, NULL) {}; bool update(THD *thd, set_var *var); byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); SHOW_TYPE show_type() { return SHOW_CHAR; } @@ -964,8 +974,9 @@ extern void fix_binlog_format_after_update(THD *thd, enum_var_type type); class sys_var_thd_binlog_format :public sys_var_thd_enum { public: - sys_var_thd_binlog_format(const char *name_arg, ulong SV::*offset_arg) - :sys_var_thd_enum(name_arg, offset_arg, + sys_var_thd_binlog_format(sys_var_chain *chain, const char *name_arg, + ulong SV::*offset_arg) + :sys_var_thd_enum(chain, name_arg, offset_arg, &binlog_format_typelib , fix_binlog_format_after_update ) @@ -1003,7 +1014,7 @@ public: CHARSET_INFO *charset; ulong ulong_value; ulonglong ulonglong_value; - handlerton *hton; + plugin_ref plugin; DATE_TIME_FORMAT *date_time_format; Time_zone *time_zone; MY_LOCALE *locale_value; @@ -1132,9 +1143,13 @@ struct sys_var_with_base Prototypes for helper functions */ -void set_var_init(); +int set_var_init(); void set_var_free(); -sys_var *find_sys_var(const char *str, uint length=0); +int mysql_append_static_vars(const SHOW_VAR *show_vars, uint count); +SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted); +int mysql_add_sys_var_chain(sys_var *chain, struct my_option *long_options); +int mysql_del_sys_var_chain(sys_var *chain); +sys_var *find_sys_var(THD *thd, const char *str, uint length=0); int sql_set_variables(THD *thd, List<set_var_base> *var_list); bool not_all_support_one_shot(List<set_var_base> *var_list); void fix_delay_key_write(THD *thd, enum_var_type type); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 15d616bdd4f..131e7c66557 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1596,7 +1596,7 @@ void close_temporary_table(THD *thd, TABLE *table, void close_temporary(TABLE *table, bool free_share, bool delete_table) { - handlerton *table_type= table->s->db_type; + handlerton *table_type= table->s->db_type(); DBUG_ENTER("close_temporary"); free_io_cache(table); @@ -6186,7 +6186,7 @@ my_bool mysql_rm_tmp_tables(void) init_tmp_table_share(&share, "", 0, "", filePathCopy); if (!open_table_def(thd, &share, 0) && ((handler_file= get_new_handler(&share, thd->mem_root, - share.db_type)))) + share.db_type())))) { handler_file->delete_table(filePathCopy); delete handler_file; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 8c0cb72e1f4..1f6a84462ae 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -2384,7 +2384,12 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used, tables_used->engine_data)) DBUG_RETURN(0); - if (tables_used->table->s->db_type->db_type == DB_TYPE_MRG_MYISAM) +#ifdef WITH_MYISAMMRG_STORAGE_ENGINE + /* + XXX FIXME: Some generic mechanism is required here instead of this + MYISAMMRG-specific implementation. + */ + if (tables_used->table->s->db_type()->db_type == DB_TYPE_MRG_MYISAM) { ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file; MYRG_INFO *file = handler->myrg_info(); @@ -2407,6 +2412,7 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used, DBUG_RETURN(0); } } +#endif } } DBUG_RETURN(n - counter); @@ -2983,7 +2989,7 @@ static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used, DBUG_PRINT("qcache", ("table: %s db: %s type: %u", tables_used->table->s->table_name.str, tables_used->table->s->db.str, - tables_used->table->s->db_type->db_type)); + tables_used->table->s->db_type()->db_type)); if (tables_used->derived) { table_count--; @@ -3008,12 +3014,18 @@ static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used, "other non-cacheable table(s)")); DBUG_RETURN(0); } - if (tables_used->table->s->db_type->db_type == DB_TYPE_MRG_MYISAM) +#ifdef WITH_MYISAMMRG_STORAGE_ENGINE + /* + XXX FIXME: Some generic mechanism is required here instead of this + MYISAMMRG-specific implementation. + */ + if (tables_used->table->s->db_type()->db_type == DB_TYPE_MRG_MYISAM) { ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file; MYRG_INFO *file = handler->myrg_info(); table_count+= (file->end_table - file->open_tables); } +#endif } } DBUG_RETURN(table_count); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 039fd71d670..eab6fea9558 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -167,15 +167,15 @@ Open_tables_state::Open_tables_state(ulong version_arg) reset_open_tables_state(); } -my_bool thd_in_lock_tables(const THD *thd) +int thd_in_lock_tables(const THD *thd) { - return thd->in_lock_tables; + return test(thd->in_lock_tables); } -my_bool thd_tablespace_op(const THD *thd) +int thd_tablespace_op(const THD *thd) { - return thd->tablespace_op; + return test(thd->tablespace_op); } @@ -191,6 +191,82 @@ void **thd_ha_data(const THD *thd, const struct handlerton *hton) return (void **) thd->ha_data + hton->slot; } +long long thd_test_options(const THD *thd, long long test_options) +{ + return thd->options & test_options; +} + +int thd_sql_command(const THD *thd) +{ + return (int) thd->lex->sql_command; +} + + +/* + Dumps a text description of a thread, its security context + (user, host) and the current query. + + SYNOPSIS + thd_security_context() + thd current thread context + buffer pointer to preferred result buffer + length length of buffer + max_query_len how many chars of query to copy (0 for all) + + RETURN VALUES + pointer to string +*/ +char *thd_security_context(THD *thd, char *buffer, int length, + int max_query_len) +{ + String str(buffer, length, &my_charset_latin1); + const Security_context *sctx= &thd->main_security_ctx; + char header[64]; + int len; + + len= my_snprintf(header, sizeof(header), + "MySQL thread id %lu, query id %lu", + thd->thread_id, (ulong) thd->query_id); + str.length(0); + str.append(header, len); + + if (sctx->host) + { + str.append(' '); + str.append(sctx->host); + } + + if (sctx->ip) + { + str.append(' '); + str.append(sctx->ip); + } + + if (sctx->user) + { + str.append(' '); + str.append(sctx->user); + } + + if (thd->proc_info) + { + str.append(' '); + str.append(thd->proc_info); + } + + if (thd->query) + { + if (max_query_len < 1) + len= thd->query_length; + else + len= min(thd->query_length, max_query_len); + str.append('\n'); + str.append(thd->query, len); + } + if (str.c_ptr_safe() == buffer) + return buffer; + return thd->strmake(str.ptr(), str.length()); +} /* Pass nominal parameters to Statement constructor only to ensure that @@ -320,6 +396,7 @@ void THD::init(void) { pthread_mutex_lock(&LOCK_global_system_variables); variables= global_system_variables; + plugin_thdvar_init(this, false); variables.time_format= date_time_format_copy((THD*) 0, variables.time_format); variables.date_format= date_time_format_copy((THD*) 0, @@ -465,6 +542,7 @@ THD::~THD() cleanup(); ha_close_connection(this); + plugin_thdvar_cleanup(this); DBUG_PRINT("info", ("freeing security context")); main_security_ctx.destroy(); @@ -1682,7 +1760,7 @@ Statement::Statement(enum enum_state state_arg, ulong id_arg, :Query_arena(&main_mem_root, state_arg), id(id_arg), mark_used_columns(MARK_COLUMNS_READ), - lex(&main_lex), + main_lex(), lex(&main_lex), query(0), query_length(0), cursor(0) diff --git a/sql/sql_class.h b/sql/sql_class.h index 1f5f7aedbb4..08b5c772c8a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -180,6 +180,20 @@ class Time_zone; struct system_variables { + /* + How dynamically allocated system variables are handled: + + The global_system_variables and max_system_variables are "authoritative" + They both should have the same 'version' and 'size'. + When attempting to access a dynamic variable, if the session version + is out of date, then the session version is updated and realloced if + neccessary and bytes copied from global to make up for missing data. + */ + ulong dynamic_variables_version; + char* dynamic_variables_ptr; + uint dynamic_variables_head; /* largest valid variable offset */ + uint dynamic_variables_size; /* how many bytes are in use */ + ulonglong myisam_max_extra_sort_file_size; ulonglong myisam_max_sort_file_size; ulonglong max_heap_table_size; @@ -245,8 +259,6 @@ struct system_variables my_bool new_mode; my_bool query_cache_wlock_invalidate; my_bool engine_condition_pushdown; - my_bool innodb_table_locks; - my_bool innodb_support_xa; my_bool ndb_force_send; my_bool ndb_use_copying_alter_table; my_bool ndb_use_exact_count; @@ -256,7 +268,7 @@ struct system_variables my_bool old_alter_table; my_bool old_passwords; - handlerton *table_type; + plugin_ref table_plugin; /* Only charset part of these variables is sensible */ CHARSET_INFO *character_set_filesystem; diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 09ee4962235..41b4c1b8e31 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -966,6 +966,7 @@ bool login_connection(THD *thd) void end_connection(THD *thd) { NET *net= &thd->net; + plugin_thdvar_cleanup(thd); if (thd->user_connect) decrease_user_connections(thd->user_connect); if (net->error && net->vio != 0 && net->report_error) @@ -1003,6 +1004,8 @@ void prepare_new_connection_state(THD* thd) if (thd->client_capabilities & CLIENT_COMPRESS) thd->net.compress=1; // Use compression + plugin_thdvar_init(thd, true); + thd->version= refresh_version; thd->proc_info= 0; thd->command= COM_SLEEP; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index ea8c0e2d83e..2ce1486e278 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -868,7 +868,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) /* If it is a temporary table, close and regenerate it */ if (!dont_send_ok && (table= find_temporary_table(thd, table_list))) { - handlerton *table_type= table->s->db_type; + handlerton *table_type= table->s->db_type(); TABLE_SHARE *share= table->s; if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE)) goto trunc_by_del; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 6f4cdbba3dd..f63aaf2d0fc 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3232,7 +3232,7 @@ void select_create::abort() { table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); - handlerton *table_type=table->s->db_type; + handlerton *table_type=table->s->db_type(); if (!table->s->tmp_table) { ulong version= table->s->version; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index af2929b6268..1c78aada405 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -172,6 +172,7 @@ void lex_start(THD *thd, const uchar *buf, uint length) lex->spcont= NULL; lex->proc_list.first= 0; lex->escape_used= FALSE; + lex->query_tables= 0; lex->reset_query_tables_list(FALSE); lex->expr_allows_subselect= TRUE; @@ -211,6 +212,12 @@ void lex_end(LEX *lex) lex->yacc_yyss= 0; lex->yacc_yyvs= 0; } + + /* release used plugins */ + plugin_unlock_list(0, (plugin_ref*)lex->plugins.buffer, + lex->plugins.elements); + reset_dynamic(&lex->plugins); + DBUG_VOID_RETURN; } @@ -1673,6 +1680,17 @@ void st_select_lex::print_limit(THD *thd, String *str) void Query_tables_list::reset_query_tables_list(bool init) { + if (!init && query_tables) + { + TABLE_LIST *table= query_tables; + for (;;) + { + delete table->view; + if (query_tables_last == &table->next_global || + !(table= table->next_global)) + break; + } + } query_tables= 0; query_tables_last= &query_tables; query_tables_own_last= 0; @@ -1727,6 +1745,10 @@ st_lex::st_lex() :result(0), yacc_yyss(0), yacc_yyvs(0), sql_command(SQLCOM_END) { + my_init_dynamic_array2(&plugins, sizeof(plugin_ref), + plugins_static_buffer, + INITIAL_LEX_PLUGIN_LIST_SIZE, + INITIAL_LEX_PLUGIN_LIST_SIZE); reset_query_tables_list(TRUE); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 821af3f946d..415745eb2aa 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -952,6 +952,11 @@ typedef struct st_lex : public Query_tables_list XID *xid; gptr yacc_yyss,yacc_yyvs; THD *thd; + + /* maintain a list of used plugins for this LEX */ + DYNAMIC_ARRAY plugins; + plugin_ref plugins_static_buffer[INITIAL_LEX_PLUGIN_LIST_SIZE]; + CHARSET_INFO *charset, *underscore_charset; /* store original leaf_tables for INSERT SELECT and PS/SP */ TABLE_LIST *leaf_tables_insert; @@ -1155,6 +1160,8 @@ typedef struct st_lex : public Query_tables_list virtual ~st_lex() { destroy_query_tables_list(); + plugin_unlock_list(NULL, (plugin_ref *)plugins.buffer, plugins.elements); + delete_dynamic(&plugins); } inline void uncacheable(uint8 cause) diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index dbac53ed5f6..cb16a5fbcfd 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -784,9 +784,9 @@ static bool handle_list_of_fields(List_iterator<char> it, } else { - if (table->s->db_type->partition_flags && - (table->s->db_type->partition_flags() & HA_USE_AUTO_PARTITION) && - (table->s->db_type->partition_flags() & HA_CAN_PARTITION)) + if (table->s->db_type()->partition_flags && + (table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION) && + (table->s->db_type()->partition_flags() & HA_CAN_PARTITION)) { /* This engine can handle automatic partitioning and there is no @@ -1664,8 +1664,8 @@ bool fix_partition_func(THD *thd, TABLE *table, goto end; if (unlikely(check_primary_key(table))) goto end; - if (unlikely((!(table->s->db_type->partition_flags && - (table->s->db_type->partition_flags() & HA_CAN_PARTITION_UNIQUE))) && + if (unlikely((!(table->s->db_type()->partition_flags && + (table->s->db_type()->partition_flags() & HA_CAN_PARTITION_UNIQUE))) && check_unique_keys(table))) goto end; if (unlikely(set_up_partition_bitmap(thd, part_info))) @@ -1872,7 +1872,7 @@ static int add_keyword_int(File fptr, const char *keyword, longlong num) static int add_engine(File fptr, handlerton *engine_type) { - const char *engine_str= hton2plugin[engine_type->slot]->name.str; + const char *engine_str= ha_resolve_storage_engine_name(engine_type); DBUG_PRINT("info", ("ENGINE: %s", engine_str)); int err= add_string(fptr, "ENGINE = "); return err + add_string(fptr, engine_str); @@ -2185,8 +2185,8 @@ bool partition_key_modified(TABLE *table, const MY_BITMAP *fields) if (!part_info) DBUG_RETURN(FALSE); - if (table->s->db_type->partition_flags && - (table->s->db_type->partition_flags() & HA_CAN_UPDATE_PARTITION_KEY)) + if (table->s->db_type()->partition_flags && + (table->s->db_type()->partition_flags() & HA_CAN_UPDATE_PARTITION_KEY)) DBUG_RETURN(FALSE); for (fld= part_info->full_part_field_array; *fld; fld++) if (bitmap_is_set(fields, (*fld)->field_index)) @@ -4201,8 +4201,8 @@ uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info, alter_info->no_parts= curr_part_no - new_part_no; } } - if (table->s->db_type->alter_table_flags && - (!(flags= table->s->db_type->alter_table_flags(alter_info->flags)))) + if (table->s->db_type()->alter_table_flags && + (!(flags= table->s->db_type()->alter_table_flags(alter_info->flags)))) { my_error(ER_PARTITION_FUNCTION_FAILURE, MYF(0)); DBUG_RETURN(1); @@ -4948,7 +4948,7 @@ the generated partition syntax in a correct manner. create_info->db_type= table->part_info->default_engine_type; } DBUG_PRINT("info", ("New engine type: %s", - hton2plugin[create_info->db_type->slot]->name.str)); + ha_resolve_storage_engine_name(create_info->db_type))); thd->work_part_info= NULL; *partition_changed= TRUE; } diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index e3e24c1f375..06f687e779f 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -15,11 +15,21 @@ #include "mysql_priv.h" #include <my_pthread.h> +#include <my_getopt.h> #define REPORT_TO_LOG 1 #define REPORT_TO_USER 2 +#ifdef DBUG_OFF +#define plugin_ref_to_int(A) A +#define plugin_int_to_ref(A) A +#else +#define plugin_ref_to_int(A) (A ? A[0] : NULL) +#define plugin_int_to_ref(A) &(A) +#endif + extern struct st_mysql_plugin *mysqld_builtins[]; +char *opt_plugin_load= NULL; char *opt_plugin_dir_ptr; char opt_plugin_dir[FN_REFLEN]; /* @@ -85,25 +95,207 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= static DYNAMIC_ARRAY plugin_dl_array; static DYNAMIC_ARRAY plugin_array; static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM]; -static rw_lock_t THR_LOCK_plugin; +/* we are always manipulating ref count, so a rwlock is unneccessary */ +static pthread_mutex_t LOCK_plugin; static bool initialized= 0; +static bool reap_needed= false; static int plugin_array_version=0; + +/* + write-lock on LOCK_system_variables_hash is required before modifying + the following variables/structures +*/ +static MEM_ROOT plugin_mem_root; +static uint global_variables_dynamic_size= 0; +static HASH bookmark_hash; + + +/* + hidden part of opaque value passed to variable check functions. + Used to provide a object-like structure to non C++ consumers. +*/ +struct st_item_value_holder : public st_mysql_value +{ + Item *item; +}; + + +/* + stored in bookmark_hash, this structure is never removed from the + hash and is used to mark a single offset for a thd local variable + even if plugins have been uninstalled and reinstalled, repeatedly. + This structure is allocated from plugin_mem_root. +*/ +struct st_bookmark +{ + char *name; + uint name_len; + int offset; + uint version; +}; + + +/* + skeleton of a plugin variable - portion of structure common to all. +*/ +struct st_mysql_sys_var +{ + MYSQL_PLUGIN_VAR_HEADER; +}; + + +/* + sys_var class for access to all plugin variables visible to the user +*/ +class sys_var_pluginvar: public sys_var +{ +public: + struct st_plugin_int *plugin; + struct st_mysql_sys_var *plugin_var; + + static void *operator new(size_t size, MEM_ROOT *mem_root) + { return (void*) alloc_root(mem_root, (uint) size); } + static void operator delete(void *ptr_arg,size_t size) + { TRASH(ptr_arg, size); } + + sys_var_pluginvar(const char *name_arg, + struct st_plugin_int *plugin_arg, + struct st_mysql_sys_var *plugin_var_arg) + :sys_var(name_arg), plugin(plugin_arg), plugin_var(plugin_var_arg) {} + sys_var_pluginvar *cast_pluginvar() { return this; } + bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; } + bool check_type(enum_var_type type) + { return !(plugin_var->flags & PLUGIN_VAR_THDLOCAL) && type != OPT_GLOBAL; } + bool check_update_type(Item_result type); + SHOW_TYPE show_type(); + byte* real_value_ptr(THD *thd, enum_var_type type); + TYPELIB* plugin_var_typelib(void); + byte* value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + bool check(THD *thd, set_var *var); + void set_default(THD *thd, enum_var_type type); + bool update(THD *thd, set_var *var); +}; + + /* prototypes */ -my_bool plugin_register_builtin(struct st_mysql_plugin *plugin); -void plugin_load(void); +static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv); +static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, + const char *list); +static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, + int *argc, char **argv, my_bool default_enabled); +static bool register_builtin(struct st_mysql_plugin *plugin, + struct st_plugin_int *tmp, + struct st_plugin_int **ptr); +static void cleanup_variables(THD *thd, struct system_variables *vars, + bool free_memory); +static void plugin_opt_set_limits(struct my_option *options, + const struct st_mysql_sys_var *opt); +#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B CALLER_INFO) +#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B ORIG_CALLER_INFO) +static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin + CALLER_INFO_PROTO); +static void intern_plugin_unlock(LEX *lex, plugin_ref plugin); +static void reap_plugins(void); + + +/* declared in set_var.cc */ +extern sys_var *intern_find_sys_var(const char *str, uint length, bool no_error); + + +/**************************************************************************** + Value type thunks, allows the C world to play in the C++ world +****************************************************************************/ + +static int item_value_type(struct st_mysql_value *value) +{ + switch (((st_item_value_holder*)value)->item->result_type()) { + case INT_RESULT: + return MYSQL_VALUE_TYPE_INT; + case REAL_RESULT: + return MYSQL_VALUE_TYPE_REAL; + default: + return MYSQL_VALUE_TYPE_STRING; + } +} + +static const char *item_val_str(struct st_mysql_value *value, + char *buffer, int *length) +{ + String str(buffer, *length, system_charset_info), *res; + if (!(res= ((st_item_value_holder*)value)->item->val_str(&str))) + return NULL; + *length= res->length(); + if (res->c_ptr_quick() == buffer) + return buffer; + + /* + Lets be nice and create a temporary string since the + buffer was too small + */ + return current_thd->strmake(res->c_ptr_quick(), res->length()); +} + + +static int item_val_int(struct st_mysql_value *value, void *buf, int intsize) +{ + Item *item= ((st_item_value_holder*)value)->item; + switch (intsize) { + case 1: + *(char*)buf= item->val_int(); + break; + case 2: + *(short*)buf= item->val_int(); + break; + case 4: + *(int*)buf= item->val_int(); + break; + case 8: + *(longlong*)buf= item->val_int(); + break; + default: + return -1; + } + if (item->is_null()) + return 1; + return 0; +} + + +static int item_val_real(struct st_mysql_value *value, void *buf, int realsize) +{ + Item *item= ((st_item_value_holder*)value)->item; + switch (realsize) { + case 8: + *(double*)buf= item->val_real(); + break; + case 4: + *(float*)buf= item->val_real(); + break; + default: + return -1; + } + if (item->is_null()) + return 1; + return 0; +} + + +/**************************************************************************** + Plugin support code +****************************************************************************/ #ifdef HAVE_DLOPEN static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl) { uint i; + struct st_plugin_dl *tmp; DBUG_ENTER("plugin_dl_find"); for (i= 0; i < plugin_dl_array.elements; i++) { - struct st_plugin_dl *tmp= dynamic_element(&plugin_dl_array, i, - struct st_plugin_dl *); + tmp= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *); if (tmp->ref_count && ! my_strnncoll(files_charset_info, (const uchar *)dl->str, dl->length, @@ -117,11 +309,11 @@ static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl) static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl) { uint i; + struct st_plugin_dl *tmp; DBUG_ENTER("plugin_dl_insert_or_reuse"); for (i= 0; i < plugin_dl_array.elements; i++) { - struct st_plugin_dl *tmp= dynamic_element(&plugin_dl_array, i, - struct st_plugin_dl *); + tmp= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *); if (! tmp->ref_count) { memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl)); @@ -147,6 +339,7 @@ static inline void free_plugin_mem(struct st_plugin_dl *p) my_free((gptr)p->plugins, MYF(MY_ALLOW_ZERO_PTR)); } + static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) { #ifdef HAVE_DLOPEN @@ -334,6 +527,9 @@ static void plugin_dl_del(const LEX_STRING *dl) #ifdef HAVE_DLOPEN uint i; DBUG_ENTER("plugin_dl_del"); + + safe_mutex_assert_owner(&LOCK_plugin); + for (i= 0; i < plugin_dl_array.elements; i++) { struct st_plugin_dl *tmp= dynamic_element(&plugin_dl_array, i, @@ -363,6 +559,9 @@ static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int ty DBUG_ENTER("plugin_find_internal"); if (! initialized) DBUG_RETURN(0); + + safe_mutex_assert_owner(&LOCK_plugin); + if (type == MYSQL_ANY_PLUGIN) { for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++) @@ -380,33 +579,105 @@ static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int ty } -my_bool plugin_is_ready(const LEX_STRING *name, int type) +static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type) { - my_bool rc= FALSE; + SHOW_COMP_OPTION rc= SHOW_OPTION_NO; struct st_plugin_int *plugin; DBUG_ENTER("plugin_is_ready"); - rw_rdlock(&THR_LOCK_plugin); - if ((plugin= plugin_find_internal(name, type)) && - plugin->state == PLUGIN_IS_READY) - rc= TRUE; - rw_unlock(&THR_LOCK_plugin); + pthread_mutex_lock(&LOCK_plugin); + if ((plugin= plugin_find_internal(name, type))) + { + rc= SHOW_OPTION_DISABLED; + if (plugin->state == PLUGIN_IS_READY) + rc= SHOW_OPTION_YES; + } + pthread_mutex_unlock(&LOCK_plugin); DBUG_RETURN(rc); } -struct st_plugin_int *plugin_lock(const LEX_STRING *name, int type) +bool plugin_is_ready(const LEX_STRING *name, int type) { - struct st_plugin_int *rc; - DBUG_ENTER("plugin_lock"); - rw_wrlock(&THR_LOCK_plugin); - if ((rc= plugin_find_internal(name, type))) + bool rc= FALSE; + if (plugin_status(name, type) == SHOW_OPTION_YES) + rc= TRUE; + return rc; +} + + +SHOW_COMP_OPTION sys_var_have_plugin::get_option() +{ + LEX_STRING plugin_name= { (char *) plugin_name_str, plugin_name_len }; + return plugin_status(&plugin_name, plugin_type); +} + + +static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO) +{ + st_plugin_int *pi= plugin_ref_to_int(rc); + DBUG_ENTER("intern_plugin_lock"); + + safe_mutex_assert_owner(&LOCK_plugin); + + if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED)) { - if (rc->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED)) - rc->ref_count++; - else - rc= 0; + plugin_ref plugin; +#ifdef DBUG_OFF + /* built-in plugins don't need ref counting */ + if (!pi->plugin_dl) + DBUG_RETURN(pi); + + plugin= pi; +#else + if (!(plugin= (plugin_ref) my_malloc_ci(sizeof(pi), MYF(MY_WME)))) + DBUG_RETURN(NULL); + //if (0x4620a20L == (long) plugin) + if (0x4656b10L == (long) plugin) + { + DBUG_PRINT("debug",("trap")); + } + + *plugin= pi; +#endif + pi->ref_count++; + DBUG_PRINT("info",("thd: 0x%lx, plugin: \"%s\", ref_count: %d", + (long) current_thd, pi->name.str, pi->ref_count)); + + if (lex) + insert_dynamic(&lex->plugins, (gptr)&plugin); + DBUG_RETURN(plugin); } - rw_unlock(&THR_LOCK_plugin); + DBUG_RETURN(NULL); +} + + +plugin_ref plugin_lock(THD *thd, plugin_ref *ptr CALLER_INFO_PROTO) +{ + LEX *lex= NULL; + plugin_ref rc; + DBUG_ENTER("plugin_lock"); + if (thd) + lex= !thd->lex ? &thd->main_lex : thd->lex; + pthread_mutex_lock(&LOCK_plugin); + rc= my_intern_plugin_lock_ci(lex, *ptr); + pthread_mutex_unlock(&LOCK_plugin); + DBUG_RETURN(rc); +} + + +plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, int type + CALLER_INFO_PROTO) +{ + LEX *lex= NULL; + plugin_ref rc= NULL; + st_plugin_int *plugin; + DBUG_ENTER("plugin_lock"); + if (thd) + lex= !thd->lex ? &thd->main_lex : thd->lex; + pthread_mutex_lock(&LOCK_plugin); + if ((plugin= plugin_find_internal(name, type))) + rc= my_intern_plugin_lock_ci(lex, plugin_int_to_ref(plugin)); + pthread_mutex_unlock(&LOCK_plugin); DBUG_RETURN(rc); } @@ -431,7 +702,14 @@ static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin) struct st_plugin_int *)); } -static my_bool plugin_add(const LEX_STRING *name, const LEX_STRING *dl, int report) + +/* + NOTE + Requires that a write-lock is held on LOCK_system_variables_hash +*/ +static bool plugin_add(MEM_ROOT *tmp_root, + const LEX_STRING *name, const LEX_STRING *dl, + int *argc, char **argv, int report) { struct st_plugin_int tmp; struct st_mysql_plugin *plugin; @@ -477,14 +755,26 @@ static my_bool plugin_add(const LEX_STRING *name, const LEX_STRING *dl, int repo tmp.name.length= name_len; tmp.ref_count= 0; tmp.state= PLUGIN_IS_UNINITIALIZED; - if (! (tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) - goto err; - plugin_array_version++; - if (my_hash_insert(&plugin_hash[plugin->type], (byte*)tmp_plugin_ptr)) + + if (!test_plugin_options(tmp_root, &tmp, argc, argv, true)) { - tmp_plugin_ptr->state= PLUGIN_IS_FREED; - goto err; + if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) + { + plugin_array_version++; + if (!my_hash_insert(&plugin_hash[plugin->type], (byte*)tmp_plugin_ptr)) + { + init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096); + DBUG_RETURN(FALSE); + } + tmp_plugin_ptr->state= PLUGIN_IS_FREED; + goto err; + } + mysql_del_sys_var_chain(tmp.system_vars); + plugin_dl_del(dl); + DBUG_RETURN(TRUE); } + /* plugin was disabled */ + plugin_dl_del(dl); DBUG_RETURN(FALSE); } } @@ -498,8 +788,14 @@ err: } -void plugin_deinitialize(struct st_plugin_int *plugin) +static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check) { + /* + we don't want to hold the LOCK_plugin mutex as it may cause + deinitialization to deadlock if plugins have worker threads + with plugin locks + */ + safe_mutex_assert_not_owner(&LOCK_plugin); if (plugin->plugin->status_vars) { @@ -539,16 +835,29 @@ void plugin_deinitialize(struct st_plugin_int *plugin) } } plugin->state= PLUGIN_IS_UNINITIALIZED; + + /* + We do the check here because NDB has a worker THD which doesn't + exit until NDB is shut down. + */ + if (ref_check && plugin->ref_count) + sql_print_error("Plugin '%s' has ref_count=%d after deinitialization.", + plugin->name.str, plugin->ref_count); } static void plugin_del(struct st_plugin_int *plugin) { DBUG_ENTER("plugin_del(plugin)"); + safe_mutex_assert_owner(&LOCK_plugin); hash_delete(&plugin_hash[plugin->plugin->type], (byte*)plugin); plugin_dl_del(&plugin->plugin_dl->dl); plugin->state= PLUGIN_IS_FREED; plugin_array_version++; + rw_wrlock(&LOCK_system_variables_hash); + mysql_del_sys_var_chain(plugin->system_vars); + rw_unlock(&LOCK_system_variables_hash); + free_root(&plugin->mem_root, MYF(0)); DBUG_VOID_RETURN; } @@ -565,18 +874,120 @@ static void plugin_del(const LEX_STRING *name) #endif -void plugin_unlock(struct st_plugin_int *plugin) +static void reap_plugins(void) { - DBUG_ENTER("plugin_unlock"); - rw_wrlock(&THR_LOCK_plugin); - DBUG_ASSERT(plugin && plugin->ref_count); - plugin->ref_count--; - if (plugin->state == PLUGIN_IS_DELETED && ! plugin->ref_count) + uint count, idx; + struct st_plugin_int *plugin, **reap, **list; + + safe_mutex_assert_owner(&LOCK_plugin); + + if (!reap_needed) + return; + + reap_needed= false; + count= plugin_array.elements; + reap= (struct st_plugin_int **)my_alloca(sizeof(plugin)*(count+1)); + *(reap++)= NULL; + + for (idx= 0; idx < count; idx++) { - plugin_deinitialize(plugin); + plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *); + if (plugin->state == PLUGIN_IS_DELETED && !plugin->ref_count) + { + /* change the status flag to prevent reaping by another thread */ + plugin->state= PLUGIN_IS_DYING; + *(reap++)= plugin; + } + } + + pthread_mutex_unlock(&LOCK_plugin); + + list= reap; + while ((plugin= *(--list))) + plugin_deinitialize(plugin, true); + + pthread_mutex_lock(&LOCK_plugin); + + while ((plugin= *(--reap))) plugin_del(plugin); + + my_afree(reap); +} + +static void intern_plugin_unlock(LEX *lex, plugin_ref plugin) +{ + int i; + st_plugin_int *pi; + DBUG_ENTER("intern_plugin_unlock"); + + safe_mutex_assert_owner(&LOCK_plugin); + + if (!plugin) + DBUG_VOID_RETURN; + + pi= plugin_ref_to_int(plugin); + +#ifdef DBUG_OFF + if (!pi->plugin_dl) + DBUG_VOID_RETURN; +#else + *(long *) plugin= -1; /* salt the ground, we're debugging */ + my_free((gptr) plugin, MYF(MY_WME)); +#endif + + DBUG_PRINT("info",("unlocking plugin, name= %s, ref_count= %d", + pi->name.str, pi->ref_count)); + if (lex) + { + /* remove one instance of this plugin from the use list */ + for (i= lex->plugins.elements - 1; i >= 0; i--) + if (plugin == *dynamic_element(&lex->plugins, i, plugin_ref*)) + { + delete_dynamic_element(&lex->plugins, i); + break; + } + DBUG_ASSERT(i >= 0); } - rw_unlock(&THR_LOCK_plugin); + + DBUG_ASSERT(pi->ref_count); + pi->ref_count--; + + if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count) + reap_needed= true; + + DBUG_VOID_RETURN; +} + + +void plugin_unlock(THD *thd, plugin_ref plugin) +{ + LEX *lex= thd ? ( !thd->lex ? &thd->main_lex : thd->lex) : NULL; + DBUG_ENTER("plugin_unlock"); + if (!plugin) + DBUG_VOID_RETURN; +#ifdef DBUG_OFF + /* built-in plugins don't need ref counting */ + if (!plugin_dlib(plugin)) + DBUG_VOID_RETURN; +#endif + pthread_mutex_lock(&LOCK_plugin); + intern_plugin_unlock(lex, plugin); + reap_plugins(); + pthread_mutex_unlock(&LOCK_plugin); + DBUG_VOID_RETURN; +} + + +void plugin_unlock_list(THD *thd, plugin_ref *list, uint count) +{ + LEX *lex= thd ? ( !thd->lex ? &thd->main_lex : thd->lex) : NULL; + DBUG_ENTER("plugin_unlock_list"); + DBUG_ASSERT(list); + pthread_mutex_lock(&LOCK_plugin); + while (count--) + intern_plugin_unlock(lex, *list++); + reap_plugins(); + pthread_mutex_unlock(&LOCK_plugin); DBUG_VOID_RETURN; } @@ -585,6 +996,8 @@ static int plugin_initialize(struct st_plugin_int *plugin) { DBUG_ENTER("plugin_initialize"); + safe_mutex_assert_owner(&LOCK_plugin); + if (plugin_type_initialize[plugin->plugin->type]) { if ((*plugin_type_initialize[plugin->plugin->type])(plugin)) @@ -626,12 +1039,29 @@ static int plugin_initialize(struct st_plugin_int *plugin) add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy #endif /* FIX_LATER */ } + + /* + set the plugin attribute of plugin's sys vars so they are pointing + to the active plugin + */ + if (plugin->system_vars) + { + sys_var_pluginvar *var= plugin->system_vars->cast_pluginvar(); + for (;;) + { + var->plugin= plugin; + if (!var->next) + break; + var= var->next->cast_pluginvar(); + } + } DBUG_RETURN(0); err: DBUG_RETURN(1); } + static byte *get_hash_key(const byte *buff, uint *length, my_bool not_used __attribute__((unused))) { @@ -641,6 +1071,15 @@ static byte *get_hash_key(const byte *buff, uint *length, } +static byte *get_bookmark_hash_key(const byte *buff, uint *length, + my_bool not_used __attribute__((unused))) +{ + struct st_bookmark *var= (st_bookmark *)buff; + *length= var->name_len + 1; + return (byte*) var->name; +} + + /* The logic is that we first load and initialize all compiled in plugins. From there we load up the dynamic types (assuming we have not been told to @@ -648,17 +1087,28 @@ static byte *get_hash_key(const byte *buff, uint *length, Finally we inializie everything, aka the dynamic that have yet to initialize. */ -int plugin_init(int skip_dynamic_loading) +int plugin_init(int *argc, char **argv, int flags) { uint i; + bool def_enabled, is_myisam; struct st_mysql_plugin **builtins; struct st_mysql_plugin *plugin; + struct st_plugin_int tmp, *plugin_ptr, **reap; + MEM_ROOT tmp_root; DBUG_ENTER("plugin_init"); if (initialized) DBUG_RETURN(0); - my_rwlock_init(&THR_LOCK_plugin, NULL); + init_alloc_root(&plugin_mem_root, 4096, 4096); + init_alloc_root(&tmp_root, 4096, 4096); + + if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0, + get_bookmark_hash_key, NULL, HASH_UNIQUE)) + goto err; + + + pthread_mutex_init(&LOCK_plugin, MY_MUTEX_INIT_FAST); if (my_init_dynamic_array(&plugin_dl_array, sizeof(struct st_plugin_dl),16,16) || @@ -669,10 +1119,14 @@ int plugin_init(int skip_dynamic_loading) for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++) { if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0, - get_hash_key, NULL, 0)) + get_hash_key, NULL, HASH_UNIQUE)) goto err; } + pthread_mutex_lock(&LOCK_plugin); + + initialized= 1; + /* First we register builtin plugins */ @@ -680,83 +1134,179 @@ int plugin_init(int skip_dynamic_loading) { for (plugin= *builtins; plugin->info; plugin++) { -// if (!(strcmp(plugin->name, "MyISAM"))) + /* by default, only ndbcluster is disabled */ + def_enabled= + my_strcasecmp(&my_charset_latin1, plugin->name, "NDBCLUSTER") != 0; + bzero(&tmp, sizeof(tmp)); + tmp.plugin= plugin; + + free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE)); + if (test_plugin_options(&tmp_root, &tmp, argc, argv, def_enabled)) + continue; + + if (register_builtin(plugin, &tmp, &plugin_ptr)) + goto err_unlock; + + /* only initialize MyISAM and CSV at this stage */ + if (!(is_myisam= + !my_strcasecmp(&my_charset_latin1, plugin->name, "MyISAM")) && + my_strcasecmp(&my_charset_latin1, plugin->name, "CSV")) + continue; + + if (plugin_initialize(plugin_ptr)) + goto err_unlock; + + /* + initialize the global default storage engine so that it may + not be null in any child thread. + */ + if (is_myisam) { - if (plugin_register_builtin(plugin)) - goto err; - struct st_plugin_int *tmp= dynamic_element(&plugin_array, - plugin_array.elements-1, - struct st_plugin_int *); - if (plugin_initialize(tmp)) - goto err; + DBUG_ASSERT(!global_system_variables.table_plugin); + global_system_variables.table_plugin= (plugin_ref) + my_malloc(sizeof(plugin_ptr), MYF(MY_WME | MY_FAE)); + global_system_variables.table_plugin[0]= plugin_ptr; + plugin_ptr->ref_count++; + DBUG_ASSERT(plugin_ptr->ref_count == 1); } } } + + /* should now be set to MyISAM storage engine */ + DBUG_ASSERT(global_system_variables.table_plugin); + + pthread_mutex_unlock(&LOCK_plugin); /* Register all dynamic plugins */ - if (!skip_dynamic_loading) - plugin_load(); + if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING)) + { + if (opt_plugin_load && + plugin_load_list(&tmp_root, argc, argv, opt_plugin_load)) + goto err; + if (!(flags & PLUGIN_INIT_SKIP_PLUGIN_TABLE)) + plugin_load(&tmp_root, argc, argv); + } - initialized= 1; + if (flags & PLUGIN_INIT_SKIP_INITIALIZATION) + goto end; /* Now we initialize all remaining plugins */ + pthread_mutex_lock(&LOCK_plugin); + reap= (st_plugin_int **) my_alloca((plugin_array.elements+1) * sizeof(void*)); + *(reap++)= NULL; + for (i= 0; i < plugin_array.elements; i++) { - struct st_plugin_int *tmp= dynamic_element(&plugin_array, i, - struct st_plugin_int *); - if (tmp->state == PLUGIN_IS_UNINITIALIZED) + plugin_ptr= dynamic_element(&plugin_array, i, struct st_plugin_int *); + if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED) { - if (plugin_initialize(tmp)) + if (plugin_initialize(plugin_ptr)) { - plugin_deinitialize(tmp); - plugin_del(tmp); + plugin_ptr->state= PLUGIN_IS_DYING; + *(reap++)= plugin_ptr; } } } + /* + Check if any plugins have to be reaped + */ + while ((plugin_ptr= *(--reap))) + { + pthread_mutex_unlock(&LOCK_plugin); + plugin_deinitialize(plugin_ptr, true); + pthread_mutex_lock(&LOCK_plugin); + plugin_del(plugin_ptr); + } + + pthread_mutex_unlock(&LOCK_plugin); + my_afree(reap); + +end: + free_root(&tmp_root, MYF(0)); DBUG_RETURN(0); +err_unlock: + pthread_mutex_unlock(&LOCK_plugin); err: + free_root(&tmp_root, MYF(0)); DBUG_RETURN(1); } -my_bool plugin_register_builtin(struct st_mysql_plugin *plugin) +static bool register_builtin(struct st_mysql_plugin *plugin, + struct st_plugin_int *tmp, + struct st_plugin_int **ptr) { - struct st_plugin_int tmp; DBUG_ENTER("plugin_register_builtin"); - tmp.plugin= plugin; - tmp.name.str= (char *)plugin->name; - tmp.name.length= strlen(plugin->name); - tmp.state= PLUGIN_IS_UNINITIALIZED; - - /* Cannot be unloaded */ - tmp.ref_count= 1; - tmp.plugin_dl= 0; + tmp->plugin= plugin; + tmp->name.str= (char *)plugin->name; + tmp->name.length= strlen(plugin->name); + tmp->state= PLUGIN_IS_UNINITIALIZED; + tmp->ref_count= 0; + tmp->plugin_dl= 0; - if (insert_dynamic(&plugin_array, (gptr)&tmp)) + if (insert_dynamic(&plugin_array, (gptr)tmp)) DBUG_RETURN(1); - if (my_hash_insert(&plugin_hash[plugin->type], - (byte*)dynamic_element(&plugin_array, - plugin_array.elements - 1, - struct st_plugin_int *))) + *ptr= dynamic_element(&plugin_array, plugin_array.elements - 1, + struct st_plugin_int *); + + if (my_hash_insert(&plugin_hash[plugin->type],(byte*) *ptr)) DBUG_RETURN(1); DBUG_RETURN(0); } -void plugin_load(void) +/* + Register a plugin at run time. (note, this doesn't initialize a plugin) + + SYNOPSIS + plugin_register_builtin() + thd current thread (used to store scratch data in mem_root) + plugin static plugin to install + + RETURN + false - plugin registered successfully +*/ +bool plugin_register_builtin(THD *thd, struct st_mysql_plugin *plugin) +{ + struct st_plugin_int tmp, *ptr; + bool result= true; + int dummy_argc= 0; + DBUG_ENTER("plugin_register_builtin"); + + bzero(&tmp, sizeof(tmp)); + tmp.plugin= plugin; + + rw_wrlock(&LOCK_system_variables_hash); + + if (test_plugin_options(thd->mem_root, &tmp, &dummy_argc, NULL, true)) + goto end; + + if ((result= register_builtin(plugin, &tmp, &ptr))) + mysql_del_sys_var_chain(tmp.system_vars); + +end: + rw_unlock(&LOCK_system_variables_hash); + + DBUG_RETURN(result);; +} + + +/* + called only by plugin_init() +*/ +static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) { TABLE_LIST tables; TABLE *table; READ_RECORD read_record_info; int error; - MEM_ROOT mem; THD *new_thd; DBUG_ENTER("plugin_load"); @@ -766,7 +1316,6 @@ void plugin_load(void) delete new_thd; DBUG_VOID_RETURN; } - init_sql_alloc(&mem, 1024, 0); new_thd->thread_stack= (char*) &tables; new_thd->store_globals(); new_thd->db= my_strdup("mysql", MYF(0)); @@ -788,13 +1337,14 @@ void plugin_load(void) { DBUG_PRINT("info", ("init plugin record")); String str_name, str_dl; - get_field(&mem, table->field[0], &str_name); - get_field(&mem, table->field[1], &str_dl); + get_field(tmp_root, table->field[0], &str_name); + get_field(tmp_root, table->field[1], &str_dl); LEX_STRING name= {(char *)str_name.ptr(), str_name.length()}; LEX_STRING dl= {(char *)str_dl.ptr(), str_dl.length()}; - if (plugin_add(&name, &dl, REPORT_TO_LOG)) + free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); + if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG)) sql_print_warning("Couldn't load plugin named '%s' with soname '%s'.", str_name.c_ptr(), str_dl.c_ptr()); } @@ -803,7 +1353,6 @@ void plugin_load(void) end_read_record(&read_record_info); new_thd->version--; // Force close to free memory end: - free_root(&mem, MYF(0)); close_thread_tables(new_thd); delete new_thd; /* Remember that we don't have a THD */ @@ -812,46 +1361,195 @@ end: } +/* + called only by plugin_init() +*/ +static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, + const char *list) +{ + char buffer[FN_REFLEN]; + LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name; + struct st_plugin_dl *plugin_dl; + struct st_mysql_plugin *plugin; + char *p= buffer; + DBUG_ENTER("plugin_load_list"); + while (list) + { + if (p == buffer + sizeof(buffer) - 1) + break; + switch ((*(p++)= *(list++))) { + case '\0': + list= NULL; /* terminate the loop */ + /* fall through */ +#ifndef __WIN__ + case ':': /* can't use this as delimiter as it may be drive letter */ +#endif + case ';': + name.str[name.length]= '\0'; + if (str != &dl) // load all plugins in named module + { + dl= name; + if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG))) + { + for (plugin= plugin_dl->plugins; plugin->info; plugin++) + { + name.str= (char *) plugin->name; + name.length= strlen(name.str); + + free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); + if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG)) + goto error; + } + plugin_dl_del(&dl); // reduce ref count + } + } + else + { + free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); + if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG)) + goto error; + } + name.length= dl.length= 0; + dl.str= NULL; name.str= p= buffer; + str= &name; + continue; + case '=': + case '#': + if (str == &name) + { + str= &dl; + str->str= p; + continue; + } + default: + str->length++; + continue; + } + } + DBUG_RETURN(FALSE); +error: + sql_print_error("Couldn't load plugin named '%s' with soname '%s'.", + name.str, dl.str); + DBUG_RETURN(TRUE); +} + + void plugin_shutdown(void) { - uint i; + uint i, count= plugin_array.elements; + struct st_plugin_int **plugins, *plugin; + struct st_plugin_dl **dl; DBUG_ENTER("plugin_shutdown"); - - /* - We loop through all plugins and call deinit() if they have one. - */ - for (i= 0; i < plugin_array.elements; i++) + + if (initialized) { - struct st_plugin_int *tmp= dynamic_element(&plugin_array, i, - struct st_plugin_int *); - plugin_deinitialize(tmp); + pthread_mutex_lock(&LOCK_plugin); + + cleanup_variables(NULL, &global_system_variables, false); + cleanup_variables(NULL, &max_system_variables, false); + + reap_needed= true; + + /* + We want to shut down plugins in a reasonable order, this will + become important when we have plugins which depend upon each other. + Circular references cannot be reaped so they are forced afterwards. + TODO: Have an additional step here to notify all active plugins that + shutdown is requested to allow plugins to deinitialize in parallel. + */ + while (reap_needed && (count= plugin_array.elements)) + { + for (i= 0; i < count; i++) + { + plugin= dynamic_element(&plugin_array, i, struct st_plugin_int *); + if (plugin->state == PLUGIN_IS_READY) + { + plugin->state= PLUGIN_IS_DELETED; + reap_needed= true; + } + } + reap_plugins(); + } + + plugins= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1)); + + /* + If we have any plugins which did not die cleanly, we force shutdown + */ + for (i= 0; i < count; i++) + { + plugins[i]= dynamic_element(&plugin_array, i, struct st_plugin_int *); + /* change the state to ensure no reaping races */ + if (plugins[i]->state == PLUGIN_IS_DELETED) + plugins[i]->state= PLUGIN_IS_DYING; + } + pthread_mutex_unlock(&LOCK_plugin); + + /* + We loop through all plugins and call deinit() if they have one. + */ + for (i= 0; i < count; i++) + if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED))) + { + sql_print_information("Plugin '%s' will be forced to shutdown", + plugins[i]->name.str); + plugin_deinitialize(plugins[i], false); + } + + pthread_mutex_lock(&LOCK_plugin); + + /* + We defer checking ref_counts until after all plugins are deinitialized + as some may have worker threads holding on to plugin references. + */ + for (i= 0; i < count; i++) + if (plugins[i]->ref_count) + sql_print_error("Plugin '%s' has ref_count=%d after shutdown.", + plugins[i]->name.str, plugins[i]->ref_count); + + for (i= 0; i < count; i++) + if (plugins[i]->state & PLUGIN_IS_UNINITIALIZED) + plugin_del(plugins[i]); + + cleanup_variables(NULL, &global_system_variables, true); + cleanup_variables(NULL, &max_system_variables, true); + + initialized= 0; + pthread_mutex_unlock(&LOCK_plugin); + pthread_mutex_destroy(&LOCK_plugin); } + my_afree(plugins); + /* Dispose of the memory */ + for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++) hash_free(&plugin_hash[i]); delete_dynamic(&plugin_array); + + count= plugin_dl_array.elements; + dl= (struct st_plugin_dl **)my_alloca(sizeof(void*) * count); + for (i= 0; i < count; i++) + dl[i]= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *); for (i= 0; i < plugin_dl_array.elements; i++) - { - struct st_plugin_dl *tmp= dynamic_element(&plugin_dl_array, i, - struct st_plugin_dl *); - free_plugin_mem(tmp); - } + free_plugin_mem(dl[i]); + my_afree(dl); delete_dynamic(&plugin_dl_array); - if (initialized) - { - initialized= 0; - rwlock_destroy(&THR_LOCK_plugin); - } + + hash_free(&bookmark_hash); + free_root(&plugin_mem_root, MYF(0)); + + global_variables_dynamic_size= 0; + DBUG_VOID_RETURN; } -my_bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl) +bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl) { TABLE_LIST tables; TABLE *table; - int error; + int error, argc=0; struct st_plugin_int *tmp; DBUG_ENTER("mysql_install_plugin"); @@ -861,14 +1559,17 @@ my_bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING if (check_table_access(thd, INSERT_ACL, &tables, 0)) DBUG_RETURN(TRUE); - /* need to open before acquiring THR_LOCK_plugin or it will deadlock */ + /* need to open before acquiring LOCK_plugin or it will deadlock */ if (! (table = open_ltable(thd, &tables, TL_WRITE))) DBUG_RETURN(TRUE); - rw_wrlock(&THR_LOCK_plugin); - if (plugin_add(name, dl, REPORT_TO_USER)) - goto err; - tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN); + pthread_mutex_lock(&LOCK_plugin); + rw_wrlock(&LOCK_system_variables_hash); + error= plugin_add(thd->mem_root, name, dl, &argc, NULL, REPORT_TO_USER); + rw_unlock(&LOCK_system_variables_hash); + + if (error || !(tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN))) + goto err; if (plugin_initialize(tmp)) { @@ -888,18 +1589,19 @@ my_bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING goto deinit; } - rw_unlock(&THR_LOCK_plugin); + pthread_mutex_unlock(&LOCK_plugin); DBUG_RETURN(FALSE); deinit: - plugin_deinitialize(tmp); - plugin_del(tmp); + tmp->state= PLUGIN_IS_DELETED; + reap_needed= true; + reap_plugins(); err: - rw_unlock(&THR_LOCK_plugin); + pthread_mutex_unlock(&LOCK_plugin); DBUG_RETURN(TRUE); } -my_bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name) +bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name) { TABLE *table; TABLE_LIST tables; @@ -910,11 +1612,11 @@ my_bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name) tables.db= (char *)"mysql"; tables.table_name= tables.alias= (char *)"plugin"; - /* need to open before acquiring THR_LOCK_plugin or it will deadlock */ + /* need to open before acquiring LOCK_plugin or it will deadlock */ if (! (table= open_ltable(thd, &tables, TL_WRITE))) DBUG_RETURN(TRUE); - rw_wrlock(&THR_LOCK_plugin); + pthread_mutex_lock(&LOCK_plugin); if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN))) { my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str); @@ -928,17 +1630,14 @@ my_bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name) goto err; } + plugin->state= PLUGIN_IS_DELETED; if (plugin->ref_count) - { push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, "Plugin is busy and will be uninstalled on shutdown"); - plugin->state= PLUGIN_IS_DELETED; - } else - { - plugin_deinitialize(plugin); - plugin_del(plugin); - } + reap_needed= true; + reap_plugins(); + pthread_mutex_unlock(&LOCK_plugin); table->use_all_columns(); table->field[0]->store(name->str, name->length, system_charset_info); @@ -951,17 +1650,17 @@ my_bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name) if ((error= table->file->ha_delete_row(table->record[0]))) { table->file->print_error(error, MYF(0)); - goto err; + DBUG_RETURN(TRUE); } } - rw_unlock(&THR_LOCK_plugin); DBUG_RETURN(FALSE); err: - rw_unlock(&THR_LOCK_plugin); + pthread_mutex_unlock(&LOCK_plugin); DBUG_RETURN(TRUE); } -my_bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, + +bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, int type, uint state_mask, void *arg) { uint idx, total; @@ -969,16 +1668,19 @@ my_bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, int version=plugin_array_version; DBUG_ENTER("plugin_foreach_with_mask"); + if (!initialized) + DBUG_RETURN(FALSE); + state_mask= ~state_mask; // do it only once - rw_rdlock(&THR_LOCK_plugin); + pthread_mutex_lock(&LOCK_plugin); total= type == MYSQL_ANY_PLUGIN ? plugin_array.elements : plugin_hash[type].records; /* Do the alloca out here in case we do have a working alloca: leaving the nested stack frame invalidates alloca allocation. */ - plugins=(struct st_plugin_int **)my_alloca(total*sizeof(*plugins)); + plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin)); if (type == MYSQL_ANY_PLUGIN) { for (idx= 0; idx < total; idx++) @@ -996,20 +1698,20 @@ my_bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL; } } - rw_unlock(&THR_LOCK_plugin); + pthread_mutex_unlock(&LOCK_plugin); for (idx= 0; idx < total; idx++) { if (unlikely(version != plugin_array_version)) { - rw_rdlock(&THR_LOCK_plugin); + pthread_mutex_lock(&LOCK_plugin); for (uint i=idx; i < total; i++) if (plugins[i] && plugins[i]->state & state_mask) plugins[i]=0; - rw_unlock(&THR_LOCK_plugin); + pthread_mutex_unlock(&LOCK_plugin); } plugin= plugins[idx]; - if (plugin && func(thd, plugin, arg)) + if (plugin && func(thd, plugin_int_to_ref(plugin), arg)) goto err; } @@ -1020,3 +1722,1320 @@ err: DBUG_RETURN(TRUE); } + +/**************************************************************************** + Internal type declarations for variables support +****************************************************************************/ + +#undef MYSQL_SYSVAR_NAME +#define MYSQL_SYSVAR_NAME(name) name +#define PLUGIN_VAR_TYPEMASK 0x007f + +#define EXTRA_OPTIONS 3 /* options for: 'foo', 'plugin-foo' and NULL */ + +typedef DECLARE_MYSQL_SYSVAR_BASIC(sysvar_bool_t, my_bool); +typedef DECLARE_MYSQL_THDVAR_BASIC(thdvar_bool_t, my_bool); +typedef DECLARE_MYSQL_SYSVAR_BASIC(sysvar_str_t, char *); +typedef DECLARE_MYSQL_THDVAR_BASIC(thdvar_str_t, char *); + +typedef DECLARE_MYSQL_SYSVAR_TYPELIB(sysvar_typelib_t); +typedef DECLARE_MYSQL_THDVAR_TYPELIB(thdvar_typelib_t); + +typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_int_t, int); +typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_long_t, long); +typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_longlong_t, longlong); +typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_uint_t, uint); +typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_ulong_t, ulong); +typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_ulonglong_t, ulonglong); + +typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_int_t, int); +typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_long_t, long); +typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_longlong_t, longlong); +typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_uint_t, uint); +typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulong_t, ulong); +typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulonglong_t, ulonglong); + +#define SET_PLUGIN_VAR_RESOLVE(opt)\ + *(mysql_sys_var_ptr_p*)&((opt)->resolve)= mysql_sys_var_ptr +typedef byte *(*mysql_sys_var_ptr_p)(void* a_thd, int offset); + + +/**************************************************************************** + default variable data check and update functions +****************************************************************************/ + +static int check_func_bool(THD *thd, struct st_mysql_sys_var *var, + void *save, st_mysql_value *value) +{ + char buff[STRING_BUFFER_USUAL_SIZE]; + const char *strvalue= "NULL", *str; + int result, length; + ulonglong tmp; + + if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING) + { + length= sizeof(buff); + if (!(str= value->val_str(value, buff, &length)) || + (result= find_type(&bool_typelib, str, length, 1)-1) < 0) + { + if (str) + strvalue= str; + goto err; + } + } + else + { + if (value->val_int(value, &tmp, sizeof(tmp)) < 0) + goto err; + if (tmp > 1) + { + llstr(tmp, buff); + strvalue= buff; + goto err; + } + result= (int) tmp; + } + *(int*)save= -result; + return 0; +err: + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue); + return 1; +} + + +static int check_func_int(THD *thd, struct st_mysql_sys_var *var, + void *save, st_mysql_value *value) +{ + ulonglong tmp; + struct my_option options; + value->val_int(value, &tmp, sizeof(tmp)); + plugin_opt_set_limits(&options, var); + *(int *)save= (int) getopt_ull_limit_value(tmp, &options); + return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) && + (*(int *)save != (int) tmp); +} + + +static int check_func_long(THD *thd, struct st_mysql_sys_var *var, + void *save, st_mysql_value *value) +{ + ulonglong tmp; + struct my_option options; + value->val_int(value, &tmp, sizeof(tmp)); + plugin_opt_set_limits(&options, var); + *(long *)save= (long) getopt_ull_limit_value(tmp, &options); + return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) && + (*(long *)save != (long) tmp); +} + + +static int check_func_longlong(THD *thd, struct st_mysql_sys_var *var, + void *save, st_mysql_value *value) +{ + ulonglong tmp; + struct my_option options; + value->val_int(value, &tmp, sizeof(tmp)); + plugin_opt_set_limits(&options, var); + *(ulonglong *)save= getopt_ull_limit_value(tmp, &options); + return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) && + (*(ulonglong *)save != tmp); +} + +static int check_func_str(THD *thd, struct st_mysql_sys_var *var, + void *save, st_mysql_value *value) +{ + char buff[STRING_BUFFER_USUAL_SIZE]; + const char *str; + int length; + + length= sizeof(buff); + if ((str= value->val_str(value, buff, &length))) + str= thd->strmake(str, length); + *(const char**)save= str; + return 0; +} + + +static int check_func_enum(THD *thd, struct st_mysql_sys_var *var, + void *save, st_mysql_value *value) +{ + char buff[STRING_BUFFER_USUAL_SIZE]; + const char *strvalue= "NULL", *str; + TYPELIB *typelib; + ulonglong tmp; + long result; + int length; + + if (var->flags & PLUGIN_VAR_THDLOCAL) + typelib= ((thdvar_typelib_t*) var)->typelib; + else + typelib= ((sysvar_typelib_t*) var)->typelib; + + if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING) + { + length= sizeof(buff); + if (!(str= value->val_str(value, buff, &length))) + goto err; + if ((result= find_type(typelib, str, length, 1)-1) < 0) + { + strvalue= str; + goto err; + } + } + else + { + if (value->val_int(value, &tmp, sizeof(tmp))) + goto err; + if (tmp >= typelib->count) + { + llstr(tmp, buff); + strvalue= buff; + goto err; + } + result= (long) tmp; + } + *(long*)save= result; + return 0; +err: + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue); + return 1; +} + + +static int check_func_set(THD *thd, struct st_mysql_sys_var *var, + void *save, st_mysql_value *value) +{ + char buff[STRING_BUFFER_USUAL_SIZE], *error= 0; + const char *strvalue= "NULL", *str; + TYPELIB *typelib; + long result; + ulonglong tmp; + uint error_len; + bool not_used; + int length; + + if (var->flags & PLUGIN_VAR_THDLOCAL) + typelib= ((thdvar_typelib_t*) var)->typelib; + else + typelib= ((sysvar_typelib_t*)var)->typelib; + + if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING) + { + length= sizeof(buff); + if (!(str= value->val_str(value, buff, &length))) + goto err; + result= find_set(typelib, str, length, NULL, + &error, &error_len, ¬_used); + if (error_len) + { + strmake(buff, error, min(sizeof(buff), error_len)); + strvalue= buff; + goto err; + } + } + else + { + if (value->val_int(value, &tmp, sizeof(tmp))) + goto err; + if (unlikely((tmp >= (ULL(1) << typelib->count)) && + (typelib->count < sizeof(long)*8))) + { + llstr(tmp, buff); + strvalue= buff; + goto err; + } + result= (long) tmp; + } + *(long*)save= result; + return 0; +err: + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue); + return 1; +} + + +static void update_func_bool(THD *thd, struct st_mysql_sys_var *var, + void *tgt, void *save) +{ + *(my_bool *) tgt= *(int *) save ? 1 : 0; +} + + +static void update_func_int(THD *thd, struct st_mysql_sys_var *var, + void *tgt, void *save) +{ + *(int *)tgt= *(int *) save; +} + + +static void update_func_long(THD *thd, struct st_mysql_sys_var *var, + void *tgt, void *save) +{ + *(long *)tgt= *(long *) save; +} + + +static void update_func_longlong(THD *thd, struct st_mysql_sys_var *var, + void *tgt, void *save) +{ + *(longlong *)tgt= *(ulonglong *) save; +} + + +static void update_func_str(THD *thd, struct st_mysql_sys_var *var, + void *tgt, void *save) +{ + char *old= *(char **) tgt; + *(char **)tgt= *(char **) save; + if (var->flags & PLUGIN_VAR_MEMALLOC) + { + *(char **)tgt= my_strdup(*(char **) save, MYF(0)); + my_free(old, MYF(0)); + } +} + + +/**************************************************************************** + System Variables support +****************************************************************************/ + + +sys_var *find_sys_var(THD *thd, const char *str, uint length) +{ + sys_var *var; + sys_var_pluginvar *pi= NULL; + plugin_ref plugin; + DBUG_ENTER("find_sys_var"); + + rw_rdlock(&LOCK_system_variables_hash); + if ((var= intern_find_sys_var(str, length, false)) && + (pi= var->cast_pluginvar())) + { + LEX *lex= thd ? ( !thd->lex ? &thd->main_lex : thd->lex ) : NULL; + pthread_mutex_lock(&LOCK_plugin); + if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin)))) + var= NULL; /* failed to lock it, it must be uninstalling */ + else + if (!(plugin_state(plugin) & PLUGIN_IS_READY)) + { + /* initialization not completed */ + var= NULL; + intern_plugin_unlock(lex, plugin); + } + pthread_mutex_unlock(&LOCK_plugin); + } + rw_unlock(&LOCK_system_variables_hash); + + /* + If the variable exists but the plugin it is associated with is not ready + then the intern_plugin_lock did not raise an error, so we do it here. + */ + if (pi && !var) + my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str); + DBUG_RETURN(var); +} + + +/* + called by register_var, construct_options and test_plugin_options. + Returns the 'bookmark' for the named variable. + LOCK_system_variables_hash should be at least read locked +*/ +static st_bookmark *find_bookmark(const char *plugin, const char *name, + int flags) +{ + st_bookmark *result= NULL; + uint namelen, length, pluginlen= 0; + char *varname, *p; + + if (!(flags & PLUGIN_VAR_THDLOCAL)) + return NULL; + + namelen= strlen(name); + if (plugin) + pluginlen= strlen(plugin) + 1; + length= namelen + pluginlen + 2; + varname= (char*) my_alloca(length); + + if (plugin) + { + strxmov(varname + 1, plugin, "_", name, NullS); + for (p= varname + 1; *p; p++) + if (*p == '-') + *p= '_'; + } + else + memcpy(varname + 1, name, namelen + 1); + + varname[0]= flags & PLUGIN_VAR_TYPEMASK; + + result= (st_bookmark*) hash_search(&bookmark_hash, + (const byte*) varname, length - 1); + + my_afree(varname); + return result; +} + + +/* + returns a bookmark for thd-local variables, creating if neccessary. + returns null for non thd-local variables. + Requires that a write lock is obtained on LOCK_system_variables_hash +*/ +static st_bookmark *register_var(const char *plugin, const char *name, + int flags) +{ + uint length= strlen(plugin) + strlen(name) + 3, size= 0, offset, new_size; + st_bookmark *result; + char *varname, *p; + + if (!(flags & PLUGIN_VAR_THDLOCAL)) + return NULL; + + switch (flags & PLUGIN_VAR_TYPEMASK) { + case PLUGIN_VAR_BOOL: + size= sizeof(my_bool); + break; + case PLUGIN_VAR_INT: + size= sizeof(int); + break; + case PLUGIN_VAR_LONG: + size= sizeof(long); + break; + case PLUGIN_VAR_LONGLONG: + size= sizeof(ulonglong); + break; + case PLUGIN_VAR_STR: + size= sizeof(char*); + break; + default: + DBUG_ASSERT(0); + return NULL; + }; + + varname= ((char*) my_alloca(length)); + strxmov(varname + 1, plugin, "_", name, NullS); + for (p= varname + 1; *p; p++) + if (*p == '-') + *p= '_'; + + if (!(result= find_bookmark(NULL, varname + 1, flags))) + { + result= (st_bookmark*) alloc_root(&plugin_mem_root, + sizeof(struct st_bookmark) + length); + varname[0]= flags & PLUGIN_VAR_TYPEMASK; + result->name= (char *) memcpy(&result[1], varname, length); + result->name_len= length - 2; + result->offset= -1; + + DBUG_ASSERT(size && !(size & (size-1))); /* must be power of 2 */ + + offset= global_system_variables.dynamic_variables_size; + offset= (offset + size - 1) & ~(size - 1); + result->offset= (int) offset; + + new_size= (offset + size + 63) & ~63; + + if (new_size > global_variables_dynamic_size) + { + global_system_variables.dynamic_variables_ptr= + my_realloc(global_system_variables.dynamic_variables_ptr, new_size, + MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); + max_system_variables.dynamic_variables_ptr= + my_realloc(max_system_variables.dynamic_variables_ptr, new_size, + MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); + global_variables_dynamic_size= new_size; + } + + global_system_variables.dynamic_variables_head= offset; + max_system_variables.dynamic_variables_head= offset; + global_system_variables.dynamic_variables_size= offset + size; + max_system_variables.dynamic_variables_size= offset + size; + global_system_variables.dynamic_variables_version++; + max_system_variables.dynamic_variables_version++; + + result->version= global_system_variables.dynamic_variables_version; + + /* this should succeed because we have already checked if a dup exists */ + if (my_hash_insert(&bookmark_hash, (byte*) result)) + { + fprintf(stderr, "failed to add placeholder to hash"); + DBUG_ASSERT(0); + } + } + my_afree(varname); + return result; +} + + +/* + returns a pointer to the memory which holds the thd-local variable or + a pointer to the global variable if thd==null. + If required, will sync with global variables if the requested variable + has not yet been allocated in the current thread. +*/ +static byte *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) +{ + DBUG_ASSERT(offset >= 0); + DBUG_ASSERT((uint)offset <= global_system_variables.dynamic_variables_head); + + if (!thd) + return (byte*) global_system_variables.dynamic_variables_ptr + offset; + + /* + dynamic_variables_size points to the largest valid offset + */ + if (!thd->variables.dynamic_variables_ptr || + (uint)offset > thd->variables.dynamic_variables_head) + { + uint idx; + + rw_rdlock(&LOCK_system_variables_hash); + + thd->variables.dynamic_variables_ptr= + my_realloc(thd->variables.dynamic_variables_ptr, + global_variables_dynamic_size, + MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); + + if (global_lock) + pthread_mutex_lock(&LOCK_global_system_variables); + + safe_mutex_assert_owner(&LOCK_global_system_variables); + + memcpy(thd->variables.dynamic_variables_ptr + + thd->variables.dynamic_variables_size, + global_system_variables.dynamic_variables_ptr + + thd->variables.dynamic_variables_size, + global_system_variables.dynamic_variables_size - + thd->variables.dynamic_variables_size); + if (global_lock) + pthread_mutex_unlock(&LOCK_global_system_variables); + + /* + now we need to iterate through any newly copied 'defaults' + and if it is a string type with MEMALLOC flag, we need to strdup + */ + for (idx= 0; idx < bookmark_hash.records; idx++) + { + sys_var_pluginvar *pi; + sys_var *var; + st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx); + + if (v->version <= thd->variables.dynamic_variables_version || + !(var= intern_find_sys_var(v->name + 1, v->name_len, true)) || + !(pi= var->cast_pluginvar()) || + v->name[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK)) + continue; + + /* Here we do anything special that may be required of the data types */ + + if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR && + pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC) + { + char **pp; + if (global_lock) + pthread_mutex_lock(&LOCK_global_system_variables); + pp= (char**) (thd->variables.dynamic_variables_ptr + + *(int*)(pi->plugin_var + 1)); + if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr + + *(int*)(pi->plugin_var + 1)))) + *pp= my_strdup(*pp, MYF(MY_WME|MY_FAE)); + if (global_lock) + pthread_mutex_unlock(&LOCK_global_system_variables); + } + } + + thd->variables.dynamic_variables_version= + global_system_variables.dynamic_variables_version; + thd->variables.dynamic_variables_head= + global_system_variables.dynamic_variables_head; + thd->variables.dynamic_variables_size= + global_system_variables.dynamic_variables_size; + + rw_unlock(&LOCK_system_variables_hash); + } + return (byte*)thd->variables.dynamic_variables_ptr + offset; +} + +static byte *mysql_sys_var_ptr(void* a_thd, int offset) +{ + return intern_sys_var_ptr((THD *)a_thd, offset, true); +} + + +void plugin_thdvar_init(THD *thd, bool lock_locals) +{ + /* we are going to allocate these lazily */ + thd->variables.dynamic_variables_version= 0; + thd->variables.dynamic_variables_size= 0; + thd->variables.dynamic_variables_ptr= 0; + + if (lock_locals) + { + DBUG_ASSERT(!(thd->variables.table_plugin)); + thd->variables.table_plugin= + my_plugin_lock(NULL, &global_system_variables.table_plugin); + } + else + { + thd->variables.table_plugin= NULL; + } +} + +static void cleanup_variables(THD *thd, struct system_variables *vars, + bool free_memory) +{ + st_bookmark *v; + sys_var_pluginvar *pivar; + sys_var *var; + int flags; + uint idx; + + rw_rdlock(&LOCK_system_variables_hash); + for (idx= 0; idx < bookmark_hash.records; idx++) + { + v= (st_bookmark*) hash_element(&bookmark_hash, idx); + if (v->version > vars->dynamic_variables_version || + !(var= intern_find_sys_var(v->name + 1, v->name_len, true)) || + !(pivar= var->cast_pluginvar()) || + v->name[0] != (pivar->plugin_var->flags & PLUGIN_VAR_TYPEMASK)) + continue; + + flags= pivar->plugin_var->flags; + + if ((flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR && + flags & PLUGIN_VAR_THDLOCAL && flags & PLUGIN_VAR_MEMALLOC) + { + char **ptr= (char**) pivar->real_value_ptr(thd, OPT_SESSION); + my_free(*ptr, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); + *ptr= NULL; + } + } + rw_unlock(&LOCK_system_variables_hash); + + intern_plugin_unlock(NULL, vars->table_plugin); + vars->table_plugin= NULL; + + if (free_memory) + { + my_free(vars->dynamic_variables_ptr, MYF(MY_ALLOW_ZERO_PTR)); + vars->dynamic_variables_ptr= NULL; + vars->dynamic_variables_size= 0; + vars->dynamic_variables_version= 0; + } +} + + +void plugin_thdvar_cleanup(THD *thd) +{ + uint idx; + plugin_ref *list; + DBUG_ENTER("plugin_thdvar_cleanup"); + + pthread_mutex_lock(&LOCK_plugin); + + cleanup_variables(thd, &thd->variables, true); + + if ((idx= thd->main_lex.plugins.elements)) + { + list= ((plugin_ref*) thd->main_lex.plugins.buffer) + idx - 1; + DBUG_PRINT("info",("unlocking %d plugins", idx)); + while ((char*) list >= thd->main_lex.plugins.buffer) + intern_plugin_unlock(NULL, *list--); + } + + reap_plugins(); + pthread_mutex_unlock(&LOCK_plugin); + + reset_dynamic(&thd->main_lex.plugins); + + DBUG_VOID_RETURN; +} + + +bool sys_var_pluginvar::check_update_type(Item_result type) +{ + if (is_readonly()) + return 1; + switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) { + case PLUGIN_VAR_INT: + case PLUGIN_VAR_LONG: + case PLUGIN_VAR_LONGLONG: + return type != INT_RESULT; + case PLUGIN_VAR_STR: + return type != STRING_RESULT; + default: + return 0; + } +} + + +SHOW_TYPE sys_var_pluginvar::show_type() +{ + switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) { + case PLUGIN_VAR_BOOL: + return SHOW_MY_BOOL; + case PLUGIN_VAR_INT: + return SHOW_INT; + case PLUGIN_VAR_LONG: + return SHOW_LONG; + case PLUGIN_VAR_LONGLONG: + return SHOW_LONGLONG; + case PLUGIN_VAR_STR: + return SHOW_CHAR_PTR; + case PLUGIN_VAR_ENUM: + case PLUGIN_VAR_SET: + return SHOW_CHAR; + default: + DBUG_ASSERT(0); + return SHOW_UNDEF; + } +} + + +byte* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type) +{ + DBUG_ASSERT(thd); + if (plugin_var->flags & PLUGIN_VAR_THDLOCAL) + { + if (type == OPT_GLOBAL) + thd= NULL; + + return intern_sys_var_ptr(thd, *(int*) (plugin_var+1), false); + } + return *(byte**) (plugin_var+1); +} + + +TYPELIB* sys_var_pluginvar::plugin_var_typelib(void) +{ + int type= plugin_var->flags & PLUGIN_VAR_TYPEMASK; + if (type == PLUGIN_VAR_ENUM || type == PLUGIN_VAR_SET) + { + if (plugin_var->flags & PLUGIN_VAR_THDLOCAL) + return ((thdvar_typelib_t *)plugin_var)->typelib; + else + return ((sysvar_typelib_t *)plugin_var)->typelib; + } + return NULL; +} + + +byte* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) +{ + byte* result; + + result= real_value_ptr(thd, type); + + if ((plugin_var->flags && PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM) + result= (byte*) get_type(plugin_var_typelib(), *(ulong*)result); + else + if ((plugin_var->flags && PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET) + { + char buffer[STRING_BUFFER_USUAL_SIZE]; + String str(buffer, sizeof(buffer), system_charset_info); + TYPELIB *typelib= plugin_var_typelib(); + ulong mask= 1, value= *(ulong*) result; + uint i; + + str.length(0); + for (i= 0; i < typelib->count; i++, mask<<=1) + { + if (!(value & mask)) + continue; + str.append(typelib->type_names[i], typelib->type_lengths[i]); + str.append(','); + } + + result= (byte*) ""; + if (str.length()) + result= (byte*) thd->strmake(str.ptr(), str.length()-1); + } + return result; +} + + +bool sys_var_pluginvar::check(THD *thd, set_var *var) +{ + st_item_value_holder value; + DBUG_ASSERT(is_readonly() || plugin_var->check); + + value.value_type= item_value_type; + value.val_str= item_val_str; + value.val_int= item_val_int; + value.val_real= item_val_real; + value.item= var->value; + + return is_readonly() || + plugin_var->check(thd, plugin_var, &var->save_result, &value); +} + + +void sys_var_pluginvar::set_default(THD *thd, enum_var_type type) +{ + void *tgt, *src; + + DBUG_ASSERT(is_readonly() || plugin_var->update); + + if (is_readonly()) + return; + + tgt= real_value_ptr(thd, type); + src= ((void **) (plugin_var + 1) + 1); + + if (plugin_var->flags & PLUGIN_VAR_THDLOCAL) + { + src= ((int*) (plugin_var + 1) + 1); + if (type != OPT_GLOBAL) + src= real_value_ptr(thd, OPT_GLOBAL); + } + + /* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */ + DBUG_ASSERT(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || + thd == current_thd); + + if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || type == OPT_GLOBAL) + { + pthread_mutex_lock(&LOCK_plugin); + plugin_var->update(thd, plugin_var, tgt, src); + pthread_mutex_unlock(&LOCK_plugin); + } + else + plugin_var->update(thd, plugin_var, tgt, src); +} + + +bool sys_var_pluginvar::update(THD *thd, set_var *var) +{ + void *tgt; + + DBUG_ASSERT(is_readonly() || plugin_var->update); + + /* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */ + DBUG_ASSERT(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || + thd == current_thd); + + if (is_readonly()) + return 1; + + pthread_mutex_lock(&LOCK_global_system_variables); + tgt= real_value_ptr(thd, var->type); + + if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || var->type == OPT_GLOBAL) + { + /* variable we are updating has global scope, so we unlock after updating */ + plugin_var->update(thd, plugin_var, tgt, &var->save_result); + pthread_mutex_unlock(&LOCK_global_system_variables); + } + else + { + pthread_mutex_unlock(&LOCK_global_system_variables); + plugin_var->update(thd, plugin_var, tgt, &var->save_result); + } + return 0; +} + + +#define OPTION_SET_LIMITS(type, options, opt) \ + options->var_type= type; \ + options->def_value= (opt)->def_val; \ + options->min_value= (opt)->min_val; \ + options->max_value= (opt)->max_val; \ + options->block_size= (opt)->blk_sz + + +static void plugin_opt_set_limits(struct my_option *options, + const struct st_mysql_sys_var *opt) +{ + switch (opt->flags & (PLUGIN_VAR_TYPEMASK | + PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL)) { + /* global system variables */ + case PLUGIN_VAR_INT: + OPTION_SET_LIMITS(GET_INT, options, (sysvar_int_t*) opt); + break; + case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED: + OPTION_SET_LIMITS(GET_UINT, options, (sysvar_uint_t*) opt); + break; + case PLUGIN_VAR_LONG: + OPTION_SET_LIMITS(GET_LONG, options, (sysvar_long_t*) opt); + break; + case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED: + OPTION_SET_LIMITS(GET_ULONG, options, (sysvar_ulong_t*) opt); + break; + case PLUGIN_VAR_LONGLONG: + OPTION_SET_LIMITS(GET_LL, options, (sysvar_longlong_t*) opt); + break; + case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED: + OPTION_SET_LIMITS(GET_ULL, options, (sysvar_ulonglong_t*) opt); + break; + case PLUGIN_VAR_ENUM: + options->var_type= GET_ENUM; + options->typelib= ((sysvar_typelib_t*) opt)->typelib; + options->def_value= *(ulong*) ((int*) (opt + 1) + 1); + options->min_value= options->block_size= 0; + options->max_value= options->typelib->count - 1; + break; + case PLUGIN_VAR_SET: + options->var_type= GET_SET; + options->typelib= ((sysvar_typelib_t*) opt)->typelib; + options->def_value= *(ulong*) ((int*) (opt + 1) + 1); + options->min_value= options->block_size= 0; + options->max_value= (ULL(1) << options->typelib->count) - 1; + break; + case PLUGIN_VAR_BOOL: + options->var_type= GET_BOOL; + options->def_value= *(my_bool*) ((void**)(opt + 1) + 1); + break; + case PLUGIN_VAR_STR: + options->var_type= GET_STR; + break; + /* threadlocal variables */ + case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL: + OPTION_SET_LIMITS(GET_INT, options, (thdvar_int_t*) opt); + break; + case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL: + OPTION_SET_LIMITS(GET_UINT, options, (thdvar_uint_t*) opt); + break; + case PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL: + OPTION_SET_LIMITS(GET_LONG, options, (thdvar_long_t*) opt); + break; + case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL: + OPTION_SET_LIMITS(GET_ULONG, options, (thdvar_ulong_t*) opt); + break; + case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL: + OPTION_SET_LIMITS(GET_LL, options, (thdvar_longlong_t*) opt); + break; + case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL: + OPTION_SET_LIMITS(GET_ULL, options, (thdvar_ulonglong_t*) opt); + break; + case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL: + options->var_type= GET_ENUM; + options->typelib= ((thdvar_typelib_t*) opt)->typelib; + options->def_value= *(ulong*) ((int*) (opt + 1) + 1); + options->min_value= options->block_size= 0; + options->max_value= options->typelib->count - 1; + break; + case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL: + options->var_type= GET_SET; + options->typelib= ((thdvar_typelib_t*) opt)->typelib; + options->def_value= *(ulong*) ((int*) (opt + 1) + 1); + options->min_value= options->block_size= 0; + options->max_value= (ULL(1) << options->typelib->count) - 1; + break; + case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL: + options->var_type= GET_BOOL; + options->def_value= *(my_bool*) ((int*) (opt + 1) + 1); + break; + case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL: + options->var_type= GET_STR; + break; + default: + DBUG_ASSERT(0); + } + options->arg_type= REQUIRED_ARG; + if (opt->flags & PLUGIN_VAR_NOCMDARG) + options->arg_type= NO_ARG; + if (opt->flags & PLUGIN_VAR_OPCMDARG) + options->arg_type= OPT_ARG; +} + + +static my_bool get_one_option(int optid __attribute__((unused)), + const struct my_option *opt, + char *argument) +{ + return 0; +} + + +static int construct_options(MEM_ROOT *mem_root, + struct st_plugin_int *tmp, + my_option *options, + my_bool **enabled, bool can_disable) +{ + const char *plugin_name= tmp->plugin->name; + uint namelen= strlen(plugin_name), optnamelen; + uint buffer_length= namelen * 4 + (can_disable ? 75 : 10); + char *name= (char*) alloc_root(mem_root, buffer_length) + 1; + char *optname, *p; + int index= 0, offset= 0; + st_mysql_sys_var *opt, **plugin_option; + st_bookmark *v; + DBUG_ENTER("construct_options"); + + /* support --skip-plugin-foo syntax */ + memcpy(name, plugin_name, namelen + 1); + my_casedn_str(&my_charset_latin1, name); + strxmov(name + namelen + 1, "plugin-", name, NullS); + + for (p= name + namelen*2 + 8; p > name; p--) + if (*p == '_') + *p= '-'; + + if (can_disable) + { + strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. " + "Disable with --skip-plugin-", name," (will save memory).", NullS); + + options[0].comment= name + namelen*2 + 10; + } + + *((my_bool *)(name -1))= **enabled; + *enabled= (my_bool *)(name - 1); + + + options[1].name= (options[0].name= name) + namelen + 1; + options[0].id= options[1].id= 256; /* must be >255. dup id ok */ + options[0].var_type= options[1].var_type= GET_BOOL; + options[0].arg_type= options[1].arg_type= NO_ARG; + options[0].def_value= options[1].def_value= **enabled; + options[0].value= options[0].u_max_value= + options[1].value= options[1].u_max_value= (gptr*) (name - 1); + options+= 2; + + /* + Two passes as the 2nd pass will take pointer addresses for use + by my_getopt and register_var() in the first pass uses realloc + */ + + for (plugin_option= tmp->plugin->system_vars; + plugin_option && *plugin_option; plugin_option++, index++) + { + opt= *plugin_option; + if (!(opt->flags & PLUGIN_VAR_THDLOCAL)) + continue; + if (!(register_var(name, opt->name, opt->flags))) + continue; + switch (opt->flags & PLUGIN_VAR_TYPEMASK) { + case PLUGIN_VAR_BOOL: + SET_PLUGIN_VAR_RESOLVE((thdvar_bool_t *) opt); + break; + case PLUGIN_VAR_INT: + SET_PLUGIN_VAR_RESOLVE((thdvar_int_t *) opt); + break; + case PLUGIN_VAR_LONG: + SET_PLUGIN_VAR_RESOLVE((thdvar_long_t *) opt); + break; + case PLUGIN_VAR_LONGLONG: + SET_PLUGIN_VAR_RESOLVE((thdvar_longlong_t *) opt); + break; + case PLUGIN_VAR_STR: + SET_PLUGIN_VAR_RESOLVE((thdvar_str_t *) opt); + break; + case PLUGIN_VAR_ENUM: + case PLUGIN_VAR_SET: + SET_PLUGIN_VAR_RESOLVE((thdvar_typelib_t *) opt); + break; + default: + sql_print_error("Unknown variable type code 0x%x in plugin '%s'.", + opt->flags, tmp->plugin->name); + DBUG_RETURN(-1); + }; + } + + for (plugin_option= tmp->plugin->system_vars; + plugin_option && *plugin_option; plugin_option++, index++) + { + switch ((opt= *plugin_option)->flags & PLUGIN_VAR_TYPEMASK) { + case PLUGIN_VAR_BOOL: + if (!opt->check) + opt->check= check_func_bool; + if (!opt->update) + opt->update= update_func_bool; + break; + case PLUGIN_VAR_INT: + if (!opt->check) + opt->check= check_func_int; + if (!opt->update) + opt->update= update_func_int; + break; + case PLUGIN_VAR_LONG: + if (!opt->check) + opt->check= check_func_long; + if (!opt->update) + opt->update= update_func_long; + break; + case PLUGIN_VAR_LONGLONG: + if (!opt->check) + opt->check= check_func_longlong; + if (!opt->update) + opt->update= update_func_longlong; + break; + case PLUGIN_VAR_STR: + if (!opt->check) + opt->check= check_func_str; + if (!opt->update) + { + opt->update= update_func_str; + if (!(opt->flags & PLUGIN_VAR_MEMALLOC)) + opt->flags |= PLUGIN_VAR_READONLY; + } + break; + case PLUGIN_VAR_ENUM: + if (!opt->check) + opt->check= check_func_enum; + if (!opt->update) + opt->update= update_func_long; + break; + case PLUGIN_VAR_SET: + if (!opt->check) + opt->check= check_func_set; + if (!opt->update) + opt->update= update_func_long; + break; + default: + sql_print_error("Unknown variable type code 0x%x in plugin '%s'.", + opt->flags, tmp->plugin->name); + DBUG_RETURN(-1); + } + + if (opt->flags & PLUGIN_VAR_NOCMDOPT) + continue; + + if (!opt->name) + { + sql_print_error("Missing variable name in plugin '%s'.", + tmp->plugin->name); + DBUG_RETURN(-1); + } + + if (!(v= find_bookmark(name, opt->name, opt->flags))) + { + optnamelen= strlen(opt->name); + optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2); + strxmov(optname, name, "-", opt->name, NullS); + optnamelen= namelen + optnamelen + 1; + } + else + optname= memdup_root(mem_root, v->name + 1, (optnamelen= v->name_len) + 1); + + /* convert '_' to '-' */ + for (p= optname; *p; p++) + if (*p == '_') + *p= '-'; + + options->name= optname; + options->comment= opt->comment; + options->app_type= (long) opt; + options->id= (options-1)->id + 1; + + if (opt->flags & PLUGIN_VAR_THDLOCAL) + *(int*)(opt + 1)= offset= v->offset; + + plugin_opt_set_limits(options, opt); + + if ((opt->flags & PLUGIN_VAR_TYPEMASK) != PLUGIN_VAR_ENUM && + (opt->flags & PLUGIN_VAR_TYPEMASK) != PLUGIN_VAR_SET) + { + if (opt->flags & PLUGIN_VAR_THDLOCAL) + options->value= options->u_max_value= (gptr*) + (global_system_variables.dynamic_variables_ptr + offset); + else + options->value= options->u_max_value= *(gptr**) (opt + 1); + } + + options[1]= options[0]; + options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8); + options[1].comment= NULL; /* hide this option */ + strxmov(p, "plugin-", optname, NullS); + + options+= 2; + } + + DBUG_RETURN(0); +} + + +static my_option *construct_help_options(MEM_ROOT *mem_root, + struct st_plugin_int *p) +{ + st_mysql_sys_var **opt; + my_option *opts; + my_bool dummy; + my_bool *dummy2= &dummy; + uint count= EXTRA_OPTIONS; + DBUG_ENTER("construct_help_options"); + + for (opt= p->plugin->system_vars; opt && *opt; opt++, count++); + + if (!(opts= (my_option*) alloc_root(mem_root, sizeof(my_option) * count))) + DBUG_RETURN(NULL); + + bzero(opts, sizeof(my_option) * count); + + if (construct_options(mem_root, p, opts, &dummy2, FALSE)) + DBUG_RETURN(NULL); + + DBUG_RETURN(opts); +} + + +/* + SYNOPSIS + test_plugin_options() + tmp_root temporary scratch space + plugin internal plugin structure + argc user supplied arguments + argv user supplied arguments + default_enabled default plugin enable status + RETURNS: + 0 SUCCESS - plugin should be enabled/loaded + NOTE: + Requires that a write-lock is held on LOCK_system_variables_hash +*/ +static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, + int *argc, char **argv, my_bool default_enabled) +{ + struct sys_var_chain chain= { NULL, NULL }; + my_bool enabled_saved= default_enabled, can_disable; + my_bool *enabled= &default_enabled; + MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ? + &tmp->mem_root : &plugin_mem_root; + st_mysql_sys_var **opt; + my_option *opts; + char *p, *varname; + int error; + st_mysql_sys_var *o; + sys_var *v; + struct st_bookmark *var; + uint len, count= EXTRA_OPTIONS; + DBUG_ENTER("test_plugin_options"); + DBUG_ASSERT(tmp->plugin && tmp->plugin->name); + + for (opt= tmp->plugin->system_vars; opt && *opt; opt++) + count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */ + + can_disable= + my_strcasecmp(&my_charset_latin1, tmp->plugin->name, "MyISAM") && + my_strcasecmp(&my_charset_latin1, tmp->plugin->name, "MEMORY"); + + if (count > EXTRA_OPTIONS || (*argc > 1)) + { + if (!(opts= (my_option*) alloc_root(tmp_root, sizeof(my_option) * count))) + { + sql_print_error("Out of memory for plugin '%s'.", tmp->plugin->name); + DBUG_RETURN(-1); + } + bzero(opts, sizeof(my_option) * count); + + if (construct_options(tmp_root, tmp, opts, &enabled, can_disable)) + { + sql_print_error("Bad options for plugin '%s'.", tmp->plugin->name); + DBUG_RETURN(-1); + } + + error= handle_options(argc, &argv, opts, get_one_option); + (*argc)++; /* add back one for the program name */ + + if (error) + { + sql_print_error("Parsing options for plugin '%s' failed.", + tmp->plugin->name); + DBUG_RETURN(error); + } + } + + if (!*enabled && !can_disable) + { + sql_print_warning("Plugin '%s' cannot be disabled", tmp->plugin->name); + *enabled= TRUE; + } + + if (*enabled) + { + for (opt= tmp->plugin->system_vars; opt && *opt; opt++) + { + if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR)) + continue; + + if ((var= find_bookmark(tmp->plugin->name, o->name, o->flags))) + v= new (mem_root) sys_var_pluginvar(var->name + 1, tmp, o); + else + { + len= strlen(tmp->plugin->name) + strlen(o->name) + 2; + varname= (char*) alloc_root(mem_root, len); + strxmov(varname, tmp->plugin->name, "-", o->name, NullS); + my_casedn_str(&my_charset_latin1, varname); + + for (p= varname; *p; p++) + if (*p == '-') + *p= '_'; + + v= new (mem_root) sys_var_pluginvar(varname, tmp, o); + } + DBUG_ASSERT(v); /* check that an object was actually constructed */ + + v->chain_sys_var(&chain); + } + if (chain.first) + { + chain.last->next = NULL; + if (mysql_add_sys_var_chain(chain.first, NULL)) + { + sql_print_error("Plugin '%s' has conflicting system variables", + tmp->plugin->name); + DBUG_RETURN(1); + } + tmp->system_vars= chain.first; + } + DBUG_RETURN(0); + } + + if (enabled_saved) + sql_print_information("Plugin '%s' disabled by command line option", + tmp->plugin->name); + DBUG_RETURN(1); +} + + +/**************************************************************************** + Help Verbose text with Plugin System Variables +****************************************************************************/ + +static int option_cmp(my_option *a, my_option *b) +{ + return my_strcasecmp(&my_charset_latin1, a->name, b->name); +} + + +void my_print_help_inc_plugins(my_option *main_options, uint size) +{ + DYNAMIC_ARRAY all_options; + struct st_plugin_int *p; + MEM_ROOT mem_root; + my_option *opt; + + init_alloc_root(&mem_root, 4096, 4096); + my_init_dynamic_array(&all_options, sizeof(my_option), size, size/4); + + if (initialized) + for (uint idx= 0; idx < plugin_array.elements; idx++) + { + p= dynamic_element(&plugin_array, idx, struct st_plugin_int *); + + if (!p->plugin->system_vars || + !(opt= construct_help_options(&mem_root, p))) + continue; + + /* Only options with a non-NULL comment are displayed in help text */ + for (;opt->id; opt++) + if (opt->comment) + insert_dynamic(&all_options, (gptr) opt); + } + + for (;main_options->id; main_options++) + insert_dynamic(&all_options, (gptr) main_options); + + sort_dynamic(&all_options, (qsort_cmp) option_cmp); + + /* main_options now points to the empty option terminator */ + insert_dynamic(&all_options, (gptr) main_options); + + my_print_help((my_option*) all_options.buffer); + my_print_variables((my_option*) all_options.buffer); + + delete_dynamic(&all_options); + free_root(&mem_root, MYF(0)); +} + diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index d86d9332a92..b3293f3ebda 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -16,6 +16,17 @@ #ifndef _sql_plugin_h #define _sql_plugin_h +class sys_var; + +/* + the following flags are valid for plugin_init() +*/ +#define PLUGIN_INIT_SKIP_DYNAMIC_LOADING 1 +#define PLUGIN_INIT_SKIP_PLUGIN_TABLE 2 +#define PLUGIN_INIT_SKIP_INITIALIZATION 4 + +#define INITIAL_LEX_PLUGIN_LIST_SIZE 16 + /* the following #define adds server-only members to enum_mysql_show_type, that is defined in plugin.h @@ -41,6 +52,7 @@ typedef struct st_mysql_show_var SHOW_VAR; #define PLUGIN_IS_DELETED 2 #define PLUGIN_IS_UNINITIALIZED 4 #define PLUGIN_IS_READY 8 +#define PLUGIN_IS_DYING 16 /* A handle for the dynamic library containing a plugin or plugins. */ @@ -63,25 +75,57 @@ struct st_plugin_int uint state; uint ref_count; /* number of threads using the plugin */ void *data; /* plugin type specific, e.g. handlerton */ + MEM_ROOT mem_root; /* memory for dynamic plugin structures */ + sys_var *system_vars; /* server variables for this plugin */ }; +#ifdef DBUG_OFF +typedef struct st_plugin_int *plugin_ref; +#define plugin_decl(pi) ((pi)->plugin) +#define plugin_dlib(pi) ((pi)->plugin_dl) +#define plugin_data(pi,cast) ((cast)((pi)->data)) +#define plugin_name(pi) (&((pi)->name)) +#define plugin_state(pi) ((pi)->state) +#else +typedef struct st_plugin_int **plugin_ref; +#define plugin_decl(pi) ((pi)[0]->plugin) +#define plugin_dlib(pi) ((pi)[0]->plugin_dl) +#define plugin_data(pi,cast) ((cast)((pi)[0]->data)) +#define plugin_name(pi) (&((pi)[0]->name)) +#define plugin_state(pi) ((pi)[0]->state) +#endif + typedef int (*plugin_type_init)(struct st_plugin_int *); +extern char *opt_plugin_load; extern char *opt_plugin_dir_ptr; extern char opt_plugin_dir[FN_REFLEN]; extern const LEX_STRING plugin_type_names[]; -extern int plugin_init(int); + +extern int plugin_init(int *argc, char **argv, int init_flags); extern void plugin_shutdown(void); -extern my_bool plugin_is_ready(const LEX_STRING *name, int type); -extern st_plugin_int *plugin_lock(const LEX_STRING *name, int type); -extern void plugin_unlock(struct st_plugin_int *plugin); -extern my_bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl); -extern my_bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name); +extern void my_print_help_inc_plugins(struct my_option *options, uint size); +extern bool plugin_is_ready(const LEX_STRING *name, int type); +#define my_plugin_lock_by_name(A,B,C) plugin_lock_by_name(A,B,C CALLER_INFO) +#define my_plugin_lock_by_name_ci(A,B,C) plugin_lock_by_name(A,B,C ORIG_CALLER_INFO) +#define my_plugin_lock(A,B) plugin_lock(A,B CALLER_INFO) +#define my_plugin_lock_ci(A,B) plugin_lock(A,B ORIG_CALLER_INFO) +extern plugin_ref plugin_lock(THD *thd, plugin_ref *ptr CALLER_INFO_PROTO); +extern plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, + int type CALLER_INFO_PROTO); +extern void plugin_unlock(THD *thd, plugin_ref plugin); +extern void plugin_unlock_list(THD *thd, plugin_ref *list, uint count); +extern bool mysql_install_plugin(THD *thd, const LEX_STRING *name, + const LEX_STRING *dl); +extern bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name); +extern bool plugin_register_builtin(struct st_mysql_plugin *plugin); +extern void plugin_thdvar_init(THD *thd, bool lock_locals); +extern void plugin_thdvar_cleanup(THD *thd); typedef my_bool (plugin_foreach_func)(THD *thd, - st_plugin_int *plugin, + plugin_ref plugin, void *arg); #define plugin_foreach(A,B,C,D) plugin_foreach_with_mask(A,B,C,PLUGIN_IS_READY,D) -extern my_bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, - int type, uint state_mask, void *arg); +extern bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, + int type, uint state_mask, void *arg); #endif diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 17163fb1940..589381ca61f 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1596,6 +1596,149 @@ int log_loaded_block(IO_CACHE* file) return 0; } +/* + Replication System Variables +*/ + +class sys_var_slave_skip_counter :public sys_var +{ +public: + sys_var_slave_skip_counter(sys_var_chain *chain, const char *name_arg) + :sys_var(name_arg) + { chain_sys_var(chain); } + bool check(THD *thd, set_var *var); + bool update(THD *thd, set_var *var); + bool check_type(enum_var_type type) { return type != OPT_GLOBAL; } + /* + We can't retrieve the value of this, so we don't have to define + type() or value_ptr() + */ +}; + +class sys_var_sync_binlog_period :public sys_var_long_ptr +{ +public: + sys_var_sync_binlog_period(sys_var_chain *chain, const char *name_arg, + ulong *value_ptr) + :sys_var_long_ptr(chain, name_arg,value_ptr) {} + bool update(THD *thd, set_var *var); +}; + +static sys_var_chain vars = { NULL, NULL }; + +static sys_var_bool_ptr sys_relay_log_purge(&vars, "relay_log_purge", + &relay_log_purge); +static sys_var_long_ptr sys_slave_net_timeout(&vars, "slave_net_timeout", + &slave_net_timeout); +static sys_var_long_ptr sys_slave_trans_retries(&vars, "slave_transaction_retries", + &slave_trans_retries); +static sys_var_sync_binlog_period sys_sync_binlog_period(&vars, "sync_binlog", &sync_binlog_period); +static sys_var_slave_skip_counter sys_slave_skip_counter(&vars, "sql_slave_skip_counter"); + +static int show_slave_skip_errors(THD *thd, SHOW_VAR *var, char *buff); + + +static SHOW_VAR fixed_vars[]= { + {"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_MY_BOOL}, + {"relay_log_space_limit", (char*) &relay_log_space_limit, SHOW_LONGLONG}, + {"slave_load_tmpdir", (char*) &slave_load_tmpdir, SHOW_CHAR_PTR}, + {"slave_skip_errors", (char*) &show_slave_skip_errors, SHOW_FUNC}, +}; + +static int show_slave_skip_errors(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type=SHOW_CHAR; + var->value= buff; + if (!use_slave_mask || bitmap_is_clear_all(&slave_error_mask)) + { + var->value= const_cast<char *>("OFF"); + } + else if (bitmap_is_set_all(&slave_error_mask)) + { + var->value= const_cast<char *>("ALL"); + } + else + { + /* 10 is enough assuming errors are max 4 digits */ + int i; + var->value= buff; + for (i= 1; + i < MAX_SLAVE_ERROR && + (buff - var->value) < SHOW_VAR_FUNC_BUFF_SIZE; + i++) + { + if (bitmap_is_set(&slave_error_mask, i)) + { + buff= int10_to_str(i, buff, 10); + *buff++= ','; + } + } + if (var->value != buff) + buff--; // Remove last ',' + if (i < MAX_SLAVE_ERROR) + buff= strmov(buff, "..."); // Couldn't show all errors + *buff=0; + } + return 0; +} + +bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) +{ + int result= 0; + pthread_mutex_lock(&LOCK_active_mi); + pthread_mutex_lock(&active_mi->rli.run_lock); + if (active_mi->rli.slave_running) + { + my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0)); + result=1; + } + pthread_mutex_unlock(&active_mi->rli.run_lock); + pthread_mutex_unlock(&LOCK_active_mi); + var->save_result.ulong_value= (ulong) var->value->val_int(); + return result; +} + + +bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) +{ + pthread_mutex_lock(&LOCK_active_mi); + pthread_mutex_lock(&active_mi->rli.run_lock); + /* + The following test should normally never be true as we test this + in the check function; To be safe against multiple + SQL_SLAVE_SKIP_COUNTER request, we do the check anyway + */ + if (!active_mi->rli.slave_running) + { + pthread_mutex_lock(&active_mi->rli.data_lock); + active_mi->rli.slave_skip_counter= var->save_result.ulong_value; + pthread_mutex_unlock(&active_mi->rli.data_lock); + } + pthread_mutex_unlock(&active_mi->rli.run_lock); + pthread_mutex_unlock(&LOCK_active_mi); + return 0; +} + + +bool sys_var_sync_binlog_period::update(THD *thd, set_var *var) +{ + sync_binlog_period= (ulong) var->save_result.ulonglong_value; + return 0; +} + +int init_replication_sys_vars() +{ + mysql_append_static_vars(fixed_vars, sizeof(fixed_vars) / sizeof(SHOW_VAR)); + + if (mysql_add_sys_var_chain(vars.first, my_long_options)) + { + /* should not happen */ + fprintf(stderr, "failed to initialize replication system variables"); + unireg_abort(1); + } + return 0; +} + #endif /* HAVE_REPLICATION */ diff --git a/sql/sql_repl.h b/sql/sql_repl.h index b106391245d..da50d47c60d 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -67,6 +67,7 @@ typedef struct st_load_file_info } LOAD_FILE_INFO; int log_loaded_block(IO_CACHE* file); +int init_replication_sys_vars(); #endif /* HAVE_REPLICATION */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 75b3f5ae981..47495cb5ec3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9458,12 +9458,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, share->fields= field_count; /* If result table is small; use a heap */ + /* future: storage engine selection can be made dynamic? */ if (blob_count || using_unique_constraint || (select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) == OPTION_BIG_TABLES || (select_options & TMP_TABLE_FORCE_MYISAM)) { + share->db_plugin= ha_lock_engine(0, myisam_hton); table->file= get_new_handler(share, &table->mem_root, - share->db_type= myisam_hton); + share->db_type()); if (group && (param->group_parts > table->file->max_key_parts() || param->group_length > table->file->max_key_length())) @@ -9471,8 +9473,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, } else { + share->db_plugin= ha_lock_engine(0, heap_hton); table->file= get_new_handler(share, &table->mem_root, - share->db_type= heap_hton); + share->db_type()); } if (!table->file) goto err; @@ -9633,7 +9636,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, if (thd->variables.tmp_table_size == ~ (ulonglong) 0) // No limit share->max_rows= ~(ha_rows) 0; else - share->max_rows= (ha_rows) (((share->db_type == heap_hton) ? + share->max_rows= (ha_rows) (((share->db_type() == heap_hton) ? min(thd->variables.tmp_table_size, thd->variables.max_heap_table_size) : thd->variables.tmp_table_size) / @@ -9781,7 +9784,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, if (thd->is_fatal_error) // If end of memory goto err; /* purecov: inspected */ share->db_record_offset= 1; - if (share->db_type == myisam_hton) + if (share->db_type() == myisam_hton) { if (create_myisam_tmp_table(table,param,select_options)) goto err; @@ -10088,6 +10091,8 @@ free_tmp_table(THD *thd, TABLE *entry) if (entry->temp_pool_slot != MY_BIT_NONE) bitmap_lock_clear_bit(&temp_pool, entry->temp_pool_slot); + plugin_unlock(0, entry->s->db_plugin); + free_root(&own_root, MYF(0)); /* the table is allocated in its own root */ thd->proc_info=save_proc_info; @@ -10107,7 +10112,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, int write_err; DBUG_ENTER("create_myisam_from_heap"); - if (table->s->db_type != heap_hton || + if (table->s->db_type() != heap_hton || error != HA_ERR_RECORD_FILE_FULL) { table->file->print_error(error,MYF(0)); @@ -10116,9 +10121,9 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, new_table= *table; share= *table->s; new_table.s= &share; - new_table.s->db_type= myisam_hton; + new_table.s->db_plugin= ha_lock_engine(thd, myisam_hton); if (!(new_table.file= get_new_handler(&share, &new_table.mem_root, - myisam_hton))) + new_table.s->db_type()))) DBUG_RETURN(1); // End of memory save_proc_info=thd->proc_info; @@ -10176,9 +10181,12 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, (void) table->file->delete_table(table->s->table_name.str); delete table->file; table->file=0; + plugin_unlock(0, table->s->db_plugin); + share.db_plugin= my_plugin_lock(0, &share.db_plugin); new_table.s= table->s; // Keep old share *table= new_table; *table->s= share; + table->file->change_table_ptr(table, table->s); table->use_all_columns(); if (save_proc_info) @@ -12761,7 +12769,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having) free_io_cache(entry); // Safety entry->file->info(HA_STATUS_VARIABLE); - if (entry->s->db_type == heap_hton || + if (entry->s->db_type() == heap_hton || (!entry->s->blob_fields && ((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->file->stats.records < thd->variables.sortbuff_size))) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 250d9d917eb..17f9c516971 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -77,24 +77,24 @@ append_algorithm(TABLE_LIST *table, String *buff); ** List all table types supported ***************************************************************************/ -static my_bool show_handlerton(THD *thd, st_plugin_int *plugin, +static my_bool show_handlerton(THD *thd, plugin_ref plugin, void *arg) { handlerton *default_type= (handlerton *) arg; Protocol *protocol= thd->protocol; - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if (!(hton->flags & HTON_HIDDEN)) { protocol->prepare_for_resend(); - protocol->store(plugin->name.str, plugin->name.length, + protocol->store(plugin_name(plugin)->str, plugin_name(plugin)->length, system_charset_info); const char *option_name= show_comp_option_name[(int) hton->state]; if (hton->state == SHOW_OPTION_YES && default_type == hton) option_name= "DEFAULT"; protocol->store(option_name, system_charset_info); - protocol->store(plugin->plugin->descr, system_charset_info); + protocol->store(plugin_decl(plugin)->descr, system_charset_info); protocol->store(hton->commit ? "YES" : "NO", system_charset_info); protocol->store(hton->prepare ? "YES" : "NO", system_charset_info); protocol->store(hton->savepoint_set ? "YES" : "NO", system_charset_info); @@ -122,7 +122,7 @@ bool mysqld_show_storage_engines(THD *thd) DBUG_RETURN(TRUE); if (plugin_foreach(thd, show_handlerton, - MYSQL_STORAGE_ENGINE_PLUGIN, thd->variables.table_type)) + MYSQL_STORAGE_ENGINE_PLUGIN, ha_default_handlerton(thd))) DBUG_RETURN(TRUE); send_eof(thd); @@ -134,24 +134,26 @@ static int make_version_string(char *buf, int buf_length, uint version) return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff); } -static my_bool show_plugins(THD *thd, st_plugin_int *plugin, +static my_bool show_plugins(THD *thd, plugin_ref plugin, void *arg) { TABLE *table= (TABLE*) arg; - struct st_mysql_plugin *plug= plugin->plugin; + struct st_mysql_plugin *plug= plugin_decl(plugin); + struct st_plugin_dl *plugin_dl= plugin_dlib(plugin); CHARSET_INFO *cs= system_charset_info; char version_buf[20]; restore_record(table, s->default_values); - table->field[0]->store(plugin->name.str, plugin->name.length, cs); + table->field[0]->store(plugin_name(plugin)->str, + plugin_name(plugin)->length, cs); table->field[1]->store(version_buf, make_version_string(version_buf, sizeof(version_buf), plug->version), cs); - switch (plugin->state) { + switch (plugin_state(plugin)) { /* case PLUGIN_IS_FREED: does not happen */ case PLUGIN_IS_DELETED: table->field[2]->store(STRING_WITH_LEN("DELETED"), cs); @@ -173,14 +175,13 @@ static my_bool show_plugins(THD *thd, st_plugin_int *plugin, make_version_string(version_buf, sizeof(version_buf), *(uint *)plug->info), cs); - if (plugin->plugin_dl) + if (plugin_dl) { - table->field[5]->store(plugin->plugin_dl->dl.str, - plugin->plugin_dl->dl.length, cs); + table->field[5]->store(plugin_dl->dl.str, plugin_dl->dl.length, cs); table->field[5]->set_notnull(); table->field[6]->store(version_buf, make_version_string(version_buf, sizeof(version_buf), - plugin->plugin_dl->version), + plugin_dl->version), cs); table->field[6]->set_notnull(); } @@ -1236,9 +1237,9 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, store_key_options(thd, packet, table, key_info); if (key_info->parser) { + LEX_STRING *parser_name= plugin_name(key_info->parser); packet->append(STRING_WITH_LEN(" /*!50100 WITH PARSER ")); - append_identifier(thd, packet, key_info->parser->name.str, - key_info->parser->name.length); + append_identifier(thd, packet, parser_name->str, parser_name->length); packet->append(STRING_WITH_LEN(" */ ")); } } @@ -1933,6 +1934,18 @@ void init_status_vars() sort_dynamic(&all_status_vars, show_var_cmp); } +void reset_status_vars() +{ + SHOW_VAR *ptr= (SHOW_VAR*) all_status_vars.buffer; + SHOW_VAR *last= ptr + all_status_vars.elements; + for (; ptr < last; ptr++) + { + /* Note that SHOW_LONG_NOFLUSH variables are not reset */ + if (ptr->type == SHOW_LONG) + *(ulong*) ptr->value= 0; + } +} + /* catch-all cleanup function, cleans up everything no matter what @@ -2063,6 +2076,8 @@ static bool show_status_array(THD *thd, const char *wild, char *value=var->value; const char *pos, *end; // We assign a lot of const's + pthread_mutex_lock(&LOCK_global_system_variables); + if (show_type == SHOW_SYS) { show_type= ((sys_var*) value)->show_type(); @@ -2145,6 +2160,9 @@ static bool show_status_array(THD *thd, const char *wild, system_charset_info); table->field[1]->store(pos, (uint32) (end - pos), system_charset_info); table->field[1]->set_notnull(); + + pthread_mutex_unlock(&LOCK_global_system_variables); + if (schema_table_store_record(thd, table)) DBUG_RETURN(TRUE); } @@ -2455,13 +2473,13 @@ struct st_add_schema_table const char *wild; }; -static my_bool add_schema_table(THD *thd, st_plugin_int *plugin, +static my_bool add_schema_table(THD *thd, plugin_ref plugin, void* p_data) { st_add_schema_table *data= (st_add_schema_table *)p_data; List<char> *file_list= data->files; const char *wild= data->wild; - ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data; + ST_SCHEMA_TABLE *schema_table= plugin_data(plugin, ST_SCHEMA_TABLE *); DBUG_ENTER("add_schema_table"); if (schema_table->hidden) @@ -2995,7 +3013,7 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables, ha_row_type[(uint) share->row_type], NullS); #ifdef WITH_PARTITION_STORAGE_ENGINE - if (show_table->s->db_type == partition_hton && + if (show_table->s->db_type() == partition_hton && show_table->part_info != NULL && show_table->part_info->no_parts > 0) ptr= strmov(ptr, " partitioned"); @@ -3270,19 +3288,20 @@ int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond) } -static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin, +static my_bool iter_schema_engines(THD *thd, plugin_ref plugin, void *ptable) { TABLE *table= (TABLE *) ptable; - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; CHARSET_INFO *scs= system_charset_info; DBUG_ENTER("iter_schema_engines"); if (!(hton->flags & HTON_HIDDEN)) { + LEX_STRING *name= plugin_name(plugin); if (!(wild && wild[0] && - wild_case_compare(scs, plugin->name.str,wild))) + wild_case_compare(scs, name->str,wild))) { LEX_STRING state[2]= {{ C_STRING_WITH_LEN("ENABLED") }, { C_STRING_WITH_LEN("DISABLED") }}; @@ -3291,11 +3310,11 @@ static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin, LEX_STRING *tmp; restore_record(table, s->default_values); - table->field[0]->store(plugin->name.str, plugin->name.length, scs); + table->field[0]->store(name->str, name->length, scs); tmp= &state[test(hton->state)]; table->field[1]->store(tmp->str, tmp->length, scs); - table->field[2]->store(plugin->plugin->descr, - strlen(plugin->plugin->descr), scs); + table->field[2]->store(plugin_decl(plugin)->descr, + strlen(plugin_decl(plugin)->descr), scs); tmp= &yesno[test(hton->commit)]; table->field[3]->store(tmp->str, tmp->length, scs); tmp= &yesno[test(hton->prepare)]; @@ -4464,10 +4483,10 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond) int res= 0; LEX *lex= thd->lex; const char *wild= lex->wild ? lex->wild->ptr() : NullS; - pthread_mutex_lock(&LOCK_global_system_variables); - res= show_status_array(thd, wild, init_vars, + rw_rdlock(&LOCK_system_variables_hash); + res= show_status_array(thd, wild, enumerate_sys_vars(thd, TRUE), lex->option_type, 0, "", tables->table, 0); - pthread_mutex_unlock(&LOCK_global_system_variables); + rw_unlock(&LOCK_system_variables_hash); DBUG_RETURN(res); } @@ -4583,12 +4602,12 @@ struct schema_table_ref 0 table not found 1 found the schema table */ -static my_bool find_schema_table_in_plugin(THD *thd, st_plugin_int *plugin, +static my_bool find_schema_table_in_plugin(THD *thd, plugin_ref plugin, void* p_table) { schema_table_ref *p_schema_table= (schema_table_ref *)p_table; const char* table_name= p_schema_table->table_name; - ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data; + ST_SCHEMA_TABLE *schema_table= plugin_data(plugin, ST_SCHEMA_TABLE *); DBUG_ENTER("find_schema_table_in_plugin"); if (!my_strcasecmp(system_charset_info, @@ -5125,12 +5144,12 @@ struct run_hton_fill_schema_files_args COND *cond; }; -static my_bool run_hton_fill_schema_files(THD *thd, st_plugin_int *plugin, +static my_bool run_hton_fill_schema_files(THD *thd, plugin_ref plugin, void *arg) { struct run_hton_fill_schema_files_args *args= (run_hton_fill_schema_files_args *) arg; - handlerton *hton= (handlerton *)plugin->data; + handlerton *hton= plugin_data(plugin, handlerton *); if(hton->fill_files_table && hton->state == SHOW_OPTION_YES) hton->fill_files_table(hton, thd, args->tables, args->cond); return false; @@ -5296,10 +5315,10 @@ int fill_schema_global_variables(THD *thd, TABLE_LIST *tables, COND *cond) int res= 0; DBUG_ENTER("fill_schema_global_variables"); - pthread_mutex_lock(&LOCK_global_system_variables); - res= show_status_array(thd, "", init_vars, OPT_GLOBAL, + rw_rdlock(&LOCK_system_variables_hash); + res= show_status_array(thd, "", enumerate_sys_vars(thd, FALSE), OPT_GLOBAL, NULL, "", tables->table, 1); - pthread_mutex_unlock(&LOCK_global_system_variables); + rw_unlock(&LOCK_system_variables_hash); DBUG_RETURN(res); } @@ -5309,10 +5328,10 @@ int fill_schema_session_variables(THD *thd, TABLE_LIST *tables, COND *cond) int res= 0; DBUG_ENTER("fill_schema_session_variables"); - pthread_mutex_lock(&LOCK_global_system_variables); - res= show_status_array(thd, "", init_vars, OPT_SESSION, + rw_rdlock(&LOCK_system_variables_hash); + res= show_status_array(thd, "", enumerate_sys_vars(thd, FALSE), OPT_SESSION, NULL, "", tables->table, 1); - pthread_mutex_unlock(&LOCK_global_system_variables); + rw_unlock(&LOCK_system_variables_hash); DBUG_RETURN(res); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 36f0acd8f67..5998423790b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -662,16 +662,14 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry) frm_action= TRUE; else { - TABLE_SHARE dummy; - - hton= ha_resolve_by_name(thd, &handler_name); - if (!hton) + plugin_ref plugin= ha_resolve_by_name(thd, &handler_name); + if (!plugin) { my_error(ER_ILLEGAL_HA, MYF(0), ddl_log_entry->handler_name); goto error; } - bzero(&dummy, sizeof(TABLE_SHARE)); - file= get_new_handler(&dummy, &mem_root, hton); + hton= plugin_data(plugin, handlerton*); + file= get_new_handler((TABLE_SHARE*)0, &mem_root, hton); if (!file) { mem_alloc_error(sizeof(handler)); @@ -1635,7 +1633,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, TABLE_SHARE *share; table->db_type= NULL; if ((share= get_cached_table_share(table->db, table->table_name))) - table->db_type= share->db_type; + table->db_type= share->db_type(); /* Disable drop of enabled log tables */ if (share && share->log_table && @@ -5031,7 +5029,7 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list, See BUG#6236. */ if (table->s->fields != create_list->elements || - table->s->db_type != create_info->db_type || + table->s->db_type() != create_info->db_type || table->s->tmp_table || create_info->used_fields & HA_CREATE_USED_ENGINE || create_info->used_fields & HA_CREATE_USED_CHARSET || @@ -5490,7 +5488,7 @@ view_err: new_name= table_name; } - old_db_type= table->s->db_type; + old_db_type= table->s->db_type(); if (!create_info->db_type) { #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -6002,7 +6000,7 @@ view_err: } if (thd->variables.old_alter_table - || (table->s->db_type != create_info->db_type) + || (table->s->db_type() != create_info->db_type) #ifdef WITH_PARTITION_STORAGE_ENGINE || partition_changed #endif @@ -6040,8 +6038,8 @@ view_err: uint *idx_p; uint *idx_end_p; - if (table->s->db_type->alter_table_flags) - alter_flags= table->s->db_type->alter_table_flags(alter_info->flags); + if (table->s->db_type()->alter_table_flags) + alter_flags= table->s->db_type()->alter_table_flags(alter_info->flags); DBUG_PRINT("info", ("alter_flags: %lu", alter_flags)); /* Check dropped indexes. */ for (idx_p= index_drop_buffer, idx_end_p= idx_p + index_drop_count; @@ -7066,7 +7064,7 @@ static bool check_engine(THD *thd, const char *table_name, if (create_info->used_fields & HA_CREATE_USED_ENGINE) { my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), - hton2plugin[(*new_engine)->slot]->name.str, "TEMPORARY"); + ha_resolve_storage_engine_name(*new_engine), "TEMPORARY"); *new_engine= 0; return TRUE; } diff --git a/sql/sql_tablespace.cc b/sql/sql_tablespace.cc index 84391a54642..b4a03a370ba 100644 --- a/sql/sql_tablespace.cc +++ b/sql/sql_tablespace.cc @@ -34,7 +34,7 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_WARN_USING_OTHER_HANDLER, ER(ER_WARN_USING_OTHER_HANDLER), - hton2plugin[hton->slot]->name.str, + ha_resolve_storage_engine_name(hton), ts_info->tablespace_name ? ts_info->tablespace_name : ts_info->logfile_group_name); } @@ -63,7 +63,7 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_ILLEGAL_HA_CREATE_OPTION, ER(ER_ILLEGAL_HA_CREATE_OPTION), - hton2plugin[hton->slot]->name.str, + ha_resolve_storage_engine_name(hton), "TABLESPACE or LOGFILE GROUP"); } if (mysql_bin_log.is_open()) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9c062407921..b9eb9d9ffc9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1043,7 +1043,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <interval_time_st> interval_time_st -%type <db_type> storage_engines +%type <db_type> storage_engines known_storage_engine %type <row_type> row_types @@ -1447,14 +1447,26 @@ create: lex->change=NullS; bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.options=$2 | $4; - lex->create_info.db_type= lex->thd->variables.table_type; + lex->create_info.db_type= ha_default_handlerton(thd); lex->create_info.default_table_charset= NULL; lex->name.str= 0; lex->name.length= 0; lex->like_name= 0; } create2 - { Lex->current_select= &Lex->select_lex; } + { + LEX *lex= YYTHD->lex; + lex->current_select= &lex->select_lex; + if (!lex->create_info.db_type) + { + lex->create_info.db_type= ha_default_handlerton(YYTHD); + push_warning_printf(YYTHD, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_USING_OTHER_HANDLER, + ER(ER_WARN_USING_OTHER_HANDLER), + ha_resolve_storage_engine_name(lex->create_info.db_type), + $5->table.str); + } + } | CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident { @@ -3365,7 +3377,7 @@ opt_ts_comment: }; opt_ts_engine: - opt_storage ENGINE_SYM opt_equal storage_engines + opt_storage ENGINE_SYM opt_equal known_storage_engine { LEX *lex= Lex; if (lex->alter_tablespace_info->storage_engine != NULL) @@ -3533,6 +3545,13 @@ partitioning: { #ifdef WITH_PARTITION_STORAGE_ENGINE LEX *lex= Lex; + LEX_STRING partition_name={C_STRING_WITH_LEN("partition")}; + if (!plugin_is_ready(&partition_name, MYSQL_STORAGE_ENGINE_PLUGIN)) + { + my_error(ER_FEATURE_DISABLED, MYF(0), + "partitioning", "--with-partition"); + YYABORT; + } lex->part_info= new partition_info(); if (!lex->part_info) { @@ -4046,7 +4065,7 @@ opt_part_option_list: opt_part_option: TABLESPACE opt_equal ident_or_text { Lex->part_info->curr_part_elem->tablespace_name= $3.str; } - | opt_storage ENGINE_SYM opt_equal storage_engines + | opt_storage ENGINE_SYM opt_equal known_storage_engine { LEX *lex= Lex; lex->part_info->curr_part_elem->engine_type= $4; @@ -4251,21 +4270,43 @@ default_collation: storage_engines: ident_or_text { - $$ = ha_resolve_by_name(YYTHD, &$1); - if ($$ == NULL) + LEX *lex= YYTHD->lex; + plugin_ref plugin; + + if ((plugin= ha_resolve_by_name(YYTHD, &$1))) + $$= plugin_data(plugin, handlerton*); + else if (YYTHD->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION) { my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str); YYABORT; } else + if (lex->sql_command == SQLCOM_ALTER_TABLE) { - push_warning_printf(YYTHD, MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_UNKNOWN_STORAGE_ENGINE, - ER(ER_UNKNOWN_STORAGE_ENGINE), $1.str); + TABLE_LIST *table= (TABLE_LIST *) lex->select_lex.table_list.first; + $$= ha_default_handlerton(YYTHD); + push_warning_printf(YYTHD, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_USING_OTHER_HANDLER, + ER(ER_WARN_USING_OTHER_HANDLER), + ha_resolve_storage_engine_name($$), + table->table_name); } }; +known_storage_engine: + ident_or_text + { + plugin_ref plugin; + if ((plugin= ha_resolve_by_name(YYTHD, &$1))) + $$= plugin_data(plugin, handlerton*); + else + { + my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str); + YYABORT; + } + }; + row_types: DEFAULT { $$= ROW_TYPE_DEFAULT; } | FIXED_SYM { $$= ROW_TYPE_FIXED; } @@ -8452,7 +8493,7 @@ show_param: if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS)) YYABORT; } - | ENGINE_SYM storage_engines + | ENGINE_SYM known_storage_engine { Lex->create_info.db_type= $2; } show_engine_param | ENGINE_SYM ALL @@ -10095,7 +10136,7 @@ sys_option_value: LEX *lex=Lex; lex->option_type= $1; lex->var_list.push_back(new set_var(lex->option_type, - find_sys_var("tx_isolation"), + find_sys_var(YYTHD, "tx_isolation"), &null_lex_str, new Item_int((int32) $5))); } @@ -10184,7 +10225,7 @@ internal_variable_name: if (!spc || !(spv = spc->find_variable(&$1))) { /* Not an SP local variable */ - sys_var *tmp=find_sys_var($1.str, $1.length); + sys_var *tmp=find_sys_var(YYTHD, $1.str, $1.length); if (!tmp) YYABORT; $$.var= tmp; @@ -10246,7 +10287,7 @@ internal_variable_name: } else { - sys_var *tmp=find_sys_var($3.str, $3.length); + sys_var *tmp=find_sys_var(YYTHD, $3.str, $3.length); if (!tmp) YYABORT; if (!tmp->is_struct()) @@ -10257,7 +10298,7 @@ internal_variable_name: } | DEFAULT '.' ident { - sys_var *tmp=find_sys_var($3.str, $3.length); + sys_var *tmp=find_sys_var(YYTHD, $3.str, $3.length); if (!tmp) YYABORT; if (!tmp->is_struct()) diff --git a/sql/structs.h b/sql/structs.h index 377d337dcfa..3c08b5a3de1 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -83,7 +83,11 @@ typedef struct st_key { */ union { +#ifdef DBUG_OFF struct st_plugin_int *parser; /* Fulltext [pre]parser */ +#else + struct st_plugin_int **parser; /* Fulltext [pre]parser */ +#endif LEX_STRING *parser_name; /* Fulltext [pre]parser name */ }; KEY_PART_INFO *key_part; diff --git a/sql/table.cc b/sql/table.cc index ed3cac85214..08acaa0304f 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -238,6 +238,9 @@ void free_table_share(TABLE_SHARE *share) pthread_cond_destroy(&share->cond); } hash_free(&share->name_hash); + + plugin_unlock(NULL, share->db_plugin); + share->db_plugin= NULL; /* We must copy mem_root from share because share is allocated through it */ memcpy((char*) &mem_root, (char*) &share->mem_root, sizeof(mem_root)); @@ -422,6 +425,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, Field **field_ptr, *reg_field; const char **interval_array; enum legacy_db_type legacy_db_type; + handlerton *hton; my_bitmap_map *bitmaps; DBUG_ENTER("open_binary_frm"); @@ -452,7 +456,11 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, DBUG_PRINT("info", ("default_part_db_type = %u", head[61])); #endif legacy_db_type= (enum legacy_db_type) (uint) *(head+3); - share->db_type= ha_checktype(thd, legacy_db_type, 0, 0); + if ((hton= ha_checktype(thd, legacy_db_type, 0, 0)) != share->db_type()) + { + plugin_unlock(NULL, share->db_plugin); + share->db_plugin= ha_lock_engine(NULL, hton); + } share->db_create_options= db_create_options= uint2korr(head+30); share->db_options_in_use= share->db_create_options; share->mysql_version= uint4korr(head+51); @@ -611,24 +619,38 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, { uint str_db_type_length= uint2korr(next_chunk); LEX_STRING name= { next_chunk + 2, str_db_type_length }; - handlerton *tmp_db_type= ha_resolve_by_name(thd, &name); - if (tmp_db_type != NULL) + plugin_ref tmp_plugin= ha_resolve_by_name(thd, &name); + if (tmp_plugin != NULL) { - share->db_type= tmp_db_type; + /* + tmp_plugin is locked with a local lock. + we unlock the old value of share->db_plugin before + replacing it with a globally locked version of tmp_plugin + */ + plugin_unlock(NULL, share->db_plugin); + share->db_plugin= my_plugin_lock(NULL, &tmp_plugin); DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)", str_db_type_length, next_chunk + 2, - ha_legacy_type(share->db_type))); + ha_legacy_type(share->db_type()))); } #ifdef WITH_PARTITION_STORAGE_ENGINE else { - if (!strncmp(next_chunk + 2, "partition", str_db_type_length)) + LEX_STRING pname= { C_STRING_WITH_LEN( "partition" ) }; + if (str_db_type_length == pname.length && + !strncmp(next_chunk + 2, pname.str, pname.length)) { - /* Use partition handler */ - share->db_type= partition_hton; + /* + Use partition handler + tmp_plugin is locked with a local lock. + we unlock the old value of share->db_plugin before + replacing it with a globally locked version of tmp_plugin + */ + plugin_unlock(NULL, share->db_plugin); + share->db_plugin= ha_lock_engine(NULL, partition_hton); DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)", str_db_type_length, next_chunk + 2, - ha_legacy_type(share->db_type))); + ha_legacy_type(share->db_type()))); } } #endif @@ -694,7 +716,8 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, } parser_name.str= next_chunk; parser_name.length= strlen(next_chunk); - keyinfo->parser= plugin_lock(&parser_name, MYSQL_FTPARSER_PLUGIN); + keyinfo->parser= my_plugin_lock_by_name(NULL, &parser_name, + MYSQL_FTPARSER_PLUGIN); if (! keyinfo->parser) { my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), parser_name.str); @@ -810,7 +833,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, /* Allocate handler */ if (!(handler_file= get_new_handler(share, thd->mem_root, - share->db_type))) + share->db_type()))) goto err; record= (char*) share->default_values-1; /* Fieldstart = 1 */ @@ -1344,7 +1367,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, /* Allocate handler */ if (!(outparam->file= get_new_handler(share, &outparam->mem_root, - share->db_type))) + share->db_type()))) goto err; error= 4; @@ -1628,7 +1651,7 @@ int closefrm(register TABLE *table, bool free_share) { if (key_info->flags & HA_USES_PARSER) { - plugin_unlock(key_info->parser); + plugin_unlock(NULL, key_info->parser); key_info->flags= 0; } } @@ -1839,10 +1862,10 @@ void open_table_error(TABLE_SHARE *share, int error, int db_errno, int errarg) handler *file= 0; const char *datext= ""; - if (share->db_type != NULL) + if (share->db_type() != NULL) { if ((file= get_new_handler(share, current_thd->mem_root, - share->db_type))) + share->db_type()))) { if (!(datext= *file->bas_ext())) datext= ""; diff --git a/sql/table.h b/sql/table.h index fc2f25f3aa8..6dba46a535e 100644 --- a/sql/table.h +++ b/sql/table.h @@ -172,7 +172,12 @@ typedef struct st_table_share ulong timestamp_offset; /* Set to offset+1 of record */ ulong reclength; /* Recordlength */ - handlerton *db_type; /* table_type for handler */ + plugin_ref db_plugin; /* storage engine plugin */ + inline handlerton *db_type() const /* table_type for handler */ + { + // DBUG_ASSERT(db_plugin); + return db_plugin ? plugin_data(db_plugin, handlerton*) : NULL; + } enum row_type row_type; /* How rows are stored */ enum tmp_table_type tmp_table; diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 14ffe5da984..f5e8d92adb6 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -1777,7 +1777,7 @@ int ha_federated::write_row(byte *buf) values_string.length(0); insert_string.length(0); insert_field_value_string.length(0); - statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status); + ha_statistic_increment(&SSV::ha_write_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); @@ -2244,8 +2244,7 @@ int ha_federated::index_read_idx_with_result_set(byte *buf, uint index, *result= 0; // In case of errors index_string.length(0); sql_query.length(0); - statistic_increment(table->in_use->status_var.ha_read_key_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_key_count); sql_query.append(share->select_query); @@ -2359,8 +2358,7 @@ int ha_federated::read_range_next() int ha_federated::index_next(byte *buf) { DBUG_ENTER("ha_federated::index_next"); - statistic_increment(table->in_use->status_var.ha_read_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_next_count); DBUG_RETURN(read_next(buf, stored_result)); } @@ -2561,8 +2559,7 @@ int ha_federated::rnd_pos(byte *buf, byte *pos) { int result; DBUG_ENTER("ha_federated::rnd_pos"); - statistic_increment(table->in_use->status_var.ha_read_rnd_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_rnd_count); if (table->s->primary_key != MAX_KEY) { /* We have a primary key, so use index_read_idx to find row */ diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc index cf11c9923eb..1d9a586f025 100644 --- a/storage/heap/ha_heap.cc +++ b/storage/heap/ha_heap.cc @@ -181,7 +181,7 @@ void ha_heap::update_key_stats() int ha_heap::write_row(byte * buf) { int res; - statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status); + ha_statistic_increment(&SSV::ha_write_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); if (table->next_number_field && buf == table->record[0]) @@ -205,7 +205,7 @@ int ha_heap::write_row(byte * buf) int ha_heap::update_row(const byte * old_data, byte * new_data) { int res; - statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status); + ha_statistic_increment(&SSV::ha_update_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); res= heap_update(file,old_data,new_data); @@ -224,7 +224,7 @@ int ha_heap::update_row(const byte * old_data, byte * new_data) int ha_heap::delete_row(const byte * buf) { int res; - statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status); + ha_statistic_increment(&SSV::ha_delete_count); res= heap_delete(file,buf); if (!res && table->s->tmp_table == NO_TMP_TABLE && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) @@ -242,8 +242,7 @@ int ha_heap::index_read(byte * buf, const byte * key, uint key_len, enum ha_rkey_function find_flag) { DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_key_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_key_count); int error = heap_rkey(file,buf,active_index, key, key_len, find_flag); table->status = error ? STATUS_NOT_FOUND : 0; return error; @@ -252,8 +251,7 @@ int ha_heap::index_read(byte * buf, const byte * key, uint key_len, int ha_heap::index_read_last(byte *buf, const byte *key, uint key_len) { DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_key_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_key_count); int error= heap_rkey(file, buf, active_index, key, key_len, HA_READ_PREFIX_LAST); table->status= error ? STATUS_NOT_FOUND : 0; @@ -263,8 +261,7 @@ int ha_heap::index_read_last(byte *buf, const byte *key, uint key_len) int ha_heap::index_read_idx(byte * buf, uint index, const byte * key, uint key_len, enum ha_rkey_function find_flag) { - statistic_increment(table->in_use->status_var.ha_read_key_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_key_count); int error = heap_rkey(file, buf, index, key, key_len, find_flag); table->status = error ? STATUS_NOT_FOUND : 0; return error; @@ -273,8 +270,7 @@ int ha_heap::index_read_idx(byte * buf, uint index, const byte * key, int ha_heap::index_next(byte * buf) { DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_next_count); int error=heap_rnext(file,buf); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -283,8 +279,7 @@ int ha_heap::index_next(byte * buf) int ha_heap::index_prev(byte * buf) { DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_prev_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_prev_count); int error=heap_rprev(file,buf); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -293,8 +288,7 @@ int ha_heap::index_prev(byte * buf) int ha_heap::index_first(byte * buf) { DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_first_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_first_count); int error=heap_rfirst(file, buf, active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -303,8 +297,7 @@ int ha_heap::index_first(byte * buf) int ha_heap::index_last(byte * buf) { DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_last_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_last_count); int error=heap_rlast(file, buf, active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -317,8 +310,7 @@ int ha_heap::rnd_init(bool scan) int ha_heap::rnd_next(byte *buf) { - statistic_increment(table->in_use->status_var.ha_read_rnd_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_rnd_next_count); int error=heap_scan(file, buf); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -328,8 +320,7 @@ int ha_heap::rnd_pos(byte * buf, byte *pos) { int error; HEAP_PTR heap_position; - statistic_increment(table->in_use->status_var.ha_read_rnd_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_rnd_count); memcpy_fixed((char*) &heap_position, pos, sizeof(HEAP_PTR)); error=heap_rrnd(file, buf, heap_position); table->status=error ? STATUS_NOT_FOUND: 0; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 14e93cca66f..5c079ca2c65 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -214,6 +214,17 @@ static handler *innobase_create_handler(handlerton *hton, static const char innobase_hton_name[]= "InnoDB"; + +static MYSQL_THDVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG, + "Enable InnoDB support for the XA two-phase commit", + /* check_func */ NULL, /* update_func */ NULL, + /* default */ TRUE); + +static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG, + "Enable InnoDB locking in LOCK TABLES", + /* check_func */ NULL, /* update_func */ NULL, + /* default */ TRUE); + static handler *innobase_create_handler(handlerton *hton, TABLE_SHARE *table, MEM_ROOT *mem_root) @@ -396,7 +407,7 @@ innobase_release_temporary_latches( return 0; } - trx = (trx_t*) thd->ha_data[hton->slot]; + trx = *(trx_t**) thd_ha_data(thd, hton); if (trx) { innobase_release_stat_resources(trx); @@ -576,78 +587,12 @@ innobase_mysql_print_thd( uint max_query_len) /* in: max query length to print, or 0 to use the default max length */ { - const THD* thd; - const Security_context *sctx; - const char* s; - - thd = (const THD*) input_thd; - /* We probably want to have original user as part of debug output. */ - sctx = &thd->main_security_ctx; - - - fprintf(f, "MySQL thread id %lu, query id %lu", - thd->thread_id, (ulong) thd->query_id); - if (sctx->host) { - putc(' ', f); - fputs(sctx->host, f); - } - - if (sctx->ip) { - putc(' ', f); - fputs(sctx->ip, f); - } - - if (sctx->user) { - putc(' ', f); - fputs(sctx->user, f); - } - - if ((s = thd->proc_info)) { - putc(' ', f); - fputs(s, f); - } - - if ((s = thd->query)) { - /* 3100 is chosen because currently 3000 is the maximum - max_query_len we ever give this. */ - char buf[3100]; - uint len; - - /* If buf is too small, we dynamically allocate storage - in this. */ - char* dyn_str = NULL; - - /* Points to buf or dyn_str. */ - char* str = buf; - - if (max_query_len == 0) { - /* ADDITIONAL SAFETY: the default is to print at - most 300 chars to reduce the probability of a - seg fault if there is a race in - thd->query_length in MySQL; after May 14, 2004 - probably no race any more, but better be - safe */ - max_query_len = 300; - } - - len = min(thd->query_length, max_query_len); - - if (len > (sizeof(buf) - 1)) { - dyn_str = my_malloc(len + 1, MYF(0)); - str = dyn_str; - } - - /* Use strmake to reduce the timeframe for a race, - compared to fwrite() */ - len = (uint) (strmake(str, s, len) - str); - putc('\n', f); - fwrite(str, 1, len, f); - - if (dyn_str) { - my_free(dyn_str, MYF(0)); - } - } + THD* thd; + char buffer[1024]; + thd = (THD*) input_thd; + fputs(thd_security_context(thd, buffer, sizeof(buffer), + max_query_len), f); putc('\n', f); } @@ -860,7 +805,7 @@ check_trx_exists( ut_ad(thd == current_thd); - trx = (trx_t*) thd->ha_data[hton->slot]; + trx = *(trx_t**) thd_ha_data(thd, hton); if (trx == NULL) { DBUG_ASSERT(thd != NULL); @@ -872,9 +817,9 @@ check_trx_exists( /* Update the info whether we should skip XA steps that eat CPU time */ - trx->support_xa = (ibool)(thd->variables.innodb_support_xa); + trx->support_xa = THDVAR(thd, support_xa); - thd->ha_data[hton->slot] = trx; + *(trx_t**) thd_ha_data(thd, hton) = trx; } else { if (trx->magic_n != TRX_MAGIC_N) { mem_analyze_corruption(trx); @@ -883,13 +828,13 @@ check_trx_exists( } } - if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) { + if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) { trx->check_foreigns = FALSE; } else { trx->check_foreigns = TRUE; } - if (thd->options & OPTION_RELAXED_UNIQUE_CHECKS) { + if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) { trx->check_unique_secondary = FALSE; } else { trx->check_unique_secondary = TRUE; @@ -977,7 +922,7 @@ innobase_register_trx_and_stmt( innobase_register_stmt(hton, thd); - if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { + if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { /* No autocommit mode, register for a transaction */ trans_register_ha(thd, TRUE, hton); @@ -1069,14 +1014,15 @@ innobase_query_caching_of_table_permitted( ut_a(full_name_len < 999); - if (thd->variables.tx_isolation == ISO_SERIALIZABLE) { + trx = check_trx_exists(legacy_innodb_hton, thd); + + if (trx->isolation_level == TRX_ISO_SERIALIZABLE) { /* In the SERIALIZABLE mode we add LOCK IN SHARE MODE to every plain SELECT if AUTOCOMMIT is not on. */ return((my_bool)FALSE); } - trx = check_trx_exists(legacy_innodb_hton, thd); if (trx->has_search_latch) { ut_print_timestamp(stderr); sql_print_error("The calling thread is holding the adaptive " @@ -1090,7 +1036,7 @@ innobase_query_caching_of_table_permitted( innobase_release_stat_resources(trx); - if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { + if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { is_autocommit = TRUE; } else { @@ -1344,7 +1290,7 @@ innobase_init(void *p) handlerton *innobase_hton= (handlerton *)p; legacy_innodb_hton= innobase_hton; - innobase_hton->state=have_innodb; + innobase_hton->state= SHOW_OPTION_YES; innobase_hton->db_type= DB_TYPE_INNODB; innobase_hton->savepoint_offset=sizeof(trx_named_savept_t); innobase_hton->close_connection=innobase_close_connection; @@ -1369,8 +1315,13 @@ innobase_init(void *p) innobase_hton->flags=HTON_NO_FLAGS; innobase_hton->release_temporary_latches=innobase_release_temporary_latches; - if (have_innodb != SHOW_OPTION_YES) - DBUG_RETURN(0); // nothing else to do +#ifdef HAVE_LARGE_PAGES + if (my_use_large_pages) + { + innobase_use_large_pages= 1; + innobase_large_page_size= opt_large_page_size; + } +#endif ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); @@ -1611,7 +1562,6 @@ innobase_init(void *p) DBUG_RETURN(FALSE); error: - have_innodb= SHOW_OPTION_DISABLED; // If we couldn't use handler DBUG_RETURN(TRUE); } @@ -1754,7 +1704,7 @@ innobase_commit( trx = check_trx_exists(hton, thd); /* Update the info whether we should skip XA steps that eat CPU time */ - trx->support_xa = (ibool)(thd->variables.innodb_support_xa); + trx->support_xa = THDVAR(thd, support_xa); /* Release a possible FIFO ticket and search latch. Since we will reserve the kernel mutex, we have to release the search system latch @@ -1786,7 +1736,7 @@ innobase_commit( " trx->conc_state != TRX_NOT_STARTED"); } if (all - || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { /* We were instructed to commit the whole transaction, or this is an SQL statement end and autocommit is on */ @@ -1948,7 +1898,7 @@ innobase_commit_complete( { trx_t* trx; - trx = (trx_t*) thd->ha_data[hton->slot]; + trx = *(trx_t**) thd_ha_data(thd, hton); if (trx && trx->active_trans) { @@ -1987,7 +1937,7 @@ innobase_rollback( trx = check_trx_exists(hton, thd); /* Update the info whether we should skip XA steps that eat CPU time */ - trx->support_xa = (ibool)(thd->variables.innodb_support_xa); + trx->support_xa = THDVAR(thd, support_xa); /* Release a possible FIFO ticket and search latch. Since we will reserve the kernel mutex, we have to release the search system latch @@ -2004,7 +1954,7 @@ innobase_rollback( } if (all - || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { error = trx_rollback_for_mysql(trx); trx->active_trans = 0; @@ -2136,7 +2086,7 @@ innobase_savepoint( (unless we are in sub-statement), so SQL layer ensures that this method is never called in such situation. */ - DBUG_ASSERT(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) || + DBUG_ASSERT(thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) || thd->in_sub_stmt); trx = check_trx_exists(hton, thd); @@ -2172,7 +2122,7 @@ innobase_close_connection( { trx_t* trx; - trx = (trx_t*)thd->ha_data[hton->slot]; + trx = *(trx_t**) thd_ha_data(thd, hton); ut_a(trx); @@ -2361,7 +2311,7 @@ ha_innobase::open( DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); } - if (ib_table->ibd_file_missing && !thd->tablespace_op) { + if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) { ut_print_timestamp(stderr); sql_print_error("MySQL is trying to open a table handle but " "the .ibd file for\ntable %s does not exist.\n" @@ -3270,11 +3220,11 @@ ha_innobase::write_row( DBUG_ENTER("ha_innobase::write_row"); if (prebuilt->trx != - (trx_t*) current_thd->ha_data[ht->slot]) { + *(trx_t**) ha_data()) { sql_print_error("The transaction object for the table handle is at " "%p, but for the current thread it is at %p", prebuilt->trx, - (trx_t*) current_thd->ha_data[ht->slot]); + *(trx_t**) ha_data()); fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr); ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200); @@ -3282,22 +3232,21 @@ ha_innobase::write_row( "InnoDB: Dump of 200 bytes around transaction.all: ", stderr); ut_print_buf(stderr, - ((byte*)(&(current_thd->ha_data[ht->slot]))) - 100, + ((byte*)(*(trx_t**) ha_data())) - 100, 200); putc('\n', stderr); ut_error; } - statistic_increment(current_thd->status_var.ha_write_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_write_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); - if ((user_thd->lex->sql_command == SQLCOM_ALTER_TABLE - || user_thd->lex->sql_command == SQLCOM_OPTIMIZE - || user_thd->lex->sql_command == SQLCOM_CREATE_INDEX - || user_thd->lex->sql_command == SQLCOM_DROP_INDEX) + if ((ha_sql_command() == SQLCOM_ALTER_TABLE + || ha_sql_command() == SQLCOM_OPTIMIZE + || ha_sql_command() == SQLCOM_CREATE_INDEX + || ha_sql_command() == SQLCOM_DROP_INDEX) && num_write_row >= 10000) { /* ALTER TABLE is COMMITted at every 10000 copied rows. The IX table lock for the original table has to be re-issued. @@ -3456,10 +3405,11 @@ no_commit: performing those statements. */ if (error == DB_DUPLICATE_KEY && auto_inc_used - && (user_thd->lex->sql_command == SQLCOM_REPLACE - || user_thd->lex->sql_command == SQLCOM_REPLACE_SELECT - || (user_thd->lex->sql_command == SQLCOM_LOAD - && user_thd->lex->duplicates == DUP_REPLACE))) { + && (ha_sql_command() == SQLCOM_REPLACE + || ha_sql_command() == SQLCOM_REPLACE_SELECT + || (ha_sql_command() == SQLCOM_LOAD + && prebuilt->trx->allow_duplicates + && prebuilt->trx->replace_duplicates))) { auto_inc = table->next_number_field->val_int(); @@ -3659,7 +3609,7 @@ ha_innobase::update_row( DBUG_ENTER("ha_innobase::update_row"); ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[ht->slot]); + *(trx_t**) ha_data()); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); @@ -3720,7 +3670,7 @@ ha_innobase::delete_row( DBUG_ENTER("ha_innobase::delete_row"); ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[ht->slot]); + *(trx_t**) ha_data()); if (last_query_id != user_thd->query_id) { prebuilt->sql_stat_start = TRUE; @@ -3818,7 +3768,7 @@ ha_innobase::try_semi_consistent_read(bool yes) row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[ht->slot]); + *(trx_t**) ha_data()); /* Row read type is set to semi consistent read if this was requested by the MySQL and either innodb_locks_unsafe_for_binlog @@ -3985,10 +3935,9 @@ ha_innobase::index_read( DBUG_ENTER("index_read"); ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[ht->slot]); + *(trx_t**) ha_data()); - statistic_increment(current_thd->status_var.ha_read_key_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_key_count); if (last_query_id != user_thd->query_id) { prebuilt->sql_stat_start = TRUE; @@ -4094,13 +4043,12 @@ ha_innobase::change_active_index( { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; KEY* key=0; - statistic_increment(current_thd->status_var.ha_read_key_count, - &LOCK_status); DBUG_ENTER("change_active_index"); + ha_statistic_increment(&SSV::ha_read_key_count); ut_ad(user_thd == current_thd); ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[ht->slot]); + *(trx_t**) ha_data()); active_index = keynr; @@ -4190,7 +4138,7 @@ ha_innobase::general_fetch( DBUG_ENTER("general_fetch"); ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[ht->slot]); + *(trx_t**) ha_data()); innodb_srv_conc_enter_innodb(prebuilt->trx); @@ -4229,8 +4177,7 @@ ha_innobase::index_next( mysql_byte* buf) /* in/out: buffer for next row in MySQL format */ { - statistic_increment(current_thd->status_var.ha_read_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_next_count); return(general_fetch(buf, ROW_SEL_NEXT, 0)); } @@ -4247,8 +4194,7 @@ ha_innobase::index_next_same( const mysql_byte* key, /* in: key value */ uint keylen) /* in: key value length */ { - statistic_increment(current_thd->status_var.ha_read_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_next_count); return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode)); } @@ -4265,8 +4211,7 @@ ha_innobase::index_prev( mysql_byte* buf) /* in/out: buffer for previous row in MySQL format */ { - statistic_increment(current_thd->status_var.ha_read_prev_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_prev_count); return(general_fetch(buf, ROW_SEL_PREV, 0)); } @@ -4285,8 +4230,7 @@ ha_innobase::index_first( int error; DBUG_ENTER("index_first"); - statistic_increment(current_thd->status_var.ha_read_first_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_first_count); error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY); @@ -4312,8 +4256,7 @@ ha_innobase::index_last( int error; DBUG_ENTER("index_last"); - statistic_increment(current_thd->status_var.ha_read_last_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_last_count); error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY); @@ -4385,8 +4328,7 @@ ha_innobase::rnd_next( int error; DBUG_ENTER("rnd_next"); - statistic_increment(current_thd->status_var.ha_read_rnd_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_rnd_next_count); if (start_of_scan) { error = index_first(buf); @@ -4422,11 +4364,10 @@ ha_innobase::rnd_pos( DBUG_ENTER("rnd_pos"); DBUG_DUMP("key", (char*) pos, ref_length); - statistic_increment(current_thd->status_var.ha_read_rnd_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_rnd_count); ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[ht->slot]); + *(trx_t**) ha_data()); if (prebuilt->clust_index_was_generated) { /* No primary key was defined for the table and we @@ -4476,7 +4417,7 @@ ha_innobase::position( uint len; ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[ht->slot]); + *(trx_t**) ha_data()); if (prebuilt->clust_index_was_generated) { /* No primary key was defined for the table and we @@ -4815,11 +4756,11 @@ ha_innobase::create( trx->mysql_thd = thd; trx->mysql_query_str = &((*thd).query); - if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) { + if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) { trx->check_foreigns = FALSE; } - if (thd->options & OPTION_RELAXED_UNIQUE_CHECKS) { + if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) { trx->check_unique_secondary = FALSE; } @@ -4976,7 +4917,7 @@ ha_innobase::discard_or_import_tablespace( ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N); ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[ht->slot]); + *(trx_t**) ha_data()); dict_table = prebuilt->table; trx = prebuilt->trx; @@ -5006,7 +4947,7 @@ ha_innobase::delete_all_rows(void) DBUG_ENTER("ha_innobase::delete_all_rows"); - if (thd->lex->sql_command != SQLCOM_TRUNCATE) { + if (ha_sql_command() != SQLCOM_TRUNCATE) { fallback: /* We only handle TRUNCATE TABLE t as a special case. DELETE FROM t will have to use ha_innobase::delete_row(). */ @@ -5074,11 +5015,11 @@ ha_innobase::delete_table( trx->mysql_thd = current_thd; trx->mysql_query_str = &((*current_thd).query); - if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) { + if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) { trx->check_foreigns = FALSE; } - if (thd->options & OPTION_RELAXED_UNIQUE_CHECKS) { + if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) { trx->check_unique_secondary = FALSE; } @@ -5094,7 +5035,7 @@ ha_innobase::delete_table( /* Drop the table in InnoDB */ error = row_drop_table_for_mysql(norm_name, trx, - thd->lex->sql_command == SQLCOM_DROP_DB); + thd_sql_command(thd) == SQLCOM_DROP_DB); /* Flush the log to reduce probability that the .frm files and the InnoDB data dictionary get out-of-sync if the user runs @@ -5166,7 +5107,7 @@ innobase_drop_database( trx->mysql_thd = current_thd; trx->mysql_query_str = &((*current_thd).query); - if (current_thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) { + if (thd_test_options(current_thd, OPTION_NO_FOREIGN_KEY_CHECKS)) { trx->check_foreigns = FALSE; } @@ -5235,7 +5176,7 @@ ha_innobase::rename_table( trx->mysql_thd = current_thd; trx->mysql_query_str = &((*current_thd).query); - if (current_thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) { + if (thd_test_options(current_thd, OPTION_NO_FOREIGN_KEY_CHECKS)) { trx->check_foreigns = FALSE; } @@ -5305,7 +5246,7 @@ ha_innobase::records_in_range( DBUG_ENTER("records_in_range"); ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[ht->slot]); + *(trx_t**) ha_data()); prebuilt->trx->op_info = (char*)"estimating records in index range"; @@ -5741,7 +5682,7 @@ ha_innobase::check( ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N); ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[ht->slot]); + *(trx_t**) ha_data()); if (prebuilt->mysql_template == NULL) { /* Build the template; we will use a dummy template @@ -6043,7 +5984,7 @@ ha_innobase::can_switch_engines(void) DBUG_ENTER("ha_innobase::can_switch_engines"); ut_a(prebuilt->trx == - (trx_t*) current_thd->ha_data[ht->slot]); + *(trx_t**) ha_data()); prebuilt->trx->op_info = "determining if there are foreign key constraints"; @@ -6128,6 +6069,19 @@ ha_innobase::extra( case HA_EXTRA_KEYREAD_PRESERVE_FIELDS: prebuilt->keep_other_fields_on_keyread = 1; break; + case HA_EXTRA_IGNORE_DUP_KEY: + prebuilt->trx->allow_duplicates= TRUE; + break; + case HA_EXTRA_WRITE_CAN_REPLACE: + prebuilt->trx->replace_duplicates= TRUE; + break; + case HA_EXTRA_WRITE_CANNOT_REPLACE: + prebuilt->trx->replace_duplicates= FALSE; + break; + case HA_EXTRA_NO_IGNORE_DUP_KEY: + prebuilt->trx->allow_duplicates= FALSE; + prebuilt->trx->replace_duplicates= FALSE; + break; default:/* Do nothing */ ; } @@ -6156,7 +6110,7 @@ on that table. MySQL-5.0 also calls this before each statement in an execution of a stored procedure. To make the execution more deterministic for binlogging, MySQL-5.0 locks all tables involved in a stored procedure with full explicit table -locks (thd->in_lock_tables is true in ::store_lock()) before executing the +locks (thd_in_lock_tables() is true in ::store_lock()) before executing the procedure. */ int @@ -6196,7 +6150,7 @@ ha_innobase::start_stmt( prebuilt->select_lock_type = LOCK_X; } else { if (trx->isolation_level != TRX_ISO_SERIALIZABLE - && thd->lex->sql_command == SQLCOM_SELECT + && ha_sql_command() == SQLCOM_SELECT && lock_type == TL_READ) { /* For other than temporary tables, we obtain @@ -6309,8 +6263,8 @@ ha_innobase::external_lock( if (trx->isolation_level == TRX_ISO_SERIALIZABLE && prebuilt->select_lock_type == LOCK_NONE - && (thd->options - & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { + && thd_test_options(thd, + OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { /* To get serializable execution, we let InnoDB conceptually add 'LOCK IN SHARE MODE' to all SELECTs @@ -6331,16 +6285,16 @@ ha_innobase::external_lock( VERY easily deadlocks. We do not set InnoDB table locks if user has not explicitly - requested a table lock. Note that thd->in_lock_tables + requested a table lock. Note that thd_in_lock_tables() can be TRUE on some cases e.g. at the start of a stored procedure call (SQLCOM_CALL). */ if (prebuilt->select_lock_type != LOCK_NONE) { - if (thd->in_lock_tables && - thd->lex->sql_command == SQLCOM_LOCK_TABLES && - thd->variables.innodb_table_locks && - (thd->options & OPTION_NOT_AUTOCOMMIT)) { + if (thd_in_lock_tables(thd) && + ha_sql_command() == SQLCOM_LOCK_TABLES && + THDVAR(thd, table_locks) && + thd_test_options(thd, OPTION_NOT_AUTOCOMMIT)) { ulint error = row_lock_table_for_mysql( prebuilt, NULL, 0); @@ -6377,7 +6331,7 @@ ha_innobase::external_lock( innobase_release_stat_resources(trx); - if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { + if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { if (trx->active_trans != 0) { innobase_commit(ht, thd, TRUE); } @@ -6419,7 +6373,7 @@ ha_innobase::transactional_table_lock( update_thd(thd); - if (prebuilt->table->ibd_file_missing && !current_thd->tablespace_op) { + if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(current_thd)) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB error:\n" "MySQL is trying to use a table handle but the .ibd file for\n" @@ -6464,7 +6418,7 @@ ha_innobase::transactional_table_lock( trx->active_trans = 1; } - if (thd->in_lock_tables && thd->variables.innodb_table_locks) { + if (thd_in_lock_tables(thd) && THDVAR(thd, table_locks)) { ulint error = DB_SUCCESS; error = row_lock_table_for_mysql(prebuilt, NULL, 0); @@ -6474,7 +6428,7 @@ ha_innobase::transactional_table_lock( DBUG_RETURN((int) error); } - if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { + if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { /* Store the current undo_no of the transaction so that we know where to roll back if we have @@ -6520,10 +6474,6 @@ innodb_show_status( DBUG_ENTER("innodb_show_status"); - if (have_innodb != SHOW_OPTION_YES) { - DBUG_RETURN(FALSE); - } - trx = check_trx_exists(hton, thd); innobase_release_stat_resources(trx); @@ -6814,21 +6764,20 @@ ha_innobase::store_lock( if (lock_type != TL_IGNORE && trx->n_mysql_tables_in_use == 0) { trx->isolation_level = innobase_map_isolation_level( - (enum_tx_isolation) - thd->variables.tx_isolation); + ha_tx_isolation()); } - if (thd->lex->sql_command == SQLCOM_DROP_TABLE) { + if (ha_sql_command() == SQLCOM_DROP_TABLE) { /* MySQL calls this function in DROP TABLE though this table handle may belong to another thd that is running a query. Let us in that case skip any changes to the prebuilt struct. */ - } else if ((lock_type == TL_READ && thd->in_lock_tables) || - (lock_type == TL_READ_HIGH_PRIORITY && thd->in_lock_tables) || + } else if ((thd_in_lock_tables(thd) && + (lock_type == TL_READ || lock_type == TL_READ_HIGH_PRIORITY)) || lock_type == TL_READ_WITH_SHARED_LOCKS || lock_type == TL_READ_NO_INSERT || - (thd->lex->sql_command != SQLCOM_SELECT + (ha_sql_command() != SQLCOM_SELECT && lock_type != TL_IGNORE)) { /* The OR cases above are in this order: @@ -6857,9 +6806,9 @@ ha_innobase::store_lock( || isolation_level == TRX_ISO_READ_COMMITTED) && isolation_level != TRX_ISO_SERIALIZABLE && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) - && (thd->lex->sql_command == SQLCOM_INSERT_SELECT - || thd->lex->sql_command == SQLCOM_UPDATE - || thd->lex->sql_command == SQLCOM_CREATE_TABLE)) { + && (ha_sql_command() == SQLCOM_INSERT_SELECT + || ha_sql_command() == SQLCOM_UPDATE + || ha_sql_command() == SQLCOM_CREATE_TABLE)) { /* If we either have innobase_locks_unsafe_for_binlog option set or this session is using READ COMMITTED @@ -6872,7 +6821,7 @@ ha_innobase::store_lock( prebuilt->select_lock_type = LOCK_NONE; prebuilt->stored_select_lock_type = LOCK_NONE; - } else if (thd->lex->sql_command == SQLCOM_CHECKSUM) { + } else if (ha_sql_command() == SQLCOM_CHECKSUM) { /* Use consistent read for checksum table */ prebuilt->select_lock_type = LOCK_NONE; @@ -6902,7 +6851,7 @@ ha_innobase::store_lock( (if it does not use a consistent read). */ if (lock_type == TL_READ - && thd->lex->sql_command == SQLCOM_LOCK_TABLES) { + && ha_sql_command() == SQLCOM_LOCK_TABLES) { /* We come here if MySQL is processing LOCK TABLES ... READ LOCAL. MyISAM under that table lock type reads the table as it was at the time the lock was @@ -6929,11 +6878,11 @@ ha_innobase::store_lock( if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE) - && !(thd->in_lock_tables - && thd->lex->sql_command == SQLCOM_LOCK_TABLES) - && !thd->tablespace_op - && thd->lex->sql_command != SQLCOM_TRUNCATE - && thd->lex->sql_command != SQLCOM_OPTIMIZE + && !(thd_in_lock_tables(thd) + && ha_sql_command() == SQLCOM_LOCK_TABLES) + && !thd_tablespace_op(thd) + && ha_sql_command() != SQLCOM_TRUNCATE + && ha_sql_command() != SQLCOM_OPTIMIZE #ifdef __WIN__ /* For alter table on win32 for succesful operation @@ -6942,10 +6891,10 @@ ha_innobase::store_lock( TL_WRITE is lifted to TL_WRITE_ALLOW_WRITE, which causes race condition when several clients do alter table simultaneously (bug #17264). This fix avoids the problem. */ - && thd->lex->sql_command != SQLCOM_ALTER_TABLE + && ha_sql_command() != SQLCOM_ALTER_TABLE #endif - && thd->lex->sql_command != SQLCOM_CREATE_TABLE) { + && ha_sql_command() != SQLCOM_CREATE_TABLE) { lock_type = TL_WRITE_ALLOW_WRITE; } @@ -6958,10 +6907,10 @@ ha_innobase::store_lock( We especially allow concurrent inserts if MySQL is at the start of a stored procedure call (SQLCOM_CALL) - (MySQL does have thd->in_lock_tables TRUE there). */ + (MySQL does have thd_in_lock_tables() TRUE there). */ if (lock_type == TL_READ_NO_INSERT - && thd->lex->sql_command != SQLCOM_LOCK_TABLES) { + && ha_sql_command() != SQLCOM_LOCK_TABLES) { lock_type = TL_READ; } @@ -7379,6 +7328,7 @@ innobase_query_is_update(void) /*==========================*/ { THD* thd = current_thd; + trx_t* trx; if (!thd) { /* InnoDB's internal threads may run InnoDB stored procedures @@ -7388,17 +7338,9 @@ innobase_query_is_update(void) return(FALSE); } - switch (thd->lex->sql_command) { - case SQLCOM_REPLACE: - case SQLCOM_REPLACE_SELECT: - return(TRUE); - case SQLCOM_LOAD: - return(thd->lex->duplicates == DUP_REPLACE); - case SQLCOM_INSERT: - return(thd->lex->duplicates == DUP_UPDATE); - default: - return(FALSE); - } + trx = check_trx_exists(legacy_innodb_hton, thd); + + return(trx->allow_duplicates); } /*********************************************************************** @@ -7417,8 +7359,8 @@ innobase_xa_prepare( int error = 0; trx_t* trx = check_trx_exists(hton, thd); - if (thd->lex->sql_command != SQLCOM_XA_PREPARE && - (all || !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) + if (thd_sql_command(thd) != SQLCOM_XA_PREPARE && + (all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { /* For ibbackup to work the order of transactions in binlog @@ -7444,7 +7386,7 @@ innobase_xa_prepare( trx->active_trans = 2; } - if (!thd->variables.innodb_support_xa) { + if (!THDVAR(thd, support_xa)) { return(0); } @@ -7464,7 +7406,7 @@ innobase_xa_prepare( } if (all - || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { /* We were instructed to prepare the whole transaction, or this is an SQL statement end and autocommit is on */ @@ -7654,6 +7596,213 @@ SHOW_VAR innodb_status_variables_export[]= { struct st_mysql_storage_engine innobase_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; +/* plugin options */ +static MYSQL_SYSVAR_BOOL(checksums, innobase_use_checksums, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "Enable InnoDB checksums validation (enabled by default). " + "Disable with --skip-innodb-checksums.", + NULL, NULL, TRUE); + +static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir, + PLUGIN_VAR_READONLY, + "The common part for InnoDB table spaces.", + NULL, NULL, NULL); + +static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "Enable InnoDB doublewrite buffer (enabled by default). " + "Disable with --skip-innodb-doublewrite.", + NULL, NULL, TRUE); + +static MYSQL_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown, + PLUGIN_VAR_OPCMDARG, + "Speeds up the shutdown process of the InnoDB storage engine. Possible " + "values are 0, 1 (faster)" + /* + NetWare can't close unclosed files, can't automatically kill remaining + threads, etc, so on this OS we disable the crash-like InnoDB shutdown. + */ +#ifndef __NETWARE__ + " or 2 (fastest - crash-like)" +#endif + ".", + NULL, NULL, 1, 0, IF_NETWARE(1,2), 0); + +static MYSQL_SYSVAR_BOOL(file_per_table, innobase_file_per_table, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "Stores each InnoDB table to an .ibd file in the database dir.", + NULL, NULL, FALSE); + +static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit, + PLUGIN_VAR_OPCMDARG, + "Set to 0 (write and flush once per second), 1 (write and flush at each commit)\ + or 2 (write at commit, flush once per second).", + NULL, NULL, 1, 0, 2, 0); + +static MYSQL_SYSVAR_STR(flush_method, innobase_unix_file_flush_method, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "With which method to flush data.", NULL, NULL, NULL); + +static MYSQL_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "Force InnoDB to not use next-key locking, to use only row-level locking.", + NULL, NULL, FALSE); + +static MYSQL_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Where full logs should be archived.", NULL, NULL, NULL); + +static MYSQL_SYSVAR_BOOL(log_archive, innobase_log_archive, + PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, + "Set to 1 if you want to have logs archived.", NULL, NULL, FALSE); + +static MYSQL_SYSVAR_STR(log_group_home_dir, innobase_log_group_home_dir, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Path to InnoDB log files.", NULL, NULL, NULL); + +static MYSQL_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct, + PLUGIN_VAR_RQCMDARG, + "Percentage of dirty pages allowed in bufferpool.", + NULL, NULL, 90, 0, 100, 0); + +static MYSQL_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag, + PLUGIN_VAR_RQCMDARG, + "Desired maximum length of the purge queue (0 = no limit)", + NULL, NULL, 0, 0, ~0L, 0); + +static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout, + PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, + "Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)", + NULL, NULL, FALSE); + +static MYSQL_SYSVAR_BOOL(status_file, innobase_create_status_file, + PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR, + "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file", + NULL, NULL, FALSE); + +static MYSQL_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.", + NULL, NULL, 1*1024*1024L, 512*1024L, ~0L, 1024); + +static MYSQL_SYSVAR_ULONG(autoextend_increment, srv_auto_extend_increment, + PLUGIN_VAR_RQCMDARG, + "Data file autoextend increment in megabytes", + NULL, NULL, 8L, 1L, 1000L, 0); + +static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", + NULL, NULL, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 1024*1024L); + +static MYSQL_SYSVAR_ULONG(commit_concurrency, srv_commit_concurrency, + PLUGIN_VAR_RQCMDARG, + "Helps in performance tuning in heavily concurrent environments.", + NULL, NULL, 0, 0, 1000, 0); + +static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter, + PLUGIN_VAR_RQCMDARG, + "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket", + NULL, NULL, 500L, 1L, ~0L, 0); + +static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Number of file I/O threads in InnoDB.", + NULL, NULL, 4, 4, 64, 0); + +static MYSQL_SYSVAR_LONG(force_recovery, innobase_force_recovery, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Helps to save your data in case the disk image of the database becomes corrupt.", + NULL, NULL, 0, 0, 6, 0); + +static MYSQL_SYSVAR_LONG(lock_wait_timeout, innobase_lock_wait_timeout, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back.", + NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0); + +static MYSQL_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "The size of the buffer which InnoDB uses to write log to the log files on disk.", + NULL, NULL, 1024*1024L, 256*1024L, ~0L, 1024); + +static MYSQL_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Size of each log file in a log group.", + NULL, NULL, 5*1024*1024L, 1*1024*1024L, LONGLONG_MAX, 1024*1024L); + +static MYSQL_SYSVAR_LONG(log_files_in_group, innobase_log_files_in_group, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.", + NULL, NULL, 2, 2, 100, 0); + +static MYSQL_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.", + NULL, NULL, 1, 1, 10, 0); + +static MYSQL_SYSVAR_LONG(open_files, innobase_open_files, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "How many files at the maximum InnoDB keeps open at the same time.", + NULL, NULL, 300L, 10L, ~0L, 0); + +static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds, + PLUGIN_VAR_RQCMDARG, + "Count of spin-loop rounds in InnoDB mutexes", + NULL, NULL, 20L, 0L, ~0L, 0); + +static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency, + PLUGIN_VAR_RQCMDARG, + "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.", + NULL, NULL, 8, 0, 1000, 0); + +static MYSQL_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay, + PLUGIN_VAR_RQCMDARG, + "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep", + NULL, NULL, 10000L, 0L, ~0L, 0); + +static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Path to individual files and their sizes.", + NULL, NULL, NULL); + +static struct st_mysql_sys_var* innobase_system_variables[]= { + MYSQL_SYSVAR(additional_mem_pool_size), + MYSQL_SYSVAR(autoextend_increment), + MYSQL_SYSVAR(buffer_pool_size), + MYSQL_SYSVAR(checksums), + MYSQL_SYSVAR(commit_concurrency), + MYSQL_SYSVAR(concurrency_tickets), + MYSQL_SYSVAR(data_file_path), + MYSQL_SYSVAR(data_home_dir), + MYSQL_SYSVAR(doublewrite), + MYSQL_SYSVAR(fast_shutdown), + MYSQL_SYSVAR(file_io_threads), + MYSQL_SYSVAR(file_per_table), + MYSQL_SYSVAR(flush_log_at_trx_commit), + MYSQL_SYSVAR(flush_method), + MYSQL_SYSVAR(force_recovery), + MYSQL_SYSVAR(locks_unsafe_for_binlog), + MYSQL_SYSVAR(lock_wait_timeout), + MYSQL_SYSVAR(log_arch_dir), + MYSQL_SYSVAR(log_archive), + MYSQL_SYSVAR(log_buffer_size), + MYSQL_SYSVAR(log_file_size), + MYSQL_SYSVAR(log_files_in_group), + MYSQL_SYSVAR(log_group_home_dir), + MYSQL_SYSVAR(max_dirty_pages_pct), + MYSQL_SYSVAR(max_purge_lag), + MYSQL_SYSVAR(mirrored_log_groups), + MYSQL_SYSVAR(open_files), + MYSQL_SYSVAR(rollback_on_timeout), + MYSQL_SYSVAR(status_file), + MYSQL_SYSVAR(support_xa), + MYSQL_SYSVAR(sync_spin_loops), + MYSQL_SYSVAR(table_locks), + MYSQL_SYSVAR(thread_concurrency), + MYSQL_SYSVAR(thread_sleep_delay), + NULL +}; + mysql_declare_plugin(innobase) { MYSQL_STORAGE_ENGINE_PLUGIN, @@ -7666,8 +7815,8 @@ mysql_declare_plugin(innobase) NULL, /* Plugin Deinit */ 0x0100 /* 1.0 */, innodb_status_variables_export,/* status variables */ - NULL, /* system variables */ - NULL /* config options */ + innobase_system_variables, /* system variables */ + NULL /* reserved */ } mysql_declare_plugin_end; diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 8232699c7f9..c68c826f6a8 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -501,6 +501,14 @@ struct trx_struct{ ulint mysql_process_no;/* since in Linux, 'top' reports process id's and not thread id's, we store the process number too */ + ibool allow_duplicates;/* normally FALSE, but if the user + wants to update duplicate rows, + (in table inserts, for example) we + set this TRUE */ + ibool replace_duplicates;/* normally FALSE, but if the user + wants to replace duplicate rows, + (in table inserts, for example) we + set this TRUE */ /*------------------------------*/ ulint n_mysql_tables_in_use; /* number of Innobase tables used in the processing of the current diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 06ec5c4b44e..25f42c6b2ed 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -633,10 +633,10 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked) for (i= 0; i < table->s->keys; i++) { - struct st_plugin_int *parser= table->key_info[i].parser; + plugin_ref parser= table->key_info[i].parser; if (table->key_info[i].flags & HA_USES_PARSER) file->s->keyinfo[i].parser= - (struct st_mysql_ftparser *)parser->plugin->info; + (struct st_mysql_ftparser *)plugin_decl(parser)->info; table->key_info[i].block_size= file->s->keyinfo[i].block_length; } return (0); @@ -651,7 +651,7 @@ int ha_myisam::close(void) int ha_myisam::write_row(byte * buf) { - statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status); + ha_statistic_increment(&SSV::ha_write_count); /* If we have a timestamp column, update it to the current time */ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) @@ -1509,7 +1509,7 @@ bool ha_myisam::is_crashed() const int ha_myisam::update_row(const byte * old_data, byte * new_data) { - statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status); + ha_statistic_increment(&SSV::ha_update_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); return mi_update(file,old_data,new_data); @@ -1517,7 +1517,7 @@ int ha_myisam::update_row(const byte * old_data, byte * new_data) int ha_myisam::delete_row(const byte * buf) { - statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status); + ha_statistic_increment(&SSV::ha_delete_count); return mi_delete(file,buf); } @@ -1525,8 +1525,7 @@ int ha_myisam::index_read(byte * buf, const byte * key, uint key_len, enum ha_rkey_function find_flag) { DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_key_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_key_count); int error=mi_rkey(file,buf,active_index, key, key_len, find_flag); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -1535,8 +1534,7 @@ int ha_myisam::index_read(byte * buf, const byte * key, int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key, uint key_len, enum ha_rkey_function find_flag) { - statistic_increment(table->in_use->status_var.ha_read_key_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_key_count); int error=mi_rkey(file,buf,index, key, key_len, find_flag); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -1546,8 +1544,7 @@ int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len) { DBUG_ENTER("ha_myisam::index_read_last"); DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_key_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_key_count); int error=mi_rkey(file,buf,active_index, key, key_len, HA_READ_PREFIX_LAST); table->status=error ? STATUS_NOT_FOUND: 0; DBUG_RETURN(error); @@ -1556,8 +1553,7 @@ int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len) int ha_myisam::index_next(byte * buf) { DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_next_count); int error=mi_rnext(file,buf,active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -1566,8 +1562,7 @@ int ha_myisam::index_next(byte * buf) int ha_myisam::index_prev(byte * buf) { DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_prev_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_prev_count); int error=mi_rprev(file,buf, active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -1576,8 +1571,7 @@ int ha_myisam::index_prev(byte * buf) int ha_myisam::index_first(byte * buf) { DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_first_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_first_count); int error=mi_rfirst(file, buf, active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -1586,8 +1580,7 @@ int ha_myisam::index_first(byte * buf) int ha_myisam::index_last(byte * buf) { DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_last_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_last_count); int error=mi_rlast(file, buf, active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -1598,8 +1591,7 @@ int ha_myisam::index_next_same(byte * buf, uint length __attribute__((unused))) { DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_next_count); int error=mi_rnext_same(file,buf); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -1615,8 +1607,7 @@ int ha_myisam::rnd_init(bool scan) int ha_myisam::rnd_next(byte *buf) { - statistic_increment(table->in_use->status_var.ha_read_rnd_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_rnd_next_count); int error=mi_scan(file, buf); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -1629,8 +1620,7 @@ int ha_myisam::restart_rnd_next(byte *buf, byte *pos) int ha_myisam::rnd_pos(byte * buf, byte *pos) { - statistic_increment(table->in_use->status_var.ha_read_rnd_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_rnd_count); int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length)); table->status=error ? STATUS_NOT_FOUND: 0; return error; diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 4392a456f60..8ab3f843637 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -148,7 +148,7 @@ int ha_myisammrg::close(void) int ha_myisammrg::write_row(byte * buf) { - statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status); + ha_statistic_increment(&SSV::ha_write_count); if (file->merge_insert_method == MERGE_INSERT_DISABLED || !file->tables) return (HA_ERR_TABLE_READONLY); @@ -166,7 +166,7 @@ int ha_myisammrg::write_row(byte * buf) int ha_myisammrg::update_row(const byte * old_data, byte * new_data) { - statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status); + ha_statistic_increment(&SSV::ha_update_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); return myrg_update(file,old_data,new_data); @@ -174,15 +174,14 @@ int ha_myisammrg::update_row(const byte * old_data, byte * new_data) int ha_myisammrg::delete_row(const byte * buf) { - statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status); + ha_statistic_increment(&SSV::ha_delete_count); return myrg_delete(file,buf); } int ha_myisammrg::index_read(byte * buf, const byte * key, uint key_len, enum ha_rkey_function find_flag) { - statistic_increment(table->in_use->status_var.ha_read_key_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_key_count); int error=myrg_rkey(file,buf,active_index, key, key_len, find_flag); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -191,8 +190,7 @@ int ha_myisammrg::index_read(byte * buf, const byte * key, int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key, uint key_len, enum ha_rkey_function find_flag) { - statistic_increment(table->in_use->status_var.ha_read_key_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_key_count); int error=myrg_rkey(file,buf,index, key, key_len, find_flag); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -200,8 +198,7 @@ int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key, int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len) { - statistic_increment(table->in_use->status_var.ha_read_key_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_key_count); int error=myrg_rkey(file,buf,active_index, key, key_len, HA_READ_PREFIX_LAST); table->status=error ? STATUS_NOT_FOUND: 0; @@ -210,8 +207,7 @@ int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len) int ha_myisammrg::index_next(byte * buf) { - statistic_increment(table->in_use->status_var.ha_read_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_next_count); int error=myrg_rnext(file,buf,active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -219,8 +215,7 @@ int ha_myisammrg::index_next(byte * buf) int ha_myisammrg::index_prev(byte * buf) { - statistic_increment(table->in_use->status_var.ha_read_prev_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_prev_count); int error=myrg_rprev(file,buf, active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -228,8 +223,7 @@ int ha_myisammrg::index_prev(byte * buf) int ha_myisammrg::index_first(byte * buf) { - statistic_increment(table->in_use->status_var.ha_read_first_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_first_count); int error=myrg_rfirst(file, buf, active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -237,8 +231,7 @@ int ha_myisammrg::index_first(byte * buf) int ha_myisammrg::index_last(byte * buf) { - statistic_increment(table->in_use->status_var.ha_read_last_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_last_count); int error=myrg_rlast(file, buf, active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -248,8 +241,7 @@ int ha_myisammrg::index_next_same(byte * buf, const byte *key __attribute__((unused)), uint length __attribute__((unused))) { - statistic_increment(table->in_use->status_var.ha_read_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_next_count); int error=myrg_rnext_same(file,buf); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -264,8 +256,7 @@ int ha_myisammrg::rnd_init(bool scan) int ha_myisammrg::rnd_next(byte *buf) { - statistic_increment(table->in_use->status_var.ha_read_rnd_next_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_rnd_next_count); int error=myrg_rrnd(file, buf, HA_OFFSET_ERROR); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -274,8 +265,7 @@ int ha_myisammrg::rnd_next(byte *buf) int ha_myisammrg::rnd_pos(byte * buf, byte *pos) { - statistic_increment(table->in_use->status_var.ha_read_rnd_count, - &LOCK_status); + ha_statistic_increment(&SSV::ha_read_rnd_count); int error=myrg_rrnd(file, buf, my_get_ptr(pos,ref_length)); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -609,7 +599,6 @@ static int myisammrg_init(void *p) myisammrg_hton= (handlerton *)p; - myisammrg_hton->state= SHOW_OPTION_YES; myisammrg_hton->db_type= DB_TYPE_MRG_MYISAM; myisammrg_hton->create= myisammrg_create_handler; myisammrg_hton->panic= myisammrg_panic; |