[Commits] 37ee92c: MDEV-6858: enforce_storage_engine option

Jan Lindström jan.lindstrom at mariadb.com
Mon Mar 9 14:46:16 EET 2015


revision-id: 37ee92c73763a81563e8dd1871709315280fec81
parent(s): f7d196bb2e605766668895027c48728f03803734
committer: Jan Lindström
branch nick: 10.1-innodb
timestamp: 2015-03-09 14:45:26 +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.

---
 mysql-test/r/enforce_storage_engine.result         | 93 ++++++++++++++++++++++
 mysql-test/r/mysqld--help.result                   |  3 +
 mysql-test/suite/sys_vars/r/all_vars.result        |  1 -
 .../sys_vars/r/enforce_storage_engine_basic.result | 39 +++++++++
 .../r/innodb_instrument_semaphores_basic.result    | 45 +++++++++++
 .../sys_vars/r/sysvars_server_notembedded.result   | 14 ++++
 .../sys_vars/t/enforce_storage_engine_basic.test   | 40 ++++++++++
 .../sys_vars/t/innodb_instrument_semaphores.test   | 42 ----------
 .../t/innodb_instrument_semaphores_basic.test      | 42 ++++++++++
 mysql-test/t/enforce_storage_engine.test           | 65 +++++++++++++++
 sql/handler.cc                                     |  1 +
 sql/mysqld.cc                                      |  7 ++
 sql/mysqld.h                                       |  1 +
 sql/sql_class.h                                    |  1 +
 sql/sql_plugin.cc                                  |  8 +-
 sql/sql_table.cc                                   |  4 +
 sql/sys_vars.cc                                    |  6 ++
 17 files changed, 368 insertions(+), 44 deletions(-)

diff --git a/mysql-test/r/enforce_storage_engine.result b/mysql-test/r/enforce_storage_engine.result
new file mode 100644
index 0000000..feb0551
--- /dev/null
+++ b/mysql-test/r/enforce_storage_engine.result
@@ -0,0 +1,93 @@
+drop table if exists t1;
+SET SESSION enforce_storage_engine=InnoDB;
+select @@session.enforce_storage_engine;
+@@session.enforce_storage_engine
+InnoDB
+CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+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=InnoDB 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=InnoDB;
+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=InnoDB DEFAULT CHARSET=latin1
+INSERT INTO t1 values (1,'abba');
+CREATE TABLE t2 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=MyISAM;
+Warnings:
+Note	1266	Using storage engine InnoDB for table 't2'
+show create table t2;
+Table	Create Table
+t2	CREATE TABLE `t2` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  `c2` varchar(10) DEFAULT NULL,
+  PRIMARY KEY (`c1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+show warnings;
+Level	Code	Message
+drop table t2;
+CREATE TABLE t3 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10));
+Warnings:
+Note	1266	Using storage engine InnoDB for table 't3'
+SHOW CREATE TABLE t3;
+Table	Create Table
+t3	CREATE TABLE `t3` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  `c2` varchar(10) DEFAULT NULL,
+  PRIMARY KEY (`c1`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t3;
+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 GLOBAL enforce_storage_engine=NULL;
+ERROR HY000: Variable 'enforce_storage_engine' is a SESSION variable and can't be used with SET GLOBAL
diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result
index 3036700..7d59ecd 100644
--- a/mysql-test/r/mysqld--help.result
+++ b/mysql-test/r/mysqld--help.result
@@ -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
diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result
index 0ace47d..840da84 100644
--- a/mysql-test/suite/sys_vars/r/all_vars.result
+++ b/mysql-test/suite/sys_vars/r/all_vars.result
@@ -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;
diff --git a/mysql-test/suite/sys_vars/r/enforce_storage_engine_basic.result b/mysql-test/suite/sys_vars/r/enforce_storage_engine_basic.result
new file mode 100644
index 0000000..cb5b199
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/enforce_storage_engine_basic.result
@@ -0,0 +1,39 @@
+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;
diff --git a/mysql-test/suite/sys_vars/r/innodb_instrument_semaphores_basic.result b/mysql-test/suite/sys_vars/r/innodb_instrument_semaphores_basic.result
new file mode 100644
index 0000000..dc8fba4
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/innodb_instrument_semaphores_basic.result
@@ -0,0 +1,45 @@
+#
+# 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
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index 83c0196..bf8f868 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -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
diff --git a/mysql-test/suite/sys_vars/t/enforce_storage_engine_basic.test b/mysql-test/suite/sys_vars/t/enforce_storage_engine_basic.test
new file mode 100644
index 0000000..62627a1
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/enforce_storage_engine_basic.test
@@ -0,0 +1,40 @@
+--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;
diff --git a/mysql-test/suite/sys_vars/t/innodb_instrument_semaphores.test b/mysql-test/suite/sys_vars/t/innodb_instrument_semaphores.test
deleted file mode 100644
index 9b302be..0000000
--- a/mysql-test/suite/sys_vars/t/innodb_instrument_semaphores.test
+++ /dev/null
@@ -1,42 +0,0 @@
---source include/have_innodb.inc
-
---echo #
---echo # innodb_instrument_semaphores
---echo #
-
---echo # save the initial value
-SET @innodb_instrument_semaphores_global_saved = @@global.innodb_instrument_semaphores;
-
---echo # default
-SELECT @@global.innodb_instrument_semaphores;
-
---echo
---echo # scope
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
-SELECT @@session.innodb_instrument_semaphores;
-SET @@global.innodb_instrument_semaphores=OFF;
-SELECT @@global.innodb_instrument_semaphores;
-SET @@global.innodb_instrument_semaphores=ON;
-SELECT @@global.innodb_instrument_semaphores;
-
---echo
---echo # valid values
-SET @@global.innodb_instrument_semaphores='OFF';
-SELECT @@global.innodb_instrument_semaphores;
-SET @@global.innodb_instrument_semaphores=ON;
-SELECT @@global.innodb_instrument_semaphores;
-SET @@global.innodb_instrument_semaphores=default;
-SELECT @@global.innodb_instrument_semaphores;
-
---echo
---echo # invalid values
---error ER_WRONG_VALUE_FOR_VAR
-SET @@global.innodb_instrument_semaphores=NULL;
---error ER_WRONG_VALUE_FOR_VAR
-SET @@global.innodb_instrument_semaphores='junk';
-
---echo
---echo # restore the initial value
-SET @@global.innodb_instrument_semaphores = @innodb_instrument_semaphores_global_saved;
-
---echo # End of test
diff --git a/mysql-test/suite/sys_vars/t/innodb_instrument_semaphores_basic.test b/mysql-test/suite/sys_vars/t/innodb_instrument_semaphores_basic.test
new file mode 100644
index 0000000..9b302be
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/innodb_instrument_semaphores_basic.test
@@ -0,0 +1,42 @@
+--source include/have_innodb.inc
+
+--echo #
+--echo # innodb_instrument_semaphores
+--echo #
+
+--echo # save the initial value
+SET @innodb_instrument_semaphores_global_saved = @@global.innodb_instrument_semaphores;
+
+--echo # default
+SELECT @@global.innodb_instrument_semaphores;
+
+--echo
+--echo # scope
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT @@session.innodb_instrument_semaphores;
+SET @@global.innodb_instrument_semaphores=OFF;
+SELECT @@global.innodb_instrument_semaphores;
+SET @@global.innodb_instrument_semaphores=ON;
+SELECT @@global.innodb_instrument_semaphores;
+
+--echo
+--echo # valid values
+SET @@global.innodb_instrument_semaphores='OFF';
+SELECT @@global.innodb_instrument_semaphores;
+SET @@global.innodb_instrument_semaphores=ON;
+SELECT @@global.innodb_instrument_semaphores;
+SET @@global.innodb_instrument_semaphores=default;
+SELECT @@global.innodb_instrument_semaphores;
+
+--echo
+--echo # invalid values
+--error ER_WRONG_VALUE_FOR_VAR
+SET @@global.innodb_instrument_semaphores=NULL;
+--error ER_WRONG_VALUE_FOR_VAR
+SET @@global.innodb_instrument_semaphores='junk';
+
+--echo
+--echo # restore the initial value
+SET @@global.innodb_instrument_semaphores = @innodb_instrument_semaphores_global_saved;
+
+--echo # End of test
diff --git a/mysql-test/t/enforce_storage_engine.test b/mysql-test/t/enforce_storage_engine.test
new file mode 100644
index 0000000..c80061e
--- /dev/null
+++ b/mysql-test/t/enforce_storage_engine.test
@@ -0,0 +1,65 @@
+-- source include/have_innodb.inc
+-- source include/not_embedded.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+SET SESSION enforce_storage_engine=InnoDB;
+select @@session.enforce_storage_engine;
+CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+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=InnoDB;
+SHOW CREATE TABLE t1;
+INSERT INTO t1 values (1,'abba');
+
+CREATE TABLE t2 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=MyISAM;
+show create table t2;
+show warnings;
+drop table t2;
+
+CREATE TABLE t3 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10));
+SHOW CREATE TABLE t3;
+DROP TABLE t3;
+
+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;
+
+--error 1228
+SET GLOBAL enforce_storage_engine=NULL;
diff --git a/sql/handler.cc b/sql/handler.cc
index 12d7ffb..d64c146 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -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
 
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index b97742d..aa85a02 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -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 "
diff --git a/sql/mysqld.h b/sql/mysqld.h
index bfce719..b0b3185 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -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;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index bd145bd..5930c6c 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -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;
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 2fe22ea..fe020d3 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -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;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index e9a1ae9..97bbfba 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -9745,12 +9745,16 @@ 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 && no_substitution)
+    *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 079861f..5707bf9 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -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.


More information about the commits mailing list