summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/hash.h3
-rw-r--r--include/my_getopt.h9
-rw-r--r--include/my_sys.h11
-rw-r--r--include/mysql.h3
-rw-r--r--include/mysql/plugin.h277
-rw-r--r--include/mysys_err.h1
-rw-r--r--include/typelib.h1
-rw-r--r--mysql-test/r/im_utils.result8
-rw-r--r--mysql-test/r/log_tables.result3
-rw-r--r--mysql-test/r/ndb_dd_basic.result4
-rw-r--r--mysql-test/r/partition_innodb.result5
-rw-r--r--mysql-test/r/ps_1general.result3
-rw-r--r--mysql-test/r/variables.result16
-rw-r--r--mysql-test/t/log_tables.test3
-rw-r--r--mysql-test/t/ndb_dd_basic.test1
-rw-r--r--mysql-test/t/partition_innodb.test1
-rw-r--r--mysql-test/t/ps_1general.test8
-rw-r--r--mysql-test/t/variables.test16
-rw-r--r--mysql-test/t/warnings_engine_disabled-master.opt2
-rw-r--r--mysys/array.c61
-rw-r--r--mysys/hash.c17
-rw-r--r--mysys/my_getopt.c50
-rw-r--r--mysys/typelib.c48
-rw-r--r--sql/ha_ndbcluster.cc35
-rw-r--r--sql/ha_partition.cc25
-rw-r--r--sql/ha_partition.h6
-rw-r--r--sql/handler.cc168
-rw-r--r--sql/handler.h11
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_sum.cc2
-rw-r--r--sql/mysql_priv.h14
-rw-r--r--sql/mysqld.cc504
-rw-r--r--sql/set_var.cc1358
-rw-r--r--sql/set_var.h391
-rw-r--r--sql/sql_base.cc4
-rw-r--r--sql/sql_cache.cc18
-rw-r--r--sql/sql_class.cc88
-rw-r--r--sql/sql_class.h18
-rw-r--r--sql/sql_connect.cc3
-rw-r--r--sql/sql_delete.cc2
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/sql_lex.cc22
-rw-r--r--sql/sql_lex.h7
-rw-r--r--sql/sql_partition.cc22
-rw-r--r--sql/sql_plugin.cc2283
-rw-r--r--sql/sql_plugin.h62
-rw-r--r--sql/sql_repl.cc143
-rw-r--r--sql/sql_repl.h1
-rw-r--r--sql/sql_select.cc24
-rw-r--r--sql/sql_show.cc93
-rw-r--r--sql/sql_table.cc24
-rw-r--r--sql/sql_tablespace.cc4
-rw-r--r--sql/sql_yacc.yy71
-rw-r--r--sql/structs.h4
-rw-r--r--sql/table.cc53
-rw-r--r--sql/table.h7
-rw-r--r--storage/federated/ha_federated.cc11
-rw-r--r--storage/heap/ha_heap.cc33
-rw-r--r--storage/innobase/handler/ha_innodb.cc545
-rw-r--r--storage/innobase/include/trx0trx.h8
-rw-r--r--storage/myisam/ha_myisam.cc40
-rw-r--r--storage/myisammrg/ha_myisammrg.cc37
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, &not_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;