summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/my_global.h2
-rw-r--r--mysql-test/r/plugin.result57
-rw-r--r--mysql-test/r/plugin_maturity.result8
-rw-r--r--mysql-test/t/plugin.test24
-rw-r--r--mysql-test/t/plugin_maturity.test6
-rw-r--r--mysql-test/t/ps.test3
-rw-r--r--sql/sql_parse.cc3
-rw-r--r--sql/sql_plugin.cc331
-rw-r--r--sql/sql_plugin.h3
-rw-r--r--sql/sql_yacc.yy14
-rw-r--r--storage/example/ha_example.cc38
11 files changed, 330 insertions, 159 deletions
diff --git a/include/my_global.h b/include/my_global.h
index a7e7d50054b..3acb204de6c 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -462,8 +462,6 @@ extern "C" int madvise(void *addr, size_t len, int behav);
#ifndef SO_EXT
#ifdef _WIN32
#define SO_EXT ".dll"
-#elif defined(__APPLE__)
-#define SO_EXT ".dylib"
#else
#define SO_EXT ".so"
#endif
diff --git a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result
index 7c89beb9725..5ccd64b5c30 100644
--- a/mysql-test/r/plugin.result
+++ b/mysql-test/r/plugin.result
@@ -3,15 +3,41 @@ Warnings:
Warning 1286 Unknown storage engine 'EXAMPLE'
Warning 1266 Using storage engine MyISAM for table 't1'
DROP TABLE t1;
-INSTALL PLUGIN example SONAME 'ha_example.so';
-INSTALL PLUGIN EXAMPLE SONAME 'ha_example.so';
+INSTALL PLUGIN example SONAME 'ha_example';
+INSTALL PLUGIN EXAMPLE SONAME 'ha_example';
ERROR HY000: Function 'EXAMPLE' already exists
UNINSTALL PLUGIN example;
-INSTALL PLUGIN example SONAME 'ha_example.so';
+INSTALL SONAME 'ha_example';
+select * from information_schema.plugins where plugin_library like 'ha_example%';
+PLUGIN_NAME EXAMPLE
+PLUGIN_VERSION 0.1
+PLUGIN_STATUS ACTIVE
+PLUGIN_TYPE STORAGE ENGINE
+PLUGIN_TYPE_VERSION #
+PLUGIN_LIBRARY ha_example.so
+PLUGIN_LIBRARY_VERSION 1.1
+PLUGIN_AUTHOR Brian Aker, MySQL AB
+PLUGIN_DESCRIPTION Example storage engine
+PLUGIN_LICENSE GPL
+LOAD_OPTION ON
+PLUGIN_MATURITY Experimental
+PLUGIN_AUTH_VERSION 0.1
+PLUGIN_NAME UNUSABLE
+PLUGIN_VERSION 3.14
+PLUGIN_STATUS ACTIVE
+PLUGIN_TYPE DAEMON
+PLUGIN_TYPE_VERSION #
+PLUGIN_LIBRARY ha_example.so
+PLUGIN_LIBRARY_VERSION 1.1
+PLUGIN_AUTHOR Sergei Golubchik
+PLUGIN_DESCRIPTION Unusable Daemon
+PLUGIN_LICENSE GPL
+LOAD_OPTION ON
+PLUGIN_MATURITY Experimental
+PLUGIN_AUTH_VERSION 3.14.15.926
CREATE TABLE t1(a int) ENGINE=EXAMPLE;
SELECT * FROM t1;
a
-DROP TABLE t1;
set global example_ulong_var=500;
set global example_enum_var= e1;
show status like 'example%';
@@ -21,7 +47,24 @@ show variables like 'example%';
Variable_name Value
example_enum_var e1
example_ulong_var 500
-UNINSTALL PLUGIN example;
+UNINSTALL SONAME 'ha_example';
+Warnings:
+Warning 1620 Plugin is busy and will be uninstalled on shutdown
+select * from information_schema.plugins where plugin_library like 'ha_example%';
+PLUGIN_NAME EXAMPLE
+PLUGIN_VERSION 0.1
+PLUGIN_STATUS DELETED
+PLUGIN_TYPE STORAGE ENGINE
+PLUGIN_TYPE_VERSION #
+PLUGIN_LIBRARY ha_example.so
+PLUGIN_LIBRARY_VERSION 1.1
+PLUGIN_AUTHOR Brian Aker, MySQL AB
+PLUGIN_DESCRIPTION Example storage engine
+PLUGIN_LICENSE GPL
+LOAD_OPTION ON
+PLUGIN_MATURITY Experimental
+PLUGIN_AUTH_VERSION 0.1
+DROP TABLE t1;
UNINSTALL PLUGIN EXAMPLE;
ERROR 42000: PLUGIN EXAMPLE does not exist
UNINSTALL PLUGIN non_exist;
@@ -30,13 +73,13 @@ ERROR 42000: PLUGIN non_exist does not exist
# Bug#32034: check_func_enum() does not check correct values but set it
# to impossible int val
#
-INSTALL PLUGIN example SONAME 'ha_example.so';
+INSTALL PLUGIN example SONAME 'ha_example';
SET GLOBAL example_enum_var= e1;
SET GLOBAL example_enum_var= e2;
SET GLOBAL example_enum_var= impossible;
ERROR 42000: Variable 'example_enum_var' can't be set to the value of 'impossible'
UNINSTALL PLUGIN example;
-INSTALL PLUGIN example SONAME 'ha_example.so';
+INSTALL PLUGIN example SONAME 'ha_example';
select @@session.sql_mode into @old_sql_mode;
set session sql_mode='';
set global example_ulong_var=500;
diff --git a/mysql-test/r/plugin_maturity.result b/mysql-test/r/plugin_maturity.result
index 97147459f6f..3249ea9b3c1 100644
--- a/mysql-test/r/plugin_maturity.result
+++ b/mysql-test/r/plugin_maturity.result
@@ -1,2 +1,8 @@
INSTALL PLUGIN example SONAME 'ha_example.so';
-ERROR HY000: Can't open shared library 'ha_example.so' (errno: 0 Loading of experimental plugins is prohibited by --plugin-maturity=stable)
+ERROR HY000: Can't open shared library 'ha_example.so' (errno: 0 Loading of experimental plugin EXAMPLE is prohibited by --plugin-maturity=stable)
+INSTALL SONAME 'ha_example.so';
+ERROR HY000: Can't open shared library 'ha_example.so' (errno: 0 Loading of experimental plugin EXAMPLE is prohibited by --plugin-maturity=stable)
+show warnings;
+Level Code Message
+Error 1126 Can't open shared library 'ha_example.so' (errno: 0 Loading of experimental plugin EXAMPLE is prohibited by --plugin-maturity=stable)
+Error 1126 Can't open shared library 'ha_example.so' (errno: 0 Loading of experimental plugin UNUSABLE is prohibited by --plugin-maturity=stable)
diff --git a/mysql-test/t/plugin.test b/mysql-test/t/plugin.test
index 6b0308cfc32..2b234b64047 100644
--- a/mysql-test/t/plugin.test
+++ b/mysql-test/t/plugin.test
@@ -4,23 +4,23 @@
CREATE TABLE t1(a int) ENGINE=EXAMPLE;
DROP TABLE t1;
---replace_regex /\.dll/.so/
-eval INSTALL PLUGIN example SONAME '$HA_EXAMPLE_SO';
+eval INSTALL PLUGIN example SONAME 'ha_example';
--replace_regex /\.dll/.so/
--error 1125
-eval INSTALL PLUGIN EXAMPLE SONAME '$HA_EXAMPLE_SO';
+eval INSTALL PLUGIN EXAMPLE SONAME 'ha_example';
UNINSTALL PLUGIN example;
+eval INSTALL SONAME 'ha_example';
+--replace_column 5 #
--replace_regex /\.dll/.so/
-eval INSTALL PLUGIN example SONAME '$HA_EXAMPLE_SO';
+--query_vertical select * from information_schema.plugins where plugin_library like 'ha_example%'
CREATE TABLE t1(a int) ENGINE=EXAMPLE;
# Let's do some advanced ops with the example engine :)
SELECT * FROM t1;
-DROP TABLE t1;
# a couple of tests for variables
set global example_ulong_var=500;
@@ -28,7 +28,13 @@ set global example_enum_var= e1;
show status like 'example%';
show variables like 'example%';
-UNINSTALL PLUGIN example;
+eval UNINSTALL SONAME 'ha_example';
+--replace_column 5 #
+--replace_regex /\.dll/.so/
+--query_vertical select * from information_schema.plugins where plugin_library like 'ha_example%'
+
+DROP TABLE t1;
+
--error 1305
UNINSTALL PLUGIN EXAMPLE;
@@ -40,8 +46,7 @@ UNINSTALL PLUGIN non_exist;
--echo # Bug#32034: check_func_enum() does not check correct values but set it
--echo # to impossible int val
--echo #
---replace_regex /\.dll/.so/
-eval INSTALL PLUGIN example SONAME '$HA_EXAMPLE_SO';
+eval INSTALL PLUGIN example SONAME 'ha_example';
SET GLOBAL example_enum_var= e1;
SET GLOBAL example_enum_var= e2;
@@ -55,8 +60,7 @@ UNINSTALL PLUGIN example;
#
# Bug #32757 hang with sql_mode set when setting some global variables
#
---replace_regex /\.dll/.so/
-eval INSTALL PLUGIN example SONAME '$HA_EXAMPLE_SO';
+eval INSTALL PLUGIN example SONAME 'ha_example';
select @@session.sql_mode into @old_sql_mode;
diff --git a/mysql-test/t/plugin_maturity.test b/mysql-test/t/plugin_maturity.test
index fe95f19b803..e1e4941492e 100644
--- a/mysql-test/t/plugin_maturity.test
+++ b/mysql-test/t/plugin_maturity.test
@@ -4,3 +4,9 @@
--replace_regex /\.dll/.so/
--error 1126
eval INSTALL PLUGIN example SONAME '$HA_EXAMPLE_SO';
+
+--replace_regex /\.dll/.so/
+--error 1126
+eval INSTALL SONAME '$HA_EXAMPLE_SO';
+--replace_regex /\.dll/.so/
+show warnings;
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index ce7c498133c..58e85c7a3a1 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -2594,13 +2594,10 @@ drop table t1;
create procedure proc_1() install plugin my_plug soname 'some_plugin.so';
---replace_regex /(Can\'t open shared library).*$/\1/
--error ER_CANT_OPEN_LIBRARY,ER_FEATURE_DISABLED
call proc_1();
---replace_regex /(Can\'t open shared library).*$/\1/
--error ER_CANT_OPEN_LIBRARY,ER_FEATURE_DISABLED
call proc_1();
---replace_regex /(Can\'t open shared library).*$/\1/
--error ER_CANT_OPEN_LIBRARY,ER_FEATURE_DISABLED
call proc_1();
drop procedure proc_1;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 7dcd392b36a..b6c8751cd3a 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4363,7 +4363,8 @@ create_sp_error:
my_ok(thd);
break;
case SQLCOM_UNINSTALL_PLUGIN:
- if (! (res= mysql_uninstall_plugin(thd, &thd->lex->comment)))
+ if (! (res= mysql_uninstall_plugin(thd, &thd->lex->comment,
+ &thd->lex->ident)))
my_ok(thd);
break;
case SQLCOM_BINLOG_BASE64_EVENT:
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index fdd6b6e75bd..edeae8aa9c8 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -297,8 +297,7 @@ public:
/* prototypes */
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 bool plugin_load_list(MEM_ROOT *, int *, char **, const char *);
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
int *, char **);
static bool register_builtin(struct st_maria_plugin *, struct st_plugin_int *,
@@ -318,6 +317,7 @@ static void reap_plugins(void);
static void report_error(int where_to, uint error, ...)
{
va_list args;
+ DBUG_ASSERT(where_to & (REPORT_TO_USER | REPORT_TO_LOG));
if (where_to & REPORT_TO_USER)
{
va_start(args, error);
@@ -351,6 +351,20 @@ bool check_valid_path(const char *path, size_t len)
return prefix < len;
}
+static void fix_dl_name(MEM_ROOT *root, LEX_STRING *dl)
+{
+ const size_t so_ext_len= sizeof(SO_EXT) - 1;
+ if (my_strcasecmp(&my_charset_latin1, dl->str + dl->length - so_ext_len,
+ SO_EXT))
+ {
+ char *s= (char*)alloc_root(root, dl->length + so_ext_len + 1);
+ memcpy(s, dl->str, dl->length);
+ strcpy(s + dl->length, SO_EXT);
+ dl->str= s;
+ dl->length+= so_ext_len;
+ }
+}
+
/****************************************************************************
Value type thunks, allows the C world to play in the C++ world
@@ -1017,31 +1031,40 @@ static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
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,
+ const LEX_STRING *name, LEX_STRING *dl,
int *argc, char **argv, int report)
{
struct st_plugin_int tmp;
struct st_maria_plugin *plugin;
+ uint oks= 0, errs= 0;
DBUG_ENTER("plugin_add");
- if (plugin_find_internal(name, MYSQL_ANY_PLUGIN))
+ if (name->str && plugin_find_internal(name, MYSQL_ANY_PLUGIN))
{
report_error(report, ER_UDF_EXISTS, name->str);
DBUG_RETURN(TRUE);
}
/* Clear the whole struct to catch future extensions. */
bzero((char*) &tmp, sizeof(tmp));
+ fix_dl_name(tmp_root, dl);
if (! (tmp.plugin_dl= plugin_dl_add(dl, report)))
DBUG_RETURN(TRUE);
/* Find plugin by name */
for (plugin= tmp.plugin_dl->plugins; plugin->info; plugin++)
{
- uint name_len= strlen(plugin->name);
- if (plugin->type >= 0 && plugin->type < MYSQL_MAX_PLUGIN_TYPE_NUM &&
- ! my_strnncoll(system_charset_info,
- (const uchar *)name->str, name->length,
- (const uchar *)plugin->name,
- name_len))
- {
+ tmp.name.str= (char *)plugin->name;
+ tmp.name.length= strlen(plugin->name);
+
+ if (plugin->type < 0 || plugin->type >= MYSQL_MAX_PLUGIN_TYPE_NUM)
+ continue; // invalid plugin
+
+ if (name->str && my_strnncoll(system_charset_info,
+ (const uchar *)name->str, name->length,
+ (const uchar *)tmp.name.str, tmp.name.length))
+ continue; // plugin name doesn't match
+
+ if (!name->str && plugin_find_internal(&tmp.name, MYSQL_ANY_PLUGIN))
+ continue; // already installed
+
struct st_plugin_int *tmp_plugin_ptr;
if (*(int*)plugin->info <
min_plugin_info_interface_version[plugin->type] ||
@@ -1051,7 +1074,8 @@ static bool plugin_add(MEM_ROOT *tmp_root,
char buf[256];
strxnmov(buf, sizeof(buf) - 1, "API version for ",
plugin_type_names[plugin->type].str,
- " plugin is too different", NullS);
+ " plugin ", tmp.name.str,
+ " not supported by this version of the server", NullS);
report_error(report, ER_CANT_OPEN_LIBRARY, dl->str, 0, buf);
goto err;
}
@@ -1060,40 +1084,49 @@ static bool plugin_add(MEM_ROOT *tmp_root,
char buf[256];
strxnmov(buf, sizeof(buf) - 1, "Loading of ",
plugin_maturity_names[plugin->maturity],
- " plugins is prohibited by --plugin-maturity=",
+ " plugin ", tmp.name.str,
+ " is prohibited by --plugin-maturity=",
plugin_maturity_names[plugin_maturity],
NullS);
report_error(report, ER_CANT_OPEN_LIBRARY, dl->str, 0, buf);
goto err;
}
tmp.plugin= plugin;
- tmp.name.str= (char *)plugin->name;
- tmp.name.length= name_len;
tmp.ref_count= 0;
tmp.state= PLUGIN_IS_UNINITIALIZED;
tmp.load_option= PLUGIN_ON;
if (test_plugin_options(tmp_root, &tmp, argc, argv))
tmp.state= PLUGIN_IS_DISABLED;
- if ((tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
+ if (!(tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
{
- plugin_array_version++;
- if (!my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr))
- {
- init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
- DBUG_RETURN(FALSE);
- }
- tmp_plugin_ptr->state= PLUGIN_IS_FREED;
+ mysql_del_sys_var_chain(tmp.system_vars);
+ restore_pluginvar_names(tmp.system_vars);
+ goto err;
}
- mysql_del_sys_var_chain(tmp.system_vars);
- restore_pluginvar_names(tmp.system_vars);
- goto err;
- }
- }
- report_error(report, ER_CANT_FIND_DL_ENTRY, name->str);
+ plugin_array_version++;
+ if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr))
+ tmp_plugin_ptr->state= PLUGIN_IS_FREED;
+ init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096);
+
+ if (name->str)
+ DBUG_RETURN(FALSE); // all done
+
+ oks++;
+ tmp.plugin_dl->ref_count++;
+ continue; // otherwise - go on
+
err:
+ errs++;
+ if (name->str)
+ break;
+ }
+
+ if (errs == 0 && oks == 0) // no plugin was found
+ report_error(report, ER_CANT_FIND_DL_ENTRY, name->str);
+
plugin_dl_del(dl);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(errs > 0 || oks == 0);
}
@@ -1760,8 +1793,6 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
{
char buffer[FN_REFLEN];
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
- struct st_plugin_dl *plugin_dl;
- struct st_maria_plugin *plugin;
char *p= buffer;
DBUG_ENTER("plugin_load_list");
while (list)
@@ -1791,19 +1822,10 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
dl= name;
mysql_mutex_lock(&LOCK_plugin);
- 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
- }
+ free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
+ name.str= 0; // load everything
+ if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
+ goto error;
}
else
{
@@ -1970,14 +1992,68 @@ void plugin_shutdown(void)
DBUG_VOID_RETURN;
}
+/**
+ complete plugin installation (after plugin_add).
+
+ That is, initialize it, and update mysql.plugin table
+*/
+static bool finalize_install(THD *thd, TABLE *table, const LEX_STRING *name)
+{
+ struct st_plugin_int *tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN);
+ int error;
+ DBUG_ASSERT(tmp);
+ mysql_mutex_assert_owner(&LOCK_plugin);
+
+ if (tmp->state == PLUGIN_IS_DISABLED)
+ {
+ if (global_system_variables.log_warnings)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF),
+ name->str, "Plugin is disabled");
+ }
+ else
+ {
+ DBUG_ASSERT(tmp->state == PLUGIN_IS_UNINITIALIZED);
+ if (plugin_initialize(tmp))
+ {
+ report_error(REPORT_TO_USER, ER_CANT_INITIALIZE_UDF, name->str,
+ "Plugin initialization function failed.");
+ tmp->state= PLUGIN_IS_DELETED;
+ return 1;
+ }
+ }
+
+ /*
+ We do not replicate the INSTALL PLUGIN statement. Disable binlogging
+ of the insert into the plugin table, so that it is not replicated in
+ row based mode.
+ */
+ tmp_disable_binlog(thd);
+ table->use_all_columns();
+ restore_record(table, s->default_values);
+ table->field[0]->store(name->str, name->length, system_charset_info);
+ table->field[1]->store(tmp->plugin_dl->dl.str, tmp->plugin_dl->dl.length,
+ files_charset_info);
+ error= table->file->ha_write_row(table->record[0]);
+ reenable_binlog(thd);
+ if (error)
+ {
+ table->file->print_error(error, MYF(0));
+ tmp->state= PLUGIN_IS_DELETED;
+ return 1;
+ }
+ return 0;
+}
-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_arg)
{
TABLE_LIST tables;
TABLE *table;
- int error, argc=orig_argc;
+ LEX_STRING dl= *dl_arg;
+ bool error;
+ int argc=orig_argc;
char **argv=orig_argv;
- struct st_plugin_int *tmp;
DBUG_ENTER("mysql_install_plugin");
if (opt_noacl)
@@ -2024,53 +2100,34 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl
report_error(REPORT_TO_USER, ER_PLUGIN_IS_NOT_LOADED, name->str);
goto err;
}
- error= plugin_add(thd->mem_root, name, dl, &argc, argv, REPORT_TO_USER);
+ error= plugin_add(thd->mem_root, name, &dl, &argc, argv, REPORT_TO_USER);
if (argv)
free_defaults(argv);
mysql_rwlock_unlock(&LOCK_system_variables_hash);
- if (error || !(tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
+ if (error)
goto err;
- if (tmp->state == PLUGIN_IS_DISABLED)
- {
- if (global_system_variables.log_warnings)
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF),
- name->str, "Plugin is disabled");
- }
+ if (name->str)
+ error= finalize_install(thd, table, name);
else
{
- if (plugin_initialize(tmp))
+ st_plugin_dl *plugin_dl= plugin_dl_find(&dl);
+ struct st_maria_plugin *plugin;
+ for (plugin= plugin_dl->plugins; plugin->info; plugin++)
{
- my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str,
- "Plugin initialization function failed.");
- goto deinit;
+ LEX_STRING str= { const_cast<char*>(plugin->name), strlen(plugin->name) };
+ error|= finalize_install(thd, table, &str);
}
}
- /*
- We do not replicate the INSTALL PLUGIN statement. Disable binlogging
- of the insert into the plugin table, so that it is not replicated in
- row based mode.
- */
- tmp_disable_binlog(thd);
- table->use_all_columns();
- restore_record(table, s->default_values);
- table->field[0]->store(name->str, name->length, system_charset_info);
- table->field[1]->store(dl->str, dl->length, files_charset_info);
- error= table->file->ha_write_row(table->record[0]);
- reenable_binlog(thd);
if (error)
- {
- table->file->print_error(error, MYF(0));
goto deinit;
- }
mysql_mutex_unlock(&LOCK_plugin);
DBUG_RETURN(FALSE);
+
deinit:
- tmp->state= PLUGIN_IS_DELETED;
reap_needed= true;
reap_plugins();
err:
@@ -2079,66 +2136,27 @@ err:
}
-bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name)
+static bool do_uninstall(THD *thd, TABLE *table, const LEX_STRING *name)
{
- TABLE *table;
- TABLE_LIST tables;
struct st_plugin_int *plugin;
- DBUG_ENTER("mysql_uninstall_plugin");
-
- if (opt_noacl)
- {
- my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables");
- DBUG_RETURN(TRUE);
- }
-
- tables.init_one_table("mysql", 5, "plugin", 6, "plugin", TL_WRITE);
-
- if (check_table_access(thd, DELETE_ACL, &tables, FALSE, 1, FALSE))
- DBUG_RETURN(TRUE);
-
- /* need to open before acquiring LOCK_plugin or it will deadlock */
- if (! (table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
- DBUG_RETURN(TRUE);
-
- /*
- Pre-acquire audit plugins for events that may potentially occur
- during [UN]INSTALL PLUGIN.
-
- When audit event is triggered, audit subsystem acquires interested
- plugins by walking through plugin list. Evidently plugin list
- iterator protects plugin list by acquiring LOCK_plugin, see
- plugin_foreach_with_mask().
-
- On the other hand [UN]INSTALL PLUGIN is acquiring LOCK_plugin
- rather for a long time.
-
- When audit event is triggered during [UN]INSTALL PLUGIN, plugin
- list iterator acquires the same lock (within the same thread)
- second time.
-
- This hack should be removed when LOCK_plugin is fixed so it
- protects only what it supposed to protect.
- */
- mysql_audit_acquire_plugins(thd, MYSQL_AUDIT_GENERAL_CLASS);
+ mysql_mutex_assert_owner(&LOCK_plugin);
- mysql_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);
- goto err;
+ return 1;
}
if (!plugin->plugin_dl)
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
WARN_PLUGIN_DELETE_BUILTIN, ER(WARN_PLUGIN_DELETE_BUILTIN));
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str);
- goto err;
+ return 1;
}
if (plugin->load_option == PLUGIN_FORCE_PLUS_PERMANENT)
{
my_error(ER_PLUGIN_IS_PERMANENT, MYF(0), name->str);
- goto err;
+ return 1;
}
plugin->state= PLUGIN_IS_DELETED;
@@ -2147,8 +2165,6 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name)
WARN_PLUGIN_BUSY, ER(WARN_PLUGIN_BUSY));
else
reap_needed= true;
- reap_plugins();
- mysql_mutex_unlock(&LOCK_plugin);
uchar user_key[MAX_KEY_LENGTH];
table->use_all_columns();
@@ -2170,13 +2186,74 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name)
if (error)
{
table->file->print_error(error, MYF(0));
- DBUG_RETURN(TRUE);
+ return 1;
}
}
- DBUG_RETURN(FALSE);
-err:
+ return 0;
+}
+
+
+bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name,
+ const LEX_STRING *dl_arg)
+{
+ TABLE *table;
+ TABLE_LIST tables;
+ LEX_STRING dl= *dl_arg;
+ bool error= false;
+ DBUG_ENTER("mysql_uninstall_plugin");
+
+ if (opt_noacl)
+ {
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables");
+ DBUG_RETURN(TRUE);
+ }
+
+ tables.init_one_table("mysql", 5, "plugin", 6, "plugin", TL_WRITE);
+
+ if (check_table_access(thd, DELETE_ACL, &tables, FALSE, 1, FALSE))
+ DBUG_RETURN(TRUE);
+
+ /* need to open before acquiring LOCK_plugin or it will deadlock */
+ if (! (table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
+ DBUG_RETURN(TRUE);
+
+ /*
+ Pre-acquire audit plugins for events that may potentially occur
+ during [UN]INSTALL PLUGIN.
+
+ When audit event is triggered, audit subsystem acquires interested
+ plugins by walking through plugin list. Evidently plugin list
+ iterator protects plugin list by acquiring LOCK_plugin, see
+ plugin_foreach_with_mask().
+
+ On the other hand [UN]INSTALL PLUGIN is acquiring LOCK_plugin
+ rather for a long time.
+
+ When audit event is triggered during [UN]INSTALL PLUGIN, plugin
+ list iterator acquires the same lock (within the same thread)
+ second time.
+ */
+ mysql_audit_acquire_plugins(thd, MYSQL_AUDIT_GENERAL_CLASS);
+
+ mysql_mutex_lock(&LOCK_plugin);
+
+ if (name->str)
+ error= do_uninstall(thd, table, name);
+ else
+ {
+ fix_dl_name(thd->mem_root, &dl);
+ st_plugin_dl *plugin_dl= plugin_dl_find(&dl);
+ struct st_maria_plugin *plugin;
+ for (plugin= plugin_dl->plugins; plugin->info; plugin++)
+ {
+ LEX_STRING str= { const_cast<char*>(plugin->name), strlen(plugin->name) };
+ error|= do_uninstall(thd, table, &str);
+ }
+ }
+ reap_plugins();
+
mysql_mutex_unlock(&LOCK_plugin);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(error);
}
diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h
index aee04de7be4..fc059142e24 100644
--- a/sql/sql_plugin.h
+++ b/sql/sql_plugin.h
@@ -159,7 +159,8 @@ 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 mysql_uninstall_plugin(THD *thd, const LEX_STRING *name,
+ const LEX_STRING *dl);
extern bool plugin_register_builtin(struct st_mysql_plugin *plugin);
extern void plugin_thdvar_init(THD *thd);
extern void plugin_thdvar_cleanup(THD *thd);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index ddb2a81cc2d..54e2f3012ff 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -15141,6 +15141,13 @@ install:
lex->comment= $3;
lex->ident= $5;
}
+ | INSTALL_SYM SONAME_SYM TEXT_STRING_sys
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_INSTALL_PLUGIN;
+ lex->comment= null_lex_str;
+ lex->ident= $3;
+ }
;
uninstall:
@@ -15150,6 +15157,13 @@ uninstall:
lex->sql_command= SQLCOM_UNINSTALL_PLUGIN;
lex->comment= $3;
}
+ | UNINSTALL_SYM SONAME_SYM TEXT_STRING_sys
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_UNINSTALL_PLUGIN;
+ lex->comment= null_lex_str;
+ lex->ident= $3;
+ }
;
/* Avoid compiler warning from sql_yacc.cc where yyerrlab1 is not used */
diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc
index 5101d73d23c..dcbfb176c6a 100644
--- a/storage/example/ha_example.cc
+++ b/storage/example/ha_example.cc
@@ -19,17 +19,23 @@
@brief
The ha_example engine is a stubbed storage engine for example purposes only;
- it does nothing at this point. Its purpose is to provide a source
+ it does almost nothing at this point. Its purpose is to provide a source
code illustration of how to begin writing new storage engines; see also
- /storage/example/ha_example.h.
+ storage/example/ha_example.h.
+
+ Additionally, this file includes an example of a daemon plugin which does
+ nothing at all - absolutely nothing, even less than example storage engine.
+ But it shows that one dll/so can contain more than one plugin.
@details
ha_example will let you create/open/delete tables, but
nothing further (for example, indexes are not supported nor can data
- be stored in the table). Use this example as a template for
- implementing the same functionality in your own storage engine. You
- can enable the example storage engine in your build by doing the
- following during your build process:<br> ./configure
+ be stored in the table). It also provides new status (example_func_example)
+ and system (example_ulong_var and example_enum_var) variables.
+
+ Use this example as a template for implementing the same functionality in
+ your own storage engine. You can enable the example storage engine in your
+ build by doing the following during your build process:<br> ./configure
--with-example-storage-engine
Once this is done, MySQL will let you create tables with:<br>
@@ -1111,6 +1117,9 @@ static struct st_mysql_show_var func_status[]=
{0,0,SHOW_UNDEF}
};
+struct st_mysql_daemon unusable_example=
+{ MYSQL_DAEMON_INTERFACE_VERSION };
+
mysql_declare_plugin(example)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
@@ -1138,10 +1147,25 @@ maria_declare_plugin(example)
PLUGIN_LICENSE_GPL,
example_init_func, /* Plugin Init */
example_done_func, /* Plugin Deinit */
- 0x0001 /* 0.1 */,
+ 0x0001, /* version number (0.1) */
func_status, /* status variables */
example_system_variables, /* system variables */
"0.1", /* string version */
MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+},
+{
+ MYSQL_DAEMON_PLUGIN,
+ &unusable_example,
+ "UNUSABLE",
+ "Sergei Golubchik",
+ "Unusable Daemon",
+ PLUGIN_LICENSE_GPL,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x030E, /* version number (3.14) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "3.14.15.926" , /* version, as a string */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
}
maria_declare_plugin_end;