mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
mdev-20: INSTALL PLUGIN SONAME
This commit is contained in:
parent
98141ea42b
commit
1c530b36d1
11 changed files with 332 additions and 161 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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).
|
||||
|
||||
bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl)
|
||||
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_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,11 +2136,70 @@ err:
|
|||
}
|
||||
|
||||
|
||||
bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name)
|
||||
static bool do_uninstall(THD *thd, TABLE *table, const LEX_STRING *name)
|
||||
{
|
||||
struct st_plugin_int *plugin;
|
||||
mysql_mutex_assert_owner(&LOCK_plugin);
|
||||
|
||||
if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
|
||||
{
|
||||
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str);
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
if (plugin->load_option == PLUGIN_FORCE_PLUS_PERMANENT)
|
||||
{
|
||||
my_error(ER_PLUGIN_IS_PERMANENT, MYF(0), name->str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
plugin->state= PLUGIN_IS_DELETED;
|
||||
if (plugin->ref_count)
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
WARN_PLUGIN_BUSY, ER(WARN_PLUGIN_BUSY));
|
||||
else
|
||||
reap_needed= true;
|
||||
|
||||
uchar user_key[MAX_KEY_LENGTH];
|
||||
table->use_all_columns();
|
||||
table->field[0]->store(name->str, name->length, system_charset_info);
|
||||
key_copy(user_key, table->record[0], table->key_info,
|
||||
table->key_info->key_length);
|
||||
if (! table->file->ha_index_read_idx_map(table->record[0], 0, user_key,
|
||||
HA_WHOLE_KEY, HA_READ_KEY_EXACT))
|
||||
{
|
||||
int error;
|
||||
/*
|
||||
We do not replicate the UNINSTALL PLUGIN statement. Disable binlogging
|
||||
of the delete from the plugin table, so that it is not replicated in
|
||||
row based mode.
|
||||
*/
|
||||
tmp_disable_binlog(thd);
|
||||
error= table->file->ha_delete_row(table->record[0]);
|
||||
reenable_binlog(thd);
|
||||
if (error)
|
||||
{
|
||||
table->file->print_error(error, MYF(0));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name,
|
||||
const LEX_STRING *dl_arg)
|
||||
{
|
||||
TABLE *table;
|
||||
TABLE_LIST tables;
|
||||
struct st_plugin_int *plugin;
|
||||
LEX_STRING dl= *dl_arg;
|
||||
bool error= false;
|
||||
DBUG_ENTER("mysql_uninstall_plugin");
|
||||
|
||||
if (opt_noacl)
|
||||
|
@ -2116,67 +2232,28 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name)
|
|||
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_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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (plugin->load_option == PLUGIN_FORCE_PLUS_PERMANENT)
|
||||
{
|
||||
my_error(ER_PLUGIN_IS_PERMANENT, MYF(0), name->str);
|
||||
goto err;
|
||||
}
|
||||
|
||||
plugin->state= PLUGIN_IS_DELETED;
|
||||
if (plugin->ref_count)
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
WARN_PLUGIN_BUSY, ER(WARN_PLUGIN_BUSY));
|
||||
if (name->str)
|
||||
error= do_uninstall(thd, table, name);
|
||||
else
|
||||
reap_needed= true;
|
||||
reap_plugins();
|
||||
mysql_mutex_unlock(&LOCK_plugin);
|
||||
|
||||
uchar user_key[MAX_KEY_LENGTH];
|
||||
table->use_all_columns();
|
||||
table->field[0]->store(name->str, name->length, system_charset_info);
|
||||
key_copy(user_key, table->record[0], table->key_info,
|
||||
table->key_info->key_length);
|
||||
if (! table->file->ha_index_read_idx_map(table->record[0], 0, user_key,
|
||||
HA_WHOLE_KEY, HA_READ_KEY_EXACT))
|
||||
{
|
||||
int error;
|
||||
/*
|
||||
We do not replicate the UNINSTALL PLUGIN statement. Disable binlogging
|
||||
of the delete from the plugin table, so that it is not replicated in
|
||||
row based mode.
|
||||
*/
|
||||
tmp_disable_binlog(thd);
|
||||
error= table->file->ha_delete_row(table->record[0]);
|
||||
reenable_binlog(thd);
|
||||
if (error)
|
||||
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++)
|
||||
{
|
||||
table->file->print_error(error, MYF(0));
|
||||
DBUG_RETURN(TRUE);
|
||||
LEX_STRING str= { const_cast<char*>(plugin->name), strlen(plugin->name) };
|
||||
error|= do_uninstall(thd, table, &str);
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(FALSE);
|
||||
err:
|
||||
reap_plugins();
|
||||
|
||||
mysql_mutex_unlock(&LOCK_plugin);
|
||||
DBUG_RETURN(TRUE);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue