maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #08249
Re: a1c4620: MDEV-6858: enforce_storage_engine option
Hi, Jan!
On Mar 08, Jan Lindström wrote:
> revision-id: a1c4620646d43eaff979c132a57ee2101070fa5e
> parent(s): 1b74f32b1d94465f6d6e14e4aa7ba1f94c32e39e
> committer: Jan Lindström
> branch nick: 10.1-innodb
> timestamp: 2015-03-08 17:23:05 +0200
> message:
>
> MDEV-6858: enforce_storage_engine option
>
> Merge from Percona Server enforced use of a specific storage engine
> authored by Stewart Smith.
>
> Modified to be session variable and modifiable only by SUPER. Use
> similar implementation as default_storage_engine.
>
> diff --git a/mysql-test/t/enforce_storage_engine.test b/mysql-test/t/enforce_storage_engine.test
> new file mode 100644
> index 0000000..36231e6
> --- /dev/null
> +++ b/mysql-test/t/enforce_storage_engine.test
> @@ -0,0 +1,35 @@
...
> +--error ER_UNKNOWN_STORAGE_ENGINE
> +CREATE TABLE t2 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=MyISAM;
> +
> +SET SESSION enforce_storage_engine=MyISAM;
> +select @@session.enforce_storage_engine;
> +select * from t1;
> +drop table t1;
> +
> +--error 1286
> +SET SESSION enforce_storage_engine=FooBar;
> +
> +select @@session.enforce_storage_engine;
Consider adding tests for "only modifiable by SUPER"
(create a new user, connect with it, see that enforce_storage_engine
cannot be changed), and for modified enforce_storage_engine
(you tested that it can be changed, but didn't do any CREATE TABLE with
the new value).
> diff --git a/sql/handler.cc b/sql/handler.cc
> index 12d7ffb..5d5ac30 100644
> --- a/sql/handler.cc
> +++ b/sql/handler.cc
> @@ -117,6 +117,15 @@ static plugin_ref ha_default_tmp_plugin(THD *thd)
> return ha_default_plugin(thd);
> }
>
> +
> +static plugin_ref ha_enforced_plugin(THD *thd)
> +{
> + if (thd->variables.enforced_table_plugin)
> + return thd->variables.enforced_table_plugin;
> + return NULL;
> +}
> +
> +
> /** @brief
> Return the default storage engine handlerton for thread
>
> @@ -148,6 +157,25 @@ handlerton *ha_default_tmp_handlerton(THD *thd)
>
>
> /** @brief
> + Return the enforced storage engine handlerton for thread
> +
> + SYNOPSIS
> + ha_enforce_handlerton(thd)
> + thd current thread
> +
> + RETURN
> + pointer to handlerton OR NULL
> +
> +*/
> +handlerton *ha_enforced_handlerton(THD *thd)
> +{
> + plugin_ref plugin= ha_enforced_plugin(thd);
> + if (plugin)
> + return plugin_hton(plugin);
> + return NULL;
> +}
> +
> +/** @brief
> Return the storage engine handlerton for the supplied name
>
> SYNOPSIS
> diff --git a/sql/mysqld.cc b/sql/mysqld.cc
> index b97742d..6966fd9 100644
> --- a/sql/mysqld.cc
> +++ b/sql/mysqld.cc
> @@ -4738,8 +4738,8 @@ static void add_file_to_crash_report(char *file)
> #define init_default_storage_engine(X,Y) \
> init_default_storage_engine_impl(#X, X, &global_system_variables.Y)
>
> -static int init_default_storage_engine_impl(const char *opt_name,
> - char *engine_name, plugin_ref *res)
> +int init_default_storage_engine_impl(const char *opt_name,
> + char *engine_name, plugin_ref *res)
You've made init_default_storage_engine_impl() extern, but you never
use it anywhere.
And you've forgot to create a command line option for
enforced_table_plugin.
> {
> if (!engine_name)
> {
> diff --git a/sql/sql_table.cc b/sql/sql_table.cc
> index e9a1ae9..184c073 100644
> --- a/sql/sql_table.cc
> +++ b/sql/sql_table.cc
> @@ -9745,12 +9745,24 @@ static bool check_engine(THD *thd, const char *db_name,
> DBUG_ENTER("check_engine");
> handlerton **new_engine= &create_info->db_type;
> handlerton *req_engine= *new_engine;
> + handlerton *enf_engine= ha_enforced_handlerton(thd);
I'd write it directly as
thd->variables.enforced_table_plugin ? plugin_hton(thd->variables.enforced_table_plugin) : NULL;
Or as an inlined function here, in sql_table.cc.
Not as two small but non-inlined functions in handler.cc, that are only
used once here.
> bool no_substitution= thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION;
> *new_engine= ha_checktype(thd, req_engine, no_substitution);
> DBUG_ASSERT(*new_engine);
> if (!*new_engine)
> DBUG_RETURN(true);
>
> + if (enf_engine)
> + {
> + if (enf_engine != *new_engine && no_substitution)
> + {
> + const char *engine_name= ha_resolve_storage_engine_name(req_engine);
> + my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), engine_name, engine_name);
> + DBUG_RETURN(TRUE);
> + }
> + *new_engine= enf_engine;
> + }
> +
> if (req_engine && req_engine != *new_engine)
> {
> push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
> diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
> index 8371df0..cd53714 100644
> --- a/sql/sys_vars.cc
> +++ b/sql/sys_vars.cc
> @@ -3437,6 +3437,28 @@ static Sys_var_plugin Sys_default_tmp_storage_engine(
> SESSION_VAR(tmp_table_plugin), NO_CMD_LINE,
> MYSQL_STORAGE_ENGINE_PLUGIN, DEFAULT(&default_tmp_storage_engine));
>
> +extern int init_default_storage_engine_impl(const char* opt_name, char *engine_name, plugin_ref *plugin);
Not used below.
> +
> +
> +static bool check_super_and_not_null(sys_var *self, THD*thd, set_var *var)
I think that NULL value should be allowed, it means "don't enforce a
storage engine".
> +{
> +#ifndef NO_EMBEDDED_ACCESS_CHECKS
> + if (!(thd->security_ctx->master_access & SUPER_ACL))
> + {
> + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
> + return true;
> + }
> +#endif
> + return var->value && var->value->is_null();
> +}
> +
> +static Sys_var_plugin Sys_enforce_storage_engine(
> + "enforce_storage_engine", "Force the use of a storage engine for new "
> + "tables",
> + SESSION_VAR(enforced_table_plugin),
> + NO_CMD_LINE, MYSQL_STORAGE_ENGINE_PLUGIN,
> + DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_super_and_not_null));
> +
> #if defined(ENABLED_DEBUG_SYNC)
> /*
> Variable can be set for the session only.
Regards,
Sergei