summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mysql/service_wsrep.h6
-rw-r--r--include/wsrep.h21
-rw-r--r--mysql-test/suite/galera/r/wsrep_strict_ddl.result194
-rw-r--r--mysql-test/suite/galera/t/wsrep_strict_ddl.test133
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_wsrep.result15
-rw-r--r--mysql-test/suite/sys_vars/r/wsrep_strict_ddl_basic.result45
-rw-r--r--mysql-test/suite/sys_vars/t/wsrep_strict_ddl_basic.test42
-rw-r--r--sql/service_wsrep.cc23
-rw-r--r--sql/share/errmsg-utf8.txt2
-rw-r--r--sql/sql_alter.cc6
-rw-r--r--sql/sql_parse.cc39
-rw-r--r--sql/sql_plugin_services.ic1
-rw-r--r--sql/sql_rename.cc7
-rw-r--r--sql/sql_table.cc24
-rw-r--r--sql/sql_trigger.cc8
-rw-r--r--sql/sql_truncate.cc20
-rw-r--r--sql/sql_view.cc9
-rw-r--r--sql/sys_vars.cc10
-rw-r--r--sql/wsrep_dummy.cc2
-rw-r--r--sql/wsrep_mysqld.cc159
-rw-r--r--sql/wsrep_mysqld.h11
21 files changed, 690 insertions, 87 deletions
diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h
index 30ed7246eac..8d132212d77 100644
--- a/include/mysql/service_wsrep.h
+++ b/include/mysql/service_wsrep.h
@@ -84,6 +84,7 @@ extern struct wsrep_service_st {
my_bool (*wsrep_get_debug_func)();
void (*wsrep_commit_ordered_func)(MYSQL_THD thd);
my_bool (*wsrep_thd_is_applying_func)(const MYSQL_THD thd);
+ ulong (*wsrep_OSU_method_get_func)(const MYSQL_THD thd);
my_bool (*wsrep_thd_has_ignored_error_func)(const MYSQL_THD thd);
void (*wsrep_thd_set_ignored_error_func)(MYSQL_THD thd, my_bool val);
} *wsrep_service;
@@ -126,9 +127,9 @@ extern struct wsrep_service_st {
#define wsrep_get_debug() wsrep_service->wsrep_get_debug_func()
#define wsrep_commit_ordered(T) wsrep_service->wsrep_commit_ordered_func(T)
#define wsrep_thd_is_applying(T) wsrep_service->wsrep_thd_is_applying_func(T)
+#define wsrep_OSU_method_get(T) wsrep_service->wsrep_OSU_method_get_func(T)
#define wsrep_thd_has_ignored_error(T) wsrep_service->wsrep_thd_has_ignored_error_func(T)
#define wsrep_thd_set_ignored_error(T,V) wsrep_service->wsrep_thd_set_ignored_error_func(T,V)
-
#else
#define MYSQL_SERVICE_WSREP_STATIC_INCLUDED
@@ -220,9 +221,8 @@ extern "C" my_bool wsrep_get_debug();
extern "C" void wsrep_commit_ordered(MYSQL_THD thd);
extern "C" my_bool wsrep_thd_is_applying(const MYSQL_THD thd);
-
+extern "C" ulong wsrep_OSU_method_get(const MYSQL_THD thd);
extern "C" my_bool wsrep_thd_has_ignored_error(const MYSQL_THD thd);
extern "C" void wsrep_thd_set_ignored_error(MYSQL_THD thd, my_bool val);
-
#endif
#endif /* MYSQL_SERVICE_WSREP_INCLUDED */
diff --git a/include/wsrep.h b/include/wsrep.h
index dbdb746409b..f8a1863b966 100644
--- a/include/wsrep.h
+++ b/include/wsrep.h
@@ -19,18 +19,27 @@
#include <my_config.h>
#ifdef WITH_WSREP
+
#define IF_WSREP(A,B) A
+
#define DBUG_ASSERT_IF_WSREP(A) DBUG_ASSERT(A)
#define WSREP_MYSQL_DB (char *)"mysql"
+
#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \
- if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) \
+ if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) \
+ goto wsrep_error_label;
+
+#define WSREP_TO_ISOLATION_BEGIN_CREATE(db_, table_, table_list_, create_info_) \
+ if (WSREP(thd) && \
+ wsrep_to_isolation_begin(thd, db_, table_, \
+ table_list_, NULL, create_info_)) \
goto wsrep_error_label;
-#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_) \
+#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, create_info_) \
if (WSREP(thd) && wsrep_thd_is_local(thd) && \
wsrep_to_isolation_begin(thd, db_, table_, \
- table_list_, alter_info_)) \
+ table_list_, alter_info_, create_info_)) \
goto wsrep_error_label;
#define WSREP_TO_ISOLATION_END \
@@ -56,14 +65,12 @@
* (e.g. embedded) */
#define IF_WSREP(A,B) B
-//#define DBUG_ASSERT_IF_WSREP(A)
#define WSREP_DEBUG(...)
-//#define WSREP_INFO(...)
-//#define WSREP_WARN(...)
#define WSREP_ERROR(...)
#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) do { } while(0)
-#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_)
+#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, create_info_)
#define WSREP_TO_ISOLATION_END
+#define WSREP_TO_ISOLATION_BEGIN_CREATE(db_, table_, table_list_, create_info_)
#define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_)
#define WSREP_SYNC_WAIT(thd_, before_)
#endif /* WITH_WSREP */
diff --git a/mysql-test/suite/galera/r/wsrep_strict_ddl.result b/mysql-test/suite/galera/r/wsrep_strict_ddl.result
new file mode 100644
index 00000000000..6d25ec35549
--- /dev/null
+++ b/mysql-test/suite/galera/r/wsrep_strict_ddl.result
@@ -0,0 +1,194 @@
+connection node_2;
+connection node_1;
+call mtr.add_suppression("WSREP: ALTER TABLE isolation failure");
+connection node_1;
+SET GLOBAL binlog_format='ROW';
+create table before_t1(a int, count int, b int, key(b)) engine=Aria;
+INSERT INTO before_t1 values (1,1,1);
+set @@global.wsrep_strict_ddl=ON;
+select @@global.wsrep_strict_ddl;
+@@global.wsrep_strict_ddl
+1
+connection node_2;
+set @@global.wsrep_strict_ddl=ON;
+select @@global.wsrep_strict_ddl;
+@@global.wsrep_strict_ddl
+1
+connection node_1;
+CREATE TABLE t1(a int) engine=Aria;
+ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
+SHOW WARNINGS;
+Level Code Message
+Error 4165 DDL-statement is forbidden as table storage engine does not support Galera replication
+Warning 1031 WSREP: wsrep_strict_ddl=true and storage engine does not support Galera replication.
+connection node_2;
+SHOW CREATE TABLE t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+connection node_1;
+CREATE TABLE t2(a int not null primary key) engine=InnoDB;
+ALTER TABLE t2 engine=MyISAM;
+ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
+SHOW WARNINGS;
+Level Code Message
+Error 4165 DDL-statement is forbidden as table storage engine does not support Galera replication
+Warning 1031 WSREP: wsrep_strict_ddl=true and storage engine does not support Galera replication.
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) NOT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+connection node_2;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) NOT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+connection node_1;
+TRUNCATE TABLE before_t1;
+ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
+SELECT * FROM before_t1;
+a count b
+1 1 1
+connection node_2;
+SET SESSION wsrep_sync_wait=15;
+SELECT @@wsrep_sync_wait;
+@@wsrep_sync_wait
+15
+SELECT * FROM before_t1;
+a count b
+connection node_1;
+CREATE VIEW x1 AS SELECT * FROM before_t1;
+ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
+SHOW CREATE VIEW x1;
+ERROR 42S02: Table 'test.x1' doesn't exist
+connection node_2;
+SHOW CREATE VIEW x1;
+ERROR 42S02: Table 'test.x1' doesn't exist
+connection node_1;
+CREATE DEFINER=`root`@`localhost` TRIGGER increment_before_t1
+AFTER INSERT ON before_t1 FOR EACH ROW
+UPDATE before_t1 SET before_t1.count = before_t1.count+1;
+ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
+SHOW CREATE TRIGGER increment_before_t1;
+ERROR HY000: Trigger does not exist
+connection node_2;
+SHOW CREATE TRIGGER increment_before_t1;
+ERROR HY000: Trigger does not exist
+connection node_1;
+CREATE INDEX xx2 ON before_t1(a);
+ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
+SHOW CREATE TABLE before_t1;
+Table Create Table
+before_t1 CREATE TABLE `before_t1` (
+ `a` int(11) DEFAULT NULL,
+ `count` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ KEY `b` (`b`)
+) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+connection node_2;
+SHOW CREATE TABLE before_t1;
+Table Create Table
+before_t1 CREATE TABLE `before_t1` (
+ `a` int(11) DEFAULT NULL,
+ `count` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ KEY `b` (`b`)
+) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+connection node_1;
+DROP INDEX b ON before_t1;
+ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
+SHOW CREATE TABLE before_t1;
+Table Create Table
+before_t1 CREATE TABLE `before_t1` (
+ `a` int(11) DEFAULT NULL,
+ `count` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ KEY `b` (`b`)
+) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+connection node_2;
+SHOW CREATE TABLE before_t1;
+Table Create Table
+before_t1 CREATE TABLE `before_t1` (
+ `a` int(11) DEFAULT NULL,
+ `count` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ KEY `b` (`b`)
+) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+connection node_1;
+ALTER TABLE before_t1 ADD COLUMN f int;
+ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
+SHOW CREATE TABLE before_t1;
+Table Create Table
+before_t1 CREATE TABLE `before_t1` (
+ `a` int(11) DEFAULT NULL,
+ `count` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ KEY `b` (`b`)
+) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+connection node_2;
+SHOW CREATE TABLE before_t1;
+Table Create Table
+before_t1 CREATE TABLE `before_t1` (
+ `a` int(11) DEFAULT NULL,
+ `count` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ KEY `b` (`b`)
+) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+connection node_1;
+RENAME TABLE before_t1 to after_t1;
+ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
+SHOW CREATE TABLE before_t1;
+Table Create Table
+before_t1 CREATE TABLE `before_t1` (
+ `a` int(11) DEFAULT NULL,
+ `count` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ KEY `b` (`b`)
+) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+SHOW CREATE TABLE after_t1;
+ERROR 42S02: Table 'test.after_t1' doesn't exist
+connection node_2;
+SHOW CREATE TABLE before_t1;
+Table Create Table
+before_t1 CREATE TABLE `before_t1` (
+ `a` int(11) DEFAULT NULL,
+ `count` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ KEY `b` (`b`)
+) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+SHOW CREATE TABLE after_t1;
+ERROR 42S02: Table 'test.after_t1' doesn't exist
+connection node_1;
+DROP TABLE before_t1;
+ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
+SHOW CREATE TABLE before_t1;
+Table Create Table
+before_t1 CREATE TABLE `before_t1` (
+ `a` int(11) DEFAULT NULL,
+ `count` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ KEY `b` (`b`)
+) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+connection node_2;
+SHOW CREATE TABLE before_t1;
+Table Create Table
+before_t1 CREATE TABLE `before_t1` (
+ `a` int(11) DEFAULT NULL,
+ `count` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ KEY `b` (`b`)
+) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+connection node_1;
+set @@global.wsrep_strict_ddl=OFF;
+select @@global.wsrep_strict_ddl;
+@@global.wsrep_strict_ddl
+0
+connection node_2;
+set @@global.wsrep_strict_ddl=OFF;
+select @@global.wsrep_strict_ddl;
+@@global.wsrep_strict_ddl
+0
+DROP TABLE t2;
+DROP TABLE before_t1;
diff --git a/mysql-test/suite/galera/t/wsrep_strict_ddl.test b/mysql-test/suite/galera/t/wsrep_strict_ddl.test
new file mode 100644
index 00000000000..c0a0cd756ba
--- /dev/null
+++ b/mysql-test/suite/galera/t/wsrep_strict_ddl.test
@@ -0,0 +1,133 @@
+--source include/galera_cluster.inc
+
+call mtr.add_suppression("WSREP: ALTER TABLE isolation failure");
+
+--connection node_1
+SET GLOBAL binlog_format='ROW';
+create table before_t1(a int, count int, b int, key(b)) engine=Aria;
+INSERT INTO before_t1 values (1,1,1);
+
+set @@global.wsrep_strict_ddl=ON;
+select @@global.wsrep_strict_ddl;
+
+--connection node_2
+set @@global.wsrep_strict_ddl=ON;
+select @@global.wsrep_strict_ddl;
+
+--connection node_1
+--error ER_GALERA_REPLICATION_NOT_SUPPORTED
+CREATE TABLE t1(a int) engine=Aria;
+SHOW WARNINGS;
+
+--connection node_2
+--error ER_NO_SUCH_TABLE
+SHOW CREATE TABLE t1;
+
+--connection node_1
+CREATE TABLE t2(a int not null primary key) engine=InnoDB;
+
+--error ER_GALERA_REPLICATION_NOT_SUPPORTED
+ALTER TABLE t2 engine=MyISAM;
+SHOW WARNINGS;
+SHOW CREATE TABLE t2;
+
+--connection node_2
+SHOW CREATE TABLE t2;
+
+--connection node_1
+--error ER_GALERA_REPLICATION_NOT_SUPPORTED
+TRUNCATE TABLE before_t1;
+SELECT * FROM before_t1;
+
+--connection node_2
+SET SESSION wsrep_sync_wait=15;
+SELECT @@wsrep_sync_wait;
+SELECT * FROM before_t1;
+
+--connection node_1
+--error ER_GALERA_REPLICATION_NOT_SUPPORTED
+CREATE VIEW x1 AS SELECT * FROM before_t1;
+--error ER_NO_SUCH_TABLE
+SHOW CREATE VIEW x1;
+
+--connection node_2
+--error ER_NO_SUCH_TABLE
+SHOW CREATE VIEW x1;
+
+--connection node_1
+--error ER_GALERA_REPLICATION_NOT_SUPPORTED
+CREATE DEFINER=`root`@`localhost` TRIGGER increment_before_t1
+ AFTER INSERT ON before_t1 FOR EACH ROW
+ UPDATE before_t1 SET before_t1.count = before_t1.count+1;
+
+--error ER_TRG_DOES_NOT_EXIST
+SHOW CREATE TRIGGER increment_before_t1;
+
+--connection node_2
+
+--error ER_TRG_DOES_NOT_EXIST
+SHOW CREATE TRIGGER increment_before_t1;
+
+--connection node_1
+--error ER_GALERA_REPLICATION_NOT_SUPPORTED
+CREATE INDEX xx2 ON before_t1(a);
+SHOW CREATE TABLE before_t1;
+
+--connection node_2
+SHOW CREATE TABLE before_t1;
+
+--connection node_1
+--error ER_GALERA_REPLICATION_NOT_SUPPORTED
+DROP INDEX b ON before_t1;
+SHOW CREATE TABLE before_t1;
+
+--connection node_2
+SHOW CREATE TABLE before_t1;
+
+--connection node_1
+--error ER_GALERA_REPLICATION_NOT_SUPPORTED
+ALTER TABLE before_t1 ADD COLUMN f int;
+SHOW CREATE TABLE before_t1;
+
+--connection node_2
+SHOW CREATE TABLE before_t1;
+
+--connection node_1
+--error ER_GALERA_REPLICATION_NOT_SUPPORTED
+RENAME TABLE before_t1 to after_t1;
+SHOW CREATE TABLE before_t1;
+--error ER_NO_SUCH_TABLE
+SHOW CREATE TABLE after_t1;
+
+--connection node_2
+SHOW CREATE TABLE before_t1;
+--error ER_NO_SUCH_TABLE
+SHOW CREATE TABLE after_t1;
+
+--connection node_1
+--error ER_GALERA_REPLICATION_NOT_SUPPORTED
+DROP TABLE before_t1;
+
+SHOW CREATE TABLE before_t1;
+
+--connection node_2
+SHOW CREATE TABLE before_t1;
+
+#
+# PROCEDURE, EVENT, FUNCTION
+# Unfortunately accessed tables are opened only
+# in SP execution so no hope at CREATE
+
+#
+# USER, ROLE, SERVER, DATABASE not really storage engine objects
+#
+
+--connection node_1
+set @@global.wsrep_strict_ddl=OFF;
+select @@global.wsrep_strict_ddl;
+
+--connectIon node_2
+set @@global.wsrep_strict_ddl=OFF;
+select @@global.wsrep_strict_ddl;
+DROP TABLE t2;
+DROP TABLE before_t1;
diff --git a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result
index a1d66e4d112..328fa1fee16 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result
@@ -706,6 +706,21 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
GLOBAL_VALUE_PATH NULL
+VARIABLE_NAME WSREP_STRICT_DDL
+SESSION_VALUE NULL
+GLOBAL_VALUE OFF
+GLOBAL_VALUE_ORIGIN COMPILE-TIME
+DEFAULT_VALUE OFF
+VARIABLE_SCOPE GLOBAL
+VARIABLE_TYPE BOOLEAN
+VARIABLE_COMMENT Reject DDL on effected tables not supporting Galera replication
+NUMERIC_MIN_VALUE NULL
+NUMERIC_MAX_VALUE NULL
+NUMERIC_BLOCK_SIZE NULL
+ENUM_VALUE_LIST OFF,ON
+READ_ONLY NO
+COMMAND_LINE_ARGUMENT OPTIONAL
+GLOBAL_VALUE_PATH NULL
VARIABLE_NAME WSREP_SYNC_WAIT
SESSION_VALUE 0
GLOBAL_VALUE 0
diff --git a/mysql-test/suite/sys_vars/r/wsrep_strict_ddl_basic.result b/mysql-test/suite/sys_vars/r/wsrep_strict_ddl_basic.result
new file mode 100644
index 00000000000..6d686f9de2e
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/wsrep_strict_ddl_basic.result
@@ -0,0 +1,45 @@
+#
+# wsrep_strict_ddl
+#
+# save the initial value
+SET @wsrep_strict_ddl_global_saved = @@global.wsrep_strict_ddl;
+# default
+SELECT @@global.wsrep_strict_ddl;
+@@global.wsrep_strict_ddl
+0
+
+# scope
+SELECT @@session.wsrep_strict_ddl;
+ERROR HY000: Variable 'wsrep_strict_ddl' is a GLOBAL variable
+SET @@global.wsrep_strict_ddl=OFF;
+SELECT @@global.wsrep_strict_ddl;
+@@global.wsrep_strict_ddl
+0
+SET @@global.wsrep_strict_ddl=ON;
+SELECT @@global.wsrep_strict_ddl;
+@@global.wsrep_strict_ddl
+1
+
+# valid values
+SET @@global.wsrep_strict_ddl='OFF';
+SELECT @@global.wsrep_strict_ddl;
+@@global.wsrep_strict_ddl
+0
+SET @@global.wsrep_strict_ddl=ON;
+SELECT @@global.wsrep_strict_ddl;
+@@global.wsrep_strict_ddl
+1
+SET @@global.wsrep_strict_ddl=default;
+SELECT @@global.wsrep_strict_ddl;
+@@global.wsrep_strict_ddl
+0
+
+# invalid values
+SET @@global.wsrep_strict_ddl=NULL;
+ERROR 42000: Variable 'wsrep_strict_ddl' can't be set to the value of 'NULL'
+SET @@global.wsrep_strict_ddl='junk';
+ERROR 42000: Variable 'wsrep_strict_ddl' can't be set to the value of 'junk'
+
+# restore the initial value
+SET @@global.wsrep_strict_ddl = @wsrep_strict_ddl_global_saved;
+# End of test
diff --git a/mysql-test/suite/sys_vars/t/wsrep_strict_ddl_basic.test b/mysql-test/suite/sys_vars/t/wsrep_strict_ddl_basic.test
new file mode 100644
index 00000000000..04d20ff3db5
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/wsrep_strict_ddl_basic.test
@@ -0,0 +1,42 @@
+--source include/have_wsrep.inc
+
+--echo #
+--echo # wsrep_strict_ddl
+--echo #
+
+--echo # save the initial value
+SET @wsrep_strict_ddl_global_saved = @@global.wsrep_strict_ddl;
+
+--echo # default
+SELECT @@global.wsrep_strict_ddl;
+
+--echo
+--echo # scope
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT @@session.wsrep_strict_ddl;
+SET @@global.wsrep_strict_ddl=OFF;
+SELECT @@global.wsrep_strict_ddl;
+SET @@global.wsrep_strict_ddl=ON;
+SELECT @@global.wsrep_strict_ddl;
+
+--echo
+--echo # valid values
+SET @@global.wsrep_strict_ddl='OFF';
+SELECT @@global.wsrep_strict_ddl;
+SET @@global.wsrep_strict_ddl=ON;
+SELECT @@global.wsrep_strict_ddl;
+SET @@global.wsrep_strict_ddl=default;
+SELECT @@global.wsrep_strict_ddl;
+
+--echo
+--echo # invalid values
+--error ER_WRONG_VALUE_FOR_VAR
+SET @@global.wsrep_strict_ddl=NULL;
+--error ER_WRONG_VALUE_FOR_VAR
+SET @@global.wsrep_strict_ddl='junk';
+
+--echo
+--echo # restore the initial value
+SET @@global.wsrep_strict_ddl = @wsrep_strict_ddl_global_saved;
+
+--echo # End of test
diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc
index 68de55b5778..8a547710143 100644
--- a/sql/service_wsrep.cc
+++ b/sql/service_wsrep.cc
@@ -52,13 +52,14 @@ extern "C" const char* wsrep_thd_transaction_state_str(const THD *thd)
return wsrep::to_c_string(thd->wsrep_cs().transaction().state());
}
-
extern "C" const char *wsrep_thd_query(const THD *thd)
{
- if (thd)
+ if (!thd)
+ return "NULL";
+
+ switch(thd->lex->sql_command)
{
- switch(thd->lex->sql_command)
- {
+ // Mask away some security related details from error log
case SQLCOM_CREATE_USER:
return "CREATE USER";
case SQLCOM_GRANT:
@@ -67,12 +68,10 @@ extern "C" const char *wsrep_thd_query(const THD *thd)
return "REVOKE";
case SQLCOM_SET_OPTION:
if (thd->lex->definer)
- return "SET PASSWORD";
+ return "SET PASSWORD";
/* fallthrough */
default:
- if (thd->query())
- return thd->query();
- }
+ return (thd->query() ? thd->query() : "NULL");
}
return "NULL";
}
@@ -321,3 +320,11 @@ extern "C" void wsrep_thd_set_ignored_error(THD *thd, my_bool val)
{
thd->wsrep_has_ignored_error= val;
}
+
+extern "C" ulong wsrep_OSU_method_get(const MYSQL_THD thd)
+{
+ if (thd)
+ return(thd->variables.wsrep_OSU_method);
+ else
+ return(global_system_variables.wsrep_OSU_method);
+}
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index dbff2b204d8..78b6cfa63c8 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -7943,3 +7943,5 @@ ER_WARN_HISTORY_ROW_START_TIME
eng "Table `%s.%s` history row start '%s' is later than row end '%s'"
ER_PART_STARTS_BEYOND_INTERVAL
eng "%`s: STARTS is later than query time, first history partition may exceed INTERVAL value"
+ER_GALERA_REPLICATION_NOT_SUPPORTED
+ eng "DDL-statement is forbidden as table storage engine does not support Galera replication" \ No newline at end of file
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index f3dd46b5139..0828e1b7ba8 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -505,9 +505,9 @@ bool Sql_cmd_alter_table::execute(THD *thd)
(!thd->is_current_stmt_binlog_format_row() ||
!thd->find_temporary_table(first_table)))
{
- WSREP_TO_ISOLATION_BEGIN_ALTER((lex->name.str ? select_lex->db.str : NULL),
- (lex->name.str ? lex->name.str : NULL),
- first_table, &alter_info);
+ WSREP_TO_ISOLATION_BEGIN_ALTER((lex->name.str ? select_lex->db.str : first_table->db.str),
+ (lex->name.str ? lex->name.str : first_table->table_name.str),
+ first_table, &alter_info, used_engine ? &create_info : NULL);
thd->variables.auto_increment_offset = 1;
thd->variables.auto_increment_increment = 1;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 141dfd9be65..e8b5e319773 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3079,6 +3079,7 @@ mysql_create_routine(THD *thd, LEX *lex)
return true;
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
+
if (!lex->sphead->m_handler->sp_create_routine(thd, lex->sphead))
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -4147,7 +4148,6 @@ mysql_execute_command(THD *thd)
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_one_table_access(thd, INDEX_ACL, all_tables))
goto error; /* purecov: inspected */
- WSREP_TO_ISOLATION_BEGIN(first_table->db.str, first_table->table_name.str, NULL);
bzero((char*) &create_info, sizeof(create_info));
create_info.db_type= 0;
@@ -4155,6 +4155,8 @@ mysql_execute_command(THD *thd)
create_info.default_table_charset= thd->variables.collation_database;
create_info.alter_info= &alter_info;
+ WSREP_TO_ISOLATION_BEGIN(first_table->db.str, first_table->table_name.str, NULL);
+
res= mysql_alter_table(thd, &first_table->db, &first_table->table_name,
&create_info, first_table, &alter_info,
0, (ORDER*) 0, 0);
@@ -4857,6 +4859,7 @@ mysql_execute_command(THD *thd)
slave_ddl_exec_mode_options == SLAVE_EXEC_MODE_IDEMPOTENT)
lex->create_info.set(DDL_options_st::OPT_IF_EXISTS);
+#ifdef WITH_WSREP
if (WSREP(thd))
{
for (TABLE_LIST *table= all_tables; table; table= table->next_global)
@@ -4870,7 +4873,8 @@ mysql_execute_command(THD *thd)
}
}
}
-
+#endif /* WITH_WSREP */
+
/* DDL and binlog write order are protected by metadata locks. */
res= mysql_rm_table(thd, first_table, lex->if_exists(), lex->tmp_table(),
lex->table_type == TABLE_TYPE_SEQUENCE);
@@ -5070,7 +5074,9 @@ mysql_execute_command(THD *thd)
(CREATE_ACL | DROP_ACL) : CREATE_ACL,
&lex->name))
break;
+
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL);
+
res= mysql_create_db(thd, &lex->name,
lex->create_info, &lex->create_info);
break;
@@ -5079,7 +5085,9 @@ mysql_execute_command(THD *thd)
{
if (prepare_db_action(thd, DROP_ACL, &lex->name))
break;
+
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL);
+
res= mysql_rm_db(thd, &lex->name, lex->if_exists());
break;
}
@@ -5111,7 +5119,9 @@ mysql_execute_command(THD *thd)
res= 1;
break;
}
+
WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL);
+
res= mysql_upgrade_db(thd, db);
if (!res)
my_ok(thd);
@@ -5122,7 +5132,9 @@ mysql_execute_command(THD *thd)
LEX_CSTRING *db= &lex->name;
if (prepare_db_action(thd, ALTER_ACL, db))
break;
+
WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL);
+
res= mysql_alter_db(thd, db, &lex->create_info);
break;
}
@@ -5196,6 +5208,7 @@ mysql_execute_command(THD *thd)
break;
#ifdef HAVE_DLOPEN
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
+
if (!(res = mysql_create_function(thd, &lex->udf)))
my_ok(thd);
#else
@@ -5213,7 +5226,9 @@ mysql_execute_command(THD *thd)
"mysql", NULL, NULL, 1, 1) &&
check_global_access(thd,CREATE_USER_ACL))
break;
+
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
+
/* Conditionally writes to binlog */
if (!(res= mysql_create_user(thd, lex->users_list,
lex->sql_command == SQLCOM_CREATE_ROLE)))
@@ -5226,8 +5241,10 @@ mysql_execute_command(THD *thd)
if (check_access(thd, DELETE_ACL, "mysql", NULL, NULL, 1, 1) &&
check_global_access(thd,CREATE_USER_ACL))
break;
- /* Conditionally writes to binlog */
+
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
+
+ /* Conditionally writes to binlog */
if (!(res= mysql_drop_user(thd, lex->users_list,
lex->sql_command == SQLCOM_DROP_ROLE)))
my_ok(thd);
@@ -5239,8 +5256,10 @@ mysql_execute_command(THD *thd)
if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1) &&
check_global_access(thd,CREATE_USER_ACL))
break;
- /* Conditionally writes to binlog */
+
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
+
+ /* Conditionally writes to binlog */
if (lex->sql_command == SQLCOM_ALTER_USER)
res= mysql_alter_user(thd, lex->users_list);
else
@@ -5255,16 +5274,19 @@ mysql_execute_command(THD *thd)
check_global_access(thd,CREATE_USER_ACL))
break;
- /* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
+
+ /* Conditionally writes to binlog */
if (!(res = mysql_revoke_all(thd, lex->users_list)))
my_ok(thd);
break;
}
+
case SQLCOM_REVOKE_ROLE:
case SQLCOM_GRANT_ROLE:
{
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
+
if (!(res= mysql_grant_role(thd, lex->users_list,
lex->sql_command != SQLCOM_GRANT_ROLE)))
my_ok(thd);
@@ -5611,6 +5633,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_DROP_PACKAGE:
case SQLCOM_DROP_PACKAGE_BODY:
if (drop_routine(thd, lex))
+
goto error;
break;
case SQLCOM_SHOW_CREATE_PROC:
@@ -5676,8 +5699,10 @@ mysql_execute_command(THD *thd)
{
if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE))
goto error;
- /* Conditionally writes to binlog. */
+
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
+
+ /* Conditionally writes to binlog. */
res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
break;
}
@@ -5983,7 +6008,7 @@ finish:
#ifdef WITH_WSREP
thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK;
-
+
WSREP_TO_ISOLATION_END;
/*
Force release of transactional locks if not in active MST and wsrep is on.
diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic
index 3faabcf5032..2db426e7b57 100644
--- a/sql/sql_plugin_services.ic
+++ b/sql/sql_plugin_services.ic
@@ -175,6 +175,7 @@ static struct wsrep_service_st wsrep_handler = {
wsrep_get_debug,
wsrep_commit_ordered,
wsrep_thd_is_applying,
+ wsrep_OSU_method_get,
wsrep_thd_has_ignored_error,
wsrep_thd_set_ignored_error
};
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 1c6cf52963a..8f818e321dd 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -286,6 +286,13 @@ do_rename(THD *thd, TABLE_LIST *ren_table, const LEX_CSTRING *new_db,
if (ha_table_exists(thd, &ren_table->db, &old_alias, &hton) && hton)
{
DBUG_ASSERT(!thd->locked_tables_mode);
+
+#ifdef WITH_WSREP
+ if (WSREP(thd) && hton &&
+ !wsrep_should_replicate_ddl(thd, hton->db_type))
+ DBUG_RETURN(1);
+#endif
+
tdc_remove_table(thd, TDC_RT_REMOVE_ALL,
ren_table->db.str, ren_table->table_name.str);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index e4a33dd99cd..240f001f7de 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2443,6 +2443,16 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
{
char *end;
int frm_delete_error= 0;
+
+#ifdef WITH_WSREP
+ if (WSREP(thd) &&
+ !wsrep_should_replicate_ddl(thd, table_type->db_type))
+ {
+ error= 1;
+ goto err;
+ }
+#endif
+
/*
It could happen that table's share in the table definition cache
is the only thing that keeps the engine plugin loaded
@@ -9461,6 +9471,17 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
&alter_prelocking_strategy);
thd->open_options&= ~HA_OPEN_FOR_ALTER;
+#ifdef WITH_WSREP
+ if (WSREP(thd) &&
+ (thd->lex->sql_command == SQLCOM_ALTER_TABLE ||
+ thd->lex->sql_command == SQLCOM_CREATE_INDEX ||
+ thd->lex->sql_command == SQLCOM_DROP_INDEX) &&
+ !wsrep_should_replicate_ddl(thd, table_list->table->s->db_type()->db_type))
+ DBUG_RETURN(true);
+#endif
+
+ DEBUG_SYNC(thd, "alter_table_after_open_tables");
+
TABLE *table= table_list->table;
bool versioned= table && table->versioned();
@@ -11503,7 +11524,8 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
(!thd->is_current_stmt_binlog_format_row() ||
!create_info.tmp_table()))
{
- WSREP_TO_ISOLATION_BEGIN(create_table->db.str, create_table->table_name.str, NULL);
+ WSREP_TO_ISOLATION_BEGIN_CREATE(create_table->db.str, create_table->table_name.str,
+ create_table, &create_info);
}
/* Regular CREATE TABLE */
res= mysql_create_table(thd, create_table, &create_info, &alter_info);
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 5802d2c811e..0ae3d58b11f 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -507,9 +507,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
goto end;
}
-#ifdef WITH_WSREP
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, tables);
-#endif
/* We should have only one table in table list. */
DBUG_ASSERT(tables->next_global == 0);
@@ -550,6 +548,12 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
}
table= tables->table;
+#ifdef WITH_WSREP
+ if (WSREP(thd) &&
+ !wsrep_should_replicate_ddl(thd, table->s->db_type()->db_type))
+ goto wsrep_error_label;
+#endif
+
/* Later on we will need it to downgrade the lock */
mdl_ticket= table->mdl_ticket;
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 8e078ff02af..a47822e43ca 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -303,6 +303,12 @@ bool Sql_cmd_truncate_table::lock_table(THD *thd, TABLE_LIST *table_ref,
versioned= table->versioned();
hton= table->file->ht;
+#ifdef WITH_WSREP
+ if (WSREP(thd) &&
+ !wsrep_should_replicate_ddl(thd, hton->db_type))
+ DBUG_RETURN(TRUE);
+#endif
+
table_ref->mdl_request.ticket= table->mdl_ticket;
}
else
@@ -320,6 +326,15 @@ bool Sql_cmd_truncate_table::lock_table(THD *thd, TABLE_LIST *table_ref,
versioned= share->versioned;
sequence= share->table_type == TABLE_TYPE_SEQUENCE;
hton= share->db_type();
+#ifdef WITH_WSREP
+ if (WSREP(thd) &&
+ hton != view_pseudo_hton &&
+ !wsrep_should_replicate_ddl(thd, hton->db_type))
+ {
+ tdc_release_share(share);
+ DBUG_RETURN(TRUE);
+ }
+#endif
tdc_release_share(share);
@@ -417,9 +432,10 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
#ifdef WITH_WSREP
if (WSREP(thd) &&
- wsrep_to_isolation_begin(thd, table_ref->db.str, table_ref->table_name.str, 0))
- DBUG_RETURN(TRUE);
+ wsrep_to_isolation_begin(thd, table_ref->db.str, table_ref->table_name.str, NULL))
+ DBUG_RETURN(TRUE);
#endif /* WITH_WSREP */
+
if (lock_table(thd, table_ref, &hton_can_recreate))
DBUG_RETURN(TRUE);
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 12dfb8bc59d..f47e910c0fe 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -37,6 +37,7 @@
#include "sql_derived.h"
#include "sql_cte.h" // check_dependencies_in_with_clauses()
#include "opt_trace.h"
+#include "wsrep_mysqld.h"
#define MD5_BUFF_LENGTH 33
@@ -454,6 +455,14 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
goto err;
}
+#ifdef WITH_WSREP
+ if(!wsrep_should_replicate_ddl_iterate(thd, static_cast<const TABLE_LIST *>(tables)))
+ {
+ res= TRUE;
+ goto err;
+ }
+#endif
+
view= lex->unlink_first_table(&link_to_local);
if (check_db_dir_existence(view->db.str))
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index ab382304973..4dfec12ee29 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -5685,12 +5685,20 @@ static Sys_var_enum Sys_wsrep_OSU_method(
static PolyLock_mutex PLock_wsrep_desync(&LOCK_wsrep_desync);
static Sys_var_mybool Sys_wsrep_desync (
"wsrep_desync", "To desynchronize the node from the cluster",
- GLOBAL_VAR(wsrep_desync),
+ GLOBAL_VAR(wsrep_desync),
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
&PLock_wsrep_desync, NOT_IN_BINLOG,
ON_CHECK(wsrep_desync_check),
ON_UPDATE(wsrep_desync_update));
+static Sys_var_mybool Sys_wsrep_strict_ddl (
+ "wsrep_strict_ddl", "Reject DDL on effected tables not supporting Galera replication",
+ GLOBAL_VAR(wsrep_strict_ddl),
+ CMD_LINE(OPT_ARG), DEFAULT(FALSE),
+ NO_MUTEX_GUARD, NOT_IN_BINLOG,
+ ON_CHECK(0),
+ ON_UPDATE(0));
+
static const char *wsrep_reject_queries_names[]= { "NONE", "ALL", "ALL_KILL", NullS };
static Sys_var_enum Sys_wsrep_reject_queries(
"wsrep_reject_queries", "Variable to set to reject queries",
diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc
index b87e807c7c9..ffc6acc8bd9 100644
--- a/sql/wsrep_dummy.cc
+++ b/sql/wsrep_dummy.cc
@@ -144,3 +144,5 @@ my_bool wsrep_thd_has_ignored_error(const THD*)
void wsrep_thd_set_ignored_error(THD*, my_bool)
{ }
+ulong wsrep_OSU_method_get(const THD*)
+{ return 0;} \ No newline at end of file
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index a3c5e91eb24..ff01473e816 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -96,6 +96,9 @@ my_bool wsrep_restart_slave; // Should mysql slave thread be
// restarted, when node joins back?
my_bool wsrep_desync; // De(re)synchronize the node from the
// cluster
+my_bool wsrep_strict_ddl; // Reject DDL to
+ // effected tables not
+ // supporting Galera replication
long wsrep_slave_threads; // No. of slave appliers threads
ulong wsrep_retry_autocommit; // Retry aborted autocommit trx
ulong wsrep_max_ws_size; // Max allowed ws (RBR buffer) size
@@ -1296,11 +1299,11 @@ static bool wsrep_prepare_key_for_isolation(const char* db,
}
static bool wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
- Alter_info* alter_info,
+ const Alter_info* alter_info,
wsrep_key_arr_t* ka)
{
Key *key;
- List_iterator<Key> key_iterator(alter_info->key_list);
+ List_iterator<Key> key_iterator(const_cast<Alter_info*>(alter_info)->key_list);
while ((key= key_iterator++))
{
if (key->type == Key::FOREIGN_KEY)
@@ -1436,12 +1439,12 @@ wsrep::key wsrep_prepare_key_for_toi(const char* db, const char* table,
wsrep::key_array
wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
- Alter_info* alter_info)
+ const Alter_info* alter_info)
{
wsrep::key_array ret;
Key *key;
- List_iterator<Key> key_iterator(alter_info->key_list);
+ List_iterator<Key> key_iterator(const_cast<Alter_info*>(alter_info)->key_list);
while ((key= key_iterator++))
{
if (key->type == Key::FOREIGN_KEY)
@@ -1463,7 +1466,7 @@ wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
wsrep::key_array wsrep_prepare_keys_for_toi(const char* db,
const char* table,
const TABLE_LIST* table_list,
- Alter_info* alter_info)
+ const Alter_info* alter_info)
{
wsrep::key_array ret;
if (db || table)
@@ -1735,6 +1738,51 @@ static int wsrep_drop_table_query(THD* thd, uchar** buf, size_t* buf_len)
/* Forward declarations. */
int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
+bool wsrep_should_replicate_ddl_iterate(THD* thd, const TABLE_LIST* table_list)
+{
+ if (WSREP(thd))
+ {
+ for (const TABLE_LIST* it= table_list; it; it= it->next_global)
+ {
+ if (!wsrep_should_replicate_ddl(thd, it->table->s->db_type()->db_type))
+ return false;
+ }
+ }
+ return true;
+}
+
+bool wsrep_should_replicate_ddl(THD* thd,
+ const enum legacy_db_type db_type)
+{
+ if (!wsrep_strict_ddl)
+ return true;
+
+ switch (db_type)
+ {
+ case DB_TYPE_INNODB:
+ return true;
+ break;
+ case DB_TYPE_MYISAM:
+ if (wsrep_replicate_myisam)
+ return true;
+ else
+ WSREP_DEBUG("wsrep OSU failed for %s", wsrep_thd_query(thd));
+ break;
+ case DB_TYPE_ARIA:
+ /* if (wsrep_replicate_aria) */
+ /* fallthrough */
+ default:
+ WSREP_DEBUG("wsrep OSU failed for %s", wsrep_thd_query(thd));
+ break;
+ }
+
+ /* STRICT, treat as error */
+ my_error(ER_GALERA_REPLICATION_NOT_SUPPORTED, MYF(0));
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA,
+ "WSREP: wsrep_strict_ddl=true and storage engine does not support Galera replication.");
+ return false;
+}
/*
Decide if statement should run in TOI.
@@ -1745,24 +1793,28 @@ int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
should be rewritten at later time for replication to contain only
non-temporary tables.
*/
-static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
- const TABLE_LIST *table_list)
+bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
+ const TABLE_LIST *table_list,
+ const HA_CREATE_INFO* create_info)
{
DBUG_ASSERT(!table || db);
DBUG_ASSERT(table_list || db);
LEX* lex= thd->lex;
SELECT_LEX* select_lex= lex->first_select_lex();
- TABLE_LIST* first_table= select_lex->table_list.first;
+ const TABLE_LIST* first_table= select_lex->table_list.first;
switch (lex->sql_command)
{
case SQLCOM_CREATE_TABLE:
- DBUG_ASSERT(!table_list);
if (thd->lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)
{
return false;
}
+ if (!wsrep_should_replicate_ddl(thd, create_info->db_type->db_type))
+ {
+ return false;
+ }
/*
If mariadb master has replicated a CTAS, we should not replicate the create table
part separately as TOI, but to replicate both create table and following inserts
@@ -1771,7 +1823,8 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
as TOI. We have to do relay log event lookup to see if row events follow the
create table event.
*/
- if (thd->slave_thread && !(thd->rgi_slave->gtid_ev_flags2 & Gtid_log_event::FL_STANDALONE))
+ if (thd->slave_thread &&
+ !(thd->rgi_slave->gtid_ev_flags2 & Gtid_log_event::FL_STANDALONE))
{
/* this is CTAS, either empty or populated table */
ulonglong event_size = 0;
@@ -1797,7 +1850,7 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
}
/* no next async replication event */
return true;
-
+ break;
case SQLCOM_CREATE_VIEW:
DBUG_ASSERT(!table_list);
@@ -1806,7 +1859,7 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
If any of the remaining tables refer to temporary table error
is returned to client, so TOI can be skipped
*/
- for (TABLE_LIST* it= first_table->next_global; it; it= it->next_global)
+ for (const TABLE_LIST* it= first_table->next_global; it; it= it->next_global)
{
if (thd->find_temporary_table(it))
{
@@ -1814,7 +1867,7 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
}
}
return true;
-
+ break;
case SQLCOM_CREATE_TRIGGER:
DBUG_ASSERT(first_table);
@@ -1824,15 +1877,12 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
return false;
}
return true;
-
- case SQLCOM_DROP_TRIGGER:
- DBUG_ASSERT(table_list);
- if (thd->find_temporary_table(table_list))
- {
+ break;
+ case SQLCOM_ALTER_TABLE:
+ if (create_info &&
+ !wsrep_should_replicate_ddl(thd, create_info->db_type->db_type))
return false;
- }
- return true;
-
+ /* fallthrough */
default:
if (table && !thd->find_temporary_table(db, table))
{
@@ -1841,7 +1891,7 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
if (table_list)
{
- for (TABLE_LIST* table= first_table; table; table= table->next_global)
+ for (const TABLE_LIST* table= first_table; table; table= table->next_global)
{
if (!thd->find_temporary_table(table->db.str, table->table_name.str))
{
@@ -1849,11 +1899,12 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
}
}
}
+
return !(table || table_list);
+ break;
}
}
-
static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
{
String log_query;
@@ -1962,14 +2013,16 @@ fail:
*/
static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
const TABLE_LIST* table_list,
- Alter_info* alter_info)
+ const Alter_info* alter_info,
+ const HA_CREATE_INFO* create_info)
{
- DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI);
+ DBUG_ASSERT(wsrep_OSU_method_get(thd) == WSREP_OSU_TOI);
+
+ WSREP_DEBUG("TOI Begin: %s", wsrep_thd_query(thd));
- WSREP_DEBUG("TOI Begin");
- if (wsrep_can_run_in_toi(thd, db, table, table_list) == false)
+ if (wsrep_can_run_in_toi(thd, db, table, table_list, create_info) == false)
{
- WSREP_DEBUG("No TOI for %s", WSREP_QUERY(thd));
+ WSREP_DEBUG("No TOI for %s", wsrep_thd_query(thd));
return 1;
}
@@ -1979,6 +2032,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
int rc;
buf_err= wsrep_TOI_event_buf(thd, &buf, &buf_len);
+
if (buf_err) {
WSREP_ERROR("Failed to create TOI event buf: %d", buf_err);
my_message(ER_UNKNOWN_ERROR,
@@ -1987,6 +2041,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
MYF(0));
return -1;
}
+
struct wsrep_buf buff= { buf, buf_len };
wsrep::key_array key_array=
@@ -1997,7 +2052,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
/* non replicated DDL, affecting temporary tables only */
WSREP_DEBUG("TO isolation skipped, sql: %s."
"Only temporary tables affected.",
- WSREP_QUERY(thd));
+ wsrep_thd_query(thd));
if (buf) my_free(buf);
return -1;
}
@@ -2005,6 +2060,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
thd_proc_info(thd, "acquiring total order isolation");
wsrep::client_state& cs(thd->wsrep_cs());
+
int ret= cs.enter_toi_local(key_array,
wsrep::const_buffer(buff.ptr, buff.len));
@@ -2012,7 +2068,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
{
DBUG_ASSERT(cs.current_error());
WSREP_DEBUG("to_execute_start() failed for %llu: %s, seqno: %lld",
- thd->thread_id, WSREP_QUERY(thd),
+ thd->thread_id, wsrep_thd_query(thd),
(long long)wsrep_thd_trx_seqno(thd));
/* jump to error handler in mysql_execute_command() */
@@ -2023,7 +2079,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
"Maximum size exceeded.",
ret,
(thd->db.str ? thd->db.str : "(null)"),
- WSREP_QUERY(thd));
+ wsrep_thd_query(thd));
my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_SIZE_EXCEEDED);
break;
default:
@@ -2031,7 +2087,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
"Check wsrep connection state and retry the query.",
ret,
(thd->db.str ? thd->db.str : "(null)"),
- WSREP_QUERY(thd));
+ wsrep_thd_query(thd));
if (!thd->is_error())
{
my_error(ER_LOCK_DEADLOCK, MYF(0), "WSREP replication failed. Check "
@@ -2079,7 +2135,7 @@ static void wsrep_TOI_end(THD *thd) {
wsrep::client_state& client_state(thd->wsrep_cs());
DBUG_ASSERT(wsrep_thd_is_local_toi(thd));
WSREP_DEBUG("TO END: %lld: %s", client_state.toi_meta().seqno().get(),
- WSREP_QUERY(thd));
+ wsrep_thd_query(thd));
wsrep_gtid_server.signal_waiters(thd->wsrep_current_gtid_seqno, false);
@@ -2104,7 +2160,7 @@ static void wsrep_TOI_end(THD *thd) {
else
{
WSREP_WARN("TO isolation end failed for: %d, schema: %s, sql: %s",
- ret, (thd->db.str ? thd->db.str : "(null)"), WSREP_QUERY(thd));
+ ret, (thd->db.str ? thd->db.str : "(null)"), wsrep_thd_query(thd));
}
}
}
@@ -2112,7 +2168,7 @@ static void wsrep_TOI_end(THD *thd) {
static int wsrep_RSU_begin(THD *thd, const char *db_, const char *table_)
{
WSREP_DEBUG("RSU BEGIN: %lld, : %s", wsrep_thd_trx_seqno(thd),
- WSREP_QUERY(thd));
+ wsrep_thd_query(thd));
if (thd->wsrep_cs().begin_rsu(5000))
{
WSREP_WARN("RSU begin failed");
@@ -2127,7 +2183,7 @@ static int wsrep_RSU_begin(THD *thd, const char *db_, const char *table_)
static void wsrep_RSU_end(THD *thd)
{
WSREP_DEBUG("RSU END: %lld : %s", wsrep_thd_trx_seqno(thd),
- WSREP_QUERY(thd));
+ wsrep_thd_query(thd));
if (thd->wsrep_cs().end_rsu())
{
WSREP_WARN("Failed to end RSU, server may need to be restarted");
@@ -2137,7 +2193,8 @@ static void wsrep_RSU_end(THD *thd)
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list,
- Alter_info* alter_info)
+ const Alter_info* alter_info,
+ const HA_CREATE_INFO* create_info)
{
/*
No isolation for applier or replaying threads.
@@ -2162,14 +2219,14 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
if (thd->global_read_lock.is_acquired())
{
WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %llu",
- WSREP_QUERY(thd), thd->thread_id);
+ wsrep_thd_query(thd), thd->thread_id);
return -1;
}
if (wsrep_debug && thd->mdl_context.has_locks())
{
WSREP_DEBUG("thread holds MDL locks at TI begin: %s %llu",
- WSREP_QUERY(thd), thd->thread_id);
+ wsrep_thd_query(thd), thd->thread_id);
}
/*
@@ -2187,24 +2244,24 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
if (thd->variables.wsrep_on && wsrep_thd_is_local(thd))
{
- switch (thd->variables.wsrep_OSU_method) {
+ switch (wsrep_OSU_method_get(thd)) {
case WSREP_OSU_TOI:
- ret= wsrep_TOI_begin(thd, db_, table_, table_list, alter_info);
+ ret= wsrep_TOI_begin(thd, db_, table_, table_list, alter_info, create_info);
break;
case WSREP_OSU_RSU:
ret= wsrep_RSU_begin(thd, db_, table_);
break;
default:
WSREP_ERROR("Unsupported OSU method: %lu",
- thd->variables.wsrep_OSU_method);
+ wsrep_OSU_method_get(thd));
ret= -1;
break;
}
switch (ret) {
- case 0: /* wsrep_TOI_begin sould set toi mode */ break;
+ case 0: /* wsrep_TOI_begin should set toi mode */ break;
case 1:
- /* TOI replication skipped, treat as success */
- ret= 0;
+ /* TOI replication skipped, treat as success */
+ ret= 0;
break;
case -1:
/* TOI replication failed, treat as error */
@@ -2221,12 +2278,12 @@ void wsrep_to_isolation_end(THD *thd)
wsrep_thd_is_in_rsu(thd));
if (wsrep_thd_is_local_toi(thd))
{
- DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI);
+ DBUG_ASSERT(wsrep_OSU_method_get(thd) == WSREP_OSU_TOI);
wsrep_TOI_end(thd);
}
else if (wsrep_thd_is_in_rsu(thd))
{
- DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_RSU);
+ DBUG_ASSERT(wsrep_OSU_method_get(thd) == WSREP_OSU_RSU);
wsrep_RSU_end(thd);
}
else
@@ -2678,17 +2735,17 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
if (create_info->tmp_table())
{
/* CREATE TEMPORARY TABLE LIKE must be skipped from replication */
- WSREP_DEBUG("CREATE TEMPORARY TABLE LIKE... skipped replication\n %s",
+ WSREP_DEBUG("CREATE TEMPORARY TABLE LIKE... skipped replication\n %s",
thd->query());
}
else if (!(thd->find_temporary_table(src_table)))
{
/* this is straight CREATE TABLE LIKE... with no tmp tables */
- WSREP_TO_ISOLATION_BEGIN(table->db.str, table->table_name.str, NULL);
+ WSREP_TO_ISOLATION_BEGIN_CREATE(table->db.str, table->table_name.str, table, create_info);
}
else
{
- /* here we have CREATE TABLE LIKE <temporary table>
+ /* here we have CREATE TABLE LIKE <temporary table>
the temporary table definition will be needed in slaves to
enable the create to succeed
*/
@@ -2707,7 +2764,7 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
thd->wsrep_TOI_pre_query= query.ptr();
thd->wsrep_TOI_pre_query_len= query.length();
- WSREP_TO_ISOLATION_BEGIN(table->db.str, table->table_name.str, NULL);
+ WSREP_TO_ISOLATION_BEGIN_CREATE(table->db.str, table->table_name.str, table, create_info);
thd->wsrep_TOI_pre_query= NULL;
thd->wsrep_TOI_pre_query_len= 0;
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 077e5602025..b51dc308646 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -98,6 +98,7 @@ extern ulong wsrep_running_applier_threads;
extern ulong wsrep_running_rollbacker_threads;
extern bool wsrep_new_cluster;
extern bool wsrep_gtid_mode;
+extern my_bool wsrep_strict_ddl;
enum enum_wsrep_reject_types {
WSREP_REJECT_NONE, /* nothing rejected */
@@ -108,7 +109,7 @@ enum enum_wsrep_reject_types {
enum enum_wsrep_OSU_method {
WSREP_OSU_TOI,
WSREP_OSU_RSU,
- WSREP_OSU_NONE,
+ WSREP_OSU_NONE
};
enum enum_wsrep_sync_wait {
@@ -360,9 +361,15 @@ extern PSI_thread_key key_wsrep_sst_donor_monitor;
struct TABLE_LIST;
class Alter_info;
+struct HA_CREATE_INFO;
+
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list,
- Alter_info* alter_info= NULL);
+ const Alter_info* alter_info= NULL,
+ const HA_CREATE_INFO* create_info= NULL);
+
+bool wsrep_should_replicate_ddl(THD* thd, const enum legacy_db_type db_type);
+bool wsrep_should_replicate_ddl_iterate(THD* thd, const TABLE_LIST* table_list);
void wsrep_to_isolation_end(THD *thd);