Commit 8249dcaa authored by Jan Lindström's avatar Jan Lindström

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.
parent ba3573ca
drop table if exists t1;
SET SESSION enforce_storage_engine=MyISAM;
select @@session.enforce_storage_engine;
@@session.enforce_storage_engine
MyISAM
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=Memory;
Warnings:
Note 1266 Using storage engine MyISAM for table 't1'
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
`c2` varchar(10) DEFAULT NULL,
PRIMARY KEY (`c1`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=MyISAM;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
`c2` varchar(10) DEFAULT NULL,
PRIMARY KEY (`c1`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
`c2` varchar(10) DEFAULT NULL,
PRIMARY KEY (`c1`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SET SESSION sql_mode='NO_ENGINE_SUBSTITUTION';
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=MyISAM;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
`c2` varchar(10) DEFAULT NULL,
PRIMARY KEY (`c1`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 values (1,'abba');
CREATE TABLE t2 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=Memory;
ERROR 42000: Unknown storage engine 'MEMORY'
SET SESSION sql_mode='';
SET SESSION enforce_storage_engine=MyISAM;
select @@session.enforce_storage_engine;
@@session.enforce_storage_engine
MyISAM
select * from t1;
c1 c2
1 abba
drop table t1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
`c2` varchar(10) DEFAULT NULL,
PRIMARY KEY (`c1`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SET SESSION enforce_storage_engine=FooBar;
ERROR 42000: Unknown storage engine 'FooBar'
select @@session.enforce_storage_engine;
@@session.enforce_storage_engine
MyISAM
SET SESSION enforce_storage_engine=MyISAM;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
SET SESSION enforce_storage_engine=NULL;
SET SESSION sql_mode='NO_ENGINE_SUBSTITUTION';
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=Memory;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
`c2` varchar(10) DEFAULT NULL,
PRIMARY KEY (`c1`)
) ENGINE=MEMORY DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=MyISAM;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
`c2` varchar(10) DEFAULT NULL,
PRIMARY KEY (`c1`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
`c2` varchar(10) DEFAULT NULL,
PRIMARY KEY (`c1`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SET GLOBAL enforce_storage_engine=NULL;
ERROR HY000: Variable 'enforce_storage_engine' is a SESSION variable and can't be used with SET GLOBAL
......@@ -169,6 +169,8 @@ The following options may be given as the first argument:
Which encryption algorithm to use for table encryption.
aes_cbc is the recommended one.. One of: none, aes_ecb,
aes_cbc, aes_ctr
--enforce-storage-engine=name
Force the use of a storage engine for new tables
--event-scheduler[=name]
Enable the event scheduler. Possible values are ON, OFF,
and DISABLED (keep the event scheduler completely
......@@ -1150,6 +1152,7 @@ delayed-queue-size 1000
div-precision-increment 4
encrypt-tmp-disk-tables FALSE
encryption-algorithm none
enforce-storage-engine (No default value)
event-scheduler OFF
expensive-subquery-limit 100
expire-logs-days 0
......
......@@ -10,7 +10,6 @@ there should be *no* long test name listed below:
select distinct variable_name as `there should be *no* variables listed below:` from t2
left join t1 on variable_name=test_name where test_name is null;
there should be *no* variables listed below:
innodb_instrument_semaphores
strict_password_validation
drop table t1;
drop table t2;
SET @start_session_value = @@session.enforce_storage_engine;
SET @@session.enforce_storage_engine = INNODB;
SET @@session.enforce_storage_engine = DEFAULT;
SELECT @@session.enforce_storage_engine;
@@session.enforce_storage_engine
NULL
SET @@session.enforce_storage_engine = MYISAM;
SELECT @@session.enforce_storage_engine;
@@session.enforce_storage_engine
MyISAM
SET @@session.enforce_storage_engine = MERGE;
SELECT @@session.enforce_storage_engine;
@@session.enforce_storage_engine
MRG_MyISAM
SET @@session.enforce_storage_engine = MEMORY;
SELECT @@session.enforce_storage_engine;
@@session.enforce_storage_engine
MEMORY
SET @@session.enforce_storage_engine = INNODB;
SELECT @@session.enforce_storage_engine;
@@session.enforce_storage_engine
InnoDB
SET @@session.enforce_storage_engine = 8199;
ERROR 42000: Incorrect argument type to variable 'enforce_storage_engine'
SET @@session.enforce_storage_engine = 65530.34;
ERROR 42000: Incorrect argument type to variable 'enforce_storage_engine'
SET @@session.enforce_storage_engine = RECORD;
ERROR 42000: Unknown storage engine 'RECORD'
SELECT @@session.enforce_storage_engine =
VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='enforce_storage_engine';
@@session.enforce_storage_engine =
VARIABLE_VALUE
1
SET @@session.enforce_storage_engine = TRUE;
ERROR 42000: Incorrect argument type to variable 'enforce_storage_engine'
SET @@session.enforce_storage_engine = FALSE;
ERROR 42000: Incorrect argument type to variable 'enforce_storage_engine'
SET @@session.enforce_storage_engine = @start_session_value;
#
# innodb_instrument_semaphores
#
# save the initial value
SET @innodb_instrument_semaphores_global_saved = @@global.innodb_instrument_semaphores;
# default
SELECT @@global.innodb_instrument_semaphores;
@@global.innodb_instrument_semaphores
0
# scope
SELECT @@session.innodb_instrument_semaphores;
ERROR HY000: Variable 'innodb_instrument_semaphores' is a GLOBAL variable
SET @@global.innodb_instrument_semaphores=OFF;
SELECT @@global.innodb_instrument_semaphores;
@@global.innodb_instrument_semaphores
0
SET @@global.innodb_instrument_semaphores=ON;
SELECT @@global.innodb_instrument_semaphores;
@@global.innodb_instrument_semaphores
1
# valid values
SET @@global.innodb_instrument_semaphores='OFF';
SELECT @@global.innodb_instrument_semaphores;
@@global.innodb_instrument_semaphores
0
SET @@global.innodb_instrument_semaphores=ON;
SELECT @@global.innodb_instrument_semaphores;
@@global.innodb_instrument_semaphores
1
SET @@global.innodb_instrument_semaphores=default;
SELECT @@global.innodb_instrument_semaphores;
@@global.innodb_instrument_semaphores
0
# invalid values
SET @@global.innodb_instrument_semaphores=NULL;
ERROR 42000: Variable 'innodb_instrument_semaphores' can't be set to the value of 'NULL'
SET @@global.innodb_instrument_semaphores='junk';
ERROR 42000: Variable 'innodb_instrument_semaphores' can't be set to the value of 'junk'
# restore the initial value
SET @@global.innodb_instrument_semaphores = @innodb_instrument_semaphores_global_saved;
# End of test
......@@ -721,6 +721,20 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME ENFORCE_STORAGE_ENGINE
SESSION_VALUE
GLOBAL_VALUE NULL
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE NULL
VARIABLE_SCOPE SESSION ONLY
VARIABLE_TYPE VARCHAR
VARIABLE_COMMENT Force the use of a storage engine for new tables
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT NULL
VARIABLE_NAME ERROR_COUNT
SESSION_VALUE 0
GLOBAL_VALUE NULL
......
--source include/not_embedded.inc
--source include/have_innodb.inc
--source include/load_sysvars.inc
SET @start_session_value = @@session.enforce_storage_engine;
SET @@session.enforce_storage_engine = INNODB;
SET @@session.enforce_storage_engine = DEFAULT;
SELECT @@session.enforce_storage_engine;
SET @@session.enforce_storage_engine = MYISAM;
SELECT @@session.enforce_storage_engine;
SET @@session.enforce_storage_engine = MERGE;
SELECT @@session.enforce_storage_engine;
SET @@session.enforce_storage_engine = MEMORY;
SELECT @@session.enforce_storage_engine;
SET @@session.enforce_storage_engine = INNODB;
SELECT @@session.enforce_storage_engine;
--Error ER_WRONG_TYPE_FOR_VAR
SET @@session.enforce_storage_engine = 8199;
--Error ER_WRONG_TYPE_FOR_VAR
SET @@session.enforce_storage_engine = 65530.34;
--Error ER_UNKNOWN_STORAGE_ENGINE
SET @@session.enforce_storage_engine = RECORD;
SELECT @@session.enforce_storage_engine =
VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='enforce_storage_engine';
--Error ER_WRONG_TYPE_FOR_VAR
SET @@session.enforce_storage_engine = TRUE;
--Error ER_WRONG_TYPE_FOR_VAR
SET @@session.enforce_storage_engine = FALSE;
SET @@session.enforce_storage_engine = @start_session_value;
-- source include/not_embedded.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
SET SESSION enforce_storage_engine=MyISAM;
select @@session.enforce_storage_engine;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=Memory;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=MyISAM;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10));
SHOW CREATE TABLE t1;
DROP TABLE t1;
SET SESSION sql_mode='NO_ENGINE_SUBSTITUTION';
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=MyISAM;
SHOW CREATE TABLE t1;
INSERT INTO t1 values (1,'abba');
--error 1286
CREATE TABLE t2 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=Memory;
SET SESSION sql_mode='';
SET SESSION enforce_storage_engine=MyISAM;
select @@session.enforce_storage_engine;
select * from t1;
drop table t1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10));
SHOW CREATE TABLE t1;
DROP TABLE t1;
--error 1286
SET SESSION enforce_storage_engine=FooBar;
select @@session.enforce_storage_engine;
--source include/add_anonymous_users.inc
connect (con1,localhost,user_1,,);
connection con1;
--error 1227
SET SESSION enforce_storage_engine=MyISAM;
disconnect con1;
connection default;
--source include/delete_anonymous_users.inc
SET SESSION enforce_storage_engine=NULL;
SET SESSION sql_mode='NO_ENGINE_SUBSTITUTION';
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=Memory;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=MyISAM;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10));
SHOW CREATE TABLE t1;
DROP TABLE t1;
--error 1228
SET GLOBAL enforce_storage_engine=NULL;
......@@ -117,6 +117,7 @@ static plugin_ref ha_default_tmp_plugin(THD *thd)
return ha_default_plugin(thd);
}
/** @brief
Return the default storage engine handlerton for thread
......
......@@ -369,6 +369,7 @@ static char *lc_time_names_name;
char *my_bind_addr_str;
static char *default_collation_name;
char *default_storage_engine, *default_tmp_storage_engine;
char *enforced_storage_engine=NULL;
static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
static I_List<THD> thread_cache;
static bool binlog_format_used= false;
......@@ -5144,6 +5145,9 @@ a file name for --log-bin-index option", opt_binlog_index_name);
if (init_default_storage_engine(default_tmp_storage_engine, tmp_table_plugin))
unireg_abort(1);
if (init_default_storage_engine(enforced_storage_engine, enforced_table_plugin))
unireg_abort(1);
#ifdef USE_ARIA_FOR_TMP_TABLES
if (!ha_storage_engine_is_enabled(maria_hton) && !opt_bootstrap)
{
......@@ -7156,6 +7160,9 @@ struct my_option my_long_options[]=
{"stack-trace", 0 , "Print a symbolic stack trace on failure",
&opt_stack_trace, &opt_stack_trace, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
#endif /* HAVE_STACKTRACE */
{"enforce-storage-engine", 0, "Force the use of a storage engine for new tables",
&enforced_storage_engine, 0, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0 },
{"external-locking", 0, "Use system (external) locking (disabled by "
"default). With this option enabled you can run myisamchk to test "
"(not repair) tables while the MySQL server is running. Disable with "
......
......@@ -138,6 +138,7 @@ extern ulong opt_replicate_events_marked_for_skip;
extern char *default_tz_name;
extern Time_zone *default_tz;
extern char *default_storage_engine, *default_tmp_storage_engine;
extern char *enforced_storage_engine;
extern bool opt_endinfo, using_udf_functions;
extern my_bool locked_in_memory;
extern bool opt_using_transactions;
......
......@@ -618,6 +618,7 @@ typedef struct system_variables
plugin_ref table_plugin;
plugin_ref tmp_table_plugin;
plugin_ref enforced_table_plugin;
/* Only charset part of these variables is sensible */
CHARSET_INFO *character_set_filesystem;
......
......@@ -3089,11 +3089,13 @@ void plugin_thdvar_init(THD *thd)
{
plugin_ref old_table_plugin= thd->variables.table_plugin;
plugin_ref old_tmp_table_plugin= thd->variables.tmp_table_plugin;
plugin_ref old_enforced_table_plugin= thd->variables.enforced_table_plugin;
DBUG_ENTER("plugin_thdvar_init");
// This function may be called many times per THD (e.g. on COM_CHANGE_USER)
thd->variables.table_plugin= NULL;
thd->variables.tmp_table_plugin= NULL;
thd->variables.enforced_table_plugin= NULL;
cleanup_variables(&thd->variables);
thd->variables= global_system_variables;
......@@ -3113,12 +3115,14 @@ void plugin_thdvar_init(THD *thd)
intern_plugin_lock(NULL, global_system_variables.tmp_table_plugin);
intern_plugin_unlock(NULL, old_table_plugin);
intern_plugin_unlock(NULL, old_tmp_table_plugin);
intern_plugin_unlock(NULL, old_enforced_table_plugin);
mysql_mutex_unlock(&LOCK_plugin);
}
else
{
thd->variables.table_plugin= NULL;
thd->variables.tmp_table_plugin= NULL;
thd->variables.enforced_table_plugin= NULL;
}
DBUG_VOID_RETURN;
......@@ -3132,7 +3136,8 @@ static void unlock_variables(THD *thd, struct system_variables *vars)
{
intern_plugin_unlock(NULL, vars->table_plugin);
intern_plugin_unlock(NULL, vars->tmp_table_plugin);
vars->table_plugin= vars->tmp_table_plugin= NULL;
intern_plugin_unlock(NULL, vars->enforced_table_plugin);
vars->table_plugin= vars->tmp_table_plugin= vars->enforced_table_plugin= NULL;
}
......@@ -3170,6 +3175,7 @@ static void cleanup_variables(struct system_variables *vars)
DBUG_ASSERT(vars->table_plugin == NULL);
DBUG_ASSERT(vars->tmp_table_plugin == NULL);
DBUG_ASSERT(vars->enforced_table_plugin == NULL);
my_free(vars->dynamic_variables_ptr);
vars->dynamic_variables_ptr= NULL;
......
......@@ -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= thd->variables.enforced_table_plugin ? plugin_hton(thd->variables.enforced_table_plugin) : NULL;
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 && enf_engine != *new_engine)
{
if (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,
......
......@@ -3439,6 +3439,12 @@ 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));
static Sys_var_plugin Sys_enforce_storage_engine(
"enforce_storage_engine", "Force the use of a storage engine for new tables",
SESSION_ONLY(enforced_table_plugin),
NO_CMD_LINE, MYSQL_STORAGE_ENGINE_PLUGIN,
DEFAULT(&enforced_storage_engine), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_has_super));
#if defined(ENABLED_DEBUG_SYNC)
/*
Variable can be set for the session only.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment